🌟 Advent of Code (AoC) 2024 🌟

PermalÀnk
Medlem ★
●

Dag: 25
SprÄk: Python (Numpy, One-liner)

Det kÀnns bra att fÄ avsluta med en one-liner

Tack till alla er som hĂ€ngt med till slutet. Det Ă€r lĂ€rorikt att kolla pĂ„ era lösningar och jĂ€mföra. Även om det Ă€r olika sprĂ„k kan man alltid lĂ€ra sig nya tricks.

Ses vi igen nÀsta Är?

import numpy as np from itertools import combinations print(sum((a & b == False).all() for a,b in combinations([np.array([[c == '#' for c in l] for l in k]) for k in [key.strip().split("\n") for key in open("input25.txt", "r").read().split("\n\n")]], 2)))

Dold text
PermalÀnk
Medlem ★
●

Jag skulle behöva lite hjÀlp att förstÄ dag 23.

Min lÀsförstÄelse brister nog, men jag fÄr inte ihop det.

Första fyra raderna i exemplet:

kh-tc qp-kh de-cg ka-co ...

Raderna efter sÀger att "Connections aren't directional".

Citat:

Each line of text in the network map represents a single connection; the line kh-tc represents a connection between the computer named kh and the computer named tc. Connections aren't directional; tc-kh would mean exactly the same thing.

In this example, there are 12 such sets of three inter-connected computers: aq,cg,yn aq,vc,wq co,de,ka co,de,ta co,ka,ta de,ka,ta kh,qp,ub qp,td,wh tb,vc,wq tc,td,wh td,wh,yn ub,vc,wq

Enligt första raden i exemplet Àr kh och tc kopplade.
Hur kan det finnas set med kh utan tc, och med tc utan kh?

Dold text
PermalÀnk
Medlem ★
●
Skrivet av jaqob:

Jag skulle behöva lite hjÀlp att förstÄ dag 23.

Enligt första raden i exemplet Àr kh och tc kopplade.
Hur kan det finnas set med kh utan tc, och med tc utan kh?

De frÄgar om noder som Àr kopplad till kh, eller tc Àr kopplad till bÄda. Eller med andra ord om de tillsammans bildar en triangel (aka complete subgraph). Nedan bildar 'A' en triangel med kh, kc, men inte 'B'.

De frÄga alltsÄ hur mÄnga "trianglar" det finns av hopkopplade datorer som har en dator vars namn startar pÄ 't'.

Lycka till!

Dold text
Visa signatur

Louqe Ghost S1 MK3 | Asus ROG Strix B660-I Gaming WiFi | Intel Core i7 12700K | nVidia RTX 2070 Super FE | Corsair 64GB (2x32GB) DDR5 5600MHz CL40 Vengeance | Samsung 980 PRO M.2 NVMe SSD 2TB | Corsair SF750 750W 80+ Platinum | Noctua NH-L12 Ghost S1 edition | Kablar frÄn pslate customs | 2 stk Dell Ultrasharp 3014 | Logitech MX Keys | Logitech MX Anywhere

PermalÀnk
Medlem ★
●
Skrivet av sunefred:

Enligt första raden i exemplet Àr kh och tc kopplade.
Hur kan det finnas set med kh utan tc, och med tc utan kh?

De frÄgar om noder som Àr kopplad till kh, eller tc Àr kopplad till bÄda. Eller med andra ord om de tillsammans bildar en triangel (aka complete subgraph). Nedan bildar 'A' en triangel med kh, kc, men inte 'B'.

<Uppladdad bildlÀnk>

De frÄga alltsÄ hur mÄnga "trianglar" det finns av hopkopplade datorer som har en dator vars namn startar pÄ 't'.

Lycka till!

Dold text

Tack!

SÄ, vi letar helt enkelt efter loopar med lÀngden tre?

Dold text
PermalÀnk
Medlem ★
●
Skrivet av jaqob:

Tack!

SÄ, vi letar helt enkelt efter loopar med lÀngden tre?

Dold text

SÄ kan man ocksÄ se det, potato, potaaato

Dold text
Visa signatur

Louqe Ghost S1 MK3 | Asus ROG Strix B660-I Gaming WiFi | Intel Core i7 12700K | nVidia RTX 2070 Super FE | Corsair 64GB (2x32GB) DDR5 5600MHz CL40 Vengeance | Samsung 980 PRO M.2 NVMe SSD 2TB | Corsair SF750 750W 80+ Platinum | Noctua NH-L12 Ghost S1 edition | Kablar frÄn pslate customs | 2 stk Dell Ultrasharp 3014 | Logitech MX Keys | Logitech MX Anywhere

PermalÀnk
Medlem
●

Dag: 25
SprÄk: Dyalog APL

Jag brukar alltid ha planer pÄ att gÄ tillbaka och lösa de problem jag inte hunnit titta pÄ efter jul nÀr jag har mer tid men det brukar aldrig bli sÄ. FÄr se om det blir annorlunda i Är eller om aoc glöms bort till nÀsta december som vanligt.

2Ă·âš+/∊∘.(∧.âČ)⍹∊¹'#'=(⊱⊆⍹0≠≱¹)⊃⎕NGET'25.txt'1

Dold text
PermalÀnk
Datavetare ★
●

Dag: 24
SprÄk: Rust

Inte sÄ konstigt att det gick att lösa del 2 visuellt, gate:arna behöver vara pÄ ett vÀldigt speciellt sÀtt för att det ska fungera dÄ det man mÄste bygga Àr en 44 bitars full-adder krets (sÄ output Àr 45 bit)...

En sÄdan ser ut sÄ hÀr (per bit, man kedjar sedan C-out för bit N till C-in till bit N+1 upp till önskat antal bitar man vill addera)

Att bara ta alla tÀnkbara kombinationer man kan switcha 4 par gate:ar lÀr ta lÄng tid. Men en sak man relativt lÀtt kan hitta Àr gate:ar dÀr sista operationen innan zNN INTE Àr en XOR, dÄ har man hitta nÄgot som ska bytas ut (min input har 3 sÄdana).

GÄr Àven enkelt att rÀkna ut vem man ska swap:a med

För zNN mÄste det finnas en vÀg frÄn xNN/yNN via tvÄ XOR operationer, sÄ man ska byta de zNN som inte har en XOR till den gate som nu har det xNN/yNN gate:en har som output som en av sina inputs.

Finns logik för att hitta övriga fel ocksÄ just dÄ det mÄste vara en full-adder, men körde bara alla möjliga kombinationer av alla gates som inte Àr XOR till zNN samt tog bort de som redan swap:ats av ovan.

Lite "sÄdÀr" lösning, som ocksÄ har rÀtt variabel körtid. Men rÀckte för att fixa mÄlet att lösa alla dagar i sekvens pÄ en Orange Pi 5 under 1s, tar strax under 500ms.

use ahash::{AHashMap, AHashSet}; use itertools::Itertools; use std::{collections::VecDeque, fs::read_to_string}; pub const INPUT_FILE: &str = "input.txt"; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Op { And, Or, Xor, } pub fn read_gates( path: &str, ) -> ( Vec<(usize, bool)>, Vec<(usize, usize, Op, usize)>, AHashMap<String, usize>, ) { let content = read_to_string(path).expect("Failed to read the file"); let sections = content.split_once("\n\n").unwrap(); let mut value_indexes = AHashMap::new(); let mut add_value_index = |name: &str| { if !value_indexes.contains_key(name) { value_indexes.insert(name.to_string(), value_indexes.len()); } }; let gates = sections .1 .lines() .map(|line| { let parts = line.split_ascii_whitespace().collect::<Vec<_>>(); let (i0, i1, out) = (parts[0], parts[2], parts[4]); add_value_index(i0); add_value_index(i1); add_value_index(out); ( i0.to_string(), i1.to_string(), match parts[1] { "AND" => Op::And, "OR" => Op::Or, "XOR" => Op::Xor, _ => panic!("Invalid operation"), }, out.to_string(), ) }) .collect::<Vec<_>>(); let initial_values = sections .0 .lines() .map(|line| { let (name, value) = line.split_once(": ").unwrap(); (*value_indexes.get(name).unwrap(), value == "1") }) .collect(); let gates_with_index = gates .iter() .map(|(i0, i1, op, out)| { ( *value_indexes.get(i0).unwrap(), *value_indexes.get(i1).unwrap(), *op, *value_indexes.get(out).unwrap(), ) }) .collect(); (initial_values, gates_with_index, value_indexes) } pub fn part1( initial_values: &[(usize, bool)], gate_configs: &[(usize, usize, Op, usize)], value_name_to_index: &AHashMap<String, usize>, ) -> u64 { let mut values = vec![None; value_name_to_index.len()]; for &(index, value) in initial_values { values[index] = Some(value); } run_gates(&mut values, gate_configs, value_name_to_index).unwrap() } pub fn part2( initial_values: &[(usize, bool)], gate_configs: &[(usize, usize, Op, usize)], value_name_to_index: &AHashMap<String, usize>, ) -> String { let mut value_index_to_name = vec![""; value_name_to_index.len()]; let mut out_index_to_bit = AHashMap::new(); let mut z_bits = 0; for (name, &index) in value_name_to_index { value_index_to_name[index] = name.as_str(); if name.starts_with("z") { z_bits += 1; let bit = name[1..].parse::<usize>().unwrap(); out_index_to_bit.insert(index, bit); } } let mut gates = Vec::new(); let mut must_swap_zs = Vec::new(); let mut may_swap_index = AHashSet::new(); let mut xor_inputs = vec![0usize; z_bits - 1]; // For an full adder, operation leading to output must be XOR, so any output to Zxx with another operation must be swapped for (index, &(i0, i1, op, out)) in gate_configs.iter().enumerate() { gates.push((i0, i1, op, out)); let in_name = value_index_to_name[i1]; let out_name = value_index_to_name[out]; if out_name.starts_with("z") { let bit = out_name[1..].parse::<usize>().unwrap(); if bit < z_bits - 1 && op != Op::Xor { must_swap_zs.push((bit, index)); } } else { if op == Op::Xor && (in_name.starts_with("x") || in_name.starts_with("y")) { let bit = in_name[1..].parse::<usize>().unwrap(); xor_inputs[bit] = index; } may_swap_index.insert(index); } } // Operation from input Xn + Yn always has a path Xn XOR Yn -> midA XOR midB -> Zn // So there outputs found above must be moved with whatever now is midA or modB let mut swapped_outputs = Vec::new(); for (bit, z_gate_index) in must_swap_zs { let mid_value = gates[xor_inputs[bit]].3; let swap_gate_index = gates .iter() .enumerate() .find(|(_, gate)| gate.2 == Op::Xor && (gate.0 == mid_value || gate.1 == mid_value)) .unwrap() .0; (gates[z_gate_index].3, gates[swap_gate_index].3) = (gates[swap_gate_index].3, gates[z_gate_index].3); swapped_outputs.push(value_index_to_name[gates[z_gate_index].3]); swapped_outputs.push(value_index_to_name[gates[swap_gate_index].3]); may_swap_index.remove(&swap_gate_index); } let mut values = vec![None; value_name_to_index.len()]; for &(index, value) in initial_values { values[index] = Some(value); } let x = register_value("x", &values, value_name_to_index); let y = register_value("y", &values, value_name_to_index); let z = x + y; for swap in may_swap_index.iter().combinations(2) { let (i, j) = (*swap[0], *swap[1]); (gates[i].3, gates[j].3) = (gates[j].3, gates[i].3); if let Some(computed_z) = run_gates(&mut values, &gates, value_name_to_index) { if z == computed_z { swapped_outputs.push(value_index_to_name[gates[i].3]); swapped_outputs.push(value_index_to_name[gates[j].3]); swapped_outputs.sort(); return swapped_outputs.join(","); } } (gates[i].3, gates[j].3) = (gates[j].3, gates[i].3); values.fill(None); for &(index, value) in initial_values { values[index] = Some(value); } } panic!("No solution found"); } fn run_gates( values: &mut Vec<Option<bool>>, gate_configs: &[(usize, usize, Op, usize)], value_name_to_index: &AHashMap<String, usize>, ) -> Option<u64> { let mut gates = VecDeque::new(); for &gate in gate_configs { gates.push_front(gate); } let mut progress = gates.len(); while let Some(gate) = gates.pop_back() { let (i0_index, i1_index, op, out_index) = gate; if let (Some(i0), Some(i1)) = (values[i0_index], values[i1_index]) { progress = gates.len(); let out = match op { Op::And => i0 & i1, Op::Or => i0 | i1, Op::Xor => i0 ^ i1, }; values[out_index] = Some(out); } else { gates.push_front(gate); progress -= 1; if progress == 0 { return None; } } } Some(register_value("z", &values, value_name_to_index)) } fn register_value( reg_name: &str, values: &Vec<Option<bool>>, value_name_to_index: &AHashMap<String, usize>, ) -> u64 { value_name_to_index .iter() .fold(0, |number, (name, &index)| { if name.starts_with(reg_name) && values[index].unwrap() { let bit = name[1..].parse::<usize>().unwrap(); number | (1 << bit) } else { number } }) } fn main() { let (initial_values, gates, value_indexes) = read_gates(INPUT_FILE); println!("part 1: {}", part1(&initial_values, &gates, &value_indexes)); println!("part 2: {}", part2(&initial_values, &gates, &value_indexes)); }

Dold text

Edit: Alla grindar renderade efter problemet Àr löst

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Datavetare ★
●

Dag: 25
SprÄk: Rust

99 ”s (M3), 320”s (Orange Pi 5)

use std::fs::read_to_string; pub const INPUT_FILE: &str = "input.txt"; pub type Schematics = [u32; 5]; pub fn read_locks_and_keys(path: &str) -> (Vec<Schematics>, Vec<Schematics>) { let content = read_to_string(path).expect("Failed to read file"); let blocks = content.split("\n\n").collect::<Vec<_>>(); let mut locks = Vec::new(); let mut keys = Vec::new(); for block in blocks { let lines = block.lines().collect::<Vec<_>>(); let mut schematic = [0; 5]; for line in &lines[1..(lines.len() - 1)] { for (i, ch) in line.chars().enumerate() { if ch == '#' { schematic[i] += 1; } } } if lines[0] == "#####" { locks.push(schematic); } else { keys.push(schematic); } } (locks, keys) } pub fn part1(locks: &[Schematics], keys: &[Schematics]) -> usize { let mut fitting_pairs = 0; for lock in locks { for key in keys { if lock.iter().zip(key.iter()).all(|(l, k)| l + k <= 5) { fitting_pairs += 1; } } } fitting_pairs } fn main() { let (locks, keys) = read_locks_and_keys(INPUT_FILE); println!("part 1: {}", part1(&locks, &keys)); }

Dold text
Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Medlem
●

Tog lite tid att göra dag 16 del 2 och dag 21.

Dag: 16
SprÄk: Java
Lösning: GitHub
Del 2 Àr vÀldigt lÄngsamt och behöver optimeras, men det fungerar Ätminstone. Försökte att köra min input med nÄgon annans kod nÀr jag fastnade för att se hur fel min lösning var men det blev ocksÄ fel.

Dag: 21
SprÄk: Java
Lösning: GitHub
Del 1 anvÀnder pathfinding och tar 16 ms, del 2 anvÀnder memorisation och behöver bara 5 ms - behöll koden som den var för del 1 Àven om det inte behövs.

Dag: 25
SprÄk: Java
Lösning: GitHub

Det enda som Àr kvar Àr att försöka lösa alla andra Ärs AoC som jag inte gjort Àn till nÀsta Är!

PermalÀnk
Medlem ★
●
Skrivet av ViLue:

Det enda som Àr kvar Àr att försöka lösa alla andra Ärs AoC som jag inte gjort Àn till nÀsta Är!

Du har 11 mÄnader pÄ dig. Kör hÄrt! Kanske gör dem i Python istÀllet dock, lite mer inbyggd funktionalitet dÀr Àn "plain" Java

Visa signatur

Louqe Ghost S1 MK3 | Asus ROG Strix B660-I Gaming WiFi | Intel Core i7 12700K | nVidia RTX 2070 Super FE | Corsair 64GB (2x32GB) DDR5 5600MHz CL40 Vengeance | Samsung 980 PRO M.2 NVMe SSD 2TB | Corsair SF750 750W 80+ Platinum | Noctua NH-L12 Ghost S1 edition | Kablar frÄn pslate customs | 2 stk Dell Ultrasharp 3014 | Logitech MX Keys | Logitech MX Anywhere

PermalÀnk
Medlem
●
Skrivet av sunefred:

Du har 11 mÄnader pÄ dig. Kör hÄrt! Kanske gör dem i Python istÀllet dock, lite mer inbyggd funktionalitet dÀr Àn "plain" Java

Halva nöjet Àr att skapa egna lösningar/funktionalitet!
Försökte att göra det förra Äret men slutade i februari nÀr jag fastnade i nÄgon pathfinding dag.