Skip to content

Instantly share code, notes, and snippets.

@justin2004
Last active December 4, 2024 01:45
Show Gist options
  • Select an option

  • Save justin2004/2396e280f68946cb3475ca0c1fe263d5 to your computer and use it in GitHub Desktop.

Select an option

Save justin2004/2396e280f68946cb3475ca0c1fe263d5 to your computer and use it in GitHub Desktop.
Advent of Code Day 1 Part 1 using APL

Advent of Code 2024 Day 1 Part 1

Using apl_in_the_shell which makes the APL language command line friendly.

Full Solution

The answer using the sample data is 11.

Here is the full solution:

apl '{+/|-⌿{⍵[⍋⍵]}⍤1⍉↑⍎¨⍵}'  day1.input.sample
11

Explanation

# Let's first look at the sample input data
cat day1.input.sample
3   4
4   3
2   5
1   3
3   9
3   3

# apl_in_the_shell (the `apl` command) handles the I/O so APL can feel like a command shell friendly language
# Let's just run the identity function {⍵} to see how `apl` sees the data
apl -r disp '{⍵}' day1.input.sample
┌─────┬─────┬─────┬─────┬─────┬─────┐
│3   4│4   3│2   5│1   3│3   9│3   3│
└─────┴─────┴─────┴─────┴─────┴─────┘
# Notice we got a vector where each item is a vector of characters

# NEXT we want those numeral characters to be numbers
apl -r disp '{⍎¨⍵}' day1.input.sample
┌───┬───┬───┬───┬───┬───┐
│3 4│4 3│2 5│1 3│3 9│3 3│
└───┴───┴───┴───┴───┴───┘
# We can execute ⍎ each ¨ vector of characters which gives us numeric vectors
# (since when you type numerals into the interpreter they get evaluated into numbers)

# NEXT since we want to sort the columns, let's turn this vector into a 2d matrix and put the columns along the first axis
apl -r disp '{⍉↑⍎¨⍵}' day1.input.sample
3 4 2 1 3 3
4 3 5 3 9 3
# We turn the vector (of vectors) into a matrix with ↑ and then transpose ⍉ it

# NEXT we can numerically sort the rows
apl -r disp '{{⍵[⍋⍵]}⍤1⍉↑⍎¨⍵}' day1.input.sample
1 2 3 3 3 4
3 3 3 4 5 9
# We applied the sort idiom {⍵[⍋⍵]} in a rank ⍤ 1 manner
# (against each rank 1 cell along the first axis (in this case (the rows))

# NEXT we have set ourselves up for this easy finishing move
# We need the difference between the first and second row... which we can do with a minus reduction -⌿ then take the absolute value |
apl '{|-⌿{⍵[⍋⍵]}⍤1⍉↑⍎¨⍵}'  day1.input.sample
2 1 0 1 2 5

# FINALLY add up all the differences with a plus reduction
apl '{+/|-⌿{⍵[⍋⍵]}⍤1⍉↑⍎¨⍵}'  day1.input.sample
11

Histogram of Tokens in Solution

text	count	percent	histogram
	3	14.29	■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
{	2	9.52	■■■■■■■■■■■■■■■■■■■■■■■■■
}	2	9.52	■■■■■■■■■■■■■■■■■■■■■■■■■
+	1	4.76	■■■■■■■■■■■■
/	1	4.76	■■■■■■■■■■■■
|	1	4.76	■■■■■■■■■■■■
-	1	4.76	■■■■■■■■■■■■
	1	4.76	■■■■■■■■■■■■
[	1	4.76	■■■■■■■■■■■■
	1	4.76	■■■■■■■■■■■■
]	1	4.76	■■■■■■■■■■■■
	1	4.76	■■■■■■■■■■■■
1	1	4.76	■■■■■■■■■■■■
	1	4.76	■■■■■■■■■■■■
	1	4.76	■■■■■■■■■■■■
	1	4.76	■■■■■■■■■■■■
¨	1	4.76	■■■■■■■■■■■■

Using APL: The Feeling

I've blogged about how it feels to use APL here: https://github.com/justin2004/weblog/tree/master/using_apl

@justin2004
Copy link
Author

compare to:
https://www.reddit.com/r/adventofcode/comments/1h5teio/2024_day_1_rust_tutorial_the_rusty_way_to/

fn part1() -> i32 {
    let f: File = std::fs::File::open(<FILE_PATH>).unwrap();
    let r: BufReader<File> = BufReader::new(f);

    let (mut firsts, mut seconds) = r
        .lines()
        .map(|line| {
            let vec = line
                .unwrap()
                .split_whitespace()
                .map(|s| s.parse::<u32>().unwrap())
                .collect::<Vec<u32>>();
            (
                vec.get(0).unwrap().to_owned(),
                vec.get(1).unwrap().to_owned(),
            )
        })
        .collect::<(Vec<u32>, Vec<u32>)>();

    firsts.sort_unstable();
    seconds.sort_unstable();

    let res: i32 = firsts
        .into_iter()
        .zip(seconds.into_iter())
        .map(|(first, second)| (second as i32 - first as i32).abs())
        .sum();
    res
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment