Skip to content

Commit

Permalink
2024 Day 12 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
gchazot committed Dec 12, 2024
1 parent b2c3143 commit cf7789d
Showing 1 changed file with 90 additions and 17 deletions.
107 changes: 90 additions & 17 deletions year_2024/src/day12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use std::collections::{HashMap, VecDeque};
pub fn execute() -> String {
let data = aoc_utils::read_lines("input/day12.txt");
let plots = from_lines(&data);
let areas = to_areas(&plots);

let part1 = calculate_cost(&plots);
let part2 = 456;
let part1 = calculate_cost_part1(&areas);
let part2 = calculate_cost_part2(&areas);

format!("{} {}", part1, part2)
}
Expand Down Expand Up @@ -79,39 +80,93 @@ fn first_unseen(seen: &Vec<Vec<bool>>) -> Option<(usize, usize)> {
None
}

fn calculate_cost(plots: &Vec<Vec<char>>) -> u64 {
let plots = to_areas(plots);
fn calculate_cost_part1(plots: &Vec<Vec<u16>>) -> u64 {
let size = plots.len();
let mut area = HashMap::<u16, u64>::new();
let mut perimeter = HashMap::<u16, u64>::new();

for (j, row) in plots.iter().enumerate() {
for (i, &id) in row.iter().enumerate() {
*area.entry(id).or_default() += 1;

let mut borders = 0;
if i == 0 || row[i - 1] != id {
*perimeter.entry(id).or_default() += 1;
borders += 1;
}
if i == size - 1 || row[i + 1] != id {
*perimeter.entry(id).or_default() += 1;
borders += 1;
}
if j == 0 || plots[j - 1][i] != id {
*perimeter.entry(id).or_default() += 1;
borders += 1;
}
if j == size - 1 || plots[j + 1][i] != id {
*perimeter.entry(id).or_default() += 1;
borders += 1;
}

if borders > 0 {
*perimeter.entry(id).or_default() += borders;
}
}
}
perimeter.iter().map(|(id, &p)| p * area[id]).sum()
}
fn calculate_cost_part2(plots: &Vec<Vec<u16>>) -> u64 {
let size = plots.len();
let mut area = HashMap::<u16, u64>::new();
let mut sides = HashMap::<u16, u64>::new();

for (j, row) in plots.iter().enumerate() {
for (i, &id) in row.iter().enumerate() {
*area.entry(id).or_default() += 1;

let mut corners = 0;

// 0 1 2
// 3 X 4
// 5 6 7
let neighbour = [
!(i == 0 || j == 0 || plots[j - 1][i - 1] != id),
!(j == 0 || plots[j - 1][i] != id),
!(i == size - 1 || j == 0 || plots[j - 1][i + 1] != id),
!(i == 0 || row[i - 1] != id),
!(i == size - 1 || row[i + 1] != id),
!(i == 0 || j == size - 1 || plots[j + 1][i - 1] != id),
!(j == size - 1 || plots[j + 1][i] != id),
!(i == size - 1 || j == size - 1 || plots[j + 1][i + 1] != id),
];

// top-left
if (neighbour[1] && neighbour[3] && !neighbour[0]) || (!neighbour[1] && !neighbour[3]) {
corners += 1;
}
// top-right
if (neighbour[1] && neighbour[4] && !neighbour[2]) || (!neighbour[1] && !neighbour[4]) {
corners += 1;
}
// bottom-left
if (neighbour[6] && neighbour[3] && !neighbour[5]) || (!neighbour[6] && !neighbour[3]) {
corners += 1;
}
// bottom-right
if (neighbour[6] && neighbour[4] && !neighbour[7]) || (!neighbour[6] && !neighbour[4]) {
corners += 1;
}

if corners > 0 {
*sides.entry(id).or_default() += corners;
}
}
}
sides.iter().map(|(id, &p)| p * area[id]).sum()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_mine() {
assert_eq!(execute(), "1477924 456");
assert_eq!(execute(), "1477924 841934");
}

#[test]
Expand All @@ -123,15 +178,33 @@ mod tests {
}

#[test]
fn test_calculate_cost() {
let e1 = from_lines(&example1());
assert_eq!(calculate_cost(&e1), 140);

let e2 = from_lines(&example2());
assert_eq!(calculate_cost(&e2), 772);
fn test_calculate_cost_part1() {
let data1 = from_lines(&example1());
let areas1 = to_areas(&data1);
assert_eq!(calculate_cost_part1(&areas1), 140);

let data2 = from_lines(&example2());
let areas2 = to_areas(&data2);
assert_eq!(calculate_cost_part1(&areas2), 772);

let data3 = from_lines(&example3());
let areas3 = to_areas(&data3);
assert_eq!(calculate_cost_part1(&areas3), 1930);
}

let e3 = from_lines(&example3());
assert_eq!(calculate_cost(&e3), 1930);
#[test]
fn test_calculate_cost_part2() {
let data1 = from_lines(&example1());
let areas1 = to_areas(&data1);
assert_eq!(calculate_cost_part2(&areas1), 80);

let data2 = from_lines(&example2());
let areas2 = to_areas(&data2);
assert_eq!(calculate_cost_part2(&areas2), 436);

let data3 = from_lines(&example3());
let areas3 = to_areas(&data3);
assert_eq!(calculate_cost_part2(&areas3), 1206);
}

fn example1() -> Vec<String> {
Expand Down

0 comments on commit cf7789d

Please sign in to comment.