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
Uiua
A Christmas Day treat: a one-liner for you all to decipher!
"#####\n.####\n.####\n.####\n.#.#.\n.#...\n.....\n\n#####\n##.##\n.#.##\n...##\n...#.\n...#.\n.....\n\n.....\n#....\n#....\n#...#\n#.#.#\n#.###\n#####\n\n.....\n.....\n#.#..\n###..\n###.#\n###.#\n#####\n\n.....\n.....\n.....\n#....\n#.#..\n#.#.#\n#####"
/+ββ(/Γ<8+)β©Β°β‘Β°β β(β‘β‘β‘/+β@#)β @#β‘(β’β’). β(ββββΈβ @\n)¬±⦷"\n\n".
Kotlin
A fun and small challenge.
First read all locks, transpose their profile and count the s (-1 for the full row).
Then do the same for the keys.
Lastly find all keys for all locks that do not sum to more than 5 with their teeth:
Code
val lockRegex = Regex("""#{5}(\r?\n[.#]{5}){6}""")
val keyRegex = Regex("""([.#]{5}\r?\n){6}#{5}""")
fun parseLocksAndKeys(inputFile: String): Pair<List<IntArray>, List<IntArray>> {
val input = readResource(inputFile)
val locks = lockRegex
.findAll(input)
.map {
it
.value
.lines()
.map { line -> line.toList() }
.transpose()
.map { line -> line.count { c -> c == '#' } - 1 }
.toIntArray()
}
.toList()
val keys = keyRegex
.findAll(input)
.map {
it
.value
.lines()
.map { line -> line.toList() }
.transpose()
.map { line -> line.count { c -> c == '#' } - 1 }
.toIntArray()
}
.toList()
return locks to keys
}
fun part1(inputFile: String): String {
val (locks, keys) = parseLocksAndKeys(inputFile)
val matches = locks.map { lock ->
keys.filter { key ->
for (i in lock.indices) {
// Make sure the length of the key and lock do not exceed 5
if (lock[i] + key[i] > 5) {
return@filter false
}
}
true
}
}
.flatten()
.count()
return matches.toString()
}
Haskell
Merry Christmas!
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Either
import Data.Text hiding (all, head, zipWith)
import Data.Text qualified as T
import Data.Text.IO as TIO
type Pins = [Int]
toKeyLock :: [Text] -> Either Pins Pins
toKeyLock v = (if T.head (head v) == '#' then Left else Right) $ fmap (pred . count "#") v
solve keys locks = sum [1 | k <- keys, l <- locks, fit k l]
where
fit a b = all (<= 5) $ zipWith (+) a b
main = TIO.getContents >>= print . uncurry solve . partitionEithers . fmap (toKeyLock . transpose . T.lines) . splitOn "\n\n"
Dart
Quick and dirty, and slightly tipsy, code.
Happy Christmas everyone!
Thanks to Eric and the team at Advent of Code, to @Ategon@programming.dev and @CameronDev@programming.dev for giving us somewhere to share and discuss our solutions, and to everyone here for the friendly and supportive community.
See you all next year!
import 'package:collection/collection.dart';
import 'package:more/more.dart';
part1(List<String> lines) {
var (w, h) = (lines.first.length, lines.indexOf(''));
var (falsey: keys, truthy: locks) = (lines..insert(0, ''))
.splitBefore((l) => l.isEmpty)
.map((g) => [
for (var x in 0.to(w)) [for (var y in 1.to(h + 1)) g[y][x]]
])
.partition((g) => g[0][0] == '#');
return keys
.map((l) => locks.count((k) =>
0.to(w).every((r) => (l[r] + k[r]).count((e) => e == '#') < 8)))
.sum;
}
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