@@ -17,15 +17,13 @@ def getFarm(filename) : Hash(Location, Node)
17
17
numRows = lines.size
18
18
numCols = lines[0 ].size
19
19
20
- lines.map_with_index { |l , i | {l, i} }
21
- .reduce(Hash (Location , Node ).new) { |acc , e1 |
22
- line, y = e1
23
- line.split(" " ).map_with_index { |c , i | {c, i} }
24
- .reduce(acc) { |acc , e2 |
25
- plant, x = e2
20
+ lines.zip(0 ..numRows)
21
+ .reduce(Hash (Location , Node ).new) { |acc , (line , y )|
22
+ line.split(" " ).zip(0 ..numCols)
23
+ .reduce(acc) { |acc , (plant , x )|
26
24
locations = [1 , -1 ].map { |i | [{x + i, y}, {x, y + i}] }
27
25
.flatten
28
- .select { |xy | 0 <= xy[ 0 ] && xy[ 0 ] < numCols && 0 <= xy[ 1 ] && xy[ 1 ] < numRows }
26
+ .select { |( x , y ) | 0 <= x && x < numCols && 0 <= y && y < numRows }
29
27
.map { |i | Location .new(* i) }
30
28
acc[Location .new(x, y)] = Node .new(plant, locations)
31
29
acc
@@ -38,7 +36,9 @@ def traverse(loc : Location, farm, explored, locations, perimeter)
38
36
{explored, locations, perimeter}
39
37
else
40
38
node = farm[loc]
41
- like_neighbors = node.neighbor_locs.select { |l | farm[l].plant == node.plant }
39
+ like_neighbors = node.neighbor_locs.select { |l |
40
+ farm[l].plant == node.plant
41
+ }
42
42
node_perimeter = 4 - like_neighbors.size
43
43
acc = {explored << loc, locations << loc, perimeter + node_perimeter}
44
44
like_neighbors.reduce(acc) { |acc , l |
@@ -51,23 +51,26 @@ def get_sides(area, farm)
51
51
nil_node = Node .new(" " , [] of Location )
52
52
area.map { |loc |
53
53
node = farm[loc]
54
- like_neighbors = node.neighbor_locs.select { |l | farm[l].plant == node.plant }
54
+ like_neighbors = node.neighbor_locs.select { |l |
55
+ farm[l].plant == node.plant
56
+ }
55
57
case like_neighbors.size
56
58
when 0
57
59
4
58
60
when 1
59
61
2
60
62
else
61
63
like_neighbors.combinations(2 )
62
- .select { |e | e[0 ].x != e[1 ].x && e[0 ].y != e[1 ].y }
63
- .map { |e | e[0 ].y == loc.y ? e : {e[1 ], e[0 ]} } # (row aligned loc, col aligned loc)
64
+ .select { |(l1 , l2 )| l1.x != l2.x && l1.y != l2.y }
64
65
.map { |e |
65
- l1, l2 = e
66
+ # (row aligned loc, col aligned loc)
67
+ l1, l2 = e[0 ].y == loc.y ? e : e.reverse
66
68
inner_loc = [Location .new(l1.x, l2.y), Location .new(l2.x, l1.y)]
67
69
.select { |e | e != loc }.first
68
70
l1_mirror = Location .new(loc.x + (loc.x - inner_loc.x), loc.y)
69
71
l2_mirror = Location .new(loc.x, loc.y + (loc.y - inner_loc.y))
70
- mirror_nodes = [farm.fetch(l1_mirror, nil_node), farm.fetch(l2_mirror, nil_node)]
72
+ mirror_nodes = [farm.fetch(l1_mirror, nil_node),
73
+ farm.fetch(l2_mirror, nil_node)]
71
74
72
75
(farm[inner_loc].plant != node.plant ? 1 : 0 ) + \
73
76
(mirror_nodes.all? { |n | n.plant != node.plant } ? 1 : 0 )
78
81
79
82
def solve (farm : Hash (Location , Node ))
80
83
acc = {Set (Location ).new, [] of {String , Set (Location ), Int32 }}
81
- locations_perimeter_list = farm.keys.reduce(acc) { |acc , l |
82
- new_explored, area, perimeter = traverse(l, farm, acc[0 ], Set (Location ).new, 0 )
84
+ locs_perimeter_list = farm.keys.reduce(acc) { |acc , l |
85
+ new_explored, area, perimeter = traverse(l, farm, acc[0 ],
86
+ Set (Location ).new, 0 )
83
87
{new_explored, acc[1 ] << {farm[l].plant, area, perimeter}}
84
88
}[1 ].select { |e | ! e[1 ].empty? }
85
- part1 = locations_perimeter_list .map { |e | e[1 ].size * e[2 ] }.sum
86
- part2 = locations_perimeter_list .map { |e | e[1 ].size * get_sides(e[1 ], farm) }.sum
89
+ part1 = locs_perimeter_list .map { |e | e[1 ].size * e[2 ] }.sum
90
+ part2 = locs_perimeter_list .map { |e | e[1 ].size * get_sides(e[1 ], farm) }.sum
87
91
{part1, part2}
88
92
end
89
93
0 commit comments