Done day 25 master
authorNeil Smith <neil.git@njae.me.uk>
Fri, 29 Nov 2019 14:03:14 +0000 (14:03 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Fri, 29 Nov 2019 14:03:14 +0000 (14:03 +0000)
advent-of-code.cabal
data/advent25.txt [new file with mode: 0644]
data/advent25a.txt [new file with mode: 0644]
problems/day24.html [new file with mode: 0644]
problems/day25.html [new file with mode: 0644]
src/advent25/advent25.hs [new file with mode: 0644]

index 61d8e6309612b0ad5bec1bee8a83081bc2224577..b30d8df6afbddae057174e385bd2d0f74201a405 100644 (file)
@@ -299,3 +299,14 @@ executable advent24naive
                      , containers
                      , text
                      , megaparsec 
+
+
+executable advent25
+  hs-source-dirs:      src/advent25
+  main-is:             advent25.hs
+  default-language:    Haskell2010
+  build-depends:       base >= 4.7 && < 5
+                     , containers
+                     , text
+                     , megaparsec 
+                     , linear
diff --git a/data/advent25.txt b/data/advent25.txt
new file mode 100644 (file)
index 0000000..2e1a237
--- /dev/null
@@ -0,0 +1,1037 @@
+-8,6,3,-5
+-7,-2,5,1
+-3,-8,1,5
+-5,1,5,6
+-3,7,-4,8
+-8,3,-8,-3
+-4,8,2,-7
+0,-5,-7,8
+6,0,0,-3
+6,4,-7,-8
+5,-3,-6,-8
+-7,-5,-7,0
+-2,-8,2,5
+-2,-5,-5,-6
+-3,8,-1,6
+7,6,7,-6
+-5,-6,0,-3
+-5,7,-4,0
+-1,-3,1,2
+8,1,0,5
+5,-3,-5,-7
+-3,0,2,1
+-4,-4,2,5
+8,4,-1,5
+1,-1,-4,6
+3,3,-8,0
+-2,8,-5,-5
+1,-6,-8,8
+-7,7,-5,2
+3,3,1,-3
+0,3,4,-4
+8,5,-5,6
+-7,-5,-7,-7
+4,-5,2,0
+-5,8,-5,8
+4,-7,2,-5
+7,7,3,1
+-1,-5,-6,-4
+1,0,6,-6
+-7,-5,-3,8
+-2,-7,-8,8
+7,3,-8,-4
+2,3,-6,5
+-3,-7,0,6
+-8,7,5,4
+5,-3,3,-3
+0,2,4,5
+-8,-2,0,-6
+0,1,0,-2
+-6,1,-7,3
+-4,-4,-7,-1
+-8,4,-4,-4
+0,7,-2,-3
+8,0,-8,-7
+0,0,3,1
+0,-7,-8,3
+7,8,8,6
+1,2,5,5
+2,5,-4,-4
+-7,-2,-2,-2
+-6,-1,2,-5
+7,-1,-8,-2
+0,-8,2,-1
+7,4,5,-8
+-8,3,0,1
+8,-8,8,5
+2,8,-2,5
+2,-5,0,-5
+-8,6,-6,-5
+6,-6,4,3
+7,0,2,2
+8,-4,8,5
+-3,-4,-7,4
+-6,-5,1,-6
+-6,2,-8,-4
+-4,-5,-6,-4
+-1,-1,2,-2
+-3,0,7,1
+-7,-3,4,3
+-1,0,-6,-3
+4,1,4,-8
+1,0,1,-5
+1,-3,6,3
+3,0,5,-8
+7,-7,-8,8
+-5,4,2,6
+4,1,3,-8
+8,2,7,-8
+6,-5,8,5
+-3,5,-3,0
+-1,3,0,4
+-8,-8,4,-3
+-1,4,6,3
+2,8,-1,6
+-5,-6,-4,5
+8,0,6,8
+-4,2,-3,-7
+8,-5,5,-2
+-6,-4,-5,3
+-2,3,7,-4
+6,-5,-5,-1
+-5,5,1,-5
+-1,-3,3,-8
+4,-8,0,-5
+7,2,-2,4
+-7,-8,-2,-8
+-6,-8,4,8
+-4,-4,7,7
+5,7,0,-1
+0,-3,-3,-8
+1,-1,-4,-8
+-8,7,3,-5
+0,5,4,5
+-3,-5,1,-5
+-2,4,2,-5
+-4,2,-3,-5
+-4,-5,3,0
+0,8,0,4
+-2,-4,-5,8
+3,-7,4,1
+-2,3,-6,-3
+-7,-7,4,-2
+3,4,-2,3
+7,-4,0,5
+7,7,-3,2
+0,-1,-4,2
+-7,8,-6,0
+-2,0,4,-1
+-6,3,-8,2
+6,5,7,8
+5,4,5,-3
+7,4,5,1
+-1,-4,5,2
+1,-7,-6,0
+-8,-7,-8,7
+8,6,2,6
+-2,-1,-1,1
+-4,0,7,4
+0,6,5,8
+3,-4,-1,-6
+5,7,6,-3
+-7,-8,5,-4
+6,6,-5,-7
+4,0,2,3
+-5,-1,-8,3
+-5,0,0,-3
+4,5,-8,-4
+-2,7,0,4
+-2,-1,8,1
+5,2,4,-4
+8,-7,-7,-8
+7,-3,-8,7
+-8,0,-3,4
+-1,-4,-7,3
+4,0,1,7
+1,-6,-8,-4
+-7,5,-1,2
+1,0,-3,0
+6,2,0,-2
+2,-8,6,8
+5,-5,8,-2
+-2,7,0,2
+-3,-3,8,-4
+-4,-7,-4,2
+8,7,-8,0
+-5,0,-8,0
+2,-4,-5,-5
+-4,-6,-2,-8
+0,6,0,8
+1,8,0,8
+-5,5,6,5
+6,-2,2,-3
+2,-6,-1,-8
+8,8,8,2
+1,2,0,6
+4,8,-8,7
+0,2,-1,0
+2,-4,7,-2
+-6,5,-1,0
+-3,6,-2,-6
+7,5,6,-2
+-8,-4,2,-5
+6,-3,2,-4
+8,-5,3,5
+-8,-5,0,3
+-8,7,4,-8
+3,-3,5,2
+-2,-6,4,-8
+0,3,0,0
+1,8,7,1
+-5,1,8,7
+-6,-4,-2,-3
+2,8,-2,-7
+6,-1,2,1
+2,2,0,-4
+-5,4,0,7
+8,5,0,-5
+2,-4,-3,3
+1,-1,0,-3
+2,8,-6,-5
+-4,-8,-7,4
+0,0,3,-7
+4,6,-1,3
+-5,5,4,-6
+0,8,4,2
+7,8,-4,-6
+-6,4,4,6
+0,7,-4,-4
+-7,0,7,-5
+7,-5,0,3
+0,-7,-1,4
+0,2,-4,-3
+2,-2,0,2
+2,-1,-1,-8
+-8,0,-6,-1
+2,-4,3,3
+-1,-7,5,1
+6,-8,-5,-2
+-1,0,-7,7
+4,-4,-8,6
+-6,7,-2,1
+0,3,1,-4
+-6,5,3,-3
+-3,8,0,1
+7,-4,5,-3
+-1,5,-6,-4
+0,-1,1,-7
+8,1,5,-5
+1,8,-5,0
+-6,-4,4,8
+-1,-5,-3,3
+3,8,-1,-8
+2,-1,-1,3
+4,7,-7,8
+-5,1,8,-4
+0,-1,0,-7
+4,-1,1,-3
+0,4,-8,-4
+7,-3,5,7
+6,0,-7,-2
+4,5,0,1
+3,-2,8,-2
+0,-1,-2,3
+-5,-6,-4,0
+8,-6,-1,-7
+0,4,-3,8
+1,6,2,4
+-1,6,-7,2
+-6,3,-2,-1
+-2,2,7,2
+0,2,4,0
+0,1,-6,4
+2,-5,8,8
+3,1,-3,4
+8,0,6,3
+3,2,-8,4
+-5,1,-1,6
+-7,6,6,2
+-5,6,2,6
+-2,-5,-5,2
+-7,-2,-2,-7
+-3,-1,6,-1
+-5,-2,1,-1
+0,-5,2,3
+-8,-4,-4,3
+1,-5,-8,-4
+-2,4,-4,-1
+2,-3,0,5
+-3,3,-4,1
+-5,-1,2,-3
+-4,-3,-7,-6
+-7,3,-8,-6
+0,-8,8,-2
+0,0,-7,4
+0,-4,3,-7
+-1,-4,6,5
+4,-5,6,8
+0,0,2,-6
+3,-5,-8,7
+2,-4,4,-3
+7,-8,-2,-6
+7,2,3,0
+-7,6,-1,6
+3,-5,-5,8
+1,4,1,-6
+4,-8,-2,4
+5,-1,1,-7
+3,2,-8,-1
+0,0,6,-5
+0,4,-7,2
+7,6,-4,-4
+1,0,-8,0
+2,6,2,0
+0,-3,-3,-3
+-2,2,4,5
+-8,3,-6,-7
+-6,3,7,5
+-2,-8,5,-7
+0,0,4,1
+5,0,3,-3
+1,5,-3,4
+0,-6,-8,1
+-6,7,-4,-1
+8,-6,4,-1
+4,7,0,7
+7,-7,4,-4
+0,-6,-8,6
+3,-2,3,0
+0,4,-5,4
+-1,0,-6,-2
+1,6,3,7
+-7,-8,-8,-2
+-8,-4,-6,-2
+-1,-5,-4,-2
+-6,2,2,6
+-2,-4,-6,0
+-6,-7,-1,-6
+3,-1,2,0
+1,-7,3,-2
+-5,7,-4,-8
+-5,-6,-4,-7
+4,-5,-1,3
+-2,-4,-2,-3
+-2,-1,0,-4
+-1,2,0,8
+-2,4,-1,-1
+-3,-6,6,1
+0,7,-8,7
+-1,7,7,-1
+7,4,-2,0
+-4,8,-6,1
+6,-3,-5,4
+0,-2,8,-5
+-1,0,-2,2
+8,-5,4,0
+-8,-2,7,-8
+3,-5,-2,1
+-3,4,-6,-3
+0,3,8,1
+6,-1,1,2
+8,3,-3,-7
+-7,-6,-7,4
+8,1,8,-8
+-8,-8,4,0
+2,-8,-4,-3
+0,7,8,2
+-6,-3,-5,2
+-5,-5,5,2
+-7,0,-6,-4
+-5,5,-3,-2
+1,7,-8,8
+0,0,-5,0
+7,-8,-4,2
+-4,2,4,-5
+2,3,-6,-3
+1,-2,-6,-4
+6,7,2,-4
+6,1,5,0
+-1,8,-5,-1
+0,3,-2,2
+-3,-2,0,7
+2,8,4,4
+0,-7,2,0
+-4,-2,4,0
+6,-8,5,-8
+0,0,0,8
+-4,3,0,4
+5,1,-2,-2
+2,-2,-5,1
+3,-1,6,8
+2,-7,-4,6
+4,0,-1,8
+-2,-6,-3,2
+3,5,-7,-8
+-3,8,5,0
+8,1,6,-6
+8,0,0,4
+6,6,-5,-3
+6,2,7,4
+-1,5,8,-6
+-3,7,-1,-5
+-4,-1,-4,-4
+4,0,-8,-7
+7,-7,5,-2
+-6,4,-4,-3
+-2,-3,-1,4
+5,-4,-5,5
+-7,3,0,-8
+8,1,6,0
+5,-3,4,5
+1,-4,4,-4
+-1,7,-8,1
+-6,-6,1,3
+-8,-8,5,0
+7,4,-1,8
+2,0,-8,-7
+-5,8,3,-2
+0,-7,-3,7
+7,2,-6,7
+-7,-7,-7,3
+-1,0,8,-1
+2,3,0,0
+-7,1,-4,4
+3,-2,6,6
+8,0,0,-7
+-5,-4,8,5
+-5,4,-8,6
+2,2,2,5
+2,6,-6,8
+8,3,-5,2
+2,0,-5,4
+-8,-5,1,2
+5,5,3,-8
+3,2,0,-4
+4,-5,7,0
+-8,-4,7,1
+-5,-1,-6,6
+7,-6,-4,-1
+-1,-7,0,3
+2,5,-5,0
+6,0,8,-8
+-4,-6,8,7
+8,0,-8,0
+7,6,2,2
+5,-5,2,-3
+-7,8,5,-7
+8,-7,4,0
+-4,4,-3,4
+-4,-2,5,8
+8,7,-3,-2
+2,-8,0,-3
+-5,-8,-2,-1
+-6,8,7,-7
+6,6,3,1
+-3,4,-1,8
+6,-4,6,-3
+4,3,-8,-5
+-2,5,8,-5
+5,-1,-4,0
+8,-7,-7,8
+-1,2,-7,8
+-3,-5,-3,7
+-2,-1,-4,4
+6,-3,6,0
+4,4,1,4
+-3,0,3,0
+7,-7,-8,-7
+-2,-7,7,-8
+-1,-1,-8,8
+2,-5,3,5
+3,-2,-7,-4
+8,6,5,-7
+-5,7,6,-2
+7,-4,8,-7
+8,4,-6,-6
+4,-2,3,-7
+-8,-1,2,-7
+5,4,-4,-1
+0,-7,3,8
+6,-6,-8,8
+5,-7,-5,-4
+-1,-6,2,4
+-8,-1,6,-7
+-8,0,5,3
+-2,-1,1,-1
+6,-1,5,6
+-6,1,0,-8
+-8,8,8,-7
+3,3,-8,1
+-5,-8,-2,4
+0,0,8,-8
+-5,4,-5,8
+6,7,-8,2
+7,0,-7,-5
+-6,0,2,-8
+0,3,-3,-3
+5,5,-4,-5
+6,-7,-4,0
+-8,0,-2,-4
+-5,-8,5,-7
+-7,3,-5,1
+-3,3,3,-4
+-1,0,-6,-1
+-2,3,-3,-2
+-5,1,-2,-3
+0,0,-3,0
+-7,-5,0,2
+2,3,-7,-3
+-5,0,-1,6
+-4,-7,5,1
+2,2,8,-5
+8,6,7,6
+6,-8,-8,-7
+-2,-3,8,7
+5,-7,1,7
+-2,0,-2,8
+0,0,-5,-6
+1,-7,-5,1
+-6,4,-7,8
+-3,3,1,1
+-8,5,-3,-1
+-7,5,-4,0
+4,0,6,4
+3,2,-5,-7
+3,7,0,6
+-6,4,-6,4
+4,-4,3,-3
+8,3,8,4
+-5,-7,0,6
+-5,2,2,-1
+-7,0,-5,3
+2,-1,0,-4
+1,-8,7,-5
+5,6,2,8
+-4,-7,6,2
+7,-1,6,4
+-2,4,1,5
+-6,-7,-1,-4
+-2,0,0,0
+3,5,3,2
+3,-4,7,0
+3,4,-6,3
+7,7,5,-6
+0,0,3,0
+0,0,-7,-1
+-8,2,7,-5
+-5,-4,-1,4
+8,2,-6,7
+-7,-7,-6,7
+1,7,3,0
+4,-1,5,-1
+0,7,-3,0
+-3,-6,-6,2
+2,6,2,3
+3,6,-6,-7
+-5,7,4,-2
+-2,3,7,-7
+5,0,-1,4
+2,7,8,0
+-3,5,-1,1
+-2,0,-6,-7
+1,2,-8,-3
+-2,-6,6,0
+7,0,8,5
+2,-6,-1,4
+0,0,-6,7
+0,1,-8,-6
+-2,-4,4,0
+-3,-4,-1,-2
+4,-5,0,6
+1,-4,-6,1
+1,-3,-5,-2
+-6,5,-3,7
+0,8,-2,1
+8,-2,5,7
+-3,5,-6,8
+-2,4,8,-8
+1,8,0,-6
+-4,5,-2,1
+-6,2,0,0
+6,0,0,-5
+3,-8,-7,-4
+2,7,0,0
+5,-8,7,0
+7,-4,-2,0
+5,-2,3,8
+-2,2,7,7
+5,0,-6,2
+7,-5,-2,5
+-6,-7,8,-6
+-1,6,8,-2
+0,3,1,1
+0,-2,-6,5
+-2,3,7,0
+5,3,-4,3
+-5,-1,7,-8
+0,-8,-4,-6
+6,5,6,-8
+7,-4,8,0
+-5,-2,4,-4
+2,-5,3,-6
+7,-8,-5,7
+0,5,-4,7
+-2,-6,0,2
+-3,8,4,2
+8,6,2,8
+-5,-2,-4,2
+8,0,0,7
+0,0,8,-5
+-4,3,0,-7
+-1,-5,-7,2
+-8,5,-8,3
+3,-4,-3,1
+-5,3,4,3
+6,0,-4,-3
+-6,7,6,0
+0,-1,-4,-3
+7,2,-3,-7
+-5,-7,8,8
+1,-8,-1,-8
+-4,8,5,-6
+-8,3,-2,-8
+-4,-6,6,5
+-5,7,3,-8
+7,5,0,-4
+6,4,-1,-4
+1,3,-2,-3
+-6,-2,-8,-1
+-7,6,4,6
+-5,4,-6,-4
+-6,-1,-6,2
+-3,3,6,-4
+5,-8,-6,4
+0,0,-1,-6
+-7,-4,6,-5
+-3,-7,-3,0
+7,4,-6,-8
+0,8,-3,-6
+-7,-6,7,-4
+0,8,-8,-4
+7,1,0,5
+0,-1,-8,4
+5,-5,-4,6
+3,5,-1,-8
+-6,-8,8,-6
+-2,-7,-3,3
+6,0,7,3
+-4,0,2,-1
+-4,8,0,8
+-8,0,-1,7
+6,5,-4,-7
+-4,0,8,4
+0,-4,8,0
+-8,-8,8,2
+-7,-3,-6,7
+-3,3,0,4
+-8,-5,-2,3
+4,-7,2,-4
+-1,7,-7,4
+-8,2,0,2
+0,-1,5,1
+6,6,2,3
+5,6,-7,-2
+1,0,-2,-5
+-5,0,8,7
+4,7,8,-8
+-2,-4,-8,8
+0,5,-6,5
+4,3,-4,-3
+2,-4,-3,4
+-3,4,7,7
+-8,-5,2,-2
+6,-3,4,-4
+-3,7,-1,2
+-4,5,1,3
+-1,7,0,-1
+0,8,7,-1
+7,4,-5,0
+7,-6,0,-7
+-5,-1,5,-1
+3,1,-8,4
+5,8,5,7
+8,3,7,-6
+8,-1,-7,-8
+-3,6,1,-7
+0,0,-8,1
+4,8,-8,-2
+-5,6,2,-6
+3,6,1,-5
+7,4,-2,-1
+-2,0,6,-6
+-8,0,-4,5
+1,-3,0,-2
+8,8,4,-4
+2,-7,-3,7
+-3,0,8,3
+0,-7,-7,-6
+-7,2,4,2
+1,-4,-8,2
+7,3,-7,1
+4,6,2,0
+-3,-2,5,8
+0,2,7,-1
+-6,-6,6,-3
+-6,7,-3,-2
+6,5,-5,7
+-8,6,-5,-2
+1,6,1,5
+-4,-2,8,-4
+1,0,-2,0
+1,7,1,-8
+0,-1,0,0
+8,4,-2,-5
+-3,7,7,-8
+0,3,6,2
+5,-5,3,5
+5,1,-7,7
+-3,-5,0,8
+-4,-5,0,-2
+-7,-7,-5,5
+5,8,7,-2
+0,-8,-4,7
+-2,6,3,-6
+7,-5,-6,0
+-7,0,0,-1
+7,7,0,-4
+-6,5,3,-2
+7,5,-3,2
+0,7,2,4
+8,5,-7,-1
+-8,-8,6,3
+0,0,2,-2
+-2,-3,0,-7
+-4,-7,-8,-8
+1,-7,-5,-4
+8,-5,1,4
+1,-2,-5,-6
+-4,-4,-2,-8
+-3,0,-3,1
+-4,0,5,-3
+5,-4,7,0
+-5,5,2,-8
+-8,6,-3,-3
+-6,-4,-3,0
+0,4,4,4
+6,1,-1,0
+-4,-1,0,-6
+3,-4,-1,-5
+-6,-1,3,-6
+-6,2,-7,-3
+-5,0,2,0
+0,-7,5,-7
+-1,4,6,1
+-5,-7,0,-7
+-6,-8,2,5
+2,5,-6,-2
+-1,7,2,-6
+-3,7,-6,6
+-7,7,4,0
+0,7,0,-5
+-3,-7,-5,0
+7,-7,-8,-2
+6,0,-3,6
+-1,6,-5,-1
+8,-4,0,8
+-8,7,8,-3
+2,-8,1,7
+8,0,-5,4
+4,6,3,-2
+0,0,-8,-5
+-3,-1,6,-8
+8,-5,-3,-1
+5,-6,8,6
+-8,6,-8,0
+-7,-2,2,2
+1,-7,-1,-1
+5,0,1,0
+-7,-2,-7,-1
+3,-6,2,-2
+-4,0,8,6
+-7,-5,-3,-7
+-6,3,-2,0
+-2,1,-8,-1
+-6,0,1,0
+-6,-2,0,8
+1,8,5,-4
+2,-2,-2,2
+1,-3,-7,0
+-3,-4,-8,-7
+0,0,0,-5
+5,-5,8,1
+0,1,-2,-1
+-5,0,-2,4
+-7,-3,8,-3
+-6,7,-3,2
+3,8,3,0
+7,-7,4,-2
+6,2,3,6
+0,-2,5,-3
+0,7,-8,0
+-1,-5,-2,-4
+0,-7,5,3
+8,5,0,8
+3,1,0,5
+8,-3,0,4
+0,-2,2,0
+1,-8,2,4
+-3,4,7,3
+1,-6,-2,0
+-6,2,-2,5
+-3,-2,-3,-1
+-1,-8,-2,0
+6,2,-3,8
+7,5,5,-3
+-8,-4,-8,-2
+-7,3,0,0
+-5,3,8,-4
+-4,3,0,-3
+-5,-1,0,-6
+4,5,2,5
+-4,2,-6,-5
+-3,7,-4,7
+0,-4,1,0
+-7,-7,-4,0
+-2,6,1,0
+3,8,8,-5
+5,-6,-4,4
+-8,-6,2,5
+5,-7,0,4
+0,2,-7,8
+0,2,-2,3
+4,-6,0,3
+-3,-1,-8,-6
+7,0,0,-6
+-1,2,2,6
+-1,-3,5,3
+-7,5,1,3
+-5,5,-8,-3
+-6,7,0,-7
+-2,-7,2,-6
+0,0,-8,6
+5,-2,-4,2
+0,3,0,1
+-7,-6,1,5
+6,7,0,-7
+5,8,1,4
+-3,-2,-5,0
+-1,7,-3,2
+-7,-6,-2,-1
+7,5,-5,-7
+0,-5,-3,-6
+0,7,-7,-8
+-6,8,-2,7
+3,-5,8,4
+0,-6,-1,-5
+6,-8,-8,6
+5,-1,-6,-3
+4,-7,2,-8
+6,0,-5,-4
+-1,1,1,5
+3,4,4,1
+8,4,-6,2
+5,-4,4,-2
+2,-2,1,5
+0,-2,2,-7
+5,-6,2,4
+-5,0,4,-7
+2,-2,-6,0
+2,6,3,5
+0,0,7,1
+-1,3,7,-3
+8,0,-3,0
+0,-5,7,-4
+-7,6,7,3
+2,-6,-3,-6
+1,-7,-7,1
+1,5,-4,-2
+0,-4,-3,3
+7,-2,0,7
+1,-7,5,3
+-3,8,0,-5
+5,-2,-2,1
+-6,3,6,7
+2,-1,-7,4
+-3,-6,2,8
+8,-4,7,-6
+-8,1,1,-7
+2,0,-5,-8
+-2,1,8,0
+-4,6,6,-7
+3,6,3,4
+0,5,3,1
+-3,2,4,-1
+0,-3,5,-7
+7,2,-6,0
+1,2,-1,-3
+-4,1,7,-3
+4,0,2,5
+3,-2,0,-7
+0,0,6,-2
+5,-5,7,4
+-5,-2,-6,4
+4,1,-5,6
+2,-6,0,0
+-5,4,-5,7
+5,-1,-4,-8
+8,-8,8,4
+-5,-1,0,-5
+-8,-2,1,-2
+1,3,1,-6
+0,3,-6,-5
+-1,5,-6,4
+6,5,-2,2
+-8,-2,3,5
+-1,-1,-4,-5
+2,0,-7,0
+6,-3,-5,6
+-7,-4,0,-6
+-1,3,5,-4
+0,1,-8,-3
+3,8,-3,-8
+0,-7,-1,3
+1,-1,-3,-6
+8,1,2,-3
+-4,3,2,-7
+8,-8,2,5
+4,8,5,2
+7,6,-7,-1
+-6,-2,-5,5
+-6,-1,-3,0
+-8,0,0,0
+-1,-2,-6,-6
+-7,-4,6,2
+2,-3,-3,0
+0,5,-5,2
+6,1,5,1
+1,6,4,0
+-5,-3,2,-6
+2,0,-1,6
+-5,-5,7,-7
+0,6,-5,5
+4,3,0,-7
+-7,8,-2,6
+3,5,3,-3
+-5,7,0,0
+1,6,5,7
+-4,-2,-4,5
+-3,-3,5,6
+8,-1,-7,4
+-8,2,-6,-3
+-4,2,-5,-3
+-4,-4,8,0
+1,3,1,4
+1,0,4,-4
+4,-7,7,-3
+-4,-1,8,-7
+0,7,8,6
+-8,0,4,3
+-7,6,3,-3
+1,-6,-2,5
+-8,-5,-1,6
+3,-8,7,-7
+1,-6,5,8
+-1,-7,4,6
+3,-2,4,6
+-4,5,1,6
+4,-8,-6,-5
+-7,-7,-8,6
+-1,-5,-4,6
+-2,0,0,6
+6,3,7,-2
+-6,-2,6,-4
+1,2,8,8
+-1,4,-4,2
+-5,7,-6,7
+8,6,-5,-3
+-8,5,0,2
+-8,6,-4,-7
+5,2,3,-2
+-2,6,1,-3
+2,-3,5,0
+4,-7,1,-7
+2,3,6,-1
+-8,2,7,4
+-7,3,-3,5
+-7,-6,2,-4
+-3,4,-7,8
+0,0,-5,-4
+0,-7,-2,-7
+-1,1,1,-2
+-5,-4,2,-4
+0,0,0,3
+-1,8,-4,8
+-1,-6,-7,6
+5,8,8,0
+-6,5,1,0
+0,4,0,-1
+-7,-1,6,8
+-6,-8,-4,5
+3,0,-8,0
+0,-4,-3,2
+0,0,-8,-8
+-5,0,-8,4
+4,8,5,3
+2,5,0,-5
+-6,8,-2,-6
+0,-6,-8,0
+1,2,3,3
+-4,8,-1,4
+7,6,-8,-2
+8,-6,0,-6
+7,5,-8,6
+1,-7,-8,-2
+1,-8,-6,5
+-5,-7,6,-4
+5,7,-5,5
+8,1,-2,-1
+-6,5,-6,5
+2,3,-1,0
+-4,-7,6,-7
+2,-2,0,-1
+-3,-3,4,-3
+0,8,-8,6
+-7,-1,4,4
+-6,1,-2,-2
+-6,-7,-2,1
+-5,-7,-6,-2
+0,1,-8,1
+8,-4,0,2
+5,6,2,0
+6,6,5,-1
+-2,1,-5,7
+-7,-4,1,-6
+-4,7,-5,3
+8,5,-4,4
+1,8,-5,1
+2,2,0,0
+8,1,-8,8
+5,8,-8,7
+-6,6,-5,-4
+0,-5,-7,-3
+-3,7,7,-4
+0,-3,8,-5
+1,-5,-2,8
+-4,-1,-8,0
+3,-5,7,3
+-7,-7,0,-8
+-2,5,-8,7
+-8,-5,-7,1
+1,4,0,5
+4,-1,-1,-8
+-7,4,-2,-2
+-2,7,-4,-4
+1,8,0,4
+-1,-2,-3,2
+-1,1,-2,-2
+-2,1,5,-5
diff --git a/data/advent25a.txt b/data/advent25a.txt
new file mode 100644 (file)
index 0000000..3089dd5
--- /dev/null
@@ -0,0 +1,8 @@
+0,0,0,0
+3,0,0,0
+0,3,0,0
+0,0,3,0
+0,0,0,3
+0,0,0,6
+9,0,0,0
+12,0,0,0
diff --git a/problems/day24.html b/problems/day24.html
new file mode 100644 (file)
index 0000000..76eea55
--- /dev/null
@@ -0,0 +1,402 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 24 - Advent of Code 2018</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" type="text/css" href="/static/style.css?20"/>
+<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
+<link rel="shortcut icon" href="/favicon.png"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  The best surprises don't
+even appear in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not Google, and I can only take
+so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, ads, social media),
+I built the whole thing myself, including the design, animations, prose, and
+all of the puzzles.
+
+The puzzles are most of the work; the easiest ones take 3-4 hours each, but the
+harder ones take 6-8 hours, and a few even longer than that. A lot of effort
+went into building this thing - I hope you're enjoying playing it as much as I
+enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2018/about">[About]</a></li><li><a href="/2018/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode-2019" target="_blank">[Shop]</a></li><li><a href="/2018/settings">[Settings]</a></li><li><a href="/2018/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2018/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">48*</span></div></div><div><h1 class="title-event">&nbsp;&nbsp;&nbsp;<span class="title-event-wrap">int y=</span><a href="/2018">2018</a><span class="title-event-wrap">;</span></h1><nav><ul><li><a href="/2018">[Calendar]</a></li><li><a href="/2018/support">[AoC++]</a></li><li><a href="/2018/sponsors">[Sponsors]</a></li><li><a href="/2018/leaderboard">[Leaderboard]</a></li><li><a href="/2018/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2018/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://smartystreets.com/aoc" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);" rel="noopener">SmartyStreets</a> - Global address validation made by developers, for developers</div></div>
+</div><!--/sidebar-->
+
+<main>
+<article class="day-desc"><h2>--- Day 24: Immune System Simulator 20XX ---</h2><p>After <a href="https://www.youtube.com/watch?v=NDVjLt_QHL8&t=7" target="_blank">a weird buzzing noise</a>, you appear back at the man's cottage. He seems relieved to see his friend, but quickly notices that the little reindeer caught some kind of cold while out exploring.</p>
+<p>The portly man explains that this reindeer's immune system isn't similar to regular reindeer immune systems:</p>
+<p>The <em>immune system</em> and the <em>infection</em> each have <span title="On second thought, it's pretty similar to regular reindeer immune systems.">an army</span> made up of several <em>groups</em>; each <em>group</em> consists of one or more identical <em>units</em>.  The armies repeatedly <em>fight</em> until only one army has units remaining.</p>
+<p><em>Units</em> within a group all have the same <em>hit points</em> (amount of damage a unit can take before it is destroyed), <em>attack damage</em> (the amount of damage each unit deals), an <em>attack type</em>, an <em>initiative</em> (higher initiative units attack first and win ties), and sometimes <em>weaknesses</em> or <em>immunities</em>. Here is an example group:</p>
+<pre><code>18 units each with 729 hit points (weak to fire; immune to cold, slashing)
+ with an attack that does 8 radiation damage at initiative 10
+</code></pre>
+<p>Each group also has an <em>effective power</em>: the number of units in that group multiplied by their attack damage. The above group has an effective power of <code>18 * 8 = 144</code>. Groups never have zero or negative units; instead, the group is removed from combat.</p>
+<p>Each <em>fight</em> consists of two phases: <em>target selection</em> and <em>attacking</em>.</p>
+<p>During the <em>target selection</em> phase, each group attempts to choose one target. In decreasing order of effective power, groups choose their targets; in a tie, the group with the higher initiative chooses first. The attacking group chooses to target the group in the enemy army to which it would deal the most damage (after accounting for weaknesses and immunities, but not accounting for whether the defending group has enough units to actually receive all of that damage).</p>
+<p>If an attacking group is considering two defending groups to which it would deal equal damage, it chooses to target the defending group with the largest effective power; if there is still a tie, it chooses the defending group with the highest initiative.  If it cannot deal any defending groups damage, it does not choose a target.  Defending groups can only be chosen as a target by one attacking group.</p>
+<p>At the end of the target selection phase, each group has selected zero or one groups to attack, and each group is being attacked by zero or one groups.</p>
+<p>During the <em>attacking</em> phase, each group deals damage to the target it selected, if any. Groups attack in decreasing order of initiative, regardless of whether they are part of the infection or the immune system. (If a group contains no units, it cannot attack.)</p>
+<p>The damage an attacking group deals to a defending group depends on the attacking group's attack type and the defending group's immunities and weaknesses.  By default, an attacking group would deal damage equal to its <em>effective power</em> to the defending group.  However, if the defending group is <em>immune</em> to the attacking group's attack type, the defending group instead takes <em>no damage</em>; if the defending group is <em>weak</em> to the attacking group's attack type, the defending group instead takes <em>double damage</em>.</p>
+<p>The defending group only loses <em>whole units</em> from damage; damage is always dealt in such a way that it kills the most units possible, and any remaining damage to a unit that does not immediately kill it is ignored. For example, if a defending group contains <code>10</code> units with <code>10</code> hit points each and receives <code>75</code> damage, it loses exactly <code>7</code> units and is left with <code>3</code> units at full health.</p>
+<p>After the fight is over, if both armies still contain units, a new fight begins; combat only ends once one army has lost all of its units.</p>
+<p>For example, consider the following armies:</p>
+<pre><code>Immune System:
+17 units each with 5390 hit points (weak to radiation, bludgeoning) with
+ an attack that does 4507 fire damage at initiative 2
+989 units each with 1274 hit points (immune to fire; weak to bludgeoning,
+ slashing) with an attack that does 25 slashing damage at initiative 3
+
+Infection:
+801 units each with 4706 hit points (weak to radiation) with an attack
+ that does 116 bludgeoning damage at initiative 1
+4485 units each with 2961 hit points (immune to radiation; weak to fire,
+ cold) with an attack that does 12 slashing damage at initiative 4
+</code></pre>
+<p>If these armies were to enter combat, the following fights, including details during the target selection and attacking phases, would take place:</p>
+<pre><code>Immune System:
+Group 1 contains 17 units
+Group 2 contains 989 units
+Infection:
+Group 1 contains 801 units
+Group 2 contains 4485 units
+
+Infection group 1 would deal defending group 1 185832 damage
+Infection group 1 would deal defending group 2 185832 damage
+Infection group 2 would deal defending group 2 107640 damage
+Immune System group 1 would deal defending group 1 76619 damage
+Immune System group 1 would deal defending group 2 153238 damage
+Immune System group 2 would deal defending group 1 24725 damage
+
+Infection group 2 attacks defending group 2, killing 84 units
+Immune System group 2 attacks defending group 1, killing 4 units
+Immune System group 1 attacks defending group 2, killing 51 units
+Infection group 1 attacks defending group 1, killing 17 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 905 units
+Infection:
+Group 1 contains 797 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 184904 damage
+Immune System group 2 would deal defending group 1 22625 damage
+Immune System group 2 would deal defending group 2 22625 damage
+
+Immune System group 2 attacks defending group 1, killing 4 units
+Infection group 1 attacks defending group 2, killing 144 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 761 units
+Infection:
+Group 1 contains 793 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 183976 damage
+Immune System group 2 would deal defending group 1 19025 damage
+Immune System group 2 would deal defending group 2 19025 damage
+
+Immune System group 2 attacks defending group 1, killing 4 units
+Infection group 1 attacks defending group 2, killing 143 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 618 units
+Infection:
+Group 1 contains 789 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 183048 damage
+Immune System group 2 would deal defending group 1 15450 damage
+Immune System group 2 would deal defending group 2 15450 damage
+
+Immune System group 2 attacks defending group 1, killing 3 units
+Infection group 1 attacks defending group 2, killing 143 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 475 units
+Infection:
+Group 1 contains 786 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 182352 damage
+Immune System group 2 would deal defending group 1 11875 damage
+Immune System group 2 would deal defending group 2 11875 damage
+
+Immune System group 2 attacks defending group 1, killing 2 units
+Infection group 1 attacks defending group 2, killing 142 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 333 units
+Infection:
+Group 1 contains 784 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 181888 damage
+Immune System group 2 would deal defending group 1 8325 damage
+Immune System group 2 would deal defending group 2 8325 damage
+
+Immune System group 2 attacks defending group 1, killing 1 unit
+Infection group 1 attacks defending group 2, killing 142 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 191 units
+Infection:
+Group 1 contains 783 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 181656 damage
+Immune System group 2 would deal defending group 1 4775 damage
+Immune System group 2 would deal defending group 2 4775 damage
+
+Immune System group 2 attacks defending group 1, killing 1 unit
+Infection group 1 attacks defending group 2, killing 142 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 49 units
+Infection:
+Group 1 contains 782 units
+Group 2 contains 4434 units
+
+Infection group 1 would deal defending group 2 181424 damage
+Immune System group 2 would deal defending group 1 1225 damage
+Immune System group 2 would deal defending group 2 1225 damage
+
+Immune System group 2 attacks defending group 1, killing 0 units
+Infection group 1 attacks defending group 2, killing 49 units
+</code></pre>
+<pre><code>Immune System:
+No groups remain.
+Infection:
+Group 1 contains 782 units
+Group 2 contains 4434 units
+</code></pre>
+<p>In the example above, the winning army ends up with <code>782 + 4434 = <em>5216</em></code> units.</p>
+<p>You scan the reindeer's condition (your puzzle input); the white-bearded man looks nervous.  As it stands now, <em>how many units would the winning army have</em>?</p>
+</article>
+<p>Your puzzle answer was <code>15493</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>Things aren't looking good for the reindeer. The man asks whether more milk and cookies would help you think.</p>
+<p>If only you could give the reindeer's immune system a boost, you might be able to change the outcome of the combat.</p>
+<p>A <em>boost</em> is an integer increase in immune system units' attack damage. For example, if you were to boost the above example's immune system's units by <code>1570</code>, the armies would instead look like this:</p>
+<pre><code>Immune System:
+17 units each with 5390 hit points (weak to radiation, bludgeoning) with
+ an attack that does <em>6077</em> fire damage at initiative 2
+989 units each with 1274 hit points (immune to fire; weak to bludgeoning,
+ slashing) with an attack that does <em>1595</em> slashing damage at initiative 3
+
+Infection:
+801 units each with 4706 hit points (weak to radiation) with an attack
+ that does 116 bludgeoning damage at initiative 1
+4485 units each with 2961 hit points (immune to radiation; weak to fire,
+ cold) with an attack that does 12 slashing damage at initiative 4
+</code></pre>
+<p>With this boost, the combat proceeds differently:</p>
+<pre><code>Immune System:
+Group 2 contains 989 units
+Group 1 contains 17 units
+Infection:
+Group 1 contains 801 units
+Group 2 contains 4485 units
+
+Infection group 1 would deal defending group 2 185832 damage
+Infection group 1 would deal defending group 1 185832 damage
+Infection group 2 would deal defending group 1 53820 damage
+Immune System group 2 would deal defending group 1 1577455 damage
+Immune System group 2 would deal defending group 2 1577455 damage
+Immune System group 1 would deal defending group 2 206618 damage
+
+Infection group 2 attacks defending group 1, killing 9 units
+Immune System group 2 attacks defending group 1, killing 335 units
+Immune System group 1 attacks defending group 2, killing 32 units
+Infection group 1 attacks defending group 2, killing 84 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 905 units
+Group 1 contains 8 units
+Infection:
+Group 1 contains 466 units
+Group 2 contains 4453 units
+
+Infection group 1 would deal defending group 2 108112 damage
+Infection group 1 would deal defending group 1 108112 damage
+Infection group 2 would deal defending group 1 53436 damage
+Immune System group 2 would deal defending group 1 1443475 damage
+Immune System group 2 would deal defending group 2 1443475 damage
+Immune System group 1 would deal defending group 2 97232 damage
+
+Infection group 2 attacks defending group 1, killing 8 units
+Immune System group 2 attacks defending group 1, killing 306 units
+Infection group 1 attacks defending group 2, killing 29 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 876 units
+Infection:
+Group 2 contains 4453 units
+Group 1 contains 160 units
+
+Infection group 2 would deal defending group 2 106872 damage
+Immune System group 2 would deal defending group 2 1397220 damage
+Immune System group 2 would deal defending group 1 1397220 damage
+
+Infection group 2 attacks defending group 2, killing 83 units
+Immune System group 2 attacks defending group 2, killing 427 units
+</code></pre>
+<p>After a few fights...</p>
+<pre><code>Immune System:
+Group 2 contains 64 units
+Infection:
+Group 2 contains 214 units
+Group 1 contains 19 units
+
+Infection group 2 would deal defending group 2 5136 damage
+Immune System group 2 would deal defending group 2 102080 damage
+Immune System group 2 would deal defending group 1 102080 damage
+
+Infection group 2 attacks defending group 2, killing 4 units
+Immune System group 2 attacks defending group 2, killing 32 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 60 units
+Infection:
+Group 1 contains 19 units
+Group 2 contains 182 units
+
+Infection group 1 would deal defending group 2 4408 damage
+Immune System group 2 would deal defending group 1 95700 damage
+Immune System group 2 would deal defending group 2 95700 damage
+
+Immune System group 2 attacks defending group 1, killing 19 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 60 units
+Infection:
+Group 2 contains 182 units
+
+Infection group 2 would deal defending group 2 4368 damage
+Immune System group 2 would deal defending group 2 95700 damage
+
+Infection group 2 attacks defending group 2, killing 3 units
+Immune System group 2 attacks defending group 2, killing 30 units
+</code></pre>
+<p>After a few more fights...</p>
+<pre><code>Immune System:
+Group 2 contains 51 units
+Infection:
+Group 2 contains 40 units
+
+Infection group 2 would deal defending group 2 960 damage
+Immune System group 2 would deal defending group 2 81345 damage
+
+Infection group 2 attacks defending group 2, killing 0 units
+Immune System group 2 attacks defending group 2, killing 27 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 51 units
+Infection:
+Group 2 contains 13 units
+
+Infection group 2 would deal defending group 2 312 damage
+Immune System group 2 would deal defending group 2 81345 damage
+
+Infection group 2 attacks defending group 2, killing 0 units
+Immune System group 2 attacks defending group 2, killing 13 units
+</code></pre>
+<pre><code>Immune System:
+Group 2 contains 51 units
+Infection:
+No groups remain.
+</code></pre>
+<p>This boost would allow the immune system's armies to win! It would be left with <code><em>51</em></code> units.</p>
+<p>You don't even know <em>how</em> you could boost the reindeer's immune system or what effect it might have, so you need to be cautious and find the <em>smallest boost</em> that would allow the immune system to win.</p>
+<p><em>How many units does the immune system have left</em> after getting the smallest boost it needs to win?</p>
+</article>
+<p>Your puzzle answer was <code>1045</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p>
+<p>At this point, you should <a href="/2018">return to your Advent calendar</a> and try another puzzle.</p>
+<p>If you still want to see it, you can <a href="24/input" target="_blank">get your puzzle input</a>.</p>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Immune+System+Simulator+20XX%22+%2D+Day+24+%2D+Advent+of+Code+2018&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F24&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="http://www.reddit.com/submit?url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F24&amp;title=I%27ve+completed+%22Immune+System+Simulator+20XX%22+%2D+Day+24+%2D+Advent+of+Code+2018" target="_blank">Reddit</a
+></span>]</span> this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('set', 'anonymizeIp', true);
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file
diff --git a/problems/day25.html b/problems/day25.html
new file mode 100644 (file)
index 0000000..8f3a053
--- /dev/null
@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+<meta charset="utf-8"/>
+<title>Day 25 - Advent of Code 2018</title>
+<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]-->
+<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" type="text/css" href="/static/style.css?20"/>
+<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/>
+<link rel="shortcut icon" href="/favicon.png"/>
+</head><!--
+
+
+
+
+Oh, hello!  Funny seeing you here.
+
+I appreciate your enthusiasm, but you aren't going to find much down here.
+There certainly aren't clues to any of the puzzles.  The best surprises don't
+even appear in the source until you unlock them for real.
+
+Please be careful with automated requests; I'm not Google, and I can only take
+so much traffic.  Please be considerate so that everyone gets to play.
+
+If you're curious about how Advent of Code works, it's running on some custom
+Perl code. Other than a few integrations (auth, analytics, ads, social media),
+I built the whole thing myself, including the design, animations, prose, and
+all of the puzzles.
+
+The puzzles are most of the work; the easiest ones take 3-4 hours each, but the
+harder ones take 6-8 hours, and a few even longer than that. A lot of effort
+went into building this thing - I hope you're enjoying playing it as much as I
+enjoyed making it for you!
+
+If you'd like to hang out, I'm @ericwastl on Twitter.
+
+- Eric Wastl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+-->
+<body>
+<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2018/about">[About]</a></li><li><a href="/2018/events">[Events]</a></li><li><a href="https://teespring.com/adventofcode-2019" target="_blank">[Shop]</a></li><li><a href="/2018/settings">[Settings]</a></li><li><a href="/2018/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2018/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">50*</span></div></div><div><h1 class="title-event">&nbsp;<span class="title-event-wrap">{'year':</span><a href="/2018">2018</a><span class="title-event-wrap">}</span></h1><nav><ul><li><a href="/2018">[Calendar]</a></li><li><a href="/2018/support">[AoC++]</a></li><li><a href="/2018/sponsors">[Sponsors]</a></li><li><a href="/2018/leaderboard">[Leaderboard]</a></li><li><a href="/2018/stats">[Stats]</a></li></ul></nav></div></header>
+
+<div id="sidebar">
+<div id="sponsor"><div class="quiet">Our <a href="/2018/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://smartystreets.com/aoc" target="_blank" onclick="if(ga)ga('send','event','sponsor','click',this.href);" rel="noopener">SmartyStreets</a> - Global address validation made by developers, for developers</div></div>
+</div><!--/sidebar-->
+
+<main>
+<style>article *[title]{border-bottom:1px dotted #ffff66;}</style><article class="day-desc"><h2>--- Day 25: Four-Dimensional Adventure ---</h2><p>The reindeer's symptoms are getting worse, and neither you nor the white-bearded man have a solution. At least the reindeer has a warm place to rest: a small bed near where you're sitting.</p>
+<p>As you reach down, the reindeer looks up at you, <span title="It was not an accident.">accidentally</span> bumping a button on your wrist-mounted device with its nose in the process - a button labeled <em>"help"</em>.</p>
+<p>"Hello, and welcome to the Time Travel Support Hotline! If you are lost in time and space, press 1. If you are trapped in a time paradox, press 2. If you need help caring for a sick reindeer, press 3. If you--"</p>
+<p><em>Beep.</em></p>
+<p>A few seconds later, you hear a new voice. "Hello; please state the nature of your reindeer." You try to describe the situation.</p>
+<p>"Just a moment, I think I can remotely run a diagnostic scan." A beam of light projects from the device and sweeps over the reindeer a few times.</p>
+<p>"Okay, it looks like your reindeer is very low on magical energy; it should fully recover if we can fix that.  Let me check your timeline for a source.... Got one. There's actually a powerful source of magical energy about 1000 years forward from you, and at roughly your position, too!  It looks like... hot chocolate?  Anyway, you should be able to travel there to pick some up; just don't forget a mug!  Is there anything else I can help you with today?"</p>
+<p>You explain that your device isn't capable of going forward in time.  "I... see. That's tricky. Well, according to this information, your device should have the necessary hardware to open a small portal and send some hot chocolate back to you. You'll need a list of <em>fixed points in spacetime</em>; I'm transmitting it to you now."</p>
+<p>"You just need to align your device to the constellations of fixed points so that it can lock on to the destination and open the portal. Let me look up how much hot chocolate that breed of reindeer needs."</p>
+<p>"It says here that your particular reindeer is-- this can't be right, it says there's only one like that in the universe!  But THAT means that you're--" You disconnect the call.</p>
+<p>The list of fixed points in spacetime (your puzzle input) is a set of four-dimensional coordinates. To align your device, acquire the hot chocolate, and save the reindeer, you just need to find the <em>number of constellations</em> of points in the list.</p>
+<p>Two points are in the same <em>constellation</em> if their manhattan distance apart is <em>no more than 3</em> or if they can form a chain of points, each a manhattan distance no more than 3 from the last, between the two of them. (That is, if a point is close enough to a constellation, it "joins" that constellation.) For example:</p>
+<pre><code> 0,0,0,0
+ 3,0,0,0
+ 0,3,0,0
+ 0,0,3,0
+ 0,0,0,3
+ 0,0,0,6
+ 9,0,0,0
+12,0,0,0
+</code></pre>
+<p>In the above list, the first six points form a single constellation: <code>0,0,0,0</code> is exactly distance <code>3</code> from the next four, and the point at <code>0,0,0,6</code> is connected to the others by being <code>3</code> away from <code>0,0,0,3</code>, which is already in the constellation. The bottom two points, <code>9,0,0,0</code> and <code>12,0,0,0</code> are in a separate constellation because no point is close enough to connect them to the first constellation.  So, in the above list, the number of constellations is <code><em>2</em></code>.  (If a point at <code>6,0,0,0</code> were present, it would connect <code>3,0,0,0</code> and <code>9,0,0,0</code>, merging all of the points into a single giant constellation instead.)</p>
+<p>In this example, the number of constellations is <code>4</code>:</p>
+<pre><code>-1,2,2,0
+0,0,2,-2
+0,0,0,-2
+-1,2,0,0
+-2,-2,-2,2
+3,0,2,-1
+-1,3,2,2
+-1,0,-1,0
+0,2,1,-2
+3,0,0,0
+</code></pre>
+<p>In this one, it's <code>3</code>:</p>
+<pre><code>1,-1,0,1
+2,0,-1,0
+3,2,-1,0
+0,0,3,1
+0,0,-1,-1
+2,3,-2,0
+-2,2,0,0
+2,-2,0,-1
+1,-1,0,-1
+3,2,0,2
+</code></pre>
+<p>Finally, in this one, it's <code>8</code>:</p>
+<pre><code>1,-1,-1,-2
+-2,-2,0,1
+0,2,1,3
+-2,3,-2,1
+0,2,3,-2
+-1,-1,1,-2
+0,-2,-1,0
+-2,2,3,-1
+1,2,2,0
+-1,-2,0,-2
+</code></pre>
+<p>The portly man nervously strokes his white beard. It's time to get that hot chocolate.</p>
+<p><em>How many constellations are formed by the fixed points in spacetime?</em></p>
+</article>
+<p>Your puzzle answer was <code>422</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>A small glowing portal opens above the mug you prepared and just enough hot chocolate streams in to fill it. You suspect the reindeer has never encountered hot chocolate before, but seems to enjoy it anyway. You hope it works.</p>
+<p>It's time to start worrying about that <em>integer underflow in time itself</em> you <a href="21">set up a few days ago</a>. You check the status of the device: "Insufficient chronal energy for activation. Energy required: <em class="star">50 stars</em>."</p>
+<p>The reindeer bumps the device with its nose.</p>
+<p>"Energy required: <em class="star">49 stars</em>."</p>
+</article>
+<form method="post" action="25/answer"><input type="hidden" name="level" value="2"/><input type="hidden" name="answer" value="0"/><p>If you like, you can <input type="submit" value="[Trigger the Underflow again]"/>.</p></form>
+<p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p>
+<p>At this point, all that is left is for you to <a href="/2018">admire your Advent calendar</a>.</p>
+<p>If you still want to see it, you can <a href="25/input" target="_blank">get your puzzle input</a>.</p>
+<p>You can also <span class="share">[Share<span class="share-content">on
+  <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Four%2DDimensional+Adventure%22+%2D+Day+25+%2D+Advent+of+Code+2018&amp;url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F25&amp;related=ericwastl&amp;hashtags=AdventOfCode" target="_blank">Twitter</a>
+  <a href="http://www.reddit.com/submit?url=https%3A%2F%2Fadventofcode%2Ecom%2F2018%2Fday%2F25&amp;title=I%27ve+completed+%22Four%2DDimensional+Adventure%22+%2D+Day+25+%2D+Advent+of+Code+2018" target="_blank">Reddit</a
+></span>]</span> this puzzle.</p>
+</main>
+
+<!-- ga -->
+<script>
+(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-69522494-1', 'auto');
+ga('set', 'anonymizeIp', true);
+ga('send', 'pageview');
+</script>
+<!-- /ga -->
+</body>
+</html>
\ No newline at end of file
diff --git a/src/advent25/advent25.hs b/src/advent25/advent25.hs
new file mode 100644 (file)
index 0000000..5cbd71f
--- /dev/null
@@ -0,0 +1,104 @@
+{-# LANGUAGE NegativeLiterals #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeFamilies #-}
+
+import Debug.Trace
+
+-- import Prelude hiding ((++))
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+import Data.Void (Void)
+import Text.Megaparsec hiding (State)
+import Text.Megaparsec.Char
+import qualified Text.Megaparsec.Char.Lexer as L
+import qualified Control.Applicative as CA
+
+import Data.List hiding (group)
+-- import Data.Function (on)
+import qualified Data.Map.Strict as M
+import Data.Map.Strict ((!))
+
+import Linear (V4(..), (^-^))
+
+
+type Coord = V4 Integer
+type Constellations = M.Map Coord Coord
+
+
+main :: IO ()
+main = do 
+        text <- TIO.readFile "data/advent25.txt"
+        let stars = successfulParse text
+        print $ part1 stars
+
+
+part1 :: [Coord] -> Int
+part1 stars = countConstellations constellations
+    where initialConstellations = foldl' (\c s -> M.insert s s c) M.empty stars
+          pairs = adjacencies stars
+          constellations = findConstellations initialConstellations pairs
+
+
+manhattan :: Coord -> Integer
+manhattan (V4 x y z t) = (abs x) + (abs y) + (abs z) + (abs t)
+
+distance :: Coord -> Coord -> Integer
+distance a b = manhattan (a ^-^ b)
+
+close :: Coord -> Coord -> Bool
+close a b = (distance a b) <= 3
+
+adjacencies :: [Coord] -> [(Coord, Coord)]
+adjacencies stars = filter (\(a, b) -> a /= b && (close a b))
+                    [ (a, b) | a <- stars, b <- stars ]
+
+
+findConstellations :: Constellations -> [(Coord, Coord)] -> Constellations
+findConstellations constellations0 pairs = foldl' mergeConstellation constellations0 pairs
+
+mergeConstellation :: Constellations -> (Coord, Coord) -> Constellations
+mergeConstellation constellations (a, b) = 
+    if ae == be
+    then constellations
+    else M.insert ae be constellations
+    where ae = exemplar constellations a
+          be = exemplar constellations b
+
+exemplar :: Constellations -> Coord -> Coord
+exemplar constellations star = 
+    if constellations!star == star
+    then star
+    else exemplar constellations (constellations!star)
+
+
+countConstellations :: Constellations -> Int
+countConstellations constellations = M.size $ M.filterWithKey (==) constellations
+
+
+type Parser = Parsec Void Text
+
+sc :: Parser ()
+sc = L.space (skipSome spaceChar) CA.empty CA.empty
+
+lexeme  = L.lexeme sc
+integer = lexeme L.decimal
+signedInteger = L.signed sc integer
+symb = L.symbol sc
+comma = symb ","
+
+coordP = V4 <$> signedInteger <* comma 
+            <*> signedInteger <* comma 
+            <*> signedInteger <* comma 
+            <*> signedInteger
+
+starsP = many coordP
+
+successfulParse :: Text -> [Coord]
+-- successfulParse _ = []
+successfulParse input = 
+        case parse starsP "input" input of
+                Left  _error -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
+                Right stars -> stars