Skip to content

Commit 8662c9e

Browse files
committed
1 parent 0736502 commit 8662c9e

File tree

2 files changed

+39
-50
lines changed

2 files changed

+39
-50
lines changed

13.hs

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,35 @@
1-
import Control.Applicative ((<|>), asum)
1+
import Control.Applicative ((<|>))
22
import Control.Arrow ((&&&))
3-
import Data.Bits (complementBit)
4-
import Data.List (transpose)
3+
import Data.List (transpose, find)
54
import Data.Maybe (fromJust)
6-
import Numeric (readBin)
75

86
main :: IO ()
97
main = interact $ (++ "\n") . show . (p1 &&& p2) . parse
108

11-
type Pattern = ([Int], [Int])
9+
type Pattern = [String]
1210

1311
parse :: String -> [Pattern]
1412
parse = from . lines
1513
where
1614
from [] = []
17-
from ls = let (pl, rest) = span (/= "") ls in pat pl : from (drop 1 rest)
18-
pat = ints &&& ints . transpose
19-
ints = map int
20-
int s = case readBin $ map (\c -> if c == '.' then '0' else '1') s of
21-
[(i, _)] -> i
22-
23-
rIndex :: [Int] -> Maybe Int
24-
rIndex = asum . rIndices
25-
26-
rIndices :: [Int] -> [Maybe Int]
27-
rIndices xs = map f [1..length xs - 1]
28-
where f i = let (a, b) = splitAt i xs
29-
j = min (length a) (length b)
30-
in if take j (reverse a) == take j b then Just i else Nothing
31-
32-
p1 :: [Pattern] -> Int
33-
p1 = sum . map (fromJust . ri)
34-
where ri (rows, cols) = (*100) <$> rIndex rows <|> rIndex cols
35-
36-
p2 :: [Pattern] -> Int
37-
p2 = sum . map smudge
38-
39-
smudge :: Pattern -> Int
40-
smudge (rows, cols) = fromJust $ (*100) <$> rf <|> rc
41-
where
42-
or = rIndex rows
43-
oc = rIndex cols
44-
rf = asum $ filter (/= or) $ concatMap rIndices rowVariants
45-
rc = asum $ filter (/= oc) $ concatMap rIndices colVariants
46-
rowVariants = [flip y x rows | y <- [0..length rows - 1], x <- [0..length cols - 1]]
47-
colVariants = [flip x y cols | y <- [0..length rows - 1], x <- [0..length cols - 1]]
48-
flip y x ns = zipWith (\i r -> if i == y then flipBit x r else r) [0..] ns
49-
flipBit x n = n `complementBit` x
15+
from ls = let (pl, rest) = span (/= "") ls in pl : from (drop 1 rest)
16+
17+
-- For all splits, find the differences across the reflection line. For part 1,
18+
-- where the mirroring is perfect, the won't be any difference. For part 2,
19+
-- where there's a single smidge, there'll be exactly one difference.
20+
21+
reflectionLine :: Int -> [String] -> Maybe Int
22+
reflectionLine dx xs = find f [1..length xs - 1]
23+
where f i = let (a, b) = splitAt i xs in difference (reverse a) b == dx
24+
25+
difference :: [String] -> [String] -> Int
26+
difference xs = sum . zipWith rd xs
27+
where rd r = sum . zipWith (\c1 c2 -> if c1 == c2 then 0 else 1) r
28+
29+
solve :: Int -> [Pattern] -> Int
30+
solve dx = sum . map (fromJust . f)
31+
where f p = (*100) <$> reflectionLine dx p <|> reflectionLine dx (transpose p)
32+
33+
p1, p2 :: [Pattern] -> Int
34+
p1 = solve 0
35+
p2 = solve 1

13.string.hs renamed to 13.ints.hs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
11
import Control.Applicative ((<|>), asum)
22
import Control.Arrow ((&&&))
3+
import Data.Bits (complementBit)
34
import Data.List (transpose)
45
import Data.Maybe (fromJust)
5-
6-
-- A variant of 13.hs that directly uses the string representation instead of
7-
-- first converting them to their bitwise int representations. Somewhat
8-
-- surprisingly, this is not slower. There is a slight difference when
9-
-- optimized: under -O2 the bitwise representation version is slightly faster.
6+
import Numeric (readBin)
107

118
main :: IO ()
129
main = interact $ (++ "\n") . show . (p1 &&& p2) . parse
1310

14-
type Pattern = ([String], [String])
11+
-- A variant of 13.hs that uses more explicit reflection testing. Additionally,
12+
-- it also uses an integer representation, although that doesn't make too big of
13+
-- a difference in runtime (compared to this same code, but using the strings
14+
-- themselves for various checks below).
15+
16+
type Pattern = ([Int], [Int])
1517

1618
parse :: String -> [Pattern]
1719
parse = from . lines
1820
where
1921
from [] = []
2022
from ls = let (pl, rest) = span (/= "") ls in pat pl : from (drop 1 rest)
21-
pat = id &&& transpose
23+
pat = ints &&& ints . transpose
24+
ints = map int
25+
int s = case readBin $ map (\c -> if c == '.' then '0' else '1') s of
26+
[(i, _)] -> i
2227

23-
rIndex :: [String] -> Maybe Int
28+
rIndex :: [Int] -> Maybe Int
2429
rIndex = asum . rIndices
2530

26-
rIndices :: [String] -> [Maybe Int]
31+
rIndices :: [Int] -> [Maybe Int]
2732
rIndices xs = map f [1..length xs - 1]
2833
where f i = let (a, b) = splitAt i xs
2934
j = min (length a) (length b)
@@ -46,6 +51,4 @@ smudge (rows, cols) = fromJust $ (*100) <$> rf <|> rc
4651
rowVariants = [flip y x rows | y <- [0..length rows - 1], x <- [0..length cols - 1]]
4752
colVariants = [flip x y cols | y <- [0..length rows - 1], x <- [0..length cols - 1]]
4853
flip y x ns = zipWith (\i r -> if i == y then flipBit x r else r) [0..] ns
49-
flipBit x s = let (a, b:c) = splitAt x s in a ++ [flipC b] ++ c
50-
flipC '.' = '#'
51-
flipC '#' = '.'
54+
flipBit x n = n `complementBit` x

0 commit comments

Comments
 (0)