add archived 2017 solutions
This commit is contained in:
parent
19d98ddf00
commit
8eb1e52c83
11 changed files with 379 additions and 1 deletions
1
2017/.gitignore
vendored
Normal file
1
2017/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.stack-work/
|
19
2017/README.md
Normal file
19
2017/README.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Advent of Code 2017
|
||||||
|
|
||||||
|
I haven't run these solutions in a very long time. I've pulled them from a private archive.
|
||||||
|
|
||||||
|
| S | M | T | W | T | F | S |
|
||||||
|
| :-: | :-: | :-: | :-: | :-: | :-: | :--: |
|
||||||
|
| | | | | | [1] | [2] |
|
||||||
|
| [3] | [4] | [5] | [6] | [7] | 8 | 9 |
|
||||||
|
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
|
||||||
|
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
|
||||||
|
| 23 | 24 | 25 | | | | |
|
||||||
|
|
||||||
|
[1]: ./src/AdventOfCode.hs
|
||||||
|
[2]: ./src/AdventOfCode.hs
|
||||||
|
[3]: ./src/AdventOfCode.hs
|
||||||
|
[4]: ./src/AdventOfCode.hs
|
||||||
|
[5]: ./src/AdventOfCode.hs
|
||||||
|
[6]: ./src/AdventOfCode/Day6.hs
|
||||||
|
[7]: ./src/AdventOfCode/Day7.hs
|
2
2017/Setup.hs
Normal file
2
2017/Setup.hs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
51
2017/aoc2017.cabal
Normal file
51
2017/aoc2017.cabal
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
name: aoc2017
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: Short description of your package
|
||||||
|
homepage: https://github.com/githubuser/aoc2017#readme
|
||||||
|
license: BSD3
|
||||||
|
license-file: LICENSE
|
||||||
|
author: Author name here
|
||||||
|
maintainer: example@example.com
|
||||||
|
copyright: 2017 Author name here
|
||||||
|
category: Web
|
||||||
|
build-type: Simple
|
||||||
|
extra-source-files: README.md
|
||||||
|
cabal-version: >=1.10
|
||||||
|
|
||||||
|
-- To avoid duplicated efforts in documentation and dealing with the
|
||||||
|
-- complications of embedding Haddock markup inside cabal files, it is
|
||||||
|
-- common to point users to the README.md file.
|
||||||
|
description: Please see the README on Github at <https://github.com/githubuser/aoc2017#readme>
|
||||||
|
|
||||||
|
library
|
||||||
|
hs-source-dirs: src
|
||||||
|
exposed-modules: AdventOfCode
|
||||||
|
, AdventOfCode.Day6
|
||||||
|
, AdventOfCode.Day7
|
||||||
|
build-depends: base >= 4.7 && < 5
|
||||||
|
, Unique
|
||||||
|
, array
|
||||||
|
, containers
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable aoc2017-exe
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: Main.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, aoc2017
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite aoc2017-test
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
hs-source-dirs: test
|
||||||
|
main-is: Spec.hs
|
||||||
|
build-depends: base
|
||||||
|
, aoc2017
|
||||||
|
, hspec
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: https://github.com/githubuser/aoc2017
|
20
2017/app/Main.hs
Normal file
20
2017/app/Main.hs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import System.Environment
|
||||||
|
import AdventOfCode
|
||||||
|
|
||||||
|
unknown args = \_ -> "No program for arguments: " ++ show args
|
||||||
|
|
||||||
|
selectProgram ["1", "1"] = captcha1
|
||||||
|
selectProgram ["1", "2"] = captcha2
|
||||||
|
selectProgram ["2", "1"] = checksum
|
||||||
|
selectProgram ["2", "2"] = sumEvenlyDivisibleValues
|
||||||
|
selectProgram ["3", "1"] = distanceToAddress
|
||||||
|
selectProgram ["4", "1"] = day41
|
||||||
|
selectProgram ["4", "2"] = day42
|
||||||
|
selectProgram ["5", "1"] = day51
|
||||||
|
selectProgram args = unknown args
|
||||||
|
|
||||||
|
main = do
|
||||||
|
args <- getArgs
|
||||||
|
interact $ selectProgram args
|
98
2017/src/AdventOfCode.hs
Normal file
98
2017/src/AdventOfCode.hs
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
module AdventOfCode where
|
||||||
|
|
||||||
|
import Data.Char
|
||||||
|
import Data.List
|
||||||
|
import Data.List.Unique (allUnique)
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.Array
|
||||||
|
|
||||||
|
-- Day 1
|
||||||
|
pairs j xs = take (length xs) $ zip (cycle xs) $ drop j (cycle xs)
|
||||||
|
hash = sum . map fst . filter (uncurry (==))
|
||||||
|
captcha j = show . hash . pairs j . map digitToInt
|
||||||
|
captcha1 = captcha 1
|
||||||
|
captcha2 ds = captcha (length ds `div` 2) ds
|
||||||
|
|
||||||
|
-- Day 2
|
||||||
|
readCells :: String -> [[Int]]
|
||||||
|
readCells = map (map read) . map words . lines
|
||||||
|
|
||||||
|
minmax xs = (minimum xs, maximum xs)
|
||||||
|
checksum buff = show $ sum $ map (uncurry . flip $ (-)) . map minmax $ readCells buff
|
||||||
|
|
||||||
|
-- Day 2
|
||||||
|
calculateRow row = result
|
||||||
|
where
|
||||||
|
sorted = reverse . sort $ row
|
||||||
|
result = fromJust $
|
||||||
|
fmap (uncurry div) $
|
||||||
|
find ((==) 0 . uncurry rem) [ (i, j) | i <- sorted, j <- tail sorted, j < i ]
|
||||||
|
sumEvenlyDivisibleValues buff = show $ sum . map calculateRow $ readCells buff
|
||||||
|
|
||||||
|
|
||||||
|
-- Day 3
|
||||||
|
chunk (b, t) =
|
||||||
|
let seq = [(t-1), (t-2)..(b)] ++ [(b+1)..(t+1)] in
|
||||||
|
concat . replicate 4 $ take (length seq - 1) seq
|
||||||
|
memory = [0,0,1,2,1,2,1,2,1,2] ++ (concatMap chunk $ zip [2..] [4,6..])
|
||||||
|
distanceToAddress buff = show $ memory !! (read buff)
|
||||||
|
|
||||||
|
-- Day 4
|
||||||
|
readDay4 :: String -> [[String]]
|
||||||
|
readDay4 = map words . lines
|
||||||
|
|
||||||
|
both fn gn x = fn x && gn x
|
||||||
|
|
||||||
|
validPassPhrase1 = allUnique
|
||||||
|
boolToInt True = 1
|
||||||
|
boolToInt False = 0
|
||||||
|
|
||||||
|
validPassPhrase2 = both allUnique noPermutations
|
||||||
|
|
||||||
|
noPermutations :: [String] -> Bool
|
||||||
|
noPermutations phrase = all noPermutations' phrase
|
||||||
|
where
|
||||||
|
noPermutations' word =
|
||||||
|
all ((flip notElem) (filter ((/=) word) phrase)) (permutations word)
|
||||||
|
|
||||||
|
day41 buff = show $ sum . map (boolToInt . validPassPhrase1) $ readDay4 buff
|
||||||
|
day42 buff = show $ sum . map (boolToInt . validPassPhrase2) $ readDay4 buff
|
||||||
|
|
||||||
|
-- Day 5
|
||||||
|
|
||||||
|
type Program = (Array Int Int, Int)
|
||||||
|
data Solution = Partial Program Int | Complete Int
|
||||||
|
|
||||||
|
inBounds (a, b) x = a <= x && x <= b
|
||||||
|
|
||||||
|
-- Part 1
|
||||||
|
-- runProgram (Complete jumps) = jumps
|
||||||
|
-- runProgram (Partial (instructions, pointer) jumps) =
|
||||||
|
-- if inBounds bounds' next
|
||||||
|
-- then runProgram $ Partial ((instructions // update), next) jumps'
|
||||||
|
-- else runProgram $ Complete jumps'
|
||||||
|
-- where
|
||||||
|
-- instruction = instructions ! pointer
|
||||||
|
-- next = pointer + instruction
|
||||||
|
-- bounds' = bounds instructions
|
||||||
|
-- jumps' = jumps + 1
|
||||||
|
-- update = [(pointer, instruction + 1)]
|
||||||
|
|
||||||
|
-- Part 2
|
||||||
|
runProgram (Complete jumps) = jumps
|
||||||
|
runProgram (Partial (instructions, pointer) jumps) =
|
||||||
|
if inBounds bounds' next
|
||||||
|
then runProgram $ Partial ((instructions // update), next) jumps'
|
||||||
|
else runProgram $ Complete jumps'
|
||||||
|
where
|
||||||
|
instruction = instructions ! pointer
|
||||||
|
next = pointer + instruction
|
||||||
|
bounds' = bounds instructions
|
||||||
|
jumps' = jumps + 1
|
||||||
|
updatedInstruction = if instruction > 2 then instruction - 1 else instruction + 1
|
||||||
|
update = [(pointer, updatedInstruction)]
|
||||||
|
|
||||||
|
makeProgram xs = Partial (listArray (0, length xs - 1) xs, 0) 0
|
||||||
|
|
||||||
|
day51 = show . runProgram . makeProgram . map read . lines
|
||||||
|
|
48
2017/src/AdventOfCode/Day6.hs
Normal file
48
2017/src/AdventOfCode/Day6.hs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
module AdventOfCode.Day6 (findFirstDuplicateAllocation, findSizeOfLoopOfDuplicateAllocation) where
|
||||||
|
|
||||||
|
import Data.List
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.Set (Set)
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
|
||||||
|
type Memory = [Int]
|
||||||
|
|
||||||
|
set i y xs = set' i y xs
|
||||||
|
where
|
||||||
|
set' i y [] = []
|
||||||
|
set' 0 y (_:xs) = y:xs
|
||||||
|
set' i y (x:xs) = x:set' (i-1) y xs
|
||||||
|
|
||||||
|
over f i xs = set i (f (xs !! i)) xs
|
||||||
|
incrementIdx = over ((+) 1)
|
||||||
|
|
||||||
|
|
||||||
|
distribute :: Int -> Int -> Memory -> Memory
|
||||||
|
distribute 0 _ ms = ms
|
||||||
|
distribute x i ms = distribute (x-1) (cyclicIdx+1) (incrementIdx cyclicIdx ms)
|
||||||
|
where cyclicIdx = i `mod` (length ms)
|
||||||
|
|
||||||
|
reallocate :: Memory -> Memory
|
||||||
|
reallocate ms = distribute max (maxIdx+1) zeroed
|
||||||
|
where
|
||||||
|
max = maximum ms
|
||||||
|
maxIdx = fromJust . findIndex ((==) max) $ ms
|
||||||
|
zeroed = set maxIdx 0 ms
|
||||||
|
|
||||||
|
findFirstDuplicateAllocation :: Memory -> Int
|
||||||
|
findFirstDuplicateAllocation ms = length $ takeWhile (uncurry (/=)) zipped
|
||||||
|
where
|
||||||
|
allocations = iterate reallocate ms
|
||||||
|
sets = scanl (flip Set.insert) Set.empty allocations
|
||||||
|
sizes = map Set.size sets
|
||||||
|
zipped = zip sizes (tail sizes)
|
||||||
|
|
||||||
|
|
||||||
|
findSizeOfLoopOfDuplicateAllocation :: Memory -> Int
|
||||||
|
findSizeOfLoopOfDuplicateAllocation ms = (+) 1 $ length $ takeWhile ((/=) $ head allocationsFromFirstDuplication) $ tail allocationsFromFirstDuplication
|
||||||
|
where
|
||||||
|
allocations = iterate reallocate ms
|
||||||
|
firstDuplicationIdx = findFirstDuplicateAllocation ms
|
||||||
|
allocationsFromFirstDuplication = drop firstDuplicationIdx allocations
|
||||||
|
|
12
2017/src/AdventOfCode/Day7.hs
Normal file
12
2017/src/AdventOfCode/Day7.hs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
module AdventOfCode.Day7 (readInput) where
|
||||||
|
|
||||||
|
|
||||||
|
readInput = map readLine . lines
|
||||||
|
where
|
||||||
|
normalize = words . (filter $ flip notElem $ "()->,")
|
||||||
|
parse :: [String] -> (String, Int, [String])
|
||||||
|
parse [name, weightStr] = (name, read weightStr, [])
|
||||||
|
parse (name:weightStr:children) = (name, read weightStr, children)
|
||||||
|
readLine = parse . normalize
|
||||||
|
|
||||||
|
|
66
2017/stack.yaml
Normal file
66
2017/stack.yaml
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
# This file was automatically generated by 'stack init'
|
||||||
|
#
|
||||||
|
# Some commonly used options have been documented as comments in this file.
|
||||||
|
# For advanced use and comprehensive documentation of the format, please see:
|
||||||
|
# http://docs.haskellstack.org/en/stable/yaml_configuration/
|
||||||
|
|
||||||
|
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
||||||
|
# A snapshot resolver dictates the compiler version and the set of packages
|
||||||
|
# to be used for project dependencies. For example:
|
||||||
|
#
|
||||||
|
# resolver: lts-3.5
|
||||||
|
# resolver: nightly-2015-09-21
|
||||||
|
# resolver: ghc-7.10.2
|
||||||
|
# resolver: ghcjs-0.1.0_ghc-7.10.2
|
||||||
|
# resolver:
|
||||||
|
# name: custom-snapshot
|
||||||
|
# location: "./custom-snapshot.yaml"
|
||||||
|
resolver: lts-9.14
|
||||||
|
|
||||||
|
# User packages to be built.
|
||||||
|
# Various formats can be used as shown in the example below.
|
||||||
|
#
|
||||||
|
# packages:
|
||||||
|
# - some-directory
|
||||||
|
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
||||||
|
# - location:
|
||||||
|
# git: https://github.com/commercialhaskell/stack.git
|
||||||
|
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||||
|
# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
|
||||||
|
# extra-dep: true
|
||||||
|
# subdirs:
|
||||||
|
# - auto-update
|
||||||
|
# - wai
|
||||||
|
#
|
||||||
|
# A package marked 'extra-dep: true' will only be built if demanded by a
|
||||||
|
# non-dependency (i.e. a user package), and its test suites and benchmarks
|
||||||
|
# will not be run. This is useful for tweaking upstream packages.
|
||||||
|
packages:
|
||||||
|
- '.'
|
||||||
|
# Dependency packages to be pulled from upstream that are not in the resolver
|
||||||
|
# (e.g., acme-missiles-0.3)
|
||||||
|
extra-deps: []
|
||||||
|
|
||||||
|
# Override default flag values for local packages and extra-deps
|
||||||
|
flags: {}
|
||||||
|
|
||||||
|
# Extra package databases containing global packages
|
||||||
|
extra-package-dbs: []
|
||||||
|
|
||||||
|
# Control whether we use the GHC we find on the path
|
||||||
|
# system-ghc: true
|
||||||
|
#
|
||||||
|
# Require a specific version of stack, using version ranges
|
||||||
|
# require-stack-version: -any # Default
|
||||||
|
# require-stack-version: ">=1.4"
|
||||||
|
#
|
||||||
|
# Override the architecture used by stack, especially useful on Windows
|
||||||
|
# arch: i386
|
||||||
|
# arch: x86_64
|
||||||
|
#
|
||||||
|
# Extra directories used by stack for building
|
||||||
|
# extra-include-dirs: [/path/to/dir]
|
||||||
|
# extra-lib-dirs: [/path/to/dir]
|
||||||
|
#
|
||||||
|
# Allow a newer minor version of GHC than the snapshot specifies
|
||||||
|
# compiler-check: newer-minor
|
60
2017/test/Spec.hs
Normal file
60
2017/test/Spec.hs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import Test.Hspec
|
||||||
|
|
||||||
|
import AdventOfCode
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = hspec $ do
|
||||||
|
describe "Day 1" $ do
|
||||||
|
describe "captcha1" $ do
|
||||||
|
it "works for the first example" $ do
|
||||||
|
captcha1 "1122" `shouldBe` "3"
|
||||||
|
|
||||||
|
it "works for the second example" $ do
|
||||||
|
captcha1 "1111" `shouldBe` "4"
|
||||||
|
|
||||||
|
it "works for the third example" $ do
|
||||||
|
captcha1 "1234" `shouldBe` "0"
|
||||||
|
|
||||||
|
it "works for the fourth example" $ do
|
||||||
|
captcha1 "91212129" `shouldBe` "9"
|
||||||
|
|
||||||
|
describe "captcha2" $ do
|
||||||
|
it "works for the first example" $ do
|
||||||
|
captcha2 "1212" `shouldBe` "6"
|
||||||
|
|
||||||
|
it "works for the second example" $ do
|
||||||
|
captcha2 "1221" `shouldBe` "0"
|
||||||
|
|
||||||
|
it "works for the third example" $ do
|
||||||
|
captcha2 "123425" `shouldBe` "4"
|
||||||
|
|
||||||
|
it "works for the fourth example" $ do
|
||||||
|
captcha2 "123123" `shouldBe` "12"
|
||||||
|
|
||||||
|
it "works for the fifth example" $ do
|
||||||
|
captcha2 "12131415" `shouldBe` "4"
|
||||||
|
describe "Day 2" $ do
|
||||||
|
describe "checksum" $ do
|
||||||
|
it "works for the given example" $ do
|
||||||
|
checksum "5 1 9 5\n7 5 3\n2 4 6 8" `shouldBe` "18"
|
||||||
|
describe "calculateRow" $ do
|
||||||
|
it "works for the first row" $ do
|
||||||
|
calculateRow [5, 9, 2, 8] `shouldBe` 4
|
||||||
|
it "works for the second row" $ do
|
||||||
|
calculateRow [9, 4, 7, 3] `shouldBe` 3
|
||||||
|
it "works for the third row" $ do
|
||||||
|
calculateRow [3, 8, 6, 5] `shouldBe` 2
|
||||||
|
describe "sumEvenlyDivisibleValues" $ do
|
||||||
|
it "works for the example input" $ do
|
||||||
|
sumEvenlyDivisibleValues "5 9 2 8\n9 4 7 3\n3 8 6 5" `shouldBe` "9"
|
||||||
|
describe "Day 3" $ do
|
||||||
|
describe "memory" $ do
|
||||||
|
it "contains the right values of distance" $ do
|
||||||
|
memory !! 2 `shouldBe` 1
|
||||||
|
memory !! 11 `shouldBe` 2
|
||||||
|
memory !! 28 `shouldBe` 3
|
||||||
|
memory !! 53 `shouldBe` 4
|
||||||
|
memory !! 86 `shouldBe` 5
|
||||||
|
memory !! 77 `shouldBe` 4
|
||||||
|
memory !! 75 `shouldBe` 6
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
1. [2015] **36/50** 🌟
|
1. [2015] **36/50** 🌟
|
||||||
1. 2016
|
1. 2016
|
||||||
1. 2017 **18/50** 🌟
|
1. [2017] **18/50** 🌟
|
||||||
1. 2018
|
1. 2018
|
||||||
1. 2019
|
1. 2019
|
||||||
1. [2020] **17/50** 🌟
|
1. [2020] **17/50** 🌟
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
1. [2022] **8/50** 🌟
|
1. [2022] **8/50** 🌟
|
||||||
|
|
||||||
[2015]: ./2015
|
[2015]: ./2015
|
||||||
|
[2017]: ./2017
|
||||||
[2020]: ./2020
|
[2020]: ./2020
|
||||||
[2021]: ./2021
|
[2021]: ./2021
|
||||||
[2022]: ./2022
|
[2022]: ./2022
|
||||||
|
|
Loading…
Reference in a new issue