Compare commits

...

25 Commits
day7 ... main

Author SHA1 Message Date
EEva (JPotier)
e0ea0a26c8 Day 15, part 1 and 2: slow solution 2020-12-29 14:32:41 +02:00
EEva (JPotier)
400d1cdc57 Initial commit 2020-12-29 10:47:28 +02:00
6aba6f131e
Day 13
Cleaned up
2020-12-21 15:34:56 +02:00
f8d0b6c0da
Day 13 (dirty) 2020-12-21 15:27:51 +02:00
6ee8b3fafa
A bit faster with Parallel, but still too slow 2020-12-18 16:23:47 +02:00
7c8cb639cb
Still too slow 2020-12-18 14:36:58 +02:00
f41863a68b
Best effort 2020-12-17 15:54:32 +02:00
EEva (JPotier)
2240fd1325 In progress 2020-12-15 08:27:32 +02:00
0e498f3caa
Part 1 2020-12-14 14:53:53 +02:00
EEva (JPotier)
47bafe66dc In progress 2020-12-13 18:50:00 +02:00
EEva (JPotier)
538fba7063 Part 2
With some approximation
2020-12-13 17:33:04 +02:00
EEva (JPotier)
c15d4ee29d Part 1 2020-12-13 16:28:56 +02:00
EEva (JPotier)
3997886348 Day 12 in progress 2020-12-13 15:15:04 +02:00
d720534eaf
Day 10 - part 2
yeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah
2020-12-11 09:30:17 +02:00
Martin Potier
a1a4a6fb52 Almost there 2020-12-11 00:18:39 +02:00
fec46e87e0
Day 10 - Part 1 2020-12-10 16:10:39 +02:00
8d16541413
Day 9 - Part 2
Hope you have a fast machine. This is long to compute :)
2020-12-10 15:25:15 +02:00
0305b145a7
Part 1 done 2020-12-10 14:26:48 +02:00
fa87faaa02
Initial commit for day9 2020-12-10 13:30:34 +02:00
09ca90be06
Bad Haskell, Debug.Trace ftw! 2020-12-10 12:49:39 +02:00
Martin Potier
4faaf34bf8 Day 8 - still in progress 2020-12-09 23:30:18 +02:00
Martin Potier
f0c7f30103 Part 1 2020-12-09 19:59:35 +02:00
2ee9fa16c4
tmp 2020-12-09 14:05:30 +02:00
54ddd70f1d
Day 8 in progress 2020-12-09 14:04:43 +02:00
Martin Potier
a0ec7f0b63 Init day8 2020-12-08 22:26:09 +02:00
12 changed files with 3174 additions and 3 deletions

95
day10/input Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

643
day8/input Normal file
View File

@ -0,0 +1,643 @@
acc -15
jmp +164
nop +157
acc -12
acc -19
acc +41
jmp +177
acc +36
acc +37
nop +471
jmp +433
acc +24
acc +13
acc -12
jmp +556
jmp +1
acc -15
acc +33
jmp +299
jmp +344
acc -3
jmp +124
acc +10
nop +562
acc +45
jmp +386
acc -3
jmp +206
acc -19
acc +12
jmp +424
acc -18
acc +23
acc +12
acc +0
jmp +311
nop +327
jmp +301
acc +20
nop +375
jmp +25
acc -13
acc +49
acc +23
acc -3
jmp +346
acc +2
acc +3
jmp +123
acc -7
nop +183
jmp +165
acc +47
acc +34
jmp +1
jmp +359
acc +12
acc +16
acc -3
acc +0
jmp +556
acc +14
acc -3
jmp +559
jmp +192
jmp +495
nop +264
acc +3
acc +47
jmp +187
acc -18
jmp +1
acc -12
jmp -58
acc +49
nop +288
jmp +145
acc +46
jmp +294
acc +38
nop +400
jmp +373
acc +7
acc +31
jmp +492
acc +40
acc +5
acc +11
jmp +263
acc +29
acc +10
acc +21
acc +14
jmp +450
nop +458
acc +38
nop +432
acc +42
jmp +191
jmp +279
nop +71
acc -17
jmp -64
acc +17
jmp +1
acc +29
jmp +506
jmp +354
acc +42
acc +32
jmp -40
jmp +184
acc +41
acc -7
acc +10
acc +38
jmp +100
jmp +104
jmp +245
jmp +335
jmp +20
acc +3
jmp +490
jmp -62
acc +34
acc +34
acc -1
jmp +6
acc +5
acc -9
acc -19
jmp +397
jmp +253
acc +9
jmp +270
acc +8
acc -16
acc +32
acc +48
jmp +258
acc +4
acc +37
nop +319
jmp +318
jmp -4
acc -5
jmp +32
nop -86
jmp +306
acc -13
acc +50
acc -16
jmp -53
acc +31
jmp +52
acc -11
jmp +89
acc +21
jmp +126
acc +44
acc +49
nop +177
jmp +44
acc +8
jmp +166
acc +20
acc -8
acc +38
acc +10
jmp +311
jmp +21
acc -10
nop +84
acc -7
acc +13
jmp +78
jmp +1
jmp +366
acc -6
acc -12
jmp -142
nop +223
jmp +42
acc -6
nop +227
nop +193
acc +23
jmp +83
acc -10
acc +12
jmp +1
acc -8
acc +3
nop +28
jmp +301
acc +23
jmp -170
nop -79
acc +21
acc +37
jmp +138
acc +37
acc +24
nop +413
acc -9
jmp -179
acc -1
acc -10
nop +261
acc -19
jmp +168
acc -16
acc +19
acc +17
acc +21
jmp -9
jmp +46
acc +4
nop +398
acc +28
jmp +396
acc +11
jmp +384
jmp +375
acc +25
acc +30
acc -11
jmp +371
jmp +249
acc -10
acc -15
jmp -7
jmp +38
acc +29
acc +15
acc +46
jmp -77
acc +43
jmp -83
jmp -42
acc +30
acc +44
acc +33
acc +14
jmp +326
acc -3
nop +49
acc +12
jmp +63
acc -13
acc -19
acc -17
jmp +126
jmp +293
acc +16
jmp -185
acc -12
jmp -92
acc -13
acc +19
acc -1
jmp -138
acc +28
nop -243
nop +352
acc +43
jmp +249
acc -5
acc +36
jmp -217
nop +197
nop -106
acc +30
jmp +194
acc +7
acc -16
nop +128
jmp -239
jmp -258
acc +11
nop -74
acc +42
acc +40
jmp +72
jmp -207
nop +337
nop -240
nop -169
jmp -55
nop +165
acc +27
acc +4
jmp -169
acc -2
jmp +69
acc +0
jmp -250
acc +11
acc +45
acc +31
jmp +195
acc -10
acc -8
nop -283
acc -2
jmp +63
acc +17
acc +12
acc +0
nop +243
jmp +190
acc +17
acc -18
jmp +78
acc +7
acc +33
jmp +244
nop +29
acc +20
nop +150
acc +29
jmp -43
acc +45
nop -132
acc +16
acc +14
jmp -237
jmp -199
acc -4
jmp +179
acc +13
acc +15
acc +6
acc +46
jmp -222
acc -8
acc +15
jmp -26
acc +38
jmp +1
nop +266
jmp +44
acc -13
nop +209
acc +21
jmp +201
acc +8
acc +18
jmp +190
acc +35
jmp -238
jmp +69
acc -11
nop -182
jmp -221
acc -16
acc -5
acc +7
jmp +39
acc +26
acc +43
acc +20
jmp +92
acc +22
jmp +81
acc +32
acc -13
jmp +30
acc +1
jmp +201
acc +4
jmp -165
acc -17
jmp -84
acc -16
acc +2
acc +47
jmp +54
jmp -195
acc +33
acc -17
jmp -18
jmp +256
acc +1
jmp -244
acc +28
acc +35
jmp +189
nop +32
acc +9
jmp +24
acc +21
acc +14
acc +17
jmp -67
acc +21
jmp -297
acc +36
acc +14
acc -13
jmp +115
acc -2
acc -13
jmp -182
nop +119
acc -4
acc +44
acc -14
jmp +61
acc +41
jmp -13
nop -116
jmp -294
jmp +7
jmp +17
acc -14
acc +42
acc -6
acc +24
jmp +151
nop -374
nop -375
acc +4
jmp -268
nop -27
acc +16
acc +2
jmp -206
jmp -320
nop -196
jmp +168
nop +36
acc +34
jmp -402
acc +36
acc +38
acc -11
nop +17
jmp -182
acc +15
jmp -145
acc +43
jmp -79
jmp -391
jmp -155
nop -94
acc +0
acc +9
jmp -441
acc +3
acc +6
acc +50
nop -334
jmp +163
acc +18
acc -11
jmp +21
acc +10
acc +4
nop +132
jmp -348
acc +18
nop -1
acc -4
nop +148
jmp +165
jmp +146
jmp -460
jmp -14
acc +26
nop -388
nop -353
jmp +119
acc +26
acc -1
acc +9
jmp -285
acc +37
jmp -345
jmp -178
acc +7
acc +13
jmp -39
acc +29
nop -200
acc +50
acc +24
jmp -160
acc +18
jmp +63
acc -11
acc +1
acc -6
acc +33
jmp -90
acc -3
acc +11
acc +45
jmp -197
jmp -169
acc +7
acc -4
jmp -281
acc +48
nop +19
nop -25
nop +9
jmp -274
nop -126
acc +22
acc -4
jmp -408
acc +1
acc +0
jmp +98
acc +25
acc +12
acc -19
jmp -90
acc +44
acc +20
acc +21
jmp -192
acc -12
jmp -70
nop +3
acc +17
jmp -349
acc +20
acc -7
acc +6
nop -43
jmp +53
acc +34
acc +48
acc -4
acc +8
jmp -126
acc +23
acc +25
jmp -349
acc -4
jmp -272
jmp -129
nop -366
jmp -292
acc +29
nop -269
acc +50
nop -254
jmp -321
jmp -23
acc +11
nop -425
nop -150
acc -9
jmp -467
acc +18
acc +27
jmp -338
jmp +1
acc +21
acc +27
acc -11
jmp -160
acc +27
acc +15
acc +0
acc +41
jmp -386
acc -10
acc +14
jmp -217
nop -484
acc +47
jmp -529
acc -10
acc +48
acc +0
jmp -430
acc +45
acc -8
acc +3
nop -103
jmp -387
acc -16
acc +39
jmp +1
acc +17
jmp -350
jmp -328
acc +30
acc +28
jmp -309
nop -361
acc +1
nop -468
jmp -212
acc +29
acc -4
jmp -249
acc +45
acc +30
acc +40
acc -17
jmp -579
acc +25
jmp -525
nop -217
acc +17
acc +3
jmp -142
nop +18
jmp -493
jmp +1
jmp -495
jmp -360
acc +7
acc +30
acc -3
nop -449
jmp -326
acc -10
acc -8
jmp -371
acc +22
acc +48
acc +6
acc +18
jmp -59
acc +17
acc +14
jmp -250
acc +19
acc +25
acc -14
acc -17
jmp -517
acc +29
acc -4
acc +9
acc +17
jmp +1

140
day8/main.hs Executable file
View File

@ -0,0 +1,140 @@
#! /usr/bin/env -S"ANSWER=42" nix-shell
#! nix-shell -p ghcid
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [pretty-simple vector containers])"
#! nix-shell -i "ghcid -c 'ghci' -T main"
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-unused-local-binds #-}
{-# LANGUAGE OverloadedStrings #-}
import Text.Pretty.Simple
-- import Data.List.NonEmpty (NonEmpty(..))
-- import qualified Data.List.NonEmpty as NE
import Data.Vector (Vector)
import Debug.Trace (trace)
import Data.List (unfoldr, zip4, unzip4)
import Data.IntMap.Strict (IntMap)
import qualified Data.Vector as V
import qualified Data.IntMap.Strict as M
data Op = OpNop !Int
| OpJmp !Int
| OpAcc !Int
deriving (Show, Ord, Eq)
data VMState = VMRun | VMHalt
deriving (Show, Ord, Eq)
data VirtualMachine = VM
{ pgmCounter :: !Int
, pgmAccumulator :: !Int
, pgmInstructions :: Vector Op
, vmState :: VMState
}
deriving (Show, Ord, Eq)
initialVM :: Vector Op -> VirtualMachine
initialVM ins = VM 1 0 ins VMRun
stepVM :: VirtualMachine -> Maybe (VirtualMachine, VirtualMachine)
stepVM current@(VM c a ins VMRun) = Just (current, checkHalt next)
where
next = go (ins V.! (c-1))
go (OpNop _) = VM (c+1) a ins VMRun
go (OpJmp n) = VM (c+n) a ins VMRun
go (OpAcc n) = VM (c+1) (a+n) ins VMRun
checkHalt vm0@(VM c0 a0 _ _) | c0 == lastCount + 1 =
trace ("halted, acc="<>show a0) $ vm0 { vmState = VMHalt }
checkHalt vm0@(VM _ _ _ _) | otherwise =
vm0
lastCount = V.length ins
stepVM (VM _ _ _ VMHalt) = Nothing
exampleData :: [String]
exampleData =
[ "nop +0"
, "acc +1"
, "jmp +4"
, "acc +3"
, "jmp -3"
, "acc -99"
, "acc +1"
, "jmp -4"
, "acc +6"
]
vmFromInput :: [String] -> VirtualMachine
vmFromInput input = initialVM (ins input)
where
ins = V.fromList . map parseOp
parseOp :: String -> Op
parseOp = go . (\(x,y)-> (x,tail y)) . break (== ' ')
where
go ("nop",'+':s) = OpNop (read s :: Int)
go ("acc",'+':s) = OpAcc (read s :: Int)
go ("jmp",'+':s) = OpJmp (read s :: Int)
go ("nop",s) = OpNop (read s :: Int)
go ("acc",s) = OpAcc (read s :: Int)
go ("jmp",s) = OpJmp (read s :: Int)
go s@_ = trace (show s) $ undefined
-- Find smallest looping prefix in list of Int, returns associated pgmAccumulator
solvePart1 :: VirtualMachine -> Int
solvePart1 vm0 =
snd . last $ shortestCycleOn $ (\vm -> (pgmCounter vm, pgmAccumulator vm)) <$> unfoldr stepVM vm0
-- Shortest cycle in [Int]
shortestCycle :: [Int] -> [Int]
shortestCycle ix = reverse $ go M.empty ix []
where
go :: (IntMap ()) -> [Int] -> [Int] -> [Int]
go mem (x:_ ) ys | (mem M.!? x) /= Nothing = ys
go mem (x:xs) ys | otherwise = go (M.insert x () mem) xs (x:ys)
go _ [] ys = ys
shortestCycleOn :: [(Int,Int)] -> [(Int,Int)]
shortestCycleOn tx = zip (shortestCycle cx) ax
where
(cx, ax) = unzip tx
shortestCycleVm :: [VirtualMachine] -> [VirtualMachine]
shortestCycleVm vx = (\(a,b,c,d) -> VM a b c d) <$> zip4 (shortestCycle cx) ax ins state
where
(cx, ax, ins, state) = unzip4 $ (\(VM a b c d) -> (a,b,c,d)) <$> vx
-- Try lots of permutations of OpNop -> OpJmp, or OpJmp -> OpNop
-- until the VirtualMachine halts, and read the value of the accumulator
solvePart2 :: Vector Op -> Vector VMState
solvePart2 = fmap (vmState . last . shortestCycleVm . unfoldr stepVM . initialVM) . swapInstructions
swapInstructions :: Vector Op -> Vector (Vector Op)
swapInstructions ins = V.imap swap ins
where
swap i (OpNop v) = ins V.// [(i,OpJmp v)]
swap i (OpJmp v) = ins V.// [(i,OpNop v)]
swap _ (OpAcc _) = ins
main :: IO ()
main = do
putStrLn "Day 8 - Part 1"
putStrLn ":: Tests"
print exampleData
print $ parseOp <$> exampleData
putStrLn ":: Solving part 1"
pPrint $ solvePart1 (vmFromInput exampleData)
input <- lines <$> readFile "day8/input"
pPrint $ solvePart1 (vmFromInput input)
putStrLn ":: Tests"
let miniIns = V.fromList [OpJmp 2, OpNop 0, OpAcc (-8)]
pPrint $ length $ swapInstructions $ miniIns
let miniVM = initialVM $ V.fromList [ OpNop 0 ]
pPrint $ miniVM { vmState = VMHalt }
pPrint $ (unfoldr stepVM) $ miniVM
putStrLn ":: Solving part 2"
pPrint $ solvePart2 $ V.fromList $ parseOp <$> exampleData
pPrint $ solvePart2 $ V.fromList $ parseOp <$> input

1000
day9/input Normal file

File diff suppressed because it is too large Load Diff

75
day9/main.hs Executable file
View File

@ -0,0 +1,75 @@
#! /usr/bin/env -S"ANSWER=42" nix-shell
#! nix-shell -p ghcid
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [pretty-simple containers])"
#! nix-shell -i "ghcid -c 'ghci' -T main"
{-# OPTIONS_GHC -Wall -Wincomplete-uni-patterns #-}
{-# OPTIONS_GHC -Wno-unused-top-binds -Wno-unused-imports #-}
{-# LANGUAGE OverloadedStrings #-}
import Data.IntMap.Strict (IntMap)
import Data.IntSet (IntSet)
import Data.List (inits, tails, sortOn)
import Data.Monoid
import Debug.Trace (trace)
import Text.Pretty.Simple
import qualified Data.IntMap.Strict as M
import qualified Data.IntSet as S
exampleData :: [Int]
exampleData = [ 35,20,15,25,47,40,62,55,65,95,102,117,150
, 182,127,219,299,277,309,576 ];
pairSums :: [Int] -> IntSet
pairSums xs = S.fromList $ do
i1 <- xs
i2 <- xs
pure (i1 + i2)
isSumOfPreamble :: Int -> [Int] -> Bool
isSumOfPreamble size xs = go tx
where
go (x:_) = x `S.member` (pairSums preamble)
go ([]) = False
(preamble, tx) = splitAt size xs
solvePart1 :: Int -> [Int] -> (Int,Bool)
solvePart1 size message =
head $ dropWhile (snd) $
map go ( takeWhile ((> size) . length) $ tails message )
where
go xs = (head $ drop size xs,isSumOfPreamble size xs)
--------------------------------------------------------------------------------
sortedContiguousSubLists :: [Int] -> [[Int]]
sortedContiguousSubLists =
dropWhile (== []) . sortOn length . concat . fmap inits . tails
listSums :: [[Int]] -> IntMap [Int]
listSums xss = M.fromList $ do
xs <- xss
pure $ (getSum $ foldMap Sum xs, xs)
solvePart2 :: Int -> [Int] -> Int
solvePart2 target message = (\x -> minimum x + maximum x) $ bigMap M.! target
where
bigMap = listSums $ sortedContiguousSubLists message
main :: IO ()
main = do
putStrLn "Test"
print exampleData
print $ 1 `S.member` (pairSums [])
print $ pairSums exampleData
putStrLn "Day 9 - Part 1"
print $ solvePart1 5 exampleData
input <- lines <$> readFile "day9/input"
print $ solvePart1 25 $ map read input
putStrLn "Test"
print $ take 10 $ drop 20 $ sortedContiguousSubLists exampleData
putStrLn "Day 9 - Part 2"
print $ solvePart2 127 exampleData
print $ solvePart2 3199139634 $ map read input

View File

@ -1,10 +1,16 @@
#! /usr/bin/env -S"ANSWER=42" nix-shell
#! nix-shell -p ghcid
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [shower])"
#! nix-shell -i "ghcid -c 'ghci -Wall' -T main"
#! 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
main :: IO ()
main = do
putStrLn "Day 1 - Part 1"
putStrLn ":: Day x - Part 1"