Refactored day 4 solution
This commit is contained in:
parent
2cdc0878a2
commit
db59bb39be
1 changed files with 40 additions and 52 deletions
|
@ -1,3 +1,4 @@
|
|||
{-# LANGUAGE TupleSections #-}
|
||||
import Data.List
|
||||
import Debug.Trace
|
||||
|
||||
|
@ -8,67 +9,54 @@ type Input = ([Int], [Board])
|
|||
|
||||
parse :: [String] -> Input
|
||||
parse (l : ls) = (n, b)
|
||||
where
|
||||
n = map read (words [ if c == ',' then ' ' else c | c <- l ])
|
||||
where n = map read $ words [ if c == ',' then ' ' else c | c <- l ]
|
||||
b = parseBoards (filter (/= "") ls)
|
||||
|
||||
solve :: Input -> (Int, Int)
|
||||
solve input = (f input, g input)
|
||||
where f = uncurry winBingo
|
||||
g = uncurry loseBingo
|
||||
|
||||
parseBoards :: [String] -> [Board]
|
||||
parseBoards [] = []
|
||||
parseBoards list = Board (map (map (Unmarked . read) . words) a) : parseBoards b
|
||||
where
|
||||
(a, b) = splitAt 5 list
|
||||
parseBoards l = parse a : parseBoards b
|
||||
where (a,b) = splitAt 5 l
|
||||
parse = map $ map (Unmarked . read) . words
|
||||
|
||||
newtype Board = Board [[Cell]]
|
||||
deriving
|
||||
Show
|
||||
type Board = [[Cell]]
|
||||
|
||||
rows :: Board -> [[Cell]]
|
||||
rows = id
|
||||
|
||||
cols :: Board -> [[Cell]]
|
||||
cols = transpose
|
||||
|
||||
hasWon :: Board -> Bool
|
||||
hasWon b = check (rows b) || check (cols b)
|
||||
where check = any $ all marked
|
||||
|
||||
score :: Int -> Board -> Int
|
||||
score n b = n * sum [ x | c <- b, Unmarked x <- c ]
|
||||
|
||||
call :: Int -> Board -> Board
|
||||
call n = map (map mark)
|
||||
where mark (Unmarked x) | x == n = Marked x
|
||||
mark x = x
|
||||
|
||||
data Cell = Unmarked Int
|
||||
| Marked Int
|
||||
deriving
|
||||
Show
|
||||
|
||||
hasWon :: Board -> Bool
|
||||
hasWon (Board b) = completed b || completed (transpose b)
|
||||
where
|
||||
completed = any (all isMarked)
|
||||
marked :: Cell -> Bool
|
||||
marked (Marked _) = True
|
||||
marked _ = False
|
||||
|
||||
isMarked :: Cell -> Bool
|
||||
isMarked (Marked _) = True
|
||||
isMarked _ = False
|
||||
solve :: Input -> (Int, Int)
|
||||
solve input = (f input, g input)
|
||||
where wins extr (n,b) = uncurry score $ extr $ bingo n b
|
||||
f = wins head
|
||||
g = wins last
|
||||
|
||||
winBingo :: [Int] -> [Board] -> Int
|
||||
winBingo (n : ns) (b : bs) =
|
||||
if any hasWon r
|
||||
then score n $ head (filter hasWon r)
|
||||
else winBingo ns r
|
||||
where
|
||||
r = iter n (b : bs)
|
||||
|
||||
loseBingo :: [Int] -> [Board] -> Int
|
||||
loseBingo (n : ns) [board]
|
||||
| hasWon b = score n b
|
||||
| otherwise = loseBingo ns [b]
|
||||
where
|
||||
[b] = iter n [board]
|
||||
loseBingo (n : ns) (b : bs) =
|
||||
loseBingo ns (filter (not . hasWon) r)
|
||||
where
|
||||
bingo :: [Int] -> [Board] -> [(Int, Board)]
|
||||
bingo _ [] = []
|
||||
bingo (n : ns) (b : bs) = map (n,) w ++ bingo ns l
|
||||
where (w,l) = partition hasWon r
|
||||
r = iter n (b : bs)
|
||||
|
||||
iter :: Int -> [Board] -> [Board]
|
||||
iter n (b : bs) = callNumber n b : iter n bs
|
||||
iter _ [] = []
|
||||
|
||||
callNumber :: Int -> Board -> Board
|
||||
callNumber n (Board b) = Board (map (map mark) b)
|
||||
where
|
||||
mark (Unmarked x) | x == n = Marked x
|
||||
mark v = v
|
||||
|
||||
score :: Int -> Board -> Int
|
||||
score n (Board b) = n * sum [ x | c <- b, Unmarked x <- c ]
|
||||
iter n (b : bs) = call n b : iter n bs
|
||||
|
|
Loading…
Reference in a new issue