Day 4: Ceres Search
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
You must log in or register to comment.
Uiua
This one was nice. The second part seemed quite daunting at first but wasn’t actually that hard in the end.
Run with example input here
Row ← ⌕ "XMAS" RevRow ← ⌕"SAMX" Sum ← /+/+ Count ← +∩Sum⊃Row RevRow PartOne ← ( &rs ∞ &fo "input-4.txt" ⊜∘≠@\n. ⊙+⟜∩Count⟜⍉ # horizontal and vertical search ⟜(/+⧈(Count⍉≡⬚@ ↻⇡⧻.)4) /+⧈(Count⍉≡⬚@ ↻¯⇡⧻.)4 ++ ) Mask ← °⊚×2⇡5 # Create variations of X-MAS Vars ← ( ["M S" " A " "M S"] ≡♭[∩⟜⍉]≡⇌. Mask ⊏0⊞▽¤ ) PartTwo ← ( &rs ∞ &fo "input-4.txt" ⊜∘≠@\n. ⧈(/+♭⊞≍⊙¤Vars▽Mask♭)3_3 Sum ) &p "Day 4:" &pf "Part 1: " &p PartOne &pf "Part 2: " &p PartTwo
Factor
spoiler
: get-input ( -- rows ) "vocab:aoc-2024/04/input.txt" utf8 file-lines ; : verticals ( rows -- lines ) [ dimension last [0..b) ] keep cols ; : slash-origins ( rows -- coords ) dimension [ first [0..b) [ 0 2array ] map ] [ first2 [ 1 - ] [ 1 (a..b] ] bi* [ 2array ] with map ] bi append ; : backslash-origins ( rows -- coords ) dimension first2 [ [0..b) [ 0 2array ] map ] [ 1 (a..b] [ 0 swap 2array ] map ] bi* append ; : slash ( rows origin -- line ) first2 [ 0 [a..b] ] [ pick dimension last [a..b) ] bi* zip swap matrix-nths ; : backslash ( rows origin -- line ) [ dup dimension ] dip first2 [ over first [a..b) ] [ pick last [a..b) ] bi* zip nip swap matrix-nths ; : slashes ( rows -- lines ) dup slash-origins [ slash ] with map ; : backslashes ( rows -- lines ) dup backslash-origins [ backslash ] with map ; : word-count ( line word -- n ) dupd [ reverse ] dip '[ _ subseq-indices length ] bi@ + ; : part1 ( -- n ) get-input { [ ] [ verticals ] [ slashes ] [ backslashes ] } cleave-array concat [ "XMAS" word-count ] map-sum ; : origin-adistances ( rows origins line-quot: ( rows origin -- line ) -- origin-adistances-assoc ) with zip-with "MAS" "SAM" [ '[ [ _ subseq-indices ] map-values ] ] bi@ bi append harvest-values [ [ 1 + ] map ] map-values ; inline : a-coords ( origin-adistances coord-quot: ( adistance -- row-delta col-delta ) -- coords ) '[ first2 [ @ 2array v+ ] with map ] map-concat ; inline : slash-a-coords ( rows -- coords ) dup slash-origins [ slash ] origin-adistances [ [ 0 swap - ] keep ] a-coords ; : backslash-a-coords ( rows -- coords ) dup backslash-origins [ backslash ] origin-adistances [ dup ] a-coords ; : part2 ( -- n ) get-input [ slash-a-coords ] [ backslash-a-coords ] bi intersect length ;
Better viewed on GitHub.
Haskell
Popular language this year :)
I got embarrassingly stuck on this one trying to be clever with list operations. Then I realized I should just use an array…
import Data.Array.Unboxed (UArray) import Data.Array.Unboxed qualified as A import Data.Bifunctor readInput :: String -> UArray (Int, Int) Char readInput s = let rows = lines s n = length rows in A.listArray ((1, 1), (n, n)) $ concat rows s1 `eq` s2 = s1 == s2 || s1 == reverse s2 part1 arr = length $ filter isXmas $ concatMap lines $ A.indices arr where isXmas ps = all (A.inRange $ A.bounds arr) ps && map (arr A.!) ps `eq` "XMAS" lines p = [take 4 $ iterate (bimap (+ di) (+ dj)) p | (di, dj) <- [(1, 0), (0, 1), (1, 1), (1, -1)]] part2 arr = length $ filter isXmas innerPoints where innerPoints = let ((i1, j1), (i2, j2)) = A.bounds arr in [(i, j) | i <- [i1 + 1 .. i2 - 1], j <- [j1 + 1 .. j2 - 1]] isXmas p = up p `eq` "MAS" && down p `eq` "MAS" up (i, j) = map (arr A.!) [(i + 1, j - 1), (i, j), (i - 1, j + 1)] down (i, j) = map (arr A.!) [(i - 1, j - 1), (i, j), (i + 1, j + 1)] main = do input <- readInput <$> readFile "input04" print $ part1 input print $ part2 input
Uiua
Just part1 for now as I need to walk the dog :-)
[edit] Part 2 now added, and a nicer approach than Part 1 in my opinion, if you’re able to keep that many dimensions straight in your head :-)
[edit 2] Tightened it up a bit more.
Grid ← ⊜∘⊸≠@\n "MMMSXXMASM\nMSAMXMSMSA\nAMXSXMAAMM\nMSAMASMSMX\nXMASAMXAMM\nXXAMMXXAMA\nSMSMSASXSS\nSAXAMASAAA\nMAMMMXMMMM\nMXMXAXMASX" ≡⍉⍉×⇡4¤[1_0 0_1 1_1 1_¯1] # Use core dirs to build sets of 4-offsets. ↯∞_2⇡△ Grid # Get all possible starting points. &p/+♭⊞(+∩(≍"XMAS")⇌.⬚@.⊡:Grid≡+¤) # Part 1. Join the two into a table, use to pick 4-elements, check, count. Diags ← [[¯. 1_1] [¯. 1_¯1]] BothMas ← /×≡(+∩(≍"MS")⇌.)⬚@.⊡≡+Diags¤¤ # True if both diags here are MAS. &p/+≡BothMas⊚="A"⟜¤Grid # Part 2. For all "A"s in grid, check diags, count where good.