Day 25: Code Chronicle
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
Haskell
A total inability to write code correctly today slowed me down a bit, but I got there in the end. Merry Christmas, everyone <3
import Data.Either
import Data.List
import Data.List.Split
readInput = partitionEithers . map readEntry . splitOn [""] . lines
where
readEntry ls =
(if head (head ls) == '#' then Left else Right)
. map (length . head . group)
$ transpose ls
main = do
(locks, keys) <- readInput <$> readFile "input25"
print . length $ filter (and . uncurry (zipWith (<=))) ((,) <$> locks <*> keys)
C
Merry Christmas everyone!
Code
#include "common.h"
int
main(int argc, char **argv)
{
static char buf[7];
static short h[500][5]; /* heights */
static short iskey[500];
int p1=0, nh=0, i,j,k;
if (argc > 1)
DISCARD(freopen(argv[1], "r", stdin));
for (nh=0; !feof(stdin) && !ferror(stdin); nh++) {
assert(nh < (int)LEN(h));
for (i=0; i<7; i++) {
fgets(buf, 7, stdin);
if (i==0)
iskey[nh] = buf[0] == '#';
for (j=0; j<5; j++)
h[nh][j] += buf[j] == '#';
}
/* skip empty line */
fgets(buf, 7, stdin);
}
for (i=0; i<nh; i++)
for (j=0; j<nh; j++)
if (iskey[i] && !iskey[j]) {
for (k=0; k<5 && h[i][k] + h[j][k] <= 7; k++) ;
p1 += k == 5;
}
printf("25: %d\n", p1);
return 0;
}
https://codeberg.org/sjmulder/aoc/src/branch/master/2024/c/day25.c
Made the 1 second challenge with most of it to spare! π
$ time bmake bench
day01 0:00.00 1912 Kb 0+88 faults
day02 0:00.00 1992 Kb 0+91 faults
day03 0:00.00 1920 Kb 0+93 faults
day04 0:00.00 1912 Kb 0+90 faults
day05 0:00.00 2156 Kb 0+91 faults
day06 0:00.03 1972 Kb 0+100 faults
day07 0:00.06 1892 Kb 0+89 faults
day08 0:00.00 1772 Kb 0+87 faults
day09 0:00.02 2024 Kb 0+137 faults
day10 0:00.00 1876 Kb 0+87 faults
day11 0:00.00 6924 Kb 0+3412 faults
day12 0:00.00 1952 Kb 0+103 faults
day13 0:00.00 1908 Kb 0+88 faults
day14 0:00.05 1944 Kb 0+92 faults
day15 0:00.00 2040 Kb 0+89 faults
day16 0:00.03 2020 Kb 0+250 faults
day17 0:00.00 1896 Kb 0+88 faults
day18 0:00.00 1952 Kb 0+107 faults
day19 0:00.01 1904 Kb 0+91 faults
day20 0:00.01 2672 Kb 0+325 faults
day21 0:00.00 1804 Kb 0+86 faults
day22 0:00.03 2528 Kb 0+371 faults
day23 0:00.02 2064 Kb 0+152 faults
day24 0:00.00 1844 Kb 0+89 faults
day25 0:00.00 1788 Kb 0+89 faults
real 0m0,359s
Javascript
Spent 10 minutes debugging my solution until I reread and found out they wanted the number of keys that fit, not the ones that overlapped. Reading comprehension is not it tonight.
const [locks, keys] = require('fs').readFileSync(0, 'utf-8').split(/\r?\n\r?\n/g).filter(v => v.length > 0).map(s => s.split(/\r?\n/g).filter(v => v.length > 0)).reduce((acc, s) => {
const lock = s[0].split('').every(v => v === '#');
const schema = s.slice(1, -1);
let rotated = [];
for (let i = 0; i < schema[0].length; i += 1) {
for (let j = 0; j < schema.length; j += 1) {
if (!rotated[i]) rotated[i] = [];
rotated[i].push(schema[j][i]);
}
}
if (!lock) {
rotated = rotated.map(v => v.reverse());
}
const pinHeights = [];
for (const row of rotated) {
const height = row.indexOf('.');
pinHeights.push(height !== -1 ? height : 5);
}
if (lock) {
acc[0].push(pinHeights);
} else {
acc[1].push(pinHeights);
}
return acc;
}, [[],[]]);
let fits = 0;
for (const lock of locks) {
for (const key of keys) {
let overlapped = false;
for (let i = 0; i < lock.length; i += 1) {
if ((lock[i] + key[i]) > 5) {
overlapped = true;
}
}
if (!overlapped) {
fits += 1;
}
}
}
console.log('Part One', fits);
Haskell
Have a nice christmas if youβre still celebrating today, otherwise hope you had a nice evening yesterday.
import Control.Arrow
import Control.Monad (join)
import Data.Bifunctor (bimap)
import qualified Data.List as List
heights = List.transpose
>>> List.map (pred . List.length . List.takeWhile (== '#'))
parse = lines
>>> init
>>> List.groupBy (curry (snd >>> (/= "")))
>>> List.map (List.filter (/= ""))
>>> List.partition ((== "#####") . head)
>>> second (List.map List.reverse)
>>> join bimap (List.map heights)
cartesianProduct xs ys = [(x, y) | x <- xs, y <- ys]
part1 = uncurry cartesianProduct
>>> List.map (uncurry (List.zipWith (+)))
>>> List.filter (List.all (<6))
>>> List.length
part2 = const 0
main = getContents
>>= print
. (part1 &&& part2)
. parse
Rust
Nice ending for this year. Lock and key arrays are just added together and all elements must be <= 5. Merry Christmas!
Solution
fn flatten_block(block: Vec<Vec<bool>>) -> [u8; 5] {
let mut flat = [0; 5];
for row in &block[1..=5] {
for x in 0..5 {
if row[x] {
flat[x] += 1;
}
}
}
flat
}
fn parse(input: &str) -> (Vec<[u8; 5]>, Vec<[u8; 5]>) {
let mut locks = Vec::new();
let mut keys = Vec::new();
for block_s in input.split("\n\n") {
let block: Vec<Vec<bool>> = block_s
.lines()
.map(|l| l.bytes().map(|b| b == b'#').collect::<Vec<bool>>())
.collect();
assert_eq!(block.len(), 7);
// Lock
if block[0].iter().all(|e| *e) {
locks.push(flatten_block(block));
} else {
keys.push(flatten_block(block));
}
}
(locks, keys)
}
fn part1(input: String) {
let (locks, keys) = parse(&input);
let mut count = 0u32;
for l in locks {
for k in &keys {
if l.iter().zip(k).map(|(li, ki)| li + ki).all(|sum| sum <= 5) {
count += 1;
}
}
}
println!("{count}");
}
fn part2(_input: String) {
println!("β");
}
util::aoc_main!();
Also on github