Compare commits
16 commits
Author | SHA1 | Date | |
---|---|---|---|
|
e0ea0a26c8 | ||
|
400d1cdc57 | ||
6aba6f131e | |||
f8d0b6c0da | |||
6ee8b3fafa | |||
7c8cb639cb | |||
f41863a68b | |||
|
2240fd1325 | ||
0e498f3caa | |||
|
47bafe66dc | ||
|
538fba7063 | ||
|
c15d4ee29d | ||
|
3997886348 | ||
d720534eaf | |||
|
a1a4a6fb52 | ||
fec46e87e0 |
8 changed files with 1309 additions and 1 deletions
95
day10/input
Normal file
95
day10/input
Normal file
|
@ -0,0 +1,95 @@
|
|||
99
|
||||
3
|
||||
1
|
||||
11
|
||||
48
|
||||
113
|
||||
131
|
||||
43
|
||||
82
|
||||
19
|
||||
4
|
||||
153
|
||||
105
|
||||
52
|
||||
56
|
||||
109
|
||||
27
|
||||
119
|
||||
147
|
||||
31
|
||||
34
|
||||
13
|
||||
129
|
||||
17
|
||||
61
|
||||
10
|
||||
29
|
||||
24
|
||||
12
|
||||
104
|
||||
152
|
||||
103
|
||||
80
|
||||
116
|
||||
79
|
||||
73
|
||||
21
|
||||
133
|
||||
44
|
||||
18
|
||||
74
|
||||
112
|
||||
136
|
||||
30
|
||||
146
|
||||
100
|
||||
39
|
||||
130
|
||||
91
|
||||
124
|
||||
70
|
||||
115
|
||||
81
|
||||
28
|
||||
151
|
||||
2
|
||||
122
|
||||
87
|
||||
143
|
||||
62
|
||||
7
|
||||
126
|
||||
95
|
||||
75
|
||||
20
|
||||
123
|
||||
63
|
||||
125
|
||||
53
|
||||
45
|
||||
141
|
||||
14
|
||||
67
|
||||
69
|
||||
60
|
||||
114
|
||||
57
|
||||
142
|
||||
150
|
||||
42
|
||||
78
|
||||
132
|
||||
66
|
||||
88
|
||||
140
|
||||
139
|
||||
106
|
||||
38
|
||||
85
|
||||
37
|
||||
51
|
||||
94
|
||||
98
|
||||
86
|
||||
68
|
92
day10/main.hs
Executable file
92
day10/main.hs
Executable file
|
@ -0,0 +1,92 @@
|
|||
#! /usr/bin/env -S"ANSWER=42" nix-shell
|
||||
#! nix-shell -p ghcid
|
||||
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [pretty-simple])"
|
||||
#! nix-shell -i "ghcid -c 'ghci' -T main"
|
||||
|
||||
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-unused-imports -Wno-type-defaults #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
import Data.List
|
||||
import Data.Monoid
|
||||
import Debug.Trace (trace)
|
||||
import Text.Pretty.Simple
|
||||
|
||||
smallExample :: [Int]
|
||||
smallExample = [16,10,15,5,1,11,7,19,6,12,4]
|
||||
|
||||
biggerExample :: [Int]
|
||||
biggerExample = [28,33,18,42,31,14,46,20,48,47,24,23,49,45,19,38,39,11,1,32,25
|
||||
,35,8,17,7,9,4,2,34,10,3]
|
||||
|
||||
solvePart1 :: [Int] -> Int
|
||||
solvePart1 xs = finally
|
||||
$ span (== 1)
|
||||
$ sort
|
||||
$ map (\(x,y) -> y - x)
|
||||
$ zip (0:sorted) (sorted ++ [l+3])
|
||||
where
|
||||
l = last sorted
|
||||
sorted = sort xs
|
||||
finally (x,y) = length x * length y
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- 1 -> 1 possibility
|
||||
-- 1 1 -> 2 possibilities
|
||||
-- 1 1 1 -> 4 possibilities
|
||||
-- 1 1 1 1 -> 7 (!) possibilities
|
||||
-- 1 1 1 1 1 -> ? possibilities
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
cleanup :: [[Int]] -> [[Int]]
|
||||
cleanup = filter (\v -> (any (/= 3) v) && (length v > 1))
|
||||
|
||||
|
||||
-- That is the actual problem right here:
|
||||
-- ··· -> 2^3 - 1 = 7
|
||||
-- ···· -> 2^4 - 1 - 2 = 13
|
||||
-- ····· -> 2^5 - 1 - 2 - 3 = 26
|
||||
combinations :: [Int] -> Int
|
||||
combinations v =
|
||||
(2 ^ n) -- All the ways to take any on/off combination in n
|
||||
- (sum [1..(n-2)]) -- All the ways to take n+ consecutive in n (illegal),
|
||||
-- *except* for n=1 and n=2 which are legal
|
||||
where
|
||||
n = (length v) - 1
|
||||
|
||||
estimatePermutations :: [Int] -> Int
|
||||
estimatePermutations = getProduct
|
||||
. foldMap Product
|
||||
. map combinations
|
||||
. cleanup
|
||||
. group
|
||||
|
||||
distanceMap :: [Int] -> [Int]
|
||||
distanceMap xs = map (\(x,y) -> y - x) $ zip (0:sorted) (sorted ++ [(last sorted)+3])
|
||||
where
|
||||
sorted = sort xs
|
||||
|
||||
solvePart2 :: [Int] -> Int
|
||||
solvePart2 = estimatePermutations . distanceMap
|
||||
where
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
input' <- lines <$> readFile "day10/input"
|
||||
let input = read <$> input'
|
||||
putStrLn ":: Tests"
|
||||
print $ smallExample
|
||||
print $ biggerExample
|
||||
putStrLn ":: Day 10 - Part 1"
|
||||
print $ solvePart1 smallExample
|
||||
print $ solvePart1 biggerExample
|
||||
print $ solvePart1 input
|
||||
putStrLn ":: Tests"
|
||||
|
||||
putStrLn ":: Day 10 - Part 2"
|
||||
print $ distanceMap smallExample
|
||||
print $ solvePart2 smallExample
|
||||
print $ distanceMap biggerExample
|
||||
print $ (map combinations . cleanup . group) $ distanceMap biggerExample
|
||||
print $ solvePart2 biggerExample
|
||||
print $ solvePart2 input
|
786
day12/input
Normal file
786
day12/input
Normal file
|
@ -0,0 +1,786 @@
|
|||
N3
|
||||
F18
|
||||
L180
|
||||
F40
|
||||
N3
|
||||
R90
|
||||
S5
|
||||
R90
|
||||
N4
|
||||
F24
|
||||
R90
|
||||
E5
|
||||
F36
|
||||
R180
|
||||
W3
|
||||
W4
|
||||
F63
|
||||
N4
|
||||
W1
|
||||
N1
|
||||
E1
|
||||
L90
|
||||
W1
|
||||
N2
|
||||
E2
|
||||
S2
|
||||
F39
|
||||
W4
|
||||
S3
|
||||
F93
|
||||
N1
|
||||
F83
|
||||
S1
|
||||
R90
|
||||
W3
|
||||
R90
|
||||
W4
|
||||
L90
|
||||
F53
|
||||
S4
|
||||
F4
|
||||
L90
|
||||
W3
|
||||
F83
|
||||
L180
|
||||
W2
|
||||
L90
|
||||
W2
|
||||
L90
|
||||
W1
|
||||
N3
|
||||
F63
|
||||
R90
|
||||
N2
|
||||
N3
|
||||
E4
|
||||
F10
|
||||
S3
|
||||
E4
|
||||
R90
|
||||
F11
|
||||
L90
|
||||
R90
|
||||
S2
|
||||
W2
|
||||
F100
|
||||
W5
|
||||
R270
|
||||
F40
|
||||
S5
|
||||
L90
|
||||
E2
|
||||
L90
|
||||
E2
|
||||
L180
|
||||
N5
|
||||
F81
|
||||
N4
|
||||
E4
|
||||
L180
|
||||
F38
|
||||
W2
|
||||
F22
|
||||
W5
|
||||
N5
|
||||
E1
|
||||
N2
|
||||
W4
|
||||
N2
|
||||
F68
|
||||
N1
|
||||
F2
|
||||
S1
|
||||
F47
|
||||
W5
|
||||
F80
|
||||
N3
|
||||
E3
|
||||
S2
|
||||
L180
|
||||
F87
|
||||
L180
|
||||
E4
|
||||
L90
|
||||
E2
|
||||
S3
|
||||
L180
|
||||
E2
|
||||
L90
|
||||
W2
|
||||
N4
|
||||
F21
|
||||
S4
|
||||
W5
|
||||
F70
|
||||
F4
|
||||
N2
|
||||
F14
|
||||
E2
|
||||
S3
|
||||
R90
|
||||
W3
|
||||
N2
|
||||
E3
|
||||
S1
|
||||
F85
|
||||
R90
|
||||
E1
|
||||
F80
|
||||
L90
|
||||
F100
|
||||
R90
|
||||
W1
|
||||
R180
|
||||
S4
|
||||
F58
|
||||
L90
|
||||
N3
|
||||
R90
|
||||
E1
|
||||
F42
|
||||
E3
|
||||
F93
|
||||
S3
|
||||
R90
|
||||
W2
|
||||
N3
|
||||
L90
|
||||
W3
|
||||
W2
|
||||
N2
|
||||
W1
|
||||
S4
|
||||
R180
|
||||
N5
|
||||
R180
|
||||
F52
|
||||
N5
|
||||
F20
|
||||
L180
|
||||
E5
|
||||
R90
|
||||
W2
|
||||
S4
|
||||
E1
|
||||
S3
|
||||
F75
|
||||
R90
|
||||
F49
|
||||
L180
|
||||
N3
|
||||
F31
|
||||
S3
|
||||
E3
|
||||
S5
|
||||
L180
|
||||
N3
|
||||
E2
|
||||
R270
|
||||
W5
|
||||
N3
|
||||
W5
|
||||
N3
|
||||
L270
|
||||
F54
|
||||
R90
|
||||
W5
|
||||
F73
|
||||
S3
|
||||
W2
|
||||
R90
|
||||
N2
|
||||
R90
|
||||
S5
|
||||
R90
|
||||
W4
|
||||
S2
|
||||
L90
|
||||
F3
|
||||
S2
|
||||
R90
|
||||
F76
|
||||
S3
|
||||
F56
|
||||
L90
|
||||
F5
|
||||
N1
|
||||
R180
|
||||
E3
|
||||
N2
|
||||
F20
|
||||
E2
|
||||
L180
|
||||
F38
|
||||
R180
|
||||
W4
|
||||
R90
|
||||
S3
|
||||
N5
|
||||
E5
|
||||
F26
|
||||
S2
|
||||
L180
|
||||
E4
|
||||
R90
|
||||
F52
|
||||
N3
|
||||
L90
|
||||
N5
|
||||
E4
|
||||
F63
|
||||
L90
|
||||
F48
|
||||
W5
|
||||
F29
|
||||
N1
|
||||
E3
|
||||
L90
|
||||
N5
|
||||
L90
|
||||
S3
|
||||
F8
|
||||
N2
|
||||
R90
|
||||
E4
|
||||
S2
|
||||
E2
|
||||
F10
|
||||
W2
|
||||
L90
|
||||
N2
|
||||
R90
|
||||
F2
|
||||
E2
|
||||
N4
|
||||
R90
|
||||
F74
|
||||
W3
|
||||
W5
|
||||
S2
|
||||
R90
|
||||
N3
|
||||
L90
|
||||
E3
|
||||
F58
|
||||
N4
|
||||
E5
|
||||
S4
|
||||
E3
|
||||
F72
|
||||
L180
|
||||
E3
|
||||
S2
|
||||
L90
|
||||
W4
|
||||
S1
|
||||
F14
|
||||
W1
|
||||
N1
|
||||
E3
|
||||
W4
|
||||
L90
|
||||
N1
|
||||
F97
|
||||
R90
|
||||
N4
|
||||
E3
|
||||
F95
|
||||
F95
|
||||
L90
|
||||
S4
|
||||
F55
|
||||
R90
|
||||
W2
|
||||
N1
|
||||
R90
|
||||
F16
|
||||
L90
|
||||
S5
|
||||
F4
|
||||
R90
|
||||
F24
|
||||
S4
|
||||
E2
|
||||
R90
|
||||
W5
|
||||
E1
|
||||
L270
|
||||
F12
|
||||
L90
|
||||
F100
|
||||
W1
|
||||
S5
|
||||
W2
|
||||
S3
|
||||
F95
|
||||
L90
|
||||
F44
|
||||
N5
|
||||
F79
|
||||
S4
|
||||
R180
|
||||
E2
|
||||
S1
|
||||
F40
|
||||
R90
|
||||
W2
|
||||
R90
|
||||
F67
|
||||
S5
|
||||
F15
|
||||
L90
|
||||
N4
|
||||
L90
|
||||
S5
|
||||
E1
|
||||
R90
|
||||
N3
|
||||
W5
|
||||
N4
|
||||
L270
|
||||
F61
|
||||
L90
|
||||
E1
|
||||
L90
|
||||
E1
|
||||
F38
|
||||
E2
|
||||
F19
|
||||
W2
|
||||
L90
|
||||
S4
|
||||
R180
|
||||
W4
|
||||
F59
|
||||
N1
|
||||
F26
|
||||
N1
|
||||
W5
|
||||
F7
|
||||
N4
|
||||
F72
|
||||
E2
|
||||
R90
|
||||
F59
|
||||
N1
|
||||
F58
|
||||
N5
|
||||
F13
|
||||
N2
|
||||
F2
|
||||
S2
|
||||
W1
|
||||
F85
|
||||
R270
|
||||
S2
|
||||
F17
|
||||
R90
|
||||
F96
|
||||
S2
|
||||
L90
|
||||
E1
|
||||
N4
|
||||
F9
|
||||
R270
|
||||
F58
|
||||
N1
|
||||
L90
|
||||
W2
|
||||
S2
|
||||
F73
|
||||
W1
|
||||
S2
|
||||
F20
|
||||
E2
|
||||
S4
|
||||
F94
|
||||
L180
|
||||
F27
|
||||
S2
|
||||
F48
|
||||
N1
|
||||
L270
|
||||
S2
|
||||
F77
|
||||
E3
|
||||
F10
|
||||
W3
|
||||
L270
|
||||
S4
|
||||
F53
|
||||
F66
|
||||
E5
|
||||
S2
|
||||
F33
|
||||
S5
|
||||
L90
|
||||
W3
|
||||
S3
|
||||
E3
|
||||
R90
|
||||
E1
|
||||
F62
|
||||
S1
|
||||
L90
|
||||
S3
|
||||
E3
|
||||
N1
|
||||
S1
|
||||
E5
|
||||
S2
|
||||
F66
|
||||
N4
|
||||
N1
|
||||
W4
|
||||
F84
|
||||
R180
|
||||
F23
|
||||
F20
|
||||
E1
|
||||
S3
|
||||
R90
|
||||
E2
|
||||
F48
|
||||
F89
|
||||
L90
|
||||
F97
|
||||
R180
|
||||
N3
|
||||
F62
|
||||
L90
|
||||
N5
|
||||
F28
|
||||
W5
|
||||
N4
|
||||
L180
|
||||
N4
|
||||
W1
|
||||
N3
|
||||
L90
|
||||
F95
|
||||
N1
|
||||
W5
|
||||
R180
|
||||
N5
|
||||
F34
|
||||
S1
|
||||
W2
|
||||
N4
|
||||
F3
|
||||
S2
|
||||
E1
|
||||
R90
|
||||
E2
|
||||
F36
|
||||
S4
|
||||
E5
|
||||
F42
|
||||
W1
|
||||
L180
|
||||
S1
|
||||
F74
|
||||
F38
|
||||
N4
|
||||
R270
|
||||
N3
|
||||
W2
|
||||
S4
|
||||
L180
|
||||
F26
|
||||
S4
|
||||
F51
|
||||
R90
|
||||
F83
|
||||
R90
|
||||
F9
|
||||
S2
|
||||
W1
|
||||
F99
|
||||
S4
|
||||
W1
|
||||
F84
|
||||
W1
|
||||
R180
|
||||
F59
|
||||
W5
|
||||
R90
|
||||
F75
|
||||
S1
|
||||
F34
|
||||
E4
|
||||
N3
|
||||
L90
|
||||
F43
|
||||
W5
|
||||
N1
|
||||
R90
|
||||
F59
|
||||
W1
|
||||
N3
|
||||
W4
|
||||
S2
|
||||
F36
|
||||
N5
|
||||
W4
|
||||
E2
|
||||
F96
|
||||
R180
|
||||
F44
|
||||
R90
|
||||
F12
|
||||
E5
|
||||
F24
|
||||
W3
|
||||
F39
|
||||
S2
|
||||
L180
|
||||
W3
|
||||
W4
|
||||
F70
|
||||
N4
|
||||
E4
|
||||
F36
|
||||
E2
|
||||
N1
|
||||
F30
|
||||
L90
|
||||
S2
|
||||
F81
|
||||
R270
|
||||
R90
|
||||
F66
|
||||
W1
|
||||
L90
|
||||
W2
|
||||
F98
|
||||
S1
|
||||
E1
|
||||
L90
|
||||
E3
|
||||
N2
|
||||
F100
|
||||
W3
|
||||
N3
|
||||
R90
|
||||
F88
|
||||
E4
|
||||
L180
|
||||
F52
|
||||
L90
|
||||
E4
|
||||
F76
|
||||
W2
|
||||
L90
|
||||
E3
|
||||
F72
|
||||
S3
|
||||
L180
|
||||
F12
|
||||
F34
|
||||
E5
|
||||
F90
|
||||
S5
|
||||
W5
|
||||
E1
|
||||
N5
|
||||
L180
|
||||
E5
|
||||
F84
|
||||
E5
|
||||
E3
|
||||
L90
|
||||
E3
|
||||
F14
|
||||
L90
|
||||
W3
|
||||
L90
|
||||
S1
|
||||
L90
|
||||
W2
|
||||
F54
|
||||
R90
|
||||
S2
|
||||
F73
|
||||
S4
|
||||
E1
|
||||
S1
|
||||
F55
|
||||
E5
|
||||
N4
|
||||
R180
|
||||
L180
|
||||
N4
|
||||
R90
|
||||
F91
|
||||
L180
|
||||
F5
|
||||
E2
|
||||
N1
|
||||
W2
|
||||
F27
|
||||
W2
|
||||
S5
|
||||
R90
|
||||
S3
|
||||
F39
|
||||
S3
|
||||
W2
|
||||
F59
|
||||
F83
|
||||
W3
|
||||
E3
|
||||
E4
|
||||
L90
|
||||
S1
|
||||
R90
|
||||
E4
|
||||
F81
|
||||
E4
|
||||
R90
|
||||
W5
|
||||
F74
|
||||
W3
|
||||
E3
|
||||
F30
|
||||
L180
|
||||
S2
|
||||
E3
|
||||
F33
|
||||
S3
|
||||
R90
|
||||
F22
|
||||
S5
|
||||
F97
|
||||
S1
|
||||
E2
|
||||
F50
|
||||
E2
|
||||
F19
|
||||
E3
|
||||
L90
|
||||
L90
|
||||
S5
|
||||
W3
|
||||
F80
|
||||
F33
|
||||
E1
|
||||
R90
|
||||
N3
|
||||
L90
|
||||
F70
|
||||
L180
|
||||
W4
|
||||
N2
|
||||
R180
|
||||
S2
|
||||
F38
|
||||
S3
|
||||
F7
|
||||
R90
|
||||
E1
|
||||
N5
|
||||
F86
|
||||
W4
|
||||
F49
|
||||
W4
|
||||
F51
|
||||
S4
|
||||
F47
|
||||
R90
|
||||
W3
|
||||
R180
|
||||
R180
|
||||
W1
|
||||
F98
|
||||
S1
|
||||
W3
|
||||
S4
|
||||
L90
|
||||
F76
|
||||
E1
|
||||
F76
|
||||
R180
|
||||
S4
|
||||
R180
|
||||
W3
|
||||
F26
|
||||
N5
|
||||
F35
|
||||
S2
|
||||
F94
|
||||
F24
|
||||
N2
|
||||
F45
|
||||
E1
|
||||
L90
|
||||
F32
|
||||
S1
|
||||
R180
|
||||
F78
|
||||
F84
|
||||
L90
|
||||
N2
|
||||
F42
|
||||
R90
|
||||
F72
|
||||
S1
|
||||
E3
|
||||
N2
|
||||
W1
|
||||
F23
|
||||
E2
|
||||
F69
|
||||
L90
|
||||
F29
|
||||
R90
|
||||
S5
|
||||
W5
|
||||
L90
|
||||
W1
|
||||
S2
|
||||
E1
|
||||
F96
|
||||
S5
|
||||
R180
|
||||
F26
|
||||
S5
|
||||
W1
|
||||
S3
|
||||
F38
|
||||
S1
|
||||
E2
|
||||
S5
|
||||
W2
|
||||
S5
|
||||
F52
|
||||
L90
|
||||
F11
|
||||
E3
|
||||
R90
|
||||
E4
|
||||
F6
|
||||
L90
|
||||
R90
|
||||
W1
|
||||
R90
|
||||
E3
|
||||
F1
|
||||
E4
|
||||
N3
|
||||
E5
|
||||
R90
|
||||
N2
|
||||
R180
|
||||
W2
|
||||
N5
|
||||
F46
|
||||
N3
|
||||
E5
|
||||
F83
|
||||
R90
|
||||
F42
|
||||
S3
|
||||
R90
|
||||
N5
|
||||
F10
|
130
day12/main.hs
Executable file
130
day12/main.hs
Executable file
|
@ -0,0 +1,130 @@
|
|||
#! /usr/bin/env -S"ANSWER=42" nix-shell
|
||||
#! nix-shell -p ghcid
|
||||
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [pretty-simple linear])"
|
||||
#! nix-shell -i "ghcid -c 'ghci' -T main"
|
||||
|
||||
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-unused-imports -Wno-type-defaults #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-matches #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DeriveAnyClass #-}
|
||||
|
||||
import Debug.Trace (trace, traceShowId, traceShow)
|
||||
import Text.Pretty.Simple
|
||||
import Control.Monad
|
||||
import Linear.V2
|
||||
import Data.Monoid
|
||||
|
||||
exampleData :: [ String ]
|
||||
exampleData =
|
||||
[ "F10"
|
||||
, "N3"
|
||||
, "F7"
|
||||
, "R90"
|
||||
, "F11"
|
||||
]
|
||||
|
||||
|
||||
|
||||
data Ship = Ship { position :: V2 Double, orientation :: V2 Double }
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
-- At first, ship is at (0,0) facing East
|
||||
ship0 :: Ship
|
||||
ship0 = Ship (pure 0) (V2 1 0)
|
||||
|
||||
-- At first, ship is at (0,0) facing East
|
||||
ship1 :: Ship
|
||||
ship1 = Ship (pure 0) (V2 10 1)
|
||||
|
||||
-- instance Semigroup Ship
|
||||
-- where
|
||||
-- (<>) s1 s2 = Ship (getSum <$> ((Sum <$> (position s1)) <> (Sum <$> (position s2))))
|
||||
-- (getSum <$> ((Sum <$> (orientation s1)) <> (Sum <$> (orientation s2))))
|
||||
--
|
||||
-- instance Monoid Ship
|
||||
-- where
|
||||
-- mempty = Ship (pure 0) (pure 0)
|
||||
|
||||
data Instruction = InsMoveForward !Double
|
||||
| InsMoveNorth !Double
|
||||
| InsMoveSouth !Double
|
||||
| InsMoveEast !Double
|
||||
| InsMoveWest !Double
|
||||
| InsTurnL !Double
|
||||
| InsTurnR !Double
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
parseIns :: String -> Instruction
|
||||
-- Action N means to move north by the given value.
|
||||
parseIns ('N':x) = InsMoveNorth (read x)
|
||||
-- Action S means to move south by the given value.
|
||||
parseIns ('S':x) = InsMoveSouth (read x)
|
||||
-- Action E means to move east by the given value.
|
||||
parseIns ('E':x) = InsMoveEast (read x)
|
||||
-- Action W means to move west by the given value.
|
||||
parseIns ('W':x) = InsMoveWest (read x)
|
||||
-- Action L means to turn left the given number of degrees.
|
||||
parseIns ('L':x) = InsTurnL (read x)
|
||||
-- Action R means to turn right the given number of degrees.
|
||||
parseIns ('R':x) = InsTurnR (read x)
|
||||
-- Action F means to move forward by the given value in the direction the ship is currently facing.
|
||||
parseIns ('F':x) = InsMoveForward (read x)
|
||||
parseIns e = trace ("Unknown instruction: "<>show e) undefined
|
||||
|
||||
|
||||
-- 2*PI rad = 360 deg
|
||||
-- 1 rad = 180/PI deg
|
||||
-- PI/180 rad = 1 deg
|
||||
|
||||
runIns1 :: Ship -> Instruction -> Ship
|
||||
runIns1 s (InsMoveForward n) = s { position = (position s) + (pure n) * (orientation s) }
|
||||
runIns1 s (InsMoveNorth n) = s { position = (position s) + (pure n) * V2 0 1 }
|
||||
runIns1 s (InsMoveSouth n) = s { position = (position s) + (pure n) * V2 0 (-1) }
|
||||
runIns1 s (InsMoveEast n) = s { position = (position s) + (pure n) * V2 1 0 }
|
||||
runIns1 s (InsMoveWest n) = s { position = (position s) + (pure n) * V2 (-1) 0 }
|
||||
runIns1 s (InsTurnL n) = s { orientation = angle ((unangle (orientation s)) + n * pi / 180) }
|
||||
runIns1 s (InsTurnR n) = s { orientation = angle ((unangle (orientation s)) - n * pi / 180) }
|
||||
|
||||
manhattanV2 :: (Num a) => V2 a -> a
|
||||
manhattanV2 (V2 x y) = (abs x) + (abs y)
|
||||
|
||||
solvePart1 :: [String] -> Double
|
||||
solvePart1 = manhattanV2 . position . foldl runIns1 ship0 . map parseIns
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
runIns2 :: Ship -> Instruction -> Ship
|
||||
runIns2 s (InsMoveForward n) = s { position = (position s) + (pure n) * (orientation s) }
|
||||
runIns2 s (InsMoveNorth n) = s { orientation = (orientation s) + V2 0 n }
|
||||
runIns2 s (InsMoveSouth n) = s { orientation = (orientation s) + V2 0 (-n) }
|
||||
runIns2 s (InsMoveEast n) = s { orientation = (orientation s) + V2 n 0 }
|
||||
runIns2 s (InsMoveWest n) = s { orientation = (orientation s) + V2 (-n) 0 }
|
||||
runIns2 s (InsTurnL n) = s { orientation = rotV2By (orientation s) n }
|
||||
runIns2 s (InsTurnR n) = s { orientation = rotV2By (orientation s) (-n) }
|
||||
|
||||
rotV2By :: (Num a, Floating a) => V2 a -> a -> V2 a
|
||||
rotV2By (V2 x1 y1) n = V2 x y
|
||||
where
|
||||
x = cos a * x1 - sin a * y1
|
||||
y = sin a * x1 + cos a * y1
|
||||
a = n * pi / 180
|
||||
|
||||
solvePart2 :: [String] -> Double
|
||||
solvePart2 = manhattanV2 . position . foldl runIns2 ship1 . map parseIns
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
input <- lines <$> readFile "day12/input"
|
||||
putStrLn ":: Tests"
|
||||
pPrint exampleData
|
||||
pPrint $ map parseIns exampleData
|
||||
pPrint $ angle (90 * pi / 180)
|
||||
putStrLn ":: Day 12 - Part 1"
|
||||
pPrint $ solvePart1 exampleData
|
||||
pPrint $ solvePart1 input
|
||||
putStrLn ":: Day 12 - Part 2"
|
||||
pPrint $ solvePart2 exampleData
|
||||
pPrint $ solvePart2 input
|
2
day13/input
Normal file
2
day13/input
Normal file
|
@ -0,0 +1,2 @@
|
|||
1000507
|
||||
29,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,631,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,13,19,x,x,x,23,x,x,x,x,x,x,x,383,x,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,17
|
129
day13/main.hs
Executable file
129
day13/main.hs
Executable file
|
@ -0,0 +1,129 @@
|
|||
#! /usr/bin/env -S"GHCRTS=-N4" nix-shell
|
||||
#! nix-shell -p ghcid
|
||||
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [pretty-simple attoparsec arithmoi])"
|
||||
#! nix-shell -i "ghcid -c 'ghci' -T main"
|
||||
|
||||
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
import Control.Applicative
|
||||
import Control.Monad (foldM)
|
||||
import Data.Attoparsec.Text (Parser)
|
||||
import Data.Euclidean (gcdExt)
|
||||
import Data.List (find,sortOn)
|
||||
import Data.Maybe (fromMaybe,catMaybes)
|
||||
import Text.Pretty.Simple
|
||||
import qualified Data.Attoparsec.Text as A
|
||||
import qualified Data.Text as T
|
||||
|
||||
exampleData :: String
|
||||
exampleData = "939\n7,13,x,x,59,x,31,19"
|
||||
|
||||
numOrXParser :: Parser (Maybe Int)
|
||||
numOrXParser = (Just <$> A.decimal) <|> ("x" *> pure Nothing)
|
||||
|
||||
inputParser :: Parser (Int,[Int])
|
||||
inputParser = do
|
||||
n <- A.decimal
|
||||
A.skipSpace
|
||||
xs <- numOrXParser `A.sepBy` ","
|
||||
pure (n,catMaybes $ xs)
|
||||
|
||||
parseInput :: String -> Either String (Int,[Int])
|
||||
parseInput = (A.parseOnly inputParser) . T.pack
|
||||
|
||||
solvePart1 :: String -> Either String Int
|
||||
solvePart1 str = do
|
||||
(n,xs) <- parseInput str
|
||||
let (bus, time) = head
|
||||
$ sortOn (snd)
|
||||
$ map (\x -> (x,fromMaybe (-1) $ find (> n) [0,x..])) xs
|
||||
pure $ bus * (time - n)
|
||||
|
||||
inputParser2 :: Parser (Int,[Maybe Int])
|
||||
inputParser2 = do
|
||||
n <- A.decimal
|
||||
A.skipSpace
|
||||
xs <- numOrXParser `A.sepBy` ","
|
||||
pure (n,xs)
|
||||
|
||||
parseInput2 :: String -> Either String (Int,[Maybe Int])
|
||||
parseInput2 = (A.parseOnly inputParser2) . T.pack
|
||||
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- Here I sneak around a bit, and realize the problem is well defined --
|
||||
-- (and solved!) already: it's called the Chinese Remainder Theorem --
|
||||
-- https://en.wikipedia.org/wiki/Chinese_remainder_theorem --
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- Apllying the theorem allows to reduce a system of equation on x: --
|
||||
-- --
|
||||
-- x ≡ a1 (mod n1) --
|
||||
-- · --
|
||||
-- · --
|
||||
-- · --
|
||||
-- x ≡ ak (mod nk) --
|
||||
-- --
|
||||
-- to a single equation: --
|
||||
-- --
|
||||
-- x ≡ as (mod ns) --
|
||||
-- --
|
||||
-- It relates to the buses schedules in the following way: t is x, the bus --
|
||||
-- number is the modulo factor (since a bus comes *every* ni) and subsequent --
|
||||
-- additions to t (for other buses) is (-ai), so, for a but coming at --
|
||||
-- t+ai, one would write x ≡ -ai (mod ni) --
|
||||
-- --
|
||||
-- I chose to encode ai and ni as a tuple (ai,ni), named startAndIds --
|
||||
-- --
|
||||
-- Basically, we're creating a “chinese” function: --
|
||||
-- --
|
||||
-- chinese :: (Int,Int) -> (Int,Int) -> (Int,Int) --
|
||||
-- --
|
||||
-- Then, given a list [(Int, Int)] we can fold over it to obtain the solution --
|
||||
-- --
|
||||
|
||||
chinese :: (Integer,Integer) -> (Integer,Integer) -> Maybe (Integer,Integer)
|
||||
chinese (0,n1) (0,n2) = chinese (n1,n1) (n2,n2)
|
||||
chinese v (0,n2) = chinese v (n2,n2)
|
||||
chinese (0,n1) v = chinese (n1,n1) v
|
||||
chinese (a1,n1) (a2,n2) = do
|
||||
-- Computes a solution such that: n1×c1 + n2×c2 = g, for some c2
|
||||
-- n1×c1 - g = - n2×c2, for some c2
|
||||
-- 1/n2 (n1×c1 - g) = - c2, for some c2 (n2 is > 0)
|
||||
-- - 1/n2 (n1×c1 - g) = c2, for some c2 (n2 is > 0)
|
||||
-- n1 and n2 must be coprimes for this to work (g must be 1), fail otherwise
|
||||
(m1,m2) <- case gcdExt n1 n2 of
|
||||
(1,c1) -> Just ( c1, negate ((n1 * c1) - 1) `div` n2 )
|
||||
_ -> Nothing
|
||||
let x = a1 * m2 * n2 + a2 * m1 * n1
|
||||
let a12 = x `mod` (n1 * n2)
|
||||
pure $ (a12, n1 * n2)
|
||||
|
||||
e2m :: Either e a -> Maybe a
|
||||
e2m (Right v) = Just v
|
||||
e2m _ = Nothing
|
||||
|
||||
solvePart2 :: String -> Maybe (Integer,Integer)
|
||||
solvePart2 str = do
|
||||
(_,xs) <- e2m $ parseInput2 str
|
||||
let startAndIds = catMaybes $ sequence <$> zip [0..] (map (fmap fromIntegral) xs)
|
||||
let chineseEqs = fmap (\(a,n) -> ((-a) `mod` n, n)) startAndIds
|
||||
foldM chinese (1,1) chineseEqs
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn ":: Test"
|
||||
pPrint $ A.parseOnly inputParser $ T.pack exampleData
|
||||
pPrint $ take 3 ((\n -> [1,(n::Integer)..]) 59)
|
||||
putStrLn ":: Day 13 - Part 1"
|
||||
input <- readFile "day13/input"
|
||||
pPrint $ solvePart1 exampleData
|
||||
pPrint $ solvePart1 input
|
||||
putStrLn ":: Test 2"
|
||||
print $ solvePart2 exampleData
|
||||
print $ solvePart2 "1\n17,x,13,19"
|
||||
print $ solvePart2 "1\n67,7,59,61"
|
||||
print $ solvePart2 "1\n67,x,7,59,61"
|
||||
print $ solvePart2 "1\n67,7,x,59,61"
|
||||
print $ solvePart2 "1\n1789,37,47,1889"
|
||||
putStrLn ":: Day 13 - Part 2"
|
||||
print $ solvePart2 input
|
73
day15/main.hs
Executable file
73
day15/main.hs
Executable file
|
@ -0,0 +1,73 @@
|
|||
#! /usr/bin/env -S"ANSWER=42" nix-shell
|
||||
#! nix-shell -p ghcid
|
||||
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [pretty-simple])"
|
||||
#! nix-shell -i "ghcid -c 'ghci' -T main"
|
||||
|
||||
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-unused-imports #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-matches #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
import Debug.Trace (trace)
|
||||
import Text.Pretty.Simple
|
||||
|
||||
import Data.IntMap.Strict (IntMap)
|
||||
import qualified Data.IntMap.Strict as I
|
||||
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.List (iterate')
|
||||
|
||||
exampleInput1 :: [Int]
|
||||
exampleInput1 = [0,3,6]
|
||||
|
||||
exampleInput2 :: [Int]
|
||||
exampleInput2 = [1,3,2]
|
||||
exampleInput3 :: [Int]
|
||||
exampleInput3 = [3,1,2]
|
||||
|
||||
input :: [Int]
|
||||
input = [0,3,1,6,7,5]
|
||||
|
||||
type Turn = Int
|
||||
type Number = Int
|
||||
|
||||
|
||||
-- Each Number is attached to the last Turn it was seen
|
||||
-- The current Turn is recorded too
|
||||
-- Last spoken Number is recorded too
|
||||
data Game = Game { unMem :: (IntMap Turn)
|
||||
, unTurn :: Turn
|
||||
, unNumber :: Number
|
||||
}
|
||||
deriving Show
|
||||
|
||||
initGame :: [Int] -> Game
|
||||
initGame keys = Game mem ((length keys) + 1) 0
|
||||
where
|
||||
mem = I.fromList (zip keys [1..])
|
||||
|
||||
next :: Game -> Game
|
||||
next (Game mem turn n) = fromMaybe (Game (I.insert n turn mem) (turn+1) 0) $ do
|
||||
lastTurn <- I.lookup n mem
|
||||
pure $ Game (I.insert n turn mem) (turn+1) (turn - lastTurn)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn ":: Day 15 - Tests 1"
|
||||
print exampleInput1
|
||||
putStrLn $ "turn 04: " <> (show $ initGame exampleInput1)
|
||||
putStrLn $ "turn 05: " <> (show $ next $ initGame exampleInput1)
|
||||
putStrLn $ "turn 06: " <> (show $ next $ next $ initGame exampleInput1)
|
||||
putStrLn $ "turn 07: " <> (show $ next $ next $ next $ initGame exampleInput1)
|
||||
putStrLn $ "turn 08: " <> (show $ next $ next $ next $ next $ initGame exampleInput1)
|
||||
putStrLn $ "turn 09: " <> (show $ next $ next $ next $ next $ next $ initGame exampleInput1)
|
||||
putStrLn $ "turn 10: " <> (show $ next $ next $ next $ next $ next $ next $ initGame exampleInput1)
|
||||
print $ last $ take 2017 $ map unNumber $ iterate next $ initGame exampleInput1
|
||||
print $ last $ take 2017 $ map unNumber $ iterate next $ initGame exampleInput2
|
||||
print $ last $ take 2017 $ map unNumber $ iterate next $ initGame exampleInput3
|
||||
putStrLn ":: Day 15 - Part 1"
|
||||
print $ last $ take (2020 - 6) $ map unNumber $ iterate next $ initGame input
|
||||
putStrLn ":: Day 15 - Part 2"
|
||||
-- print $ last $ take (30000000 - 3) $ map unNumber $ iterate' next $ initGame exampleInput1
|
||||
print $ last $ take (30000000 - 6) $ map unNumber $ iterate' next $ initGame input
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-unused-imports #-}
|
||||
{-# OPTIONS_GHC -Wno-unused-matches #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
import Debug.Trace (trace)
|
||||
|
@ -12,4 +13,4 @@ import Text.Pretty.Simple
|
|||
|
||||
main :: IO ()
|
||||
main = do
|
||||
putStrLn "Day x - Part 1"
|
||||
putStrLn ":: Day x - Part 1"
|
||||
|
|
Loading…
Reference in a new issue