···
+
import Data.Ratio ((%), Ratio)
+
import Data.Maybe (catMaybes)
+
import Data.Ord (comparing)
+
import Data.List (sortBy)
+
import qualified Data.Map as Map
+
type Machine = (Button, [Button], [Int])
+
parse :: String -> [Machine]
+
parse = map parseLine . lines
+
where parseDisplay :: String -> [Int]
+
parseDisplay s = [i | (i,c) <- zip [0..] (init (tail s)), c == '#']
+
parseInts :: String -> [Int]
+
parseInts s = map read $ split ',' $ (init (tail s))
+
in (parseDisplay disp, map parseInts (init (tail w)), parseInts jolt)
+
xor :: [Int] -> [Int] -> [Int]
+
xor (a:as) (b:bs) | a < b = (a : xor as (b:bs))
+
xor (a:as) (b:bs) | a == b = xor as bs
+
xor (a:as) (b:bs) | a > b = (b : xor (a:as) bs)
+
minimumMaybe :: [Maybe Int] -> Maybe Int
+
ns' -> Just $ minimum ns'
+
solveMachine :: Machine -> Maybe Int
+
solveMachine ([],[],_) = Just 0
+
solveMachine (_,[],_) = Nothing
+
solveMachine (goal, (b:bs), jolt) =
+
minimumMaybe [solveMachine (goal, bs, jolt),
+
(+ 1) <$> solveMachine (xor goal b, bs, jolt)]
part1 :: String -> String
+
let machines = parse input
+
solutions = map solveMachine machines
+
in case sequence solutions of
+
Just ss -> show $ sum ss
+
buttonToRepeat :: Int -> Button -> [Int]
+
buttonToRepeat i button = go 0 button
+
where go n [] = repeat 0
+
gaussJordan :: Map (Int,Int) (Ratio Int) -> Map Int (Ratio Int) -> (Map (Int,Int) (Ratio Int), Map Int (Ratio Int), Int)
+
gaussJordan m g = error "GJ"
+
solveMachine2 :: [Button] -> [Int] -> Maybe Int
+
solveMachine2 buttons goal =
+
let mat = Map.fromList [((i,j),1 % 1) | (i,b) <- zip [0..] buttons, j <- b]
+
g = Map.fromList $ zip [0..] (map (% 1) goal)
+
(mat', g', rank) = gaussJordan mat g
part2 :: String -> String
+
let machines = parse input
+
solutions = map (\(_,b,g) -> solveMachine2 b g) machines
+
in case sequence solutions of
+
Just ss -> show $ sum ss