Skip to content

Commit da71475

Browse files
jamestomasino, add alternate solve for difficult day 12 (#77)
1 parent 889b0d2 commit da71475

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

2024/12/jamestomasino.v

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import os
2+
3+
struct Region {
4+
id rune
5+
mut:
6+
area i64
7+
perimeter []Perimeter
8+
sides []Perimeter
9+
}
10+
11+
struct Perimeter {
12+
p Point
13+
d Vector
14+
}
15+
16+
struct Point {
17+
x int
18+
y int
19+
}
20+
21+
struct Vector {
22+
dx int
23+
dy int
24+
}
25+
26+
fn is_valid_move(row int, col int, max_y int, max_x int) bool {
27+
return row >= 0 && row < max_y && col >= 0 && col < max_x
28+
}
29+
30+
fn check_cell(mut region &Region, mut visited [][]bool, grid []string, row int, col int, max_y int, max_x int) {
31+
directions := [[0, 1], [0, -1], [1, 0], [-1, 0]]
32+
for dir in directions {
33+
new_row := row + dir[0]
34+
new_col := col + dir[1]
35+
// Is the new position on the grid
36+
if is_valid_move(new_row, new_col, max_y, max_x) {
37+
// Does new direction match our grid id
38+
runes := grid[new_row].runes()
39+
if runes[new_col] == region.id {
40+
// Have we visited this before
41+
if !visited[new_row][new_col] {
42+
// add to region size
43+
region.area += 1
44+
// mark as visited
45+
visited[new_row][new_col] = true
46+
// recursive directional search
47+
check_cell(mut region, mut visited, grid, new_row, new_col, max_y,
48+
max_x)
49+
}
50+
} else {
51+
// edge detected
52+
region.perimeter << Perimeter{
53+
p: Point{
54+
y: row
55+
x: col
56+
}
57+
d: Vector{
58+
dy: dir[0]
59+
dx: dir[1]
60+
}
61+
}
62+
}
63+
} else {
64+
// grid border, add to perimeter
65+
region.perimeter << Perimeter{
66+
p: Point{
67+
y: row
68+
x: col
69+
}
70+
d: Vector{
71+
dy: dir[0]
72+
dx: dir[1]
73+
}
74+
}
75+
}
76+
}
77+
}
78+
79+
fn main() {
80+
grid := os.read_lines('garden.input')!
81+
82+
max_y := grid.len
83+
max_x := grid[0].len
84+
85+
// initialize a 2D array to keep track of grid and visited elements
86+
mut visited := [][]bool{len: max_y, init: []bool{len: max_x}}
87+
88+
// transverse grid
89+
mut regions := []Region{}
90+
for row in 0 .. max_y {
91+
for col in 0 .. max_x {
92+
// if element is unvisited:
93+
if !visited[row][col] {
94+
// identify new region and give it an identifier (char value)
95+
visited[row][col] = true
96+
runes := grid[row].runes()
97+
mut region := &Region{
98+
id: runes[col]
99+
area: 1
100+
}
101+
// check for each direction to see if 0) valid 1) unvisited and 2) matching id
102+
check_cell(mut region, mut visited, grid, row, col, max_y, max_x)
103+
regions << region
104+
}
105+
}
106+
}
107+
108+
mut price := i64(0)
109+
mut price2 := i64(0)
110+
for mut r in regions {
111+
price += r.area * r.perimeter.len
112+
113+
mut new_set := []Perimeter{}
114+
for per in r.perimeter {
115+
new_set << Perimeter{
116+
p: Point{
117+
y: per.p.y - per.d.dx
118+
x: per.p.x + per.d.dy
119+
}
120+
d: per.d
121+
}
122+
}
123+
r.sides = set_subtract(r.perimeter, new_set)
124+
price2 += r.area * r.sides.len
125+
// println('Region: ${r.id} (Area ${r.area}, Perimeter ${r.perimeter.len}, Sides ${r.sides.len})')
126+
}
127+
println('Part 1 total price: ${price}')
128+
println('Part 2 total price: ${price2}')
129+
}
130+
131+
fn set_subtract[T](set1 []T, set2 []T) []T {
132+
mut result := []T{}
133+
for item in set1 {
134+
if !set2.contains(item) {
135+
result << item
136+
}
137+
}
138+
return result
139+
}

known/2024/12/jamestomasino.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Part 1 total price: 1930
2+
Part 2 total price: 1206

0 commit comments

Comments
 (0)