Skip to content

Commit fb35d22

Browse files
AOC 2025 Day 1 -> 4 solutions (#83)
* Day 1 solutions * Day 2 solutions * Day 3 solutions * Day 4 solutions * Update input file name * Delete 2025/01/kylepritchard.input * Delete 2025/02/kylepritchard.input * Delete 2025/03/kylepritchard.input * Delete 2025/04/kylepritchard.input * Change input file name Updated input file name from 'kylepritchard.input' to 'ids.input' in main function. * Refactor main module and functions for clarity * Change input file name from kylepritchard.input to department.input * Change input file from 'kylepritchard.input' to 'banks.input' * rebase to main and run `v run verify.v` * run `v fmt -w .` --------- Co-authored-by: Dylan Donnell <[email protected]>
1 parent 695787f commit fb35d22

File tree

8 files changed

+382
-0
lines changed

8 files changed

+382
-0
lines changed

2025/01/kylepritchard.v

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
module main
2+
3+
import os
4+
import strconv
5+
6+
fn main() {
7+
codes := os.read_file('rotations.input') or { panic('Failed to read file') }
8+
9+
mut start := 50
10+
mut count := 0
11+
mut count2 := 0
12+
13+
for line in codes.split_into_lines() {
14+
if line.len == 0 {
15+
continue
16+
}
17+
18+
if line[0] == `L` {
19+
move_str := line[1..].trim_space()
20+
mut move := strconv.atoi(move_str) or { 0 }
21+
22+
for move > 0 {
23+
start--
24+
if start == 0 {
25+
count2++
26+
}
27+
if start == -1 {
28+
start = 99
29+
}
30+
move--
31+
}
32+
33+
if start == 0 {
34+
count++
35+
}
36+
} else {
37+
move_str := line[1..].trim_space()
38+
mut move := strconv.atoi(move_str) or { 0 }
39+
40+
for move > 0 {
41+
start++
42+
if start == 100 {
43+
start = 0
44+
}
45+
if start == 0 {
46+
count2++
47+
}
48+
move--
49+
}
50+
51+
if start == 0 {
52+
count++
53+
}
54+
}
55+
}
56+
57+
println('Part 1: ${count}')
58+
println('Part 2: ${count2}')
59+
}

2025/02/kylepritchard.v

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
module main
2+
3+
import os
4+
import strconv
5+
6+
fn has_exact_two_halves(s string) bool {
7+
if s.len % 2 != 0 {
8+
return false
9+
}
10+
half := s.len / 2
11+
return s[0..half] == s[half..]
12+
}
13+
14+
fn has_repeating_pattern(s string) bool {
15+
for pattern_len in 1 .. s.len / 2 + 1 {
16+
if s.len % pattern_len != 0 {
17+
continue
18+
}
19+
20+
pattern := s[0..pattern_len]
21+
mut matches := true
22+
23+
repetitions := s.len / pattern_len
24+
for rep in 1 .. repetitions {
25+
start := rep * pattern_len
26+
end := start + pattern_len
27+
if s[start..end] != pattern {
28+
matches = false
29+
break
30+
}
31+
}
32+
33+
if matches {
34+
return true
35+
}
36+
}
37+
return false
38+
}
39+
40+
fn main() {
41+
content := os.read_file('ids.input') or { panic('Failed to read file: ${err}') }
42+
43+
ids := content.split(',')
44+
45+
mut sum1 := i64(0)
46+
mut sum2 := i64(0)
47+
48+
for id in ids {
49+
if id.len == 0 {
50+
continue
51+
}
52+
53+
range_parts := id.split('-')
54+
55+
start_str := range_parts[0].trim_space()
56+
end_str := range_parts[1].trim_space()
57+
58+
start := strconv.parse_int(start_str, 10, 64) or {
59+
eprintln('Start number isn\'t valid: "${id}"')
60+
continue
61+
}
62+
63+
end := strconv.parse_int(end_str, 10, 64) or {
64+
eprintln('End number isn\'t valid: "${id}"')
65+
continue
66+
}
67+
68+
for num in start .. end + 1 {
69+
num_str := num.str()
70+
71+
// Part 1
72+
if has_exact_two_halves(num_str) {
73+
sum1 += num
74+
}
75+
76+
// Part 2
77+
if has_repeating_pattern(num_str) {
78+
sum2 += num
79+
}
80+
}
81+
}
82+
83+
println('Part 1: ${sum1}')
84+
println('Part 2: ${sum2}')
85+
}

2025/03/kylepritchard.v

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
module main
2+
3+
import os
4+
import strconv
5+
6+
fn max_sequence(s string, k int) string {
7+
to_remove := s.len - k
8+
mut remove_left := to_remove
9+
10+
mut stack := []u8{len: 0, cap: s.len}
11+
12+
for i in 0 .. s.len {
13+
c := s[i]
14+
for stack.len > 0 && remove_left > 0 && stack[stack.len - 1] < c {
15+
stack.delete_last()
16+
remove_left--
17+
}
18+
stack << c
19+
}
20+
21+
if remove_left > 0 {
22+
stack = stack[..stack.len - remove_left].clone()
23+
}
24+
25+
if stack.len > k {
26+
stack = stack[..k].clone()
27+
}
28+
29+
return stack.bytestr()
30+
}
31+
32+
fn main() {
33+
content := os.read_file('banks.input') or { panic('Failed to read file: ${err}') }
34+
lines := content.split_into_lines()
35+
36+
// Part 1
37+
mut total_joltage := i64(0)
38+
for line in lines {
39+
if line.len == 0 {
40+
continue
41+
}
42+
43+
seq := max_sequence(line, 2)
44+
if seq.len == 0 {
45+
continue
46+
}
47+
48+
num := strconv.parse_int(seq, 10, 64) or { 0 }
49+
total_joltage += num
50+
}
51+
52+
println('Part 1: ${total_joltage}')
53+
54+
// Part 2
55+
total_joltage = 0
56+
for line in lines {
57+
if line.len == 0 {
58+
continue
59+
}
60+
61+
seq := max_sequence(line, 12)
62+
if seq.len == 0 {
63+
continue
64+
}
65+
66+
num := strconv.parse_int(seq, 10, 64) or { 0 }
67+
total_joltage += num
68+
}
69+
70+
println('Part 2: ${total_joltage}')
71+
}

2025/04/kylepritchard.v

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
module main
2+
3+
import os
4+
5+
struct Pos {
6+
row int
7+
col int
8+
}
9+
10+
struct Offset {
11+
dr int
12+
dc int
13+
}
14+
15+
fn count_adjacent(grid []u8, rows int, cols int, i int, j int, neighbors []Offset) int {
16+
mut count := 0
17+
18+
for offset in neighbors {
19+
ni := i + offset.dr
20+
nj := j + offset.dc
21+
22+
if ni >= 0 && nj >= 0 && ni < rows && nj < cols { // inside grid
23+
nidx := ni * cols + nj
24+
if grid[nidx] == `@` {
25+
count++
26+
if count >= 4 {
27+
break
28+
}
29+
}
30+
}
31+
}
32+
return count
33+
}
34+
35+
fn main() {
36+
// Read input file
37+
content := os.read_file('department.input') or { panic('Failed to read file: ${err}') }
38+
lines := content.split_into_lines()
39+
40+
mut grid_lines := []string{}
41+
for line in lines {
42+
if line.len > 0 {
43+
grid_lines << line
44+
}
45+
}
46+
47+
rows := grid_lines.len
48+
cols := grid_lines[0].len
49+
50+
mut grid1 := []u8{len: rows * cols, cap: rows * cols}
51+
mut grid2 := []u8{len: rows * cols, cap: rows * cols}
52+
53+
for i in 0 .. rows {
54+
line := grid_lines[i]
55+
row_start := i * cols
56+
for j in 0 .. cols {
57+
grid1[row_start + j] = line[j]
58+
grid2[row_start + j] = line[j]
59+
}
60+
}
61+
62+
neighbors := [
63+
Offset{-1, -1}, // diagonal above left
64+
Offset{-1, 0}, // above
65+
Offset{-1, 1}, // diagional above right
66+
Offset{0, -1}, // left
67+
Offset{0, 1}, // right
68+
Offset{1, -1}, // diagonal below left
69+
Offset{1, 0}, // below
70+
Offset{1, 1}, // diagonal below right
71+
]
72+
73+
// Part 1
74+
mut part1_count := 0
75+
for i in 0 .. rows {
76+
row_start := i * cols
77+
for j in 0 .. cols {
78+
idx := row_start + j
79+
if grid1[idx] == `@` {
80+
adj_count := count_adjacent(grid1, rows, cols, i, j, neighbors)
81+
if adj_count < 4 {
82+
part1_count++
83+
}
84+
}
85+
}
86+
}
87+
88+
println('Part 1: ${part1_count}')
89+
90+
// Part 2
91+
mut total_removed := 0
92+
mut current_grid := grid2.clone()
93+
mut changed := true
94+
95+
mut to_check := []Pos{cap: rows * cols}
96+
97+
for i in 0 .. rows {
98+
for j in 0 .. cols {
99+
to_check << Pos{i, j}
100+
}
101+
}
102+
103+
for changed {
104+
changed = false
105+
mut to_remove := []Pos{cap: to_check.len}
106+
mut next_to_check := []Pos{cap: rows * cols}
107+
mut modified := []bool{len: rows * cols, init: false}
108+
109+
for pos in to_check {
110+
i := pos.row
111+
j := pos.col
112+
idx := i * cols + j
113+
114+
if current_grid[idx] != `@` {
115+
continue
116+
}
117+
118+
adj_count := count_adjacent(current_grid, rows, cols, i, j, neighbors)
119+
if adj_count < 4 {
120+
to_remove << pos
121+
}
122+
}
123+
124+
// Remove rolls
125+
if to_remove.len > 0 {
126+
changed = true
127+
total_removed += to_remove.len
128+
129+
// Mark positions as removed and track their neighbors
130+
for pos in to_remove {
131+
i := pos.row
132+
j := pos.col
133+
idx := i * cols + j
134+
current_grid[idx] = `.`
135+
modified[idx] = true
136+
137+
// Add neighbors to next iteration's check list
138+
for offset in neighbors {
139+
ni := i + offset.dr
140+
nj := j + offset.dc
141+
if ni >= 0 && nj >= 0 && ni < rows && nj < cols {
142+
nidx := ni * cols + nj
143+
if !modified[nidx] {
144+
modified[nidx] = true
145+
next_to_check << Pos{ni, nj}
146+
}
147+
}
148+
}
149+
}
150+
151+
to_check = next_to_check.clone()
152+
} else {
153+
// No more to remove
154+
break
155+
}
156+
}
157+
158+
println('Part 2: ${total_removed}')
159+
}

known/2025/01/kylepritchard.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Part 1: 3
2+
Part 2: 6

known/2025/02/kylepritchard.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Part 1: 1227775554
2+
Part 2: 4174379265

known/2025/03/kylepritchard.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Part 1: 357
2+
Part 2: 3121910778619

known/2025/04/kylepritchard.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Part 1: 13
2+
Part 2: 43

0 commit comments

Comments
 (0)