Day 15
This commit is contained in:
parent
20db7749dc
commit
14bf6df148
5 changed files with 115 additions and 1 deletions
|
@ -2,7 +2,7 @@
|
||||||
--
|
--
|
||||||
-- see: https://github.com/sol/hpack
|
-- see: https://github.com/sol/hpack
|
||||||
--
|
--
|
||||||
-- hash: ea04591b11d049b24eb195b76d379646dcfbc1c5bf4ee126d894309a7a7a3708
|
-- hash: c000ca3243983619481d89396b163acf8fb77f12488850d0f27e659ab2f1bd40
|
||||||
|
|
||||||
name: adventofcode
|
name: adventofcode
|
||||||
version: 0.1.0.0
|
version: 0.1.0.0
|
||||||
|
@ -44,6 +44,7 @@ library
|
||||||
Day12
|
Day12
|
||||||
Day13
|
Day13
|
||||||
Day14
|
Day14
|
||||||
|
Day15
|
||||||
other-modules:
|
other-modules:
|
||||||
Paths_adventofcode
|
Paths_adventofcode
|
||||||
build-depends:
|
build-depends:
|
||||||
|
|
10
app/Main.hs
10
app/Main.hs
|
@ -22,6 +22,7 @@ import qualified Day11
|
||||||
import qualified Day12
|
import qualified Day12
|
||||||
import qualified Day13
|
import qualified Day13
|
||||||
import qualified Day14
|
import qualified Day14
|
||||||
|
import qualified Day15
|
||||||
|
|
||||||
showSol :: [Char] -> Doc -> IO ()
|
showSol :: [Char] -> Doc -> IO ()
|
||||||
showSol txt d = putText . toS . render $
|
showSol txt d = putText . toS . render $
|
||||||
|
@ -49,6 +50,7 @@ solutions = Map.fromList [(["01"], day01)
|
||||||
,(["12"], day12)
|
,(["12"], day12)
|
||||||
,(["13"], day13)
|
,(["13"], day13)
|
||||||
,(["14"], day14)
|
,(["14"], day14)
|
||||||
|
,(["15"], day15)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,3 +175,11 @@ day14 = do
|
||||||
showSol "Solution 1" (int (fromMaybe 0 sol1))
|
showSol "Solution 1" (int (fromMaybe 0 sol1))
|
||||||
sol2 <- Day14.solution2 Day14.input
|
sol2 <- Day14.solution2 Day14.input
|
||||||
showSol "Solution 2" (int sol2)
|
showSol "Solution 2" (int sol2)
|
||||||
|
|
||||||
|
day15 :: IO ()
|
||||||
|
day15 = do
|
||||||
|
putText "Day 15:"
|
||||||
|
let sol1 = Day15.solution1 Day15.input
|
||||||
|
showSol "Solution 1" (int sol1)
|
||||||
|
let sol2 = Day15.solution2 Day15.input
|
||||||
|
showSol "Solution 1" (int sol2)
|
||||||
|
|
|
@ -27,6 +27,7 @@ library:
|
||||||
- Day12
|
- Day12
|
||||||
- Day13
|
- Day13
|
||||||
- Day14
|
- Day14
|
||||||
|
- Day15
|
||||||
dependencies:
|
dependencies:
|
||||||
- base >=4.7 && <5
|
- base >=4.7 && <5
|
||||||
- protolude
|
- protolude
|
||||||
|
|
88
src/Day15.hs
Normal file
88
src/Day15.hs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
|
{-|
|
||||||
|
description:
|
||||||
|
|
||||||
|
--- Day 15: Dueling Generators ---
|
||||||
|
|
||||||
|
Here, you encounter a pair of dueling generators. The generators, called
|
||||||
|
generator A and generator B, are trying to agree on a sequence of numbers.
|
||||||
|
However, one of them is malfunctioning, and so the sequences don't always match.
|
||||||
|
|
||||||
|
As they do this, a judge waits for each of them to generate its next value,
|
||||||
|
compares the lowest 16 bits of both values, and keeps track of the number of
|
||||||
|
times those parts of the values match.
|
||||||
|
|
||||||
|
The generators both work on the same principle. To create its next value, a
|
||||||
|
generator will take the previous value it produced, multiply it by a factor
|
||||||
|
(generator A uses 16807; generator B uses 48271), and then keep the remainder of
|
||||||
|
dividing that resulting product by 2147483647. That final remainder is the value
|
||||||
|
it produces next.
|
||||||
|
|
||||||
|
To calculate each generator's first value, it instead uses a specific starting
|
||||||
|
value as its "previous value" (as listed in your puzzle input).
|
||||||
|
|
||||||
|
For example, suppose that for starting values, generator A uses 65, while
|
||||||
|
generator B uses 8921. Then, the first five pairs of generated values are:
|
||||||
|
|
||||||
|
--Gen. A-- --Gen. B--
|
||||||
|
1092455 430625591
|
||||||
|
1181022009 1233683848
|
||||||
|
245556042 1431495498
|
||||||
|
1744312007 137874439
|
||||||
|
1352636452 285222916
|
||||||
|
In binary, these pairs are (with generator A's value first in each pair):
|
||||||
|
|
||||||
|
00000000000100001010101101100111
|
||||||
|
00011001101010101101001100110111
|
||||||
|
|
||||||
|
01000110011001001111011100111001
|
||||||
|
01001001100010001000010110001000
|
||||||
|
|
||||||
|
00001110101000101110001101001010
|
||||||
|
01010101010100101110001101001010
|
||||||
|
|
||||||
|
01100111111110000001011011000111
|
||||||
|
00001000001101111100110000000111
|
||||||
|
|
||||||
|
01010000100111111001100000100100
|
||||||
|
00010001000000000010100000000100
|
||||||
|
|
||||||
|
Here, you can see that the lowest (here, rightmost) 16 bits of the third value
|
||||||
|
match: 1110001101001010. Because of this one match, after processing these five
|
||||||
|
pairs, the judge would have added only 1 to its total.
|
||||||
|
|
||||||
|
To get a significant sample, the judge would like to consider 40 million pairs.
|
||||||
|
(In the example above, the judge would eventually find a total of 588 pairs that
|
||||||
|
match in their lowest 16 bits.)
|
||||||
|
|
||||||
|
After 40 million pairs, what is the judge's final count?
|
||||||
|
|
||||||
|
|-}
|
||||||
|
module Day15 where
|
||||||
|
|
||||||
|
import Protolude
|
||||||
|
|
||||||
|
input :: (Int64,Int64)
|
||||||
|
input = (618,814)
|
||||||
|
|
||||||
|
testInput :: (Int64,Int64)
|
||||||
|
testInput = (65,8921)
|
||||||
|
|
||||||
|
generatorA :: Int64 -> Int64
|
||||||
|
generatorA x = x * 16807 `rem` 2147483647
|
||||||
|
|
||||||
|
generatorB :: Int64 -> Int64
|
||||||
|
generatorB x = x * 48271 `rem` 2147483647
|
||||||
|
|
||||||
|
toInt16 :: Int64 -> Int16
|
||||||
|
toInt16 = fromIntegral
|
||||||
|
|
||||||
|
solution1 input =
|
||||||
|
let lst1 = map toInt16 $ iterate generatorA (fst input)
|
||||||
|
lst2 = map toInt16 $ iterate generatorB (snd input)
|
||||||
|
in length (filter (uncurry (==)) (take 40000000 (zip lst1 lst2)))
|
||||||
|
|
||||||
|
solution2 input =
|
||||||
|
let lst1 = map toInt16 . filter ((== 0) . (`rem` 4)) $ iterate generatorA (fst input)
|
||||||
|
lst2 = map toInt16 . filter ((== 0) . (`rem` 8)) $ iterate generatorB (snd input)
|
||||||
|
in length (filter (uncurry (==)) (take 5000000 (zip lst1 lst2)))
|
14
test/Spec.hs
14
test/Spec.hs
|
@ -19,6 +19,7 @@ import qualified Day11
|
||||||
import qualified Day12
|
import qualified Day12
|
||||||
import qualified Day13
|
import qualified Day13
|
||||||
import qualified Day14
|
import qualified Day14
|
||||||
|
import qualified Day15
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = defaultMain $
|
main = defaultMain $
|
||||||
|
@ -37,6 +38,7 @@ main = defaultMain $
|
||||||
, testDay12
|
, testDay12
|
||||||
, testDay13
|
, testDay13
|
||||||
, testDay14
|
, testDay14
|
||||||
|
, testDay15
|
||||||
]
|
]
|
||||||
|
|
||||||
testDay01 =
|
testDay01 =
|
||||||
|
@ -259,3 +261,15 @@ testDay14 =
|
||||||
(assertFailure "Should be 1242 groups")
|
(assertFailure "Should be 1242 groups")
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
testDay15 =
|
||||||
|
testGroup "Day 15"
|
||||||
|
[ testGroup "Solution 1"
|
||||||
|
[ testCase "Example" $
|
||||||
|
Day15.solution1 Day15.testInput @?= 588
|
||||||
|
]
|
||||||
|
, testGroup "Solution 2"
|
||||||
|
[ testCase "Example" $
|
||||||
|
Day15.solution2 Day15.testInput @?= 309
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in a new issue