youtube.com/shorts/d8OWepBkOqY
Day 18 - RAM Run
=> More informations about this toot | View the thread
youtu.be/fVE2lfZNCCI
Day 15 - Warehouse Woes
Pt2 only, part 1 isnt terribly interesting.
=> More informations about this toot | View the thread
For anyone else doing rust, this might be useful:
It basically generates an asciicinema/asciicast file, which is then can be used to render a video.
use std::io::Write;
use std::process::Command;
pub struct Recorder {
filename: String,
output: File,
width: usize,
height: usize,
position: f32,
frametime: f32,
do_render: bool,
}
// Generate: https://docs.asciinema.org/manual/asciicast/v2/
impl Recorder {
pub fn new(filename: &str, w: usize, h: usize, framerate: u32, do_render: bool) -> Recorder {
let mut r = Recorder {
filename: String::from(filename),
output: File::create(format!("{filename}.cast")).unwrap(),
width: w,
height: h,
position: 0f32,
frametime: 1f32 / framerate as f32,
do_render,
};
r.init();
r
}
fn init(&mut self) {
self.output
.write_all(
format!(
"{{\"version\": 2, \"width\": {}, \"height\": {}}}\n",
self.width, self.height
)
.as_bytes(),
)
.unwrap();
}
pub fn println(&mut self, s: &str) {
let line = format!("{s}\n");
self.print(&line);
}
pub fn print(&mut self, s: &str) {
let escaped = serde_json::to_string(&(self.position, "o", s)).unwrap();
self.output
.write_all(format!("{escaped}\n").as_bytes())
.unwrap();
}
const RESET: &'static str = "\u{001b}[H\u{001b}[2J\u{001b}[3J";
pub fn sleep(&mut self, d: f32) {
self.frametime += d;
}
pub fn new_frame(&mut self) {
self.position += self.frametime;
self.print(Self::RESET);
}
}
impl Drop for Recorder {
fn drop(&mut self) {
if self.do_render {
let castname = format!("{}.cast", self.filename);
let gifname = format!("{}.gif", self.filename);
let mp4name = format!("{}.mp4", self.filename);
self.output.flush().unwrap();
let mut command = Command::new("agg");
command.arg(castname);
command.arg(gifname.as_str());
let mut proc = command.spawn().unwrap();
proc.wait().unwrap();
let _ = std::fs::remove_file(mp4name.as_str());
let mut command = Command::new("ffmpeg");
command.arg("-i");
command.arg(gifname.as_str());
command.arg(mp4name.as_str());
let mut proc = command.spawn().unwrap();
proc.wait().unwrap();
}
}
}
=> More informations about this toot | View the thread
https://www.youtube.com/watch?v=OR9QTQ2pg3s
Day 14 - Robots.
Try find the image :D
If no one finds it in the next few days, I’ll update with a timestamp.
=> More informations about this toot | View the thread
Visualisation Megathread
https://programming.dev/post/23569482
=> More informations about this toot | View the thread
Final Leaderboard
https://programming.dev/post/23565395
=> More informations about this toot | View the thread
Using LLMs to solve AOC
https://programming.dev/post/23540347
=> More informations about this toot | View the thread
Final Leaderbord
https://programming.dev/post/23330966
=> More informations about this toot | View the thread
🎄 - 2024 DAY 25 SOLUTIONS -🎄
https://programming.dev/post/23287241
=> More informations about this toot | View the thread
Day 24 - Pt2 - Manual Inspection?
https://programming.dev/post/23246961
=> More informations about this toot | View the thread
🤖 - 2024 DAY 24 SOLUTIONS - 🤖
https://programming.dev/post/23243817
=> More informations about this toot | View the thread
Rust
Part2 works, and is fast enough, but still feels kinda gross. No idea if this is a known algorithm or not.
mod tests {
use std::collections::HashMap;
#[test]
fn day23_part1_test() {
let input = std::fs::read_to_string("src/input/day_23.txt").unwrap();
let links = input
.lines()
.map(|l| l.split_once('-').unwrap())
.collect::<Vec<(&str, &str)>>();
let mut peer_map = HashMap::new();
for pair in links {
peer_map.entry(pair.0).or_insert(Vec::new()).push(pair.1);
peer_map.entry(pair.1).or_insert(Vec::new()).push(pair.0);
}
let mut rings = vec![];
for (pc, peers) in &peer_map {
if !pc.starts_with('t') {
continue;
}
for (i, first) in peers.iter().enumerate() {
for second in peers[i..].iter() {
if first == second {
continue;
}
if !peer_map.get(first).unwrap().contains(second) {
continue;
}
let mut set = vec![pc, second, first];
set.sort();
if !rings.contains(&set) {
rings.push(set);
}
}
}
}
println!("{}", rings.len());
}
#[test]
fn day23_part2_test() {
let input = std::fs::read_to_string("src/input/day_23.txt").unwrap();
let links = input
.lines()
.map(|l| l.split_once('-').unwrap())
.collect::<Vec<(&str, &str)>>();
let mut peer_map = HashMap::new();
for pair in links {
let p1 = peer_map.entry(pair.0).or_insert(Vec::new());
if !p1.contains(&pair.1) {
p1.push(pair.1);
}
let p2 = peer_map.entry(pair.1).or_insert(Vec::new());
if !p2.contains(&pair.0) {
p2.push(pair.0);
}
}
let mut biggest_network = String::new();
for (pc, peers) in &peer_map {
let mut network = HashMap::new();
network.insert(pc, peers.len());
for first in peers {
let mut total = 1;
for second in peers.iter() {
if first == second {
continue;
}
if peer_map.get(first).unwrap().contains(second) {
total += 1;
}
}
network.insert(first, total);
}
let mut network_size = peers.len();
loop {
if network_size == 0 {
break;
}
let mut out = network
.iter()
.filter_map(|(k, v)| {
if v >= &network_size {
return Some(**k);
}
None
})
.collect::<Vec<_>>();
if out.len() == network_size + 1 {
out.sort();
let pw = out.join(",");
// println!("{}", pw);
if pw.len() > biggest_network.len() {
biggest_network = pw;
}
break;
}
network_size -= 1;
}
}
println!("{}", biggest_network);
}
}
=> More informations about this toot | View the thread
💻 - 2024 DAY 23 SOLUTIONS -💻
https://programming.dev/post/23198319
=> More informations about this toot | View the thread
Rust
Part 2 is crazy slow, but it works, so thats cool :D
mod tests {
use std::collections::HashMap;
use std::iter::zip;
fn step(start: usize) -> usize {
let mut next = start;
next = ((next * 64) ^ next) % 16777216;
next = ((next / 32) ^ next) % 16777216;
next = ((next * 2048) ^ next) % 16777216;
next
}
fn simulate(initial: usize) -> usize {
let mut next = initial;
for _ in 0..2000 {
next = step(next);
}
next
}
#[test]
fn test_step() {
assert_eq!(15887950, step(123));
}
#[test]
fn test_simulate() {
assert_eq!(8685429, simulate(1));
}
#[test]
fn day22_part1_test() {
let input = std::fs::read_to_string("src/input/day_22.txt").unwrap();
let initial_values = input
.split("\n")
.map(|s| s.parse::<usize>().unwrap())
.collect::<Vec<usize>>();
let mut total = 0;
for value in initial_values {
total += simulate(value);
}
println!("{}", total);
}
fn count_bananas(p0: &str, p1: &[String], p2: &[Vec<usize>]) -> usize {
let mut total = 0;
for (delta, value) in zip(p1, p2) {
match delta.find(p0) {
None => continue,
Some(i) => total += value[i + 3],
}
}
total
}
#[test]
fn day22_part2_test() {
let input = std::fs::read_to_string("src/input/day_22.txt").unwrap();
let initial_values = input
.split("\n")
.map(|s| s.parse::<usize>().unwrap())
.collect::<Vec<usize>>();
let mut all_deltas = vec![];
let mut all_values = vec![];
for value in initial_values {
let mut deltas = String::with_capacity(2000);
let mut values = vec![];
let mut prev = value;
for _ in 0..2000 {
let next = step(prev);
values.push(next % 10);
deltas.push((10u8 + b'A' + ((prev % 10) as u8) - ((next % 10) as u8)) as char);
prev = next;
}
all_deltas.push(deltas);
all_values.push(values);
}
let mut cache = HashMap::new();
for (i, delta) in all_deltas.iter().enumerate() {
for j in 0..delta.len() - 3 {
let seq = &delta[j..j + 4];
if cache.contains_key(seq) {
continue;
}
let bananas = count_bananas(seq, &all_deltas[i..], &all_values[i..]);
cache.insert(seq, bananas);
}
}
let max_bananas = cache.values().max().unwrap();
println!("{}", max_bananas);
}
}
=> More informations about this toot | View the thread
Rust
Like many it seems, this one also broke my brain. Its basically the same as Day 19, but something about it mentally broke me.
mod tests {
use std::collections::HashMap;
static NUMPAD: [[char; 3]; 4] = [
['7', '8', '9'],
['4', '5', '6'],
['1', '2', '3'],
['X', '0', 'A'],
];
static DPAD: [[char; 3]; 2] = [['X', '^', 'A'], ['<', 'v', '>']];
fn valid_path(pad: &[[char; 3]], start: (isize, isize), path: &str) -> bool {
let mut pos = (start.0, start.1);
for c in path.chars() {
match c {
'^' => pos.0 -= 1,
'v' => pos.0 += 1,
'<' => pos.1 -= 1,
'>' => pos.1 += 1,
'A' => {}
_ => unreachable!(),
};
if pad[pos.0 as usize][pos.1 as usize] == 'X' {
return false;
}
}
true
}
fn move_pad(pad: &[[char; 3]], start: char, end: char) -> Vec<String> {
let mut start_coord = (0, 0);
let mut end_coord = (0, 0);
for i in 0..pad.len() {
for j in 0..3 {
if pad[i][j] == end {
end_coord = (i as isize, j as isize);
}
if pad[i][j] == start {
start_coord = (i as isize, j as isize);
}
}
}
let delta_i = end_coord.0 - start_coord.0;
let vert = match delta_i {
-3 => "^^^",
-2 => "^^",
-1 => "^",
0 => "",
1 => "v",
2 => "vv",
3 => "vvv",
_ => unreachable!(),
};
let delta_j = end_coord.1 - start_coord.1;
let horz = match delta_j {
-2 => "<<",
-1 => "<",
0 => "",
1 => ">",
2 => ">>",
_ => unreachable!(),
};
let vert_path = horz.to_string() + vert + "A";
let horz_path = vert.to_string() + horz + "A";
if !valid_path(pad, start_coord, &vert_path) {
return vec![horz_path];
}
if !valid_path(pad, start_coord, &horz_path) {
return vec![vert_path];
}
vec![vert_path, horz_path]
}
fn dpad_seq_len(p0: &str, depth: usize, cache: &mut HashMap<(String, usize), usize>) -> usize {
if depth == 0 {
return p0.len();
}
if let Some(cost) = cache.get(&(p0.to_string(), depth)) {
return *cost;
}
let mut first = 'A';
let mut length = 0;
for second in p0.chars() {
let moves = move_pad(&DPAD, first, second);
let mut min = usize::MAX;
for m in moves {
let l = dpad_seq_len(&m, depth - 1, cache);
if l < min {
min = l;
}
}
length += min;
first = second;
}
cache.insert((p0.to_string(), depth), length);
length
}
fn numpad_seq_len(
p0: &str,
depth: usize,
cache: &mut HashMap<(String, usize), usize>,
) -> usize {
let mut first = 'A';
let mut length = 0;
for second in p0.chars() {
let moves = move_pad(&NUMPAD, first, second);
let mut min = usize::MAX;
for m in moves {
let l = dpad_seq_len(&m, depth, cache);
if l < min {
min = l;
}
}
length += min;
first = second;
}
length
}
#[test]
fn test_numpad2dpad() {
let mut cache = HashMap::new();
assert_eq!(68, numpad_seq_len("029A", 2, &mut cache));
assert_eq!(60, numpad_seq_len("980A", 2, &mut cache));
assert_eq!(68, numpad_seq_len("179A", 2, &mut cache));
assert_eq!(64, numpad_seq_len("456A", 2, &mut cache));
assert_eq!(64, numpad_seq_len("379A", 2, &mut cache));
}
#[test]
fn day21_part1_test() {
let mut cache = HashMap::new();
let input = std::fs::read_to_string("src/input/day_21.txt").unwrap();
let codes = input.split('\n').collect::<Vec<&str>>();
let mut total = 0;
for code in codes {
let min_length = numpad_seq_len(code, 2, &mut cache);
println!("{code}: {min_length}");
total += min_length * code[0..3].parse::<usize>().unwrap();
}
println!("{}", total);
}
#[test]
fn day21_part2_test() {
let mut cache = HashMap::new();
let input = std::fs::read_to_string("src/input/day_21.txt").unwrap();
let codes = input.split('\n').collect::<Vec<&str>>();
let mut total = 0;
for code in codes {
let min_length = numpad_seq_len(code, 25, &mut cache);
println!("{code}: {min_length}");
total += min_length * code[0..3].parse::<usize>().unwrap();
}
println!("{}", total);
}
}
=> More informations about this toot | View the thread
🐒 - 2024 DAY 22 SOLUTIONS - 🐒
https://programming.dev/post/23151169
=> More informations about this toot | View the thread
⌨️ - 2024 DAY 21 SOLUTIONS -⌨️
https://programming.dev/post/23107860
=> More informations about this toot | View the thread
🏃♀️ - 2024 DAY 20 SOLUTIONS -🏃♀️
https://programming.dev/post/23064988
=> More informations about this toot | View the thread
Rust
Pretty similar to the other rust answer. This definitely requires
spoilermemoization
of some form, but when done right, is very performant. 122ms for both.
mod tests {
use std::collections::HashMap;
fn count_solutions(
design: &str,
patterns: &[&str],
seen_designs: &mut HashMap<String, i64>,
) -> i64 {
if design.is_empty() {
return 1;
}
if let Some(s) = seen_designs.get(design) {
return *s;
}
let mut count = 0;
for pattern in patterns {
if design.starts_with(pattern) {
count += count_solutions(&design[pattern.len()..], patterns, seen_designs);
}
}
seen_designs.insert(design.to_string(), count);
count
}
#[test]
fn day19_both_test() {
let input = std::fs::read_to_string("src/input/day_19.txt").unwrap();
let parts = input.split_once("\n\n").unwrap();
let patterns = parts.0.split(", ").collect::<Vec<&str>>();
let designs = parts.1.split('\n').collect::<Vec<&str>>();
let mut count = 0;
let mut total = 0;
let mut seen_designs = HashMap::new();
for design in designs {
let shortlist = patterns
.iter()
.filter_map(|p| {
if design.contains(p) {
return Some(*p);
}
None
})
.collect::<Vec<&str>>();
let sol_count = count_solutions(design, &shortlist, &mut seen_designs);
total += sol_count;
count += (sol_count != 0) as usize;
}
println!("{}", count);
println!("{}", total);
}
}
=> More informations about this toot | View the thread
👻 - 2024 DAY 19 SOLUTIONS -👻
https://programming.dev/post/23017702
=> More informations about this toot | View the thread
=> This profile with reblog | Go to CameronDev@programming.dev account This content has been proxied by September (3851b).Proxy Information
text/gemini