]box on
]rows on
Was ON
Was OFF
Isaac Flath
December 2, 2022
]box on
]rows on
Was ON
Was OFF
In this blog post I will supply my solutions to Advent of Code 2022 as I work through them in APL. I don’t expect to keep up with doing them every day, but will work on them as I have time and keep adding to this post.
f ← ,⎕CSV 'day1_input.txt' ⍬4
sums ← {+/¨ (≢¨⍵) ⊆⊢ ⍵} f
part1 ← ⌈/ sums
part2 ← +/ 3↑sums[⍒sums]
'Part 1 Solution : ' part1
'Part 2 Solution : ' part2
┌──────────────────┬─────┐ │Part 1 Solution : │71780│ └──────────────────┴─────┘
┌──────────────────┬──────┐ │Part 2 Solution : │212489│ └──────────────────┴──────┘
Shared Code:
(≢¨f)
: Create a mask of items we can use to separate inventories of each elf(≢¨⍵) ⊆⊢ ⍵
: Use mask to break data into sub-arrays for each elf+/¨ (≢¨⍵) ⊆⊢ ⍵
: Sum inventory of each elfPart 1:
⌈/
: Get maximum value from array created abovePart 2:
sums[⍒sums]
: Sort array in descending order3↑sums[⍒sums]
: Get first (largest) 3 items in array+/ 3↑sums[⍒sums]
: Sum the first (largest) 3 items in arrayf ← ⎕CSV 'day2_input.txt' ⍬4
lookup ← {+/ S[C ⍳ ,⍵]}
C S←↓⍉9 2⍴'A X' 4 'B X' 1 'C X' 7 'A Y' 8 'B Y' 5 'C Y' 2 'A Z' 3 'B Z' 9 'C Z' 6
C
S
part1 ← lookup f
C S←↓⍉9 2⍴'A X' 3 'A Y' 4 'A Z' 8 'B X' 1 'B Y' 5 'B Z' 9 'C X' 2 'C Y' 6 'C Z' 7
C
S
part2 ← lookup f
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐ │A X│B X│C X│A Y│B Y│C Y│A Z│B Z│C Z│ └───┴───┴───┴───┴───┴───┴───┴───┴───┘
4 1 7 8 5 2 3 9 6
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐ │A X│A Y│A Z│B X│B Y│B Z│C X│C Y│C Z│ └───┴───┴───┴───┴───┴───┴───┴───┴───┘
3 4 8 1 5 9 2 6 7
'Part 1 Solution : ' part1
'Part 2 Solution : ' part2
┌──────────────────┬─────┐ │Part 1 Solution : │13446│ └──────────────────┴─────┘
┌──────────────────┬─────┐ │Part 2 Solution : │13509│ └──────────────────┴─────┘
Shared Code:
C ⍳ ,f
: Look up each item in f and find its index location in CS[C ⍳ ,⍵]
: Use indexes to get array of scores{+/ S[C ⍳ ,⍵]}
: Sum arrayPart 1:
Part 2:
f ← (⎕A,⍨⎕C ⎕A)∘⍳¨⊃⎕NGET'day3_input.txt'1
part1 ← +/1↑¨{(2÷⍨⍴¨⍵)(↑∩↓)¨⍵}f
part2 ← +/1↑¨∩/{(3÷⍨≢⍵)3⍴⍵}f
'Part 1 Solution : ' part1
'Part 2 Solution : ' part2
┌──────────────────┬──────┐ │Part 1 Solution : │┌────┐│ │ ││7785││ │ │└────┘│ └──────────────────┴──────┘
┌──────────────────┬──────┐ │Part 2 Solution : │┌────┐│ │ ││2633││ │ │└────┘│ └──────────────────┴──────┘
Shared Code:
⊃⎕NGET'day3_input.txt'1
: Load the data(⎕A,⍨⎕C ⎕A)
: Get alphabet (lower and upper case)∘⍳¨
: Index into each piece of data to find position in alphabetPart1:
⍴¨w
: Get length of each elf’s inventory(2÷⍨⍴¨w)
: Divide by 2 to get half-way point{(2÷⍨⍴¨w) (↑∩↓)¨ ⍵}
: Function to the intersection of the first and last halves of each elf’s inventory1↑¨ {(2÷⍨⍴¨w) (↑∩↓)¨ ⍵} f
: de-dupe by keeping only 1st result for each elf+/1↑¨∩/{(3÷⍨≢⍵)3⍴⍵}f
: SumPart2:
(3÷⍨≢⍵)
: Get number of groups of elves{(3÷⍨≢⍵)3⍴⍵
: Reshape data to be a n_groups x 3 elves matrix∩/{(3÷⍨≢⍵)3⍴⍵}f
: Get the intersection (items that all 3 elves have)1↑¨∩/{(3÷⍨≢⍵)3⍴⍵}f
: de-dupe by keeping only 1st result for each elf+/1↑¨∩/{(3÷⍨≢⍵)3⍴⍵}f
: Sumf ← {⎕csv⍠'Separator' '-'⊢⍵⍬4}¨↓⍉⎕csv'day4_input.txt'
c1 c2 c3 c4 ← ↓⍉⊃,/f
fn ← {a1 a2←⍺ ⋄ w1 w2←⍵ ⋄ a1≤w1 ∧ a2≥w2}
part1 ← +/ (c1 c2 fn c3 c4) ∨ c3 c4 fn c1 c2
part2 ← +/ (c1 c2 fn c3 c3) ∨ c3 c4 fn c1 c1
+/c1 c2 fn c3 c4
+/c3 c4 fn c1 c2
293
333
'Part 1 Solution : ' part1
'Part 2 Solution : ' part2
┌──────────────────┬───┐ │Part 1 Solution : │599│ └──────────────────┴───┘
┌──────────────────┬───┐ │Part 2 Solution : │928│ └──────────────────┴───┘
Shared Code:
Read File
⎕csv'day4_input.txt' ⍬4
: Read CSV file
↓⍉⎕csv'day4_input.txt'
Transpose and put into format for processing
{⎕csv⍠'Separator' '-'⊢⍵⍬4}¨↓⍉⎕csv'day4_input.txt'
: Process each column as a nested csv with -
as the separator to split out start/end numbers
⊃,/{⎕csv⍠'Separator' '-'⊢⍵⍬4}¨↓⍉5↑⎕csv'day4_input.txt'
: Convert nested arrays into flat 2d matrix
↓⍉⊃,/{⎕csv⍠'Separator' '-'⊢⍵⍬4}¨↓⍉5↑⎕csv'day4_input.txt'
: Reformat into column vectors for destructured assignment
Format Matrix
⊃,/f
: Convert nested arrays into flat 2d matrix↓⍉⊃,/f
: Create separate column vectors for destructured assignmentBoolean logic
a1 a2 ← ⍺ ⋄ w1 w2 ← ⍵
: Destructured assignment to split out function arguments(a1 ≤ w1 ∧ a2 ≥ w2)
: Boolean logic for problemPart 1:
c1 c2 fn c3 c4
: Does the 1st elf’s assignment fully enclose the 2nd elf’s assignment?c3 c4 fn c1 c2
: Does the 2nd elf’s assignment fully enclose the 1st elf’s assignment?(c1 c2 fn c3 c4) ∨ c3 c4 fn c1 c2
: Combine with or
logic+/ (c1 c2 fn c3 c4) ∨ c3 c4 fn c1 c2
: Sum booleans to get part 1 solutionPart 2:
c1 c2 fn c3 c3
: Does the 1st elf’s assignment enclose the 2nd elf’s lowest assignment?c3 c4 fn c1 c1
: Does the 2nd elf’s assignment enclose the 1st elf’s lowest assignment?(c1 c2 fn c3 c3) ∨ c3 c4 fn c1 c1
: Combine with or
logic+/ (c1 c2 fn c3 c3) ∨ c3 c4 fn c1 c1
: Sum booleans to get part 2 solutionboard moves ← (∊~0=⍴¨f)⊆(f←⊃⎕NGET'day5_input.txt'1)
moves ← ⌽↓(6⍴0 1)/⎕csv⍠'Separator' ' '⊢moves⍬4
board ← ¯1↓⎕csv⍠'Widths' ((8⍴4),3)⊢board⍬4
board ← ' '∘(1↓,⊢⍤/⍨1(⊢∨⌽)0,≠)¨↓⍉⊃¨1↓¨board
step ← {(move from to)←⍺ ⋄ ((⍺⍺ move↑⊃⍵[from])∘,¨@to)(move∘↓¨@from)⍵}
⎕ ← 'part 1: ',⊃¨⊃ ⌽step/moves,⊂board
⎕ ← 'part 2: ',⊃¨⊃ ⊣step/moves,⊂board
part 1: JRVNHHCSJ
part 2: GNFBSBJLH
Shared Code:
File Processing
(f←⊃⎕NGET'day5_input.txt'1)
: Read file(∊~0=⍴¨f)
Create boolean mask indicating where the board and moves section split is(∊~0=⍴¨f)⊆(f←⊃⎕NGET'day5_input.txt'1)
: Use boolean mask to partition board and moves to separate variablesClean Moves Input
⎕csv⍠'Separator' ' '⊢moves⍬4
: Process moves data as a CSV with space as separator(6⍴0 1)/⎕csv⍠'Separator' ' '⊢moves⍬4
: Remove the non-numeric columns with words in them↓(6⍴0 1)/⎕csv⍠'Separator' ' '⊢moves⍬4
: Change to vector of columns for processing⌽↓(6⍴0 1)/⎕csv⍠'Separator' ' '⊢moves⍬4
: Reverse so we can process as a reductionClean Board Input
⊃¨1↓¨board
: Strip brackets and unnest matrix↓⍉⊃¨1↓¨board
: Format into vector of columns for processing' '∘(1↓,⊢⍤/⍨1(⊢∨⌽)0,≠)↓⍉⊃¨1↓¨board
: Remove leading, trailing and duplicate blanksStep Function:
(move from to)←⍺
: Break numeric arguments for move instructions into separate variables⍵[from]
: Get the items in the “from” locationmove↑⊃⍵[from]
: Take only the move quantity from the items in the from location(⍺⍺ move↑⊃⍵[from])
: Apply a function to the items in the from location before doing anything else(⍺⍺ move↑⊃⍵[from])∘,¨@to)
: Add the items in the from
location to the to
location(move∘↓¨@from)
: Drop the items being moved from the from location{(move from to)←⍺ ⋄ ((⍺⍺ move↑⊃⍵[from])∘,¨@to)(move∘↓¨@from)⍵}
: Combine for function definitionPart 1:
⌽ step/moves,⊂board
: Call the step function using a reduction across the moves. When moving the boxes reverse the lists so it simulates moving one box at a time.⊃¨⊃ ⌽ step/moves,⊂board
: Take only the first element in each cellPart 2:
⌽ step/moves,⊂board
: Call the step function using a reduction across the moves. When moving the boxes do not reverse (identity function) so it simulates moving a full stack at a time.⊃¨⊃ ⌽ step/moves,⊂board
: Take only the first element in each cellf← ∊⎕CSV'day6_input.txt'
part1 part2 ← {¯1+⍵+⍵⍳⍨≢¨⍵∪/f}¨ 4 14
'Part 1 Solution : ' part1
'Part 2 Solution : ' part2
┌──────────────────┬────┐ │Part 1 Solution : │1760│ └──────────────────┴────┘
┌──────────────────┬────┐ │Part 2 Solution : │2974│ └──────────────────┴────┘
Shared Code:
f← ∊⎕CSV'day6_input.txt'
: Read data file∪/f
: Get unique characters from input data⍵∪/f
: Instead of unique characters from input data, unique characters in each group of ⍵
characters from input data.≢¨⍵∪/f
: Get number of unique characters are in each group⍵⍳⍨≢¨⍵∪/f
: Look for the first group where the number of unique characters is equal to ⍵
¯1+⍵+⍵⍳⍨≢¨⍵∪/f
: Get ending index of group instead of starting location of groupPart 1:
Part 2:
I have decided not to finish advent of code in APL for now. There are several reasons for this:
The time it takes to solve each in APL is getting much longer. There are two main things that are super common in advent of code that APL does not handle well. This was a good learning experience.
APL seems to be clunky at handling data cleaning, which many of these challenges from here on out include.
APL seems to handle flat (ie numeric) arrays extremely well. Nested arrays such as text are not as clean. Many of the problems require text data as well.
This is useful to know. Part of the reason I was interested in working on this is APL was to understand what I would and would not use the language for. Many proponents of APL use it for almost everything - that’s not I think is best in my opinion.
I still plan to use APL as a tool for thought when reading and implement research papers. But once I understand the contents of the paper I will move to another language to apply the concept to real world data.