import System.IO import Data.List (intersect) -- import Data.Array ((!), listArray) import Debug.Trace (traceShow) main = do let input = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\n\ \Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\n\ \Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\n\ \Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\n\ \Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\n\ \Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11" let ans1 = part1 input let ans2 = part2 input putStr "Part 1 answer: " putStr . show $ ans1 putStr "\nPart 2 answer: " putStr . show $ ans2 putStr "\n" test = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\n\ \Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\n\ \Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\n\ \Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\n\ \Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\n\ \Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11" part1 :: String -> Int part1 = foldr valueWin 0 . parseInput where valueWin 0 acc = acc valueWin x acc = acc + 2^(x-1) -- part2 :: String -> Int part2 input = foldr go initialCards (zip [1..3] wins) where wins = parseInput input initialCards = zip [1..] $ replicate (length wins) 1 go (i,win) acc = map (\(i',copies) -> if i' `elem` [i+1 .. i+win] then (i', copies+multiplier) else (i', copies)) acc where multiplier = snd $ acc!!i parseInput :: String -> [Int] -- returns wins array parseInput input = map (\(m,w) -> length $ intersect m w) (zip myNumbers winningNumbers) where allNumbers = map (drop 2 . words) . lines $ input myNumbers = map (takeWhile (/="|")) allNumbers winningNumbers = map (drop 1 . dropWhile (/="|")) allNumbers