-
• #227
Is today the beginnings of our assembly-like language then?
-
• #228
Day 2 done without too much pain once I got familiar with techniques for parsing the input.
https://gist.github.com/dmckennell/86ac3155367122502be2643f4b021edfNice to see such a broad range of languages this year. Enjoying reading through and understanding the approaches of others.
-
• #229
For day 1, there's quite an elegant solution using
zipWith
. Note that you don't actually have to chunk things up, as pointed out, since the windows overlap you only ever have to care about the start and end points (which can be achieved by zipping together the input list and the input list offset by the window length):module Main where inp :: String -> IO [Int] inp path = do c <- readFile path return $ map read (lines c) solve :: Int -> [Int] -> Int solve n xs = length . filter id $ zipWith (<) xs (drop n xs) main :: IO () main = do vals <- inp "day01.input" print $ solve 1 vals print $ solve 3 vals
FWIW, an idiomatic way of chunking a list would be:
import Data.List (tails) chunk :: Int -> [a] -> [[a]] chunk n xs = foldr (zipWith (:)) (repeat []) (take n (tails xs))
Why does this work? Suppose you have two lists
[1, 2, 3, 4]
and[2, 3, 4]
. If you zip them together you get[(1, 2), (2, 3), (3, 4)]
which is chunking by two.tails
produces all tails of a listtails [1, 2, 3, 4] = [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4], []]
. So if wetake n
we will get the right inputs for zipping together to produce a window of length n. We can't usezip
though, because that needs two lists. Sofoldr (zipWith (:)) (repeat [])
is generalisingzip
ton
inputs and producing a list of lists as outputs (rather than a list of tuples)... -
• #231
Ahhh very nice. Thanks for the explanation!
-
• #232
Here's my haskell part 2. I noticed you had a comment where you had an issue using
foldr
, but things work withfoldl
. The reason for this is thatfoldr
is for a right-associative operator. But the operator as defined in the problem (for part 2) is left associative (if you think about this, it's because you're starting at the beginning of the list and updating the depth based on the current aim). So you can either dofoldr op ... (reverse instructions)
orfoldl op ... instructions
. If you're then doingfoldl
, it's better to usefoldl'
(fromData.Foldable
) as you're more efficient since you collapse as you go, rather than consing all the computation at once. Sincefoldl
doesn't work on infinite lists anyway, this is always safe to do.module Main where import Data.Foldable (foldl') data Move = F Int | D Int deriving (Eq, Show) parse :: String -> Maybe Move parse ('f':xs) = Just . F $ read (drop 7 xs) parse ('d':xs) = Just . D $ read (drop 4 xs) parse ('u':xs) = Just . D $ -read (drop 2 xs) parse _ = Nothing inp :: String -> IO (Maybe [Move]) inp path = do c <- readFile path return $ mapM parse (lines c) part1 :: Maybe [Move] -> Int part1 Nothing = 0 part1 (Just xs) = h * d where (h, d) = foldl' (\(h, d) x -> case x of F n -> (h + n, d) D n -> (h, d + n)) (0, 0) xs part2 :: Maybe [Move] -> Int part2 Nothing = 0 part2 (Just xs) = h * d where (h, d, _) = foldl' (\(h, d, a) x -> case x of F n -> (h + n, d + (a * n), a) D n -> (h, d, a + n)) (0, 0, 0) xs main :: IO () main = do instructions <- inp "../inputs/2021/day02.input" print $ part1 instructions print $ part2 instructions
-
• #233
Thanks @Greenbank appreciate the feedback.
So obvious when you explain it like that!
Edit: Day 2 now done.
-
• #234
Bit more of a challenge to produce something nice and readable today... (with Python lists of lists anyway)
-
• #235
Just finished part 1 in python:
https://github.com/tango130/AoC_2021/blob/8e85120637adb7a80b2edd77b288c32e0654fb11/Day3_Part1.py
-
• #236
Stupid lack of error tracking meant going round in circles. Realised it made one of my binary numbers for Day 3 Part 2 off by one 🤦♂️ That was a frustrating runaround!
-
• #237
Hehe
-
• #238
🤣
-
• #239
Took me longer than I would have liked today. Pushing Python solutions to GitHub:
https://github.com/willjrh/Advent-of-code-21 -
• #240
def bin2num(binary): # print([x * 2 ** ind for ind, x in enumerate(reversed(binary))]) return np.sum([x * 2 ** ind for ind, x in enumerate(reversed(binary))])
You can probably make use of something like
int("".join(x), base=2)
-
• #241
Thanks, I actually did notice this from looking at other solutions!
Now starting day 4, I will have a little more time to think about a nice solution today, without that awful burden of work. -
• #242
For the first time ever, I actually had the solution to the second part after completing the first part. Probably just means I overdid part 1 though.
-
• #243
I got fed up trying to make day 3 nice: https://github.com/rhowe/aoc/blob/main/03/3part2.jsonnet
-
• #244
Bit of a bastard today. Here's my solution - didn't spend any time making it nice and screwed myself a bit with the hash method because I forgot you had to keep track of the unmarked numbers
-
• #245
I did it broadly the way you did first time round, and then thought harder about how to check for when a card wins, and did this: https://gist.github.com/wence-/500e1bc4633192ac6fee67433aedd974#file-day04-py
-
• #246
Brain isn't working today. Not sure I cba with part 2: https://github.com/rhowe/aoc/blob/main/04/4part1.jsonnet
-
• #247
Very clever!
I was going to do a double hashmap (hash x to point to all boards containing x, then for each board containing x, hash x to position of x in board y) to get it quicker if necessary, so I don't have to check if each board contains x, then that'd probably be as quick as it ought to be O(n) lookups I think? But the hashmap can't match your min/max thing to find time to solve - I always have to check the whole row/column.
-
• #248
I did it a similar way (after an initial naive version), although I only solve each board once and keep track of the minimum/maximum (and correpsonding 'scores') as I read in each board.
Thinking was this:-
- Read in the numbers and have a map between position and number (and vice versa)
- You have to solve every board to know whether it will be the first or the last
- A board is just 10 sets of 5 values corresponding to the 5 rows and 5 columns, plus the full set of numbers in that board (which you'll need to
- In the 10 sets of 5 numbers, instead of storing the actual numbers, store the positions that they appear in the list (through the map created when reading in the list of input numbers)
- In each of these 10 sets of 5 numbers, find the maximum of these
- And then the 'solve time' for this board is the minimum of these 10 maximum values
- You can then loop through the set of all 25 numbers in the board and sum the values which appear after the 'solve time' for this board (e.g. the sum of the uncalled numbers)
- Keep track of the minimum and maximum 'solve time' as I process the boards (and keep the corresponding final scores) - output these values at the end
- Read in the numbers and have a map between position and number (and vice versa)
-
• #249
Today's part 2 was quite easy to anticipate.
https://gist.github.com/dmckennell/a1ecf3f1366c7feabad19051eb521c3b -
• #250
Yup, here's how I did it:-
https://gist.github.com/alexgreenbank/ddda4609eff0ac434fa51a5f71567f5f
decided to actually do it this year. doing it in haskell to brush up after 2 years of almost exclusively doing js/ts and python. posting results in https://github.com/ZooeyMiller/advent-of-code-2021
day1 code is messy as heck sadly...