aboutsummaryrefslogtreecommitdiff
path: root/Puzzle3.hs
blob: 516b9bb325a8f2737cd67692cb15083b53bf56ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{-
Copyright (C) 2017 Yuchen Pei.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU Affero General Public
License along with this program.  If not, see
<https://www.gnu.org/licenses/>.
-}
import Data.Maybe (fromJust)
import Data.List (elemIndex)
import Control.Monad (liftM2)

f :: Int -> Int
f n = floor $ (sqrt (fromIntegral n - 0.5) + 1) / 2

solve1 :: Int -> Int
solve1 n = let k = f n in abs ((n - 2 - (2 * k - 1)) `mod` (2 * k) - k) + k

-- Second puzzle adapted from u/bblum's solution at https://www.reddit.com/r/adventofcode/comments/7h7ufl/2017_day_3_solutions/dqpq2uz/

walk :: Int -> Int -> Int -> [Int]
walk n from to | to > 0 = replicate n from ++ [from, from + 1 .. to - 1] ++ walk (n + 1) to (-to)
walk n from to | to < 0 = replicate n from ++ [from, from - 1 .. to + 1] ++ walk (n + 1) to (1 - to)

-- in walk 0 0 1 for x axis: walk n from to: to > 0: replicate n from builds the right wall, [from, from + 1 .. to - 1] builds the ceiling; n < 0: the replicate bit builds the left wall and the [..] bit builds the floor.
spiral :: [(Int, Int)]
spiral = zipWith (,) (walk 0 0 1) (walk 1 0 1)

sumList :: [Int] -> [Int]
sumList xs = let m = length xs in xs ++ [sum $ map (\n -> if n < m then xs !! n else 0) $ neighbours (spiral !! m)]

neighbours :: (Int, Int) -> [Int]
neighbours (x, y) = fromJust . flip elemIndex spiral <$> liftM2 (,) [x - 1 .. x + 1] [y - 1 .. y + 1]

solve2 :: Int -> Int
solve2 x = last $ until ((>x) . last) sumList [1]