This commit is contained in:
Yann Esposito (Yogsototh) 2017-12-15 06:53:13 +01:00
parent 20db7749dc
commit 14bf6df148
Signed by untrusted user who does not match committer: yogsototh
GPG key ID: 7B19A4C650D59646
5 changed files with 115 additions and 1 deletions

View file

@ -2,7 +2,7 @@
--
-- see: https://github.com/sol/hpack
--
-- hash: ea04591b11d049b24eb195b76d379646dcfbc1c5bf4ee126d894309a7a7a3708
-- hash: c000ca3243983619481d89396b163acf8fb77f12488850d0f27e659ab2f1bd40
name: adventofcode
version: 0.1.0.0
@ -44,6 +44,7 @@ library
Day12
Day13
Day14
Day15
other-modules:
Paths_adventofcode
build-depends:

View file

@ -22,6 +22,7 @@ import qualified Day11
import qualified Day12
import qualified Day13
import qualified Day14
import qualified Day15
showSol :: [Char] -> Doc -> IO ()
showSol txt d = putText . toS . render $
@ -49,6 +50,7 @@ solutions = Map.fromList [(["01"], day01)
,(["12"], day12)
,(["13"], day13)
,(["14"], day14)
,(["15"], day15)
]
@ -173,3 +175,11 @@ day14 = do
showSol "Solution 1" (int (fromMaybe 0 sol1))
sol2 <- Day14.solution2 Day14.input
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)

View file

@ -27,6 +27,7 @@ library:
- Day12
- Day13
- Day14
- Day15
dependencies:
- base >=4.7 && <5
- protolude

88
src/Day15.hs Normal file
View 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)))

View file

@ -19,6 +19,7 @@ import qualified Day11
import qualified Day12
import qualified Day13
import qualified Day14
import qualified Day15
main :: IO ()
main = defaultMain $
@ -37,6 +38,7 @@ main = defaultMain $
, testDay12
, testDay13
, testDay14
, testDay15
]
testDay01 =
@ -259,3 +261,15 @@ testDay14 =
(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
]
]