Day 21 - refactoring for clarity and conciseness

This commit is contained in:
Jonathan Chan 2017-12-21 13:58:44 -08:00
parent 3d8c035561
commit ed514f1519
2 changed files with 17 additions and 33 deletions

48
21.hs
View File

@ -1,11 +1,11 @@
import Data.List (transpose) import Data.List (transpose)
import Data.List.Split (splitOn, chunksOf) import Data.List.Split (splitOn, chunksOf)
import Data.Map.Strict (Map, insert, empty, (!)) import Data.HashMap (Map, insert, empty, (!))
type Rules = Map String String type Rules = Map String String
squareRoot = floor . sqrt . fromIntegral squareRoot = floor . sqrt . fromIntegral
validTwos = [ validTwos = [
[0..3], [0..3],
[0, 2, 1, 3], [0, 2, 1, 3],
[1, 0, 3, 2], [1, 0, 3, 2],
@ -28,50 +28,34 @@ validThrees = [
] ]
valids :: String -> [String] valids :: String -> [String]
valids str = case length str of valids str = map (map (str !!)) $ case length str of
4 -> map (map (str !!)) validTwos 4 -> validTwos
9 -> map (map (str !!)) validThrees 9 -> validThrees
row :: Int -> Int -> String -> [String]
row multiple size str =
map concat . transpose . map (chunksOf multiple) . chunksOf size $ str
derow :: Int -> [String] -> String
derow multiple sbsq =
concat . concat . transpose . map (chunksOf multiple) $ sbsq
chunk :: String -> [[String]] chunk :: String -> [[String]]
chunk str = chunk str =
let size = squareRoot $ length str let size = squareRoot $ length str
multiple = if even size then 2 else 3 multiple = if even size then 2 else 3
rows = chunksOf (size * multiple) str makeRow = map concat . transpose . map (chunksOf multiple) . chunksOf size
in map (row multiple size) rows in map makeRow $ chunksOf (size * multiple) str
dechunk :: [[String]] -> String dechunk :: [[String]] -> String
dechunk rows = dechunk rows =
let multiple = squareRoot . length . head . head $ rows let multiple = squareRoot . length . head . head $ rows
in concat $ map (derow multiple) rows unmakeRow = concat . concat . transpose . map (chunksOf multiple)
in concat $ map unmakeRow rows
enhance :: Rules -> String -> String enhance :: Rules -> String -> String
enhance rules grid = enhance rules = dechunk . map (map (rules !)) . chunk
dechunk . map (map (rules !)) . chunk $ grid
addRules :: [String] -> String -> Rules -> Rules
addRules keys value rules = foldr (\key currRules -> insert key value currRules) rules keys
countOn :: String -> Int
countOn grids = length . filter (== '#') $ grids
parseLine :: String -> Rules -> Rules parseLine :: String -> Rules -> Rules
parseLine line rules = parseLine line =
let inputStr : outputStr : [] = splitOn " => " line let input : output : [] = splitOn " => " $ filter (/= '/') line
input = splitOn "/" inputStr in flip (foldr (\key currRules -> insert key output currRules)) $ valids input
output = splitOn "/" outputStr
in addRules (valids $ concat input) (concat output) rules
main :: IO () main :: IO ()
main = do main = do
rules <- foldr parseLine empty . lines <$> readFile "21.txt" rules <- foldr parseLine empty . lines <$> readFile "21.txt"
let iterations = map countOn $ iterate (enhance rules) ".#...####" let iterations = map (length . filter (=='#')) $ iterate (enhance rules) ".#...####"
print $ iterations !! 5 print $ iterations !! 5
print $ iterations !! 18 print $ iterations !! 18

2
21.txt
View File

@ -105,4 +105,4 @@
#.#/###/#.# => ##.#/.###/..##/.#.. #.#/###/#.# => ##.#/.###/..##/.#..
###/###/#.# => .#../.###/..#./#... ###/###/#.# => .#../.###/..#./#...
###/#.#/### => ###./####/.###/#.## ###/#.#/### => ###./####/.###/#.##
###/###/### => #..#/.#../#.../...# ###/###/### => #..#/.#../#.../...#