From 2a5b18fb1fe742f706c5ce5a563c179b6d1c0fda Mon Sep 17 00:00:00 2001
From: Zach Perrault <zach@perrault.email>
Date: Thu, 10 Dec 2020 14:34:10 -0500
Subject: [PATCH] solve: day 10

  - solve: day 10, part 1
  - solve: day 10, part 2
---
 2020/10/day10.hs |  4 ++++
 2020/10/part1.hs | 15 +++++++++++++++
 2020/10/part2.hs | 28 ++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)
 create mode 100644 2020/10/day10.hs
 create mode 100755 2020/10/part1.hs
 create mode 100755 2020/10/part2.hs

diff --git a/2020/10/day10.hs b/2020/10/day10.hs
new file mode 100644
index 0000000..91572a6
--- /dev/null
+++ b/2020/10/day10.hs
@@ -0,0 +1,4 @@
+module Day10 where
+
+parse :: String -> [Int]
+parse = map read . lines
diff --git a/2020/10/part1.hs b/2020/10/part1.hs
new file mode 100755
index 0000000..e8235af
--- /dev/null
+++ b/2020/10/part1.hs
@@ -0,0 +1,15 @@
+#!/usr/bin/env runghc
+
+import Day10
+import Data.List
+
+main = interact (show . solve . parse)
+
+solve xs = ones * threes
+  where
+    sorted = 0:(sort xs)
+    differences = zipWith (flip (-)) sorted (tail sorted)
+    ones = count 1 differences
+    threes = count 3 differences + 1
+
+count x = length . filter (==x)
diff --git a/2020/10/part2.hs b/2020/10/part2.hs
new file mode 100755
index 0000000..f65bcbf
--- /dev/null
+++ b/2020/10/part2.hs
@@ -0,0 +1,28 @@
+#!/usr/bin/env runghc
+
+import Day10
+import Data.Array
+import Data.IntSet (IntSet)
+import qualified Data.IntSet as IntSet
+
+main = interact (show . solve . parse)
+
+countPaths inp = pathsFrom start
+  where
+    start = IntSet.findMax inpSet + 3
+
+    pathsFrom 0 = 1
+    pathsFrom x
+      | x < 0 = 0
+      | IntSet.member x allowed =
+          sum $ map ((!) memo) $ filter (>= 0) $ map ((-) x) [1, 2, 3]
+      | otherwise = 0
+
+    inpSet = IntSet.fromList inp
+    allowed = IntSet.insert start inpSet
+
+    memo = listArray bnds
+      [ pathsFrom i | i <- range bnds ]
+    bnds = (0, start)
+
+solve = countPaths