Browse Source

Day 18

master
Chris Smith 5 years ago
parent
commit
9318d45ddd
3 changed files with 173 additions and 0 deletions
  1. 2
    0
      answers/18.txt
  2. 50
    0
      data/18.txt
  3. 121
    0
      day18.nim

+ 2
- 0
answers/18.txt View File

@@ -0,0 +1,2 @@
1
+645946
2
+227688

+ 50
- 0
data/18.txt View File

@@ -0,0 +1,50 @@
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
+.|....#.....#.....##.#..|#...|||.|....|#..|#|...#.

+ 121
- 0
day18.nim View File

@@ -0,0 +1,121 @@
1
+import sequtils, strutils
2
+
3
+type
4
+    GroundType = enum
5
+        gtVoid, gtOpen, gtTrees, gtLumberYard
6
+    Ground = array[-1..50, array[-1..50, GroundType]]
7
+
8
+iterator around(x, y: int): tuple[x,y: int] =
9
+    for i in -1..1:
10
+        for j in -1..1:
11
+            if i != 0 or j != 0:
12
+                yield (x + i, y + j)
13
+
14
+func hasAtLeastThree(ground: Ground, groundType: GroundType, x,y: int): bool =
15
+    var count = 0
16
+    for point in around(x, y):
17
+        if ground[point.y][point.x] == groundType:
18
+            count.inc
19
+            if count == 3:
20
+                return true
21
+    return false
22
+
23
+func resourceValue(ground: Ground): int =
24
+    # Multiplying the number of wooded acres by the number of lumberyards gives
25
+    # the total resource value 
26
+    var trees, yards: int
27
+    for row in ground:
28
+        for cell in row:
29
+            if cell == gtLumberYard:
30
+                yards.inc
31
+            elif cell == gtTrees:
32
+                trees.inc
33
+    trees * yards
34
+
35
+func turnToTrees(ground: Ground, x,y: int): bool =
36
+    # An open acre will become filled with trees if three or more adjacent
37
+    # acres contained trees.
38
+    ground.hasAtLeastThree(gtTrees, x, y)
39
+
40
+func turnToLumberYard(ground: Ground, x,y: int): bool =
41
+    # An acre filled with trees will become a lumberyard if three or more
42
+    # adjacent acres were lumberyards.
43
+    ground.hasAtLeastThree(gtLumberYard, x, y)
44
+
45
+func remainLumberYard(ground: Ground, x,y: int): bool =
46
+    # An acre containing a lumberyard will remain a lumberyard if it was
47
+    # adjacent to at least one other lumberyard and at least one acre
48
+    # containing trees. 
49
+    var foundYard, foundTrees: bool
50
+    for point in around(x,y):
51
+        if ground[point.y][point.x] == gtLumberYard:
52
+            foundYard = true
53
+        if ground[point.y][point.x] == gtTrees:
54
+            foundTrees = true
55
+        if foundTrees and foundYard:
56
+            return true
57
+    return false
58
+
59
+proc load(dest: var Ground) =
60
+    var y: int
61
+    for line in readFile("data/18.txt").strip.splitlines:
62
+        for x, c in line:
63
+            dest[y][x] = case c:
64
+                of '.': gtOpen
65
+                of '|': gtTrees
66
+                of '#': gtLumberYard
67
+                else: gtVoid
68
+        y.inc
69
+
70
+proc step(source: Ground, dest: var Ground) =
71
+    for y, row in source:
72
+        for x, cell in row:
73
+            dest[y][x] = case cell:
74
+                of gtVoid: gtVoid
75
+                of gtOpen:
76
+                    if source.turnToTrees(x, y):
77
+                        gtTrees
78
+                    else:
79
+                        gtOpen
80
+                of gtTrees:
81
+                    if source.turnToLumberYard(x, y):
82
+                        gtLumberYard
83
+                    else:
84
+                        gtTrees
85
+                of gtLumberYard:
86
+                    if source.remainLumberYard(x, y):
87
+                        gtLumberYard
88
+                    else:
89
+                        gtOpen
90
+
91
+const loops = 1_000_000_000
92
+
93
+var
94
+    grounds: array[100, Ground] # Arbitrary guess for maximum loop size
95
+    activeGround, t: int
96
+
97
+grounds[0].load
98
+
99
+while t < loops:
100
+    t.inc
101
+    
102
+    let nextGround = (activeGround + 1) mod grounds.len
103
+    grounds[activeGround].step(grounds[nextGround])
104
+    activeGround = nextGround
105
+    
106
+    if t == 10:
107
+        echo grounds[activeGround].resourceValue
108
+    
109
+    # This isn't solvable by brute force, so assume that at some point the
110
+    # state will repeat itself. If we find a loop, just jump the time ahead
111
+    # by as many loops as we can, and carry on evaluating for the last few.
112
+    for i, o in grounds:
113
+        if i != activeGround and o == grounds[activeGround]:
114
+            let
115
+                loopLength = (grounds.len + activeGround - i) mod grounds.len
116
+                remaining = (loops - t) mod loopLength
117
+            t = loops
118
+            activeGround = (i + remaining) mod grounds.len
119
+            break
120
+
121
+echo grounds[activeGround].resourceValue