-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path20.koto
109 lines (90 loc) · 2.53 KB
/
20.koto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# https://adventofcode.com/2020/day/20
edge_id = |edge|
# An edge is a series of 1s and 0s, a numerical ID can then be produced by packing the
# edge as a binary number.
bits = (copy edge).count()
result = edge
.enumerate()
.fold 0, |result, (i, bit)|
result.or bit.shift_left bits - i - 1
result
make_tile = |tile_id, grid|
tile_id: tile_id
grid: grid
edges: ||
edge_ids = |edge|
yield edge_id (copy edge)
yield edge_id edge.reversed()
ids = edge_ids self.grid.first()
yield ids.next()
yield ids.next()
ids = edge_ids self.grid.last()
yield ids.next()
yield ids.next()
ids = edge_ids self.grid.each |row| row.first()
yield ids.next()
yield ids.next()
ids = edge_ids self.grid.each |row| row.last()
yield ids.next()
yield ids.next()
@display: ||
row_to_string = |row|
row
.each |cell| if cell == 1 then "#" else "."
.to_string()
result = "\nTile ${self.tile_id}:\n"
for row in self.grid
result += "${row_to_string row}\n"
result
make_edge_map = |tiles|
result = {}
for tile in tiles
for edge_id in tile.edges()
result.update edge_id, [], |tile_ids|
tile_ids.push tile.tile_id
tile_ids
result
corner_ids = |edge_map|
unique_edge_count = {}
for edge_id, tile_ids in edge_map
match tile_ids
[unique] then
unique_edge_count.update unique, 0, |count| count += 1
unique_edge_count
.keep |(tile_id, count)| count == 4 # 2 unique edges, * 2 for flipping
.each |(tile_id, _)| tile_id
part_one = |tiles|
edge_map = make_edge_map tiles
(corner_ids edge_map).product()
parse_input = |input|
tiles = []
lines = input.lines()
loop
line = lines.next()
# Tile xxxx:
tile_id = line[5..9].to_number()
# 10 rows like: .#..####.#
grid = lines
.take 10
.each |line|
line
.chars()
.each |c| if c == '#' then 1 else 0
.to_tuple()
.to_tuple()
tiles.push make_tile tile_id, grid
match lines.next()
null then break tiles
"" then continue
other then throw "Expected empty line, got '{}'".format other
@main = ||
tiles = io.extend_path koto.script_dir, "input", "20"
>> io.read_to_string
>> parse_input
print "Part one: ${part_one tiles}" # 51214443014783
@tests =
@test part_one: ||
path = io.extend_path koto.script_dir, "input", "20-example"
tiles = parse_input io.read_to_string path
assert_eq tiles.size(), 9
assert_eq (part_one tiles), 20899048083289