🏡 index : ~doyle/aoc.git

#!/usr/bin/env nix-shell
#!nix-shell --pure -i "runghc -- -i../" -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])"

import Aoc (parseMultiChoiceGrid, readAndParseStdin)
import Data.List (findIndices, transpose)
import Data.Maybe (isJust, isNothing)

main = do
  input <- readAndParseStdin parseMultiChoiceGrid
  print $ part1 input
  print $ part2 input

part1 :: [[Maybe Bool]] -> Int
part1 = countScore . tiltNorth

part2 :: [[Maybe Bool]] -> Int
part2 = countScore . spinCycle 1000
  where
    spinCycle 0 acc = acc
    spinCycle n acc = spinCycle (n - 1) ((tiltEast . tiltSouth . tiltWest . tiltNorth) acc)

countScore :: [[Maybe Bool]] -> Int
countScore [] = 0
countScore (x : xs) = length (filter (== Just True) x) * (length xs + 1) + countScore xs

tiltNorth :: [[Maybe Bool]] -> [[Maybe Bool]]
tiltNorth = transpose . map (move [] 0) . transpose
  where
    move :: [Maybe Bool] -> Int -> [Maybe Bool] -> [Maybe Bool]
    move acc _ [] = acc
    move acc lastSeenJust (x : xs)
      | x == Just True = move (take lastSeenJust acc ++ x : drop lastSeenJust acc) (lastSeenJust + 1) xs
      | x == Just False = move (acc ++ [x]) (length acc + 1) xs
      | isNothing x = move (acc ++ [x]) lastSeenJust xs

tiltWest :: [[Maybe Bool]] -> [[Maybe Bool]]
tiltWest = transpose . tiltNorth . transpose

tiltEast :: [[Maybe Bool]] -> [[Maybe Bool]]
tiltEast = transpose . reverse . tiltNorth . reverse . transpose

tiltSouth :: [[Maybe Bool]] -> [[Maybe Bool]]
tiltSouth = reverse . tiltNorth . reverse