Compare commits

...

3 commits

Author SHA1 Message Date
46fb1147fb
day11/python: optimizations 2020-12-13 18:32:24 +01:00
4b5d09f5df
test.sh: ignore all example* files 2020-12-13 18:32:23 +01:00
73b16b4b0f
day13: add haskell solution 2020-12-13 18:32:23 +01:00
7 changed files with 61 additions and 12 deletions

2
.gitignore vendored
View file

@ -1 +1 @@
example.txt
example*

View file

@ -17,5 +17,6 @@ https://adventofcode.com/2020/
| 9 | | `**` | |
|10 | | `**` | |
|11 | `**` | | |
|13 | | `**` | |
`test.sh` can be used to run all solutions and automatically compares them to (my) puzzle inputs and the expected outputs.

2
data/day13.expected Normal file
View file

@ -0,0 +1,2 @@
2215
1058443396696792

2
data/day13.input Normal file
View file

@ -0,0 +1,2 @@
1005162
19,x,x,x,x,x,x,x,x,41,x,x,x,x,x,x,x,x,x,823,x,x,x,x,x,x,x,23,x,x,x,x,x,x,x,x,17,x,x,x,x,x,x,x,x,x,x,x,29,x,443,x,x,x,x,x,37,x,x,x,x,x,x,13

View file

@ -57,20 +57,17 @@ class Layout:
return len(new_tiles) != 0
def _find_neighbour(self, row: int, col: int, direction: Tuple[int, int]) -> Optional[Tuple[int, int]]:
curr_row = row
curr_col = col
steps = 0
while self.max_neighbour_steps is None or steps < self.max_neighbour_steps:
curr_row += direction[0]
curr_col += direction[1]
if curr_row < 0 or curr_row >= self.num_rows:
row += direction[0]
col += direction[1]
if row < 0 or row >= self.num_rows:
break
if curr_col < 0 or curr_col >= self.num_cols:
if col < 0 or col >= self.num_cols:
break
if self.get(curr_row, curr_col) != Tile.FLOOR:
return (curr_row, curr_col)
if self.get(row, col) != Tile.FLOOR:
return (row, col)
steps += 1
return None
@ -89,7 +86,7 @@ class Layout:
yield self.get(nrow, ncol)
def count_neighbours(self, row: int, col: int) -> int:
return len([tile for tile in self.neighbours(row, col) if tile == Tile.OCCUPIED])
return sum(1 for tile in self.neighbours(row, col) if tile == Tile.OCCUPIED)
def run(layout: Layout) -> int:

47
day13/day13.hs Normal file
View file

@ -0,0 +1,47 @@
module Day13 where
import AoC
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Ord
import Data.Tuple
-- | inverse integer modulus, "remainder until the next multiple of d"
--
-- @(n + n `'invMod'` d) `'mod'` d == 0@
invMod :: Integral a => a -> a -> a
invMod n d | r == 0 = 0
| otherwise = d - r
where r = n `mod` d
-- | @'combineRemainders' (r1, d1) (r2, d2) = (r3, d3)@ combines a relation of the form
--
-- @
-- x = r1 (mod d1)
-- x = r2 (mod d2)
-- @
--
-- into a single relation
--
-- @
-- x = r3 (mod d3)
-- @
--
-- @d1@ should be larger than @d2@ for better performance.
combineRemainders :: (Integral a) => (a, a) -> (a, a) -> (a, a)
combineRemainders (r1, d1) (r2, d2) = (fromJust . find (\x -> x `mod` d2 == r2) $ [r1,d1+r1..], d1*d2)
part1 :: Int -> [Int] -> Int
part1 arr = uncurry (*) . minimumBy (comparing snd) . map (toSnd $ invMod arr)
where toSnd f x = (x, f x)
part2 :: [Maybe Int] -> Int
part2 = fst . foldl1 combineRemainders . map (\(r, d) -> (r `invMod` d, d)) . catMaybes . map sequence . enumerate 0
where enumerate start (x:xs) = (start, x) : enumerate (succ start) xs
enumerate _ [] = []
main = runAoC (intoTuple . map (map (fmap read . justIf (/="x")) . splitOn ",") . lines) (uncurry part1 . fmap catMaybes) (part2 . snd)
where intoTuple [[Just x], y] = (x, y)
justIf p x = if p x then Just x else Nothing

View file

@ -34,7 +34,7 @@ for day in day*; do
echo -n "$solution... "
case "${solution##*/}" in
example.txt|.*)
example*|.*)
echo SKIP
continue
esac