Skip to content

Commit c69a05a

Browse files
committed
[2025] Solution for Day 4
1 parent 11761ca commit c69a05a

File tree

5 files changed

+150
-1
lines changed

5 files changed

+150
-1
lines changed

2025/src/bin/day04.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use aoc2025::days::day04::{part1, part2};
2+
use std::env;
3+
use std::fs;
4+
use std::process;
5+
6+
fn main() {
7+
let args: Vec<String> = env::args().collect();
8+
if args.len() < 2 {
9+
println!("Missing required arguments");
10+
process::exit(1);
11+
}
12+
13+
let contents = fs::read_to_string(&args[1]).expect("Something went wrong");
14+
println!("Part 1: {}", part1(&contents));
15+
println!("Part 2: {}", part2(&contents));
16+
}

2025/src/days.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod day01;
22
pub mod day02;
33
pub mod day03;
4+
pub mod day04;

2025/src/days/day04.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use std::vec;
2+
3+
pub fn part1(contents: &str) -> i64 {
4+
let grid = parse_input(contents);
5+
let mut count = 0;
6+
7+
for y in 0..grid.len() {
8+
for x in 0..grid[0].len() {
9+
if grid[y][x] == '@' && is_movable(&grid, x, y) {
10+
count += 1;
11+
}
12+
}
13+
}
14+
count
15+
}
16+
17+
pub fn part2(contents: &str) -> i64 {
18+
let mut grid = parse_input(contents);
19+
let mut count = 0;
20+
let mut found = true;
21+
22+
while found {
23+
found = false;
24+
let mut new_grid = grid.clone();
25+
26+
for y in 0..grid.len() {
27+
for x in 0..grid[0].len() {
28+
if grid[y][x] == '@' && is_movable(&grid, x, y) {
29+
new_grid[y][x] = '.';
30+
found = true;
31+
count += 1;
32+
}
33+
}
34+
}
35+
grid = new_grid;
36+
}
37+
count
38+
}
39+
40+
fn parse_input(contents: &str) -> Vec<Vec<char>> {
41+
let mut grid = vec![];
42+
for l in contents.lines() {
43+
grid.push(l.chars().collect());
44+
}
45+
grid
46+
}
47+
48+
fn is_movable(grid: &Vec<Vec<char>>, x: usize, y: usize) -> bool {
49+
let mut count: usize = 0;
50+
let rows = grid.len();
51+
let cols = grid[0].len();
52+
53+
if x > 0 && y > 0 && grid[y - 1][x - 1] == '@' {
54+
count += 1;
55+
}
56+
if x > 0 && grid[y][x - 1] == '@' {
57+
count += 1;
58+
}
59+
if x > 0 && y < rows - 1 && grid[y + 1][x - 1] == '@' {
60+
count += 1;
61+
}
62+
if x < cols - 1 && grid[y][x + 1] == '@' {
63+
count += 1;
64+
}
65+
if x < cols - 1 && y > 0 && grid[y - 1][x + 1] == '@' {
66+
count += 1;
67+
}
68+
if y > 0 && grid[y - 1][x] == '@' {
69+
count += 1;
70+
}
71+
if y < rows - 1 && grid[y + 1][x] == '@' {
72+
count += 1;
73+
}
74+
if x < cols - 1 && y < rows - 1 && grid[y + 1][x + 1] == '@' {
75+
count += 1;
76+
}
77+
count < 4
78+
}
79+
80+
#[cfg(test)]
81+
mod tests {
82+
use super::*;
83+
84+
#[test]
85+
fn test_part1() {
86+
let input = vec![
87+
"..@@.@@@@.",
88+
"@@@.@.@.@@",
89+
"@@@@@.@.@@",
90+
"@.@@@@..@.",
91+
"@@.@@@@.@@",
92+
".@@@@@@@.@",
93+
".@.@.@.@@@",
94+
"@.@@@.@@@@",
95+
".@@@@@@@@.",
96+
"@.@.@@@.@.",
97+
];
98+
99+
assert_eq!(part1(&input.join("\n")), 13);
100+
}
101+
102+
#[test]
103+
fn test_part2() {
104+
let input = vec![
105+
"..@@.@@@@.",
106+
"@@@.@.@.@@",
107+
"@@@@@.@.@@",
108+
"@.@@@@..@.",
109+
"@@.@@@@.@@",
110+
".@@@@@@@.@",
111+
".@.@.@.@@@",
112+
"@.@@@.@@@@",
113+
".@@@@@@@@.",
114+
"@.@.@@@.@.",
115+
];
116+
117+
assert_eq!(part2(&input.join("\n")), 43);
118+
}
119+
}

2025/tests/day04.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use aoc2025::days::day04::{part1, part2};
2+
3+
#[test]
4+
fn test_part1() {
5+
let content = std::include_str!("../../private/inputs/2025/day04.txt");
6+
assert_eq!(part1(&content), 1564);
7+
}
8+
9+
#[test]
10+
fn test_part2() {
11+
let content = std::include_str!("../../private/inputs/2025/day04.txt");
12+
assert_eq!(part2(&content), 9401);
13+
}

private

0 commit comments

Comments
 (0)