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
110
111
|
import strutils
import sequtils
import sets
import strformat
type Point = tuple[row: int, col: int]
proc has(occupied: HashSet[Point], point: Point): bool =
point in occupied
proc parsePoint(point: string): Point =
let tokens = point.split(",")
assert(tokens.len() == 2)
Point((tokens[1].parseInt(), tokens[0].parseInt()))
proc parseLine(line: string): seq[Point] =
map(line.replace("-> ").split(" "), parsePoint)
var maxRow = -1
var maxCol = -1
var minCol = 10000
proc parseFile(content: string): HashSet[Point] =
let lines = content.strip.splitLines()
var rockLists = map(lines, parseLine)
for row in rockLists:
for point in row:
maxRow = max(maxRow, point.row)
maxCol = max(maxCol, point.col)
minCol = min(minCol, point.col)
for rocks in rockLists:
# a = begin, b = end
for i, a in rocks[0..^2]:
let b = rocks[i+1]
echo fmt"a = {a}, b = {b}"
for col in min(a.col, b.col) .. max(a.col, b.col):
let toPush = Point((a.row, col))
result.incl(toPush)
for row in min(a.row, b.row) .. max(a.row, b.row):
let toPush = Point((row, a.col))
result.incl(toPush)
proc draw(occupied: HashSet[Point]): void =
for row in 0 .. maxRow:
var line = ""
for col in minCol .. maxCol:
let current = Point((row, col))
line &= (if occupied.has(current): '#' else: '.')
echo line
proc below(point: Point): Point =
Point((point.row+1, point.col))
proc rbelow(point: Point): Point =
Point((point.row+1, point.col+1))
proc lbelow(point: Point): Point =
Point((point.row+1, point.col-1))
proc outOfBounds(point: Point): bool =
point.row > maxRow
var part2 = false
proc drop(occupied: var HashSet[Point], col: int): bool =
var point = Point((0, col))
if part2 and occupied.has(point):
return false
while true:
let
below = point.below()
rbelow = point.rbelow()
lbelow = point.lbelow()
if point.outOfBounds():
if part2:
break
return false
if not occupied.has(below):
point = below
continue
if not occupied.has(lbelow):
point = lbelow
continue
if not occupied.has(rbelow):
point = rbelow
continue
break
occupied.incl(point)
return true
proc solve(occupied: HashSet[Point]): int =
var occupied = occupied
while drop(occupied, 500):
result += 1
let content = readFile("./input.txt")
let occupied = parseFile(content)
occupied.draw()
echo fmt"{maxRow}, {minCol}-{maxCol}"
echo solve(occupied)
part2 = true
echo solve(occupied)
|