🌟 Advent of Code (AoC) 2021 🌟

PermalÀnk
●

Dag: 15
SprÄk: Python

from heapq import heapify, heappop, heappush import numpy as np REPEAT_COUNT = 5 p1_world = np.array([[int(c) for c in line.rstrip()] for line in open("15.in")]) p2_world = ( np.tile(p1_world, (REPEAT_COUNT, REPEAT_COUNT)) + np.repeat(np.arange(REPEAT_COUNT), len(p1_world))[:, None] + np.repeat(np.arange(REPEAT_COUNT), len(p1_world))[None, :] ) p2_world[p2_world > 9] -= 9 def calc_risk(pos): return p2_world[pos[0]][pos[1]] def generate_neighbours(world, i, j): HEIGHT, WIDTH = world.shape for di, dj in ((0, 1), (1, 0), (0, -1), (-1, 0)): if 0 <= (n_i := i + di) < HEIGHT and 0 <= (n_j := j + dj) < WIDTH: yield n_i, n_j def find_bottom_right_risk(world): HEIGHT, WIDTH = world.shape goal = (HEIGHT - 1, WIDTH - 1) frontier = [(0, (0, 0))] heapify(frontier) seen = set([(0, 0)]) while frontier: risk, pos = heappop(frontier) if pos == goal: return risk for n in generate_neighbours(world, *pos): if n not in seen: seen.add(n) heappush(frontier, (risk + calc_risk(n), n)) raise NotImplementedError print(find_bottom_right_risk(p1_world)) print(find_bottom_right_risk(p2_world))

Dold text
PermalÀnk
Medlem ★
●

Ok. Orkar inte ens lÀsa dagens, Àn mindre lösa den.

Visa signatur

The power of GNU compiles you!
"Often statistics are used as a drunken man uses lampposts -- for support rather than illumination."

PermalÀnk
Medlem
●

Dag: 16
SprÄk: Carth

En lite annan sorts uppgift Ă€n tidigare dagar. Kul med omvĂ€xling! Å andra sidan blev min kod mycket lĂ€ngre och mindre översiktlig idag Ă€n mĂ„nga tidigare dagar. SĂ„ kan det gĂ„!

Klicka för mer information

(import std) (data Version (Version Nat8)) (data PacketType (Lit Int) (Op Nat8 (Array Packet))) (data Packet (Packet Version PacketType)) (define main (do io/bind run-part1-tests (display "") run-part2-tests (display "") (<- input (io/map unwrap! (read-file "inputs/day16.txt"))) (let1 packet (car (parse-packet (parse-bits input)))) (display (str-append "Part 1: " (show-int (version-sum packet)))) (display (str-append "Part 2: " (show-int (eval packet)))))) (define (eval (Packet _ p)) (match p (case (Lit x) x) (case (Op op es) (let1 xs (map eval (array/iter es)) (match (to-int op) (case 0 (sum xs)) (case 1 (product xs)) (case 2 (minimum xs)) (case 3 (maximum xs)) (case 5 (let1 [x1 xs] (next! xs) (if (> x1 (iter/first! xs)) 1 0))) (case 6 (let1 [x1 xs] (next! xs) (if (< x1 (iter/first! xs)) 1 0))) (case _ (let1 [x1 xs] (next! xs) (if (= x1 (iter/first! xs)) 1 0)))))))) (define btoi (fmatch (case True 1) (case False 0))) (define (version-sum (Packet (Version v) pt)) (+ (to-int v) (match pt (case (Lit _) 0) (case (Op _ subs) (sum (map version-sum (array/iter subs))))))) (define (parse-packet bits) (let (([bver bits] (unwrap-or-else (fun (_) (panic "parse-packet: failed to get version bits")) (array/split (cast 3) bits))) (ver (: (bits-to-num bver) Nat8)) ([btyp bits] (unwrap-or-else (fun (_) (panic "parse-packet: failed to get type bits")) (array/split (cast 3) bits))) ([pt bits] (match (bits-to-num btyp) (case 4 (parse-lit bits)) (case oid (parse-op (to-n8 oid) bits))))) [(Packet (Version ver) pt) bits])) (define (parse-op oid bits) (define (lt-n-bits? n [mbits _msubs]) (< mbits n)) (define (lt-n-subs? n [_mbits msubs]) (< msubs n)) (let (([len-type bits] (unwrap-or-else (fun (_) (panic "parse-op: failed to get len-type")) (array/split-first bits))) ([cont? bits] (if len-type (map-car (<o lt-n-subs? bits-to-num) (unwrap-or-else (fun (_) (panic "parse-op: failed to get n subs")) (array/split (cast 11) bits))) (map-car (<o lt-n-bits? bits-to-num) (unwrap-or-else (fun (_) (panic "parse-op: failed to get n bits")) (array/split (cast 15) bits))))) ([subs bits] (parse-subs cont? [(to-nat 0) (to-nat 0)] bits))) [(Op oid (array/collect-list subs)) bits])) (define (parse-subs cont? count' bits0) (if (not (cont? count')) [LNil bits0] (let (([sub bits] (parse-packet bits0)) (sub-size (- (array/length bits0) (array/length bits))) (count' (map-two (+ sub-size) inc count')) ([subs bits] (parse-subs cont? count' bits))) [(list/cons sub subs) bits]))) (define (parse-lit bits) (define (go acc bits) (let (([cont? bits] (unwrap-or-else (fun (_) (panic "parse-lit: failed to get continue bit")) (array/split-first bits))) ([bs bits] (unwrap-or-else (fun (_) (panic "parse-lit: failed to split 4")) (array/split (cast 4) bits))) (acc (array/append acc bs))) (if cont? (go acc bits) [(Lit (bits-to-num acc)) bits]))) (go array/nil bits)) (define (bits-to-num bits) (let1 inv (<o cast (- (- (array/length bits) (cast 1)))) (foldl (fun (x [i b]) (set-bit (inv i) b x)) (cast 0) (enumerate (array/iter bits))))) (define (show-packet (Packet (Version v) pt)) (define show-pt (fmatch (case (Lit n) (show-int n)) (case (Op oid ps) (apps str-append "op " (show-nat (cast oid)) " [" (string/concat (intersperse ", " (map show-packet (array/iter ps)))) "]")))) (apps str-append "{version = " (show-nat (cast v)) ", " (show-pt pt) "}")) (define (parse-bits s) (define (digit-bits c) (let1 b (if (>= c ascii-A) (+ (- c ascii-A) (cast 10)) (- c ascii-0)) (map (fun (i) (bit-set? (to-n8 (- 3 i)) b)) (xrange 0 4)))) (array/collect (flat-map digit-bits (string/bytes s)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; TESTING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define run-part1-tests (define tests1 (list ["D2FE28" 6] ["8A004A801A8002F478" 16] ["620080001611562C8802118E34" 12] ["C0015000016115A2E0802F182340" 23] ["A0016C880162017C3686B18A3D4780" 31])) (do io/bind (display "Running part 1 tests:") (io/for (list/iter tests1) (fun ([inp vsum-expected]) (do io/bind (<- p (parse-packet-debug inp)) (let1 vsum-found (version-sum p)) (display (apps str-append (if (= vsum-expected vsum-found) " OK ---- " " ERR ### ") "expected " (show-int vsum-expected) ", found " (show-int vsum-found)))))))) (define run-part2-tests (define tests2 (list ["C200B40A82" 3] ["04005AC33890" 54] ["880086C3E88112" 7] ["CE00C43D881120" 9] ["D8005AC2A8F0" 1] ["F600BC2D8F" 0] ["9C005AC2F8F0" 0] ["9C0141080250320F1802104A08" 1])) (do io/bind (display "Running part 2 tests:") (io/for (list/iter tests2) (fun ([inp val-expected]) (do io/bind (<- p (parse-packet-debug inp)) (let1 val-found (eval p)) (display (apps str-append (if (= val-expected val-found) " OK ---- " " ERR ### ") "expected " (show-int val-expected) ", found " (show-int val-found)))))))) (define (parse-packet-debug inp) (do io/bind (display (str-append " " inp)) (let1 bits (parse-bits inp)) (display (str-append " bits = " (array/show (<o show-int btoi) bits))) (let1 [p _] (parse-packet bits)) (display (str-append " packet = " (show-packet p))) (io/pure p)))

Visa mer
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Hedersmedlem ★
●

Dag: 15
SprÄk: TypeScript (med Node.js)
Lösning: https://github.com/exscape/AOC2021/blob/main/src/day15.ts

Äntligen! Hade stora problem med denna. Började med att lĂ€sa pĂ„ om pathfinding, och kom rĂ€tt snabbt fram till att anvĂ€nda Dijkstras algoritm. LĂ€ste pĂ„ och implementerade den, men det blev alldeles för lĂ„ngsamt, och de priority queues jag hittade till JavaScript funkade rĂ€tt sĂ„dĂ€r.

Fick Àntligen till det nÀr jag hittade en heap jag kunde anvÀnda, Àven om det blev klumpigt (körde bitshifting för att göra om x/y till en 32-bitars int, eftersom den bara kunde lagra heltal och floats). KÀndes overkill att implementera Àven den sjÀlv, dÄ jag inte har vanan dÀr heller.
Tar ÀndÄ strax över 500 ms för bÄda delarna, sÄ inte Àr jag direkt nöjd, men men. Innan jag fick till det med heapen tog det 1100 ms att lösa del 1 pÄ 100x100.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

PermalÀnk
Medlem ★
●
Skrivet av GLaDER:

Dag: 15
SprÄk: Python 3
Lösning: GitHub

Dijkstra alltsÄ.... det tog alldeles för lÄng tid innan jag fick till algoritmen; och jag Àr fortfarande inte nöjd med exekveringstiden. PÄ Del 2 var min approach att Àndra input, istÀllet för att göra nÄgot "smart" med algoritmen. 12s att hitta en lösning.

Dold text

Dag: 16
SprÄk: Python 3
Lösning: GitHub

Vilken lÀsförstÄelseuppgift.... tycker det hÀr Àr vÀrsta sortens uppgifter, men varje Är dyker det upp nÄgra uppgifter som tar timmar att lösa pÄ ett vettigt sÀtt. (VÀskuppgiften och allergenuppgiften frÄn förra Äret var av samma karaktÀr.) Men det var ju lite kul att fÄ anvÀnda nya match i Python 3.10

Dold text
Visa signatur

:(){ :|:& };:

đŸŠđŸ»â€â™‚ïž   đŸšŽđŸ»â€â™‚ïž   đŸƒđŸ»â€â™‚ïž   ☕

PermalÀnk
Medlem ★
●

Dag: 16
SprÄk: Python

I dag blev det mycket kod (50 rader) och en del fula tricks. Det blev till att lÀsa uppgiften Ätskilliga gÄnger innan jag lyckades förstÄ hur allt skulle hÀnga ihop.

from math import prod from operator import gt, lt, eq def pops(s, n): s1 = s[0][:n] s[0] = s[0][n:] return s1 def popi(s, n): return int(pops(s, n), 2) def lit(s, t, vsum): packet, digits = pops(s, 5), "" while packet[0] == '1': digits += packet[1:] packet = pops(s, 5) return vsum, int(digits + packet[1:], 2) def op0(s, vsum, f): l, values = popi(s, 15), [] s1 = [pops(s, l)] while s1[0]: vsum, value = packet(s1, vsum) values.append(value) return vsum, f(values) def op1(s, vsum, f): vers, values = zip(*[packet(s, 0) for i in range(popi(s, 11))]) return vsum + sum(vers), f(values) f1 = [sum, prod, min, max, None, gt, lt, eq] def op(s, t, vsum, f): return [op0, op1][popi(s, 1)](s, vsum, f) def op03(s, t, vsum): return op(s, t, vsum, lambda vs: f1[t](vs)) def op57(s, t, vsum): return op(s, t, vsum, lambda vs: f1[t](*vs)) f2 = [op03, op03, op03, op03, lit, op57, op57, op57] def packet(s, vsum): vsum += popi(s, 3) t = popi(s, 3) return f2[t](s, t, vsum) def parse(s): s = [format(int(s,16), f"#0{len(s)*4 + 2}b")[2:]] print(*packet(s, 0)) s = open("input16").read().strip() parse(s)

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

Dag: 16
SprÄk: Python

I dag blev det mycket kod (50 rader) och en del fula tricks. Det blev till att lÀsa uppgiften Ätskilliga gÄnger innan jag lyckades förstÄ hur allt skulle hÀnga ihop.

from math import prod from operator import gt, lt, eq def pops(s, n): s1 = s[0][:n] s[0] = s[0][n:] return s1 def popi(s, n): return int(pops(s, n), 2) def lit(s, t, vsum): packet, digits = pops(s, 5), "" while packet[0] == '1': digits += packet[1:] packet = pops(s, 5) return vsum, int(digits + packet[1:], 2) def op0(s, vsum, f): l, values = popi(s, 15), [] s1 = [pops(s, l)] while s1[0]: vsum, value = packet(s1, vsum) values.append(value) return vsum, f(values) def op1(s, vsum, f): vers, values = zip(*[packet(s, 0) for i in range(popi(s, 11))]) return vsum + sum(vers), f(values) f1 = [sum, prod, min, max, None, gt, lt, eq] def op(s, t, vsum, f): return [op0, op1][popi(s, 1)](s, vsum, f) def op03(s, t, vsum): return op(s, t, vsum, lambda vs: f1[t](vs)) def op57(s, t, vsum): return op(s, t, vsum, lambda vs: f1[t](*vs)) f2 = [op03, op03, op03, op03, lit, op57, op57, op57] def packet(s, vsum): vsum += popi(s, 3) t = popi(s, 3) return f2[t](s, t, vsum) def parse(s): s = [format(int(s,16), f"#0{len(s)*4 + 2}b")[2:]] print(*packet(s, 0)) s = open("input16").read().strip() parse(s)

Dold text

Jag tror vi har motsatt approach nĂ€r vi programmerar Min devis Ă€r: LĂ€sbarhet ĂŒber alles!

Visa signatur

:(){ :|:& };:

đŸŠđŸ»â€â™‚ïž   đŸšŽđŸ»â€â™‚ïž   đŸƒđŸ»â€â™‚ïž   ☕

PermalÀnk
Medlem ★
●
Skrivet av GLaDER:

Jag tror vi har motsatt approach nĂ€r vi programmerar Min devis Ă€r: LĂ€sbarhet ĂŒber alles!

Det har jag pÄ jobbet. HÀr Àr det annat som gÀller.

Men som van Python-programmerare tror jag att jag föredrar en list comprehension framför en loop dÀr man för hand lÀgger till list-elementen ett och ett. Jag tycker det Àr lÀttare att lÀsa. Sedan kan det ju gÄ till överdrift. Har man mer Àn tvÄ nÀstlingar i en list comprehension Àr koden write-only för man kommer aldrig kunna förstÄ vad den gör om man rÄkar titta bort mer Àn fem sekunder.

Meningsbyggnad
PermalÀnk
Hedersmedlem ★
●

Dag: 16
SprÄk: TypeScript (med Node.js)
Lösning: https://github.com/exscape/AOC2021/blob/main/src/day16.ts

Kanske den roligaste hittills i slutÀndan.
0.8 ms för parsing och berÀkningar, trots att jag skapar nya strÀngar varje gÄng den lÀser in nÄgra bits. Inte illa!

Skrivet av GLaDER:

Jag tror vi har motsatt approach nĂ€r vi programmerar Min devis Ă€r: LĂ€sbarhet ĂŒber alles!

Samma hÀr, vilket jag hoppas mÀrks. Sen Àr ju ingen kod perfekt om man inte sitter för evigt och finputsar.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

PermalÀnk
Medlem
●

Dag: 15
SprÄk: Rust

use std::{ cmp::Reverse, collections::{BinaryHeap, HashMap}, ops::Div, }; type RiskLevel = HashMap<(usize, usize), usize>; struct Chiton { map: RiskLevel, costs: RiskLevel, width: usize, height: usize, } impl Chiton { pub fn new(input: &str) -> Self { let mut map = HashMap::new(); let mut costs = HashMap::new(); let mut height = 0; let mut width = 0; for (y, line) in input.lines().enumerate() { for (x, c) in line.chars().enumerate() { map.insert((x, y), c.to_digit(10).unwrap() as usize); costs.insert((x, y), usize::MAX); height = y; width = x; } } Self { map, costs, width: width + 1, height: height + 1, } } pub fn solve_part1(&self) -> usize { self.solve(self.width, self.height, &self.map, self.costs.clone()) } pub fn solve_part2(&self) -> usize { let mut new_map = HashMap::new(); let mut costs = HashMap::new(); for tile_y in 0..5 { for tile_x in 0..5 { for y in 0..self.height { for x in 0..self.width { let pos = (x + tile_x * self.width, y + tile_y * self.height); let value = self.map[&(x, y)] + tile_x + tile_y; new_map.insert(pos, value % 10 + value.div(10)); costs.insert(pos, usize::MAX); } } } } self.solve(self.width * 5, self.height * 5, &new_map, costs) } fn solve(&self, width: usize, height: usize, map: &RiskLevel, mut costs: RiskLevel) -> usize { let mut visit = BinaryHeap::new(); visit.push((Reverse(0), (0, 0))); while let Some(args) = visit.pop() { let (Reverse(cost), pos) = args; if cost < costs[&pos] { costs.insert(pos, cost); for p in self.adjacent(width, height, pos) { visit.push((Reverse(cost + map[&p]), p)); } } } costs[&(width - 1, height - 1)] } fn adjacent(&self, width: usize, height: usize, (x, y): (usize, usize)) -> Vec<(usize, usize)> { [(0, -1), (-1, 0), (1, 0), (0, 1)] .iter() .filter(|&(dx, dy)| { let x = x as i64; let y = y as i64; x + dx >= 0 && y + dy >= 0 && x + dx < width as i64 && y + dy < height as i64 }) .map(|&(dx, dy)| ((x as i64 + dx) as usize, (y as i64 + dy) as usize)) .collect() } } fn main() { let input = std::fs::read_to_string("input.txt").unwrap(); let chiton = Chiton::new(&input); println!("Part 1: {}", chiton.solve_part1()); // 720 println!("Part 2: {}", chiton.solve_part2()); // 3025 }

Dold text
Visa signatur

AMD Ryzen 3700X, Gigabyte Elite X570, 32GB Ballistix Sport, NH-D15S, SAPPHIRE NITRO+ RX 7900 XTX, Corsair AX760, LG OLED C2 42"

PermalÀnk
Medlem
●

Dag: 16
SprÄk: C#

Idag var det knepigt. Tog vÀldigt lÄng tid innan jag förstod hela uppgiften. FrÄn början försökte jag jobba utifrÄn hexadecimaler men det blev vÀldigt bökigt sÄ jag gjorde om hela hexinputen till en binÀrstrÀng och jobbade med den istÀllet, efter det sÄ gick allt betydligt smidigare..

internal class Puzzle16 : Puzzle<long> { private int _versionSum; protected override void Solve(string[] lines) { var bitReader = new BitReader(string.Join(null, lines[0] .Select(c => Convert.ToString(Convert.ToInt32("" + c, 16), 2).PadLeft(4, '0')))); var result = ParsePacket(bitReader); One = _versionSum; Two = result; } private long ParsePacket(BitReader bitReader) { var version = bitReader.ReadNext(3); var type = bitReader.ReadNext(3); _versionSum += version; if (type == 4) { return GetPayloadForPacketType4(bitReader); } var packets = new List<long>(); if (bitReader.ReadNext(1) == 0) { var length = bitReader.ReadNext(15); var prevIdx = bitReader.CurrentIdx; while ((bitReader.CurrentIdx - prevIdx) != length) { packets.Add(ParsePacket(bitReader)); } } else { packets.AddRange(Enumerable.Range(0, bitReader.ReadNext(11)) .Select(_ => ParsePacket(bitReader))); } return type switch { 0 => packets.Sum(), 1 => packets.Aggregate(1L, (a, b) => a * b), 2 => packets.Min(), 3 => packets.Max(), 5 => packets[0] > packets[1] ? 1 : 0, 6 => packets[0] < packets[1] ? 1 : 0, 7 => packets[0] == packets[1] ? 1 : 0, _ => 0 }; } private static long GetPayloadForPacketType4(BitReader reader) { var groups = new List<long>(); while (true) { var group = reader.ReadNext(5); groups.Add(group & 0xF); if ((group & 0x10) == 0) { break; } } groups.Reverse(); long result = 0; for (int i = 0; i < groups.Count; i++) { result |= groups[i] << (i * 4); } return result; } private class BitReader { private readonly string _packet; public int CurrentIdx { get; private set; } public BitReader(string packet) { _packet = packet; } public int ReadNext(int bitSize) => Convert.ToInt32(_packet[CurrentIdx..(CurrentIdx += bitSize)], 2); } }

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

Dag: 16
SprÄk: Python 3
Lösning: GitHub

Vilken lÀsförstÄelseuppgift.... tycker det hÀr Àr vÀrsta sortens uppgifter, men varje Är dyker det upp nÄgra uppgifter som tar timmar att lösa pÄ ett vettigt sÀtt. (VÀskuppgiften och allergenuppgiften frÄn förra Äret var av samma karaktÀr.) Men det var ju lite kul att fÄ anvÀnda nya match i Python 3.10

Dold text

Dag: 17
SprÄk: Python 3
Lösning: GitHub

Rolig uppgift idag! Kom fram till lösningen med ren brute-force men efter lite diskussion pÄ Slack hittade vi vettiga randvillkor och jag fick ner exekveringstiden frÄn ~15s till drygt 1s.

Dold text
Visa signatur

:(){ :|:& };:

đŸŠđŸ»â€â™‚ïž   đŸšŽđŸ»â€â™‚ïž   đŸƒđŸ»â€â™‚ïž   ☕

PermalÀnk
Medlem
●

Dag: 17
SprÄk: C#

Skönt med en uppgift som var lÀttare att förstÄ Enda jag inte Àr nöjd med Àr hÄrdkodningen av grÀnsvÀrdena. Finns sÀkert nÄgot smart sÀtt att rÀkna ut dessa.

internal class Puzzle17 : Puzzle<int> { private ((int x, int y) from, (int x, int y) to) _targetArea; protected override void Solve(string[] lines) { var x = lines[0][(2 + lines[0].IndexOf("x="))..lines[0].IndexOf(",")].Split("..").Select(int.Parse).ToArray(); var y = lines[0][(2 + lines[0].IndexOf("y="))..].Split("..").Select(int.Parse).ToArray(); _targetArea = ( (x[0], y[0]), (x[1], y[1]) ); var hits = 0; var topYShot = int.MinValue; foreach (var forward in Enumerable.Range(0, 300)) { foreach (var upward in Enumerable.Range(-200, 400)) { if (Shoot(forward, upward, out var topY)) { hits++; topYShot = Math.Max(topYShot, topY); } } } One = topYShot; Two = hits; } private bool Shoot(int forward, int upward, out int topY) { topY = int.MinValue; var currentPosition = (x: 0, y: 0); while (true) { currentPosition.x += forward; currentPosition.y += upward; topY = Math.Max(topY, currentPosition.y); upward--; if (forward > 0) { forward -= 1; } else if (forward < 0) { forward += 1; } if (IsWithinTarget(currentPosition)) { return true; } if (MissedTarget(currentPosition)) { return false; } } } private bool IsWithinTarget((int x, int y) coord) => _targetArea.from.x <= coord.x && _targetArea.to.x >= coord.x && _targetArea.from.y <= coord.y && _targetArea.to.y >= coord.y; private bool MissedTarget((int x, int y) coord) => coord.x > _targetArea.to.x || coord.y < _targetArea.from.y; }

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

Dag: 17
SprÄk: C#

Skönt med en uppgift som var lÀttare att förstÄ Enda jag inte Àr nöjd med Àr hÄrdkodningen av grÀnsvÀrdena. Finns sÀkert nÄgot smart sÀtt att rÀkna ut dessa.

Dold text

Om du vill ha lite tips: v

for x_vel in range(max(x_target) + 1): for y_vel in range(min(y_target), -2 * min(y_target)):

Dessutom borde det gÄ att hitta ett programatiskt lÀgsta vÀrde pÄ x, utifrÄn var ens "target area" börjar. SÄ lÄngt kom jag dock aldrig.

Dold text
Visa signatur

:(){ :|:& };:

đŸŠđŸ»â€â™‚ïž   đŸšŽđŸ»â€â™‚ïž   đŸƒđŸ»â€â™‚ïž   ☕

PermalÀnk
Medlem ★
●

Dag: 17
SprÄk: Python

Hitta alla möjliga x-hastigheter som trÀffar target area
Hitta alla möjliga y-hastigheter som trÀffar target area
Ta kryssprodukten och kolla om nÄgot av koordinatparen hamnar i target area.

Min range för vilka y-hastigheter som Àr vÀrde att testa hittades genom lite experimenterande. HÀr tar jag gÀrna emot tips pÄ hur man gör det pÄ ett smart sÀtt.

import re from itertools import zip_longest, product xlo, xhi, ylo, yhi = map(int, re.findall("\-?\d+", open("input17").read().strip())) def xpath(dx, lo, hi): x = 0 p = [x] while dx and x < hi: x += dx dx -= 1 p.append(x) return p if any(lo <= x <= hi for x in p) else None def ypath(dy, lo, hi): y = 0 p = [y] while y > lo: y += dy dy -= 1 p.append(y) return p if any(lo <= y <= hi for y in p) else None def missing_xcoords(xpath, ypath): return (xlo <= xpath[-1] <= xhi # In the target area? and xpath[-1] - xpath[-2] == 1 # Falling straight down? and len(xpath) < len(ypath)) # Need to extend? def hit(xpath, ypath): if missing_xcoords(xpath, ypath): l = zip_longest(xpath, ypath, fillvalue = xpath[-1]) else: l = zip(xpath, ypath) return any(map(lambda p: xlo <= p[0] <= xhi and ylo <= p[1] <= yhi, l)) xl = [p for i in range(xhi + 1) if (p := xpath(i, xlo, xhi))] yl = [p for i in range(ylo, 200) if (p := ypath(i, ylo, yhi))] print(max(max(p) for p in yl), sum(hit(*p) for p in product(xl, yl)))

Dold text
PermalÀnk
Medlem
●

Dag: 17
SprÄk: Carth

Del 1 kunde jag lösa pÄ papper. Första gÄngen jag löst en AoC uppgift sÄ. Sjovt!

Klicka för mer information

(import std) (define main (do io/bind (<- input (io/map unwrap! (read-file "inputs/day17.txt"))) (let1 [tx1 tx2 ty1 ty2] (parse! (do parse/bind (parse/string "target area: x=") (<- x1 parse/int) (parse/string "..") (<- x2 parse/int) (parse/string ", y=") (<- y1 parse/int) (parse/string "..") (<- y2 parse/int) (parse/pure [x1 x2 y1 y2])) input)) (display (str-append "Part 1: " (show-int (tri (dec (neg ty1)))))) (apps |> (iter/cartesian (range (to-int (sqrt (cast (* 2 tx1)))) tx2) (range ty1 (dec (neg ty1)))) (filter (fun ([px py]) (any (fun ([x y]) (and (<= tx1 x) (>= ty2 y))) (take-while (fun ([x y]) (and (<= x tx2) (>= y ty1))) (map (fun (t) [(x-at-t px t) (y-at-t py t)]) (range-from 1)))))) count show-nat (str-append "Part 2: ") display))) (define (x-at-t px t) (let1 t (min px t) (/ (* t (- (* 2 px) (- t 1))) 2))) (define (y-at-t py t) (/ (* t (- (* 2 py) (- t 1))) 2)) (define (tri a) (/ (* a (+ a 1)) 2))

Visa mer
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem
●
Skrivet av Ingetledigtnamn:

Dag: 17
SprÄk: Python

Hitta alla möjliga x-hastigheter som trÀffar target area
Hitta alla möjliga y-hastigheter som trÀffar target area
Ta kryssprodukten och kolla om nÄgot av koordinatparen hamnar i target area.

Min range för vilka y-hastigheter som Àr vÀrde att testa hittades genom lite experimenterande. HÀr tar jag gÀrna emot tips pÄ hur man gör det pÄ ett smart sÀtt.

import re from itertools import zip_longest, product xlo, xhi, ylo, yhi = map(int, re.findall("\-?\d+", open("input17").read().strip())) def xpath(dx, lo, hi): x = 0 p = [x] while dx and x < hi: x += dx dx -= 1 p.append(x) return p if any(lo <= x <= hi for x in p) else None def ypath(dy, lo, hi): y = 0 p = [y] while y > lo: y += dy dy -= 1 p.append(y) return p if any(lo <= y <= hi for y in p) else None def missing_xcoords(xpath, ypath): return (xlo <= xpath[-1] <= xhi # In the target area? and xpath[-1] - xpath[-2] == 1 # Falling straight down? and len(xpath) < len(ypath)) # Need to extend? def hit(xpath, ypath): if missing_xcoords(xpath, ypath): l = zip_longest(xpath, ypath, fillvalue = xpath[-1]) else: l = zip(xpath, ypath) return any(map(lambda p: xlo <= p[0] <= xhi and ylo <= p[1] <= yhi, l)) xl = [p for i in range(xhi + 1) if (p := xpath(i, xlo, xhi))] yl = [p for i in range(ylo, 200) if (p := ypath(i, ylo, yhi))] print(max(max(p) for p in yl), sum(hit(*p) for p in product(xl, yl)))

Dold text

Kurvan nÀr du skjuter en sond uppÄt Àr symmetrisk pÄ vÀgen upp och pÄ vÀgen ner, med andra ord kommer den alltid ligga i x-axeln i ett tidssteg pÄ vÀgen ner. Om du skjuter uppÄt med hastighet v=3, till exempel, sÄ kommer ditt höjdvÀrde i varje steg vara

(0), 3, 5, 6, 6, 5, 3, 0, -4, ...

HÀr kan man se ett mönster. I tidssteget dÀr vi ÄtervÀnt till x-axeln kommer vÄr hastighet vara -(v+1). SÄ vÄr första negativa höjd kommer vara 0 - (v+1) = -(v+1). I exemplet ovan, -(3+1) = -4. Detta medför att om vÄr starthastighet uppÄt Àr lika med eller större Àn inversen av mÄlets bottenvÀrde y_min, sÄ kommer vÄrt första negativa vÀrde, -(-y_min + 1) = y_min - 1, redan vara förbi bottenkanten! y_min ger oss alltsÄ inte bara en undre grÀns att testa, utan Àven en övre grÀns. Vi behöver bara testa vertikala starthastigheter inom [y_min ... -y_min - 1]. SÄ om mÄlet har sin botten vid t.ex. -7, sÄ behöver vi bara testa starthastigheter i y-led inom [-7, 6].

Dold text
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem
●

Dag: 17
SprÄk: C#

Gött med en lÀttare uppgift efter gÄrdagens mardröm. Lite trist med trippla for-loopar men kom inte pÄ nÄgot vettigt sÀtt att lösa det pÄ i C#.

internal class Day17 : Puzzle { public override object PartOne() => GetTarget() .Pipe(Solve) .MaxHeight; public override object PartTwo() => GetTarget() .Pipe(Solve) .Count; private static (int Count, int MaxHeight) Solve(Area target) { var count = 0; var maxVerticalVelocity = 0; var minHorizontalVelocity = CalculateMinHorizontalVelocity(target.X1); for (var vY = target.Y1; vY <= -target.Y1 - 1; vY++) for (var vX = minHorizontalVelocity; vX <= target.X2; vX++) for (var t = 0; t < int.MaxValue; t++) { var verticalPosition = CalculatePosition(vY, t); var horizontalPosition = CalculateHorizontalPosition(vX, t); if (verticalPosition.IsBetween(target.Y1, target.Y2) && horizontalPosition.IsBetween(target.X1, target.X2)) { maxVerticalVelocity = vY; count += 1; break; } if (verticalPosition < target.Y1) break; } return (count, CalculateMaxPosition(maxVerticalVelocity)); } private static int CalculateMaxPosition(int v) => v * (v + 1) / 2; private static int CalculatePosition(int v, int t) => (t + 1) * (2 * v - t) / 2; private static int CalculateHorizontalPosition(int v, int t) => t >= v ? CalculateMaxPosition(v) : CalculatePosition(v, t); private static int CalculateMinHorizontalVelocity(int pos) => (int)Math.Ceiling((Math.Sqrt(8 * pos + 1) - 1) / 2); private Area GetTarget() { var values = Utilities.GetInput(GetType()) .Pipe(x => Regex.Matches(x, @-?\d+) .Select(y => int.Parse(y.Value))).ToArray(); return new Area(values[0], values[1], values[2], values[3]); } private record Area(int X1, int X2, int Y1, int Y2); }

Dold text
PermalÀnk
Medlem
●

Dag: 17
SprÄk: C++

Motivationen börjar tryta lite nu.

int solve_part1(area t) { int v0_ymax = abs(t.ymin)-1; //the maximum y velocity still hitting y_min int y_max = v0_ymax * (v0_ymax+1)/2; //integrate to velocity zero (arithmetic series sum) return y_max; } int solve_part2(area t) { int v0x_min = int( -.5+sqrt((2.0d*double(t.xmin)+0.25d))); int v0x_max = t.xmax; int v0y_min = t.ymin; int v0y_max = abs(t.ymin) -1 ; int x,y,vx,vy,i; int n = 0; for (int v0x = v0x_min; v0x <= v0x_max; v0x++) { for (int v0y = v0y_min; v0y <= v0y_max; v0y++) { vy = v0y; vx = v0x; x = y = 0; while (true) { x += (vx > 0) * vx; y += vy; if (x > t.xmax || y < t.ymin) { //this is a miss break; } else if (x >= t.xmin && x <= t.xmax) { if (y >= t.ymin && y <= t.ymax) { n++; break; } } vx--; vy--; } } } return n; }

Dold text
PermalÀnk
Medlem
●

Dag: 15
SprÄk: C++

Och hÀr kommer min lösning pÄ dag 15 som jag nu har stÀdat upp Ätminstone till lÀsbart skick. TÀnkte direkt pÄ Djikstra men har aldrig implementerat den tidigare. God hjÀlp av Zlashy, tack.

#include <climits> #include <algorithm> #include <map> #include <queue> #include <stack> #include "../utils/file_reader.cpp" #include "../utils/result_printer.cpp" typedef pair<int,int> coord; typedef pair<coord,int> point; typedef map<coord,int> grid; struct risk_map_struct { int x_size; int y_size; grid risk_level; }; vector<coord> get_neighbours() { vector<coord> neighbours = {{1,0},{0,1},{0,-1},{-1,0}}; return neighbours; } risk_map_struct parse(vector<string> str_data) { risk_map_struct risk_map; grid risk_level; int n_rows = str_data.size(); int n_cols = str_data[0].size(); for (int i = 0; i < n_rows; i++) { string str_row = str_data[i]; for (int j = 0; j < n_cols; j++) { risk_level.insert(make_pair(make_pair(i,j),int(str_row[j]-48))); } } risk_map.risk_level = risk_level; risk_map.x_size = n_cols; risk_map.y_size = n_rows; return risk_map; } risk_map_struct expand_grid(risk_map_struct risk_map) { risk_map_struct expanded_map; expanded_map.x_size = risk_map.x_size*5; expanded_map.y_size = risk_map.y_size*5; grid exp_risk_level; vector<vector<int>> test; for (int i = 0; i < expanded_map.y_size; i++) { vector<int> str_row; for (int j = 0; j < expanded_map.x_size; j++) { int col = j%risk_map.x_size; int row = i%risk_map.y_size; coord coord_ = make_pair(row, col); int val = (risk_map.risk_level.at(coord_)); int add = i/risk_map.y_size + j/risk_map.x_size; int new_val = val + add; while (new_val > 9) { new_val-=9; } exp_risk_level.insert(make_pair(make_pair(i,j), new_val)); } test.push_back(str_row); } expanded_map.risk_level = exp_risk_level; return expanded_map; } int solve(risk_map_struct risk_map, bool part2) { if (part2) risk_map = expand_grid(risk_map); vector<coord> nbs = get_neighbours(); point source; map<coord,coord> prevs; coord start = make_pair(0,0); coord target = make_pair(risk_map.x_size-1 ,risk_map.y_size-1); grid risk(risk_map.risk_level); auto cmp = [](const point &a, const point &b) { return a.second > b.second; }; priority_queue< point, vector<point>, decltype(cmp)> queue(cmp); for (auto const& [key, val] : risk_map.risk_level) { risk.at(key) = INT_MAX; } risk.at(start) = 0; source = make_pair(start,0); queue.push(source); while(queue.size()>0) { //cout << queue.size() << endl;; source = queue.top(); queue.pop(); for (auto &nb:nbs) { coord u = make_pair(source.first.first+nb.first, source.first.second+nb.second); if (!risk.count(u)) continue; int new_risk = source.second + risk_map.risk_level.at(u); if (new_risk < risk.at(u)) { risk.at(u) = new_risk; queue.push(make_pair(u,new_risk)); prevs.insert(make_pair(u,source.first)); } } } return risk.at(target); }

Dold text
PermalÀnk
Hedersmedlem ★
●

Dag: 17
SprÄk: TypeScript (med Node.js)
Lösning: https://github.com/exscape/AOC2021/blob/main/src/day17.ts

GÄr förvisso pÄ under 10 ms, men jag vill ÀndÄ optimera sÄ att den inte söker lika mÄnga onödiga kombinationer av hastigheter.
Har inte klurat ut hur jag ska begrÀnsa vilken y-hastighet den testar som högst Ànnu. Satte grÀnsen pÄ 1000 bara pÄ mÄfÄ eftersom det kÀnns extremt överdrivet (133 rÀcker för rÀtt svar med min indata).
Försökte loopa och bryta tills vissa conditions möttes men det misslyckades ocksÄ; alla jag hittade som inte tuggade för evigt bröt innan rÀtt svar hittats.

Dold text
Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

PermalÀnk
Medlem ★
●
Skrivet av Thomas:

Har inte klurat ut hur jag ska begrÀnsa vilken y-hastighet den testar som högst Ànnu. Satte grÀnsen pÄ 1000 bara pÄ mÄfÄ eftersom det kÀnns extremt överdrivet (133 rÀcker för rÀtt svar med min indata).
Försökte loopa och bryta tills vissa conditions möttes men det misslyckades ocksÄ; alla jag hittade som inte tuggade för evigt bröt innan rÀtt svar hittats.

Dold text

Se detta inlÀgg dÀr Bryal förklarade för mig

Dold text
PermalÀnk
Medlem
●

Dag: 17
SprÄk: Rust

use std::{iter, str::FromStr}; #[derive(Debug, Default, Clone, Copy)] pub struct Point(i64, i64); #[derive(Debug, Default, Clone, Copy)] pub struct Area { start: Point, end: Point, } #[derive(Debug, Default, Clone, Copy)] pub struct Probe { pos: Point, velocity: Point, area: Area, } impl FromStr for Area { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { let r: Vec<_> = s .split(",") .flat_map(|s| s.split("..")) .map(|s| { s.chars() .filter(|&c| matches!(c, '0'..='9' | '-')) .collect::<String>() }) .filter_map(|s| s.parse::<i64>().ok()) .collect(); Ok(Self { start: Point(r[0], r[2]), end: Point(r[1], r[3]), }) } } impl Area { pub fn check(&self, point: Point) -> bool { let min_x = self.start.0.min(self.end.0); let max_x = self.start.0.max(self.end.0); let min_y = self.start.1.min(self.end.1); let max_y = self.start.1.max(self.end.1); min_x <= point.0 && max_x >= point.0 && min_y <= point.1 && max_y >= point.1 } pub fn range(&self) -> impl Iterator<Item = (i64, i64)> { let max_x = self.start.0.max(self.end.0); let min_y = self.start.1.min(self.end.1); (1..=max_x).flat_map(move |r| iter::repeat(r).zip(min_y..=min_y.abs())) } } impl Probe { pub fn new(area: Area, velocity: Point) -> Self { Self { pos: Default::default(), velocity, area, } } pub fn step(&mut self) { self.pos.0 += self.velocity.0; self.pos.1 += self.velocity.1; self.velocity.0 -= self.velocity.0.signum(); self.velocity.1 -= 1; } pub fn within_target(&self) -> bool { self.area.check(self.pos) } pub fn bounds_check(&self) -> bool { let max_x = self.area.start.0.max(self.area.end.0); let min_y = self.area.start.1.min(self.area.end.1); max_x < self.pos.0 || min_y > self.pos.1 } pub fn simulate(&mut self) -> Option<i64> { let mut max = 0; while !self.bounds_check() { max = self.pos.1.max(max); self.step(); if self.within_target() { return Some(max); } } None } } pub fn solve(area: Area, mut func: impl FnMut(i64) -> bool) { for (x, y) in area.range() { if let Some(value) = Probe::new(area, Point(x, y)).simulate() { if !func(value) { return; } } } } fn main() { let area = std::fs::read_to_string("input.txt") .unwrap() .lines() .filter_map(|s| s.parse::<Area>().ok()) .next() .unwrap(); let mut max = 0; solve(area, |value| { max = max.max(value); if max > value { return false; } true }); println!("Part 1: {}", max); // 2850 let mut count = 0; solve(area, |_| { count += 1; true }); println!("Part 2: {}", count); // 1117 }

Dold text
Visa signatur

AMD Ryzen 3700X, Gigabyte Elite X570, 32GB Ballistix Sport, NH-D15S, SAPPHIRE NITRO+ RX 7900 XTX, Corsair AX760, LG OLED C2 42"

PermalÀnk
Hedersmedlem ★
●

Är det fel i beskrivningen för dag 18, eller missförstĂ„r jag bara?

Citat:

For example, the final sum of this list is [[[[1,1],[2,2]],[3,3]],[4,4]]:

[1,1]
[2,2]
[3,3]
[4,4]

The final sum of this list is [[[[3,0],[5,3]],[4,4]],[5,5]]:

[1,1]
[2,2]
[3,3]
[4,4]
[5,5]

The final sum of this list is [[[[5,0],[7,4]],[5,5]],[6,6]]:

[1,1]
[2,2]
[3,3]
[4,4]
[5,5]
[6,6]

Vilka listor Àr det som de pratar om pÄ varje rad före kolon?
Det ser mera ut som att meningen ska vara t ex "The final sum of the list [[[[3,0],[5,3]],[4,4]],[5,5]] is:"

Har dock inte kollat igenom uppgiften ordentligt och börjat koda, men om det ovan inte stÀmmer kÀnns det rÀtt otydligt skrivet.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

PermalÀnk
●
Skrivet av Thomas:

Är det fel i beskrivningen för dag 18, eller missförstĂ„r jag bara?

Vilka listor Àr det som de pratar om pÄ varje rad före kolon?
Det ser mera ut som att meningen ska vara t ex "The final sum of the list [[[[3,0],[5,3]],[4,4]],[5,5]] is:"

Har dock inte kollat igenom uppgiften ordentligt och börjat koda, men om det ovan inte stÀmmer kÀnns det rÀtt otydligt skrivet.

Det som menas Àr att om din input Àr

[1,1] [2,2] [3,3] [4,4]

sÄ ska summan bli

[[[[1,1],[2,2]],[3,3]],[4,4]]

Det Àr otydligt skrivet.

PermalÀnk
Medlem
●

Dag: 18
SprÄk: Carth

Lösningen pÄ del 2 blev kanske inte den snabbaste, men har ingen lust att försöka hitta nÄn smartare lösning dÀr. Nu ska ut och julhandlas!

Klicka för mer information

(import std) (data SfNum (SfRegular Int) (SfPair (Box [SfNum SfNum]))) (define main (do io/bind (<- input (io/map unwrap! (read-file "inputs/day18.txt"))) (let1 nums (map parse-sf-num (lines input))) (let1 [n ns] (next! nums)) (let1 final (foldl (<oo reduce sf-add) (reduce n) ns)) (display "Part 1:") (display (show-sf-num final)) (display (show-int (magnitude final))) (display "") (display (str-append "Part 2: " (show-int (maximum (map (apps <o magnitude reduce (uncurry sf-add)) (iter/cartesian nums nums)))))))) (define magnitude (fmatch (case (SfRegular x) x) (case (SfPair (Box [l r])) (+ (* 3 (magnitude l)) (* 2 (magnitude r)))))) (define sf-add mk-pair) (define (reduce sf) (match (explode sf) (case (Some sf') (reduce sf')) (case None (match (split sf) (case (Some sf') (reduce sf')) (case None sf))))) (define split (fmatch (case (SfRegular x) (if (>= x 10) (Some (mk-pair (SfRegular (/ x 2)) (SfRegular (/ (inc x) 2)))) None)) (case (SfPair (Box [l r])) (maybe/map (<o SfPair box) (maybe/or (maybe/map (flip cons' r) (split l)) (nonstrict (maybe/map (cons' l) (split r)))))))) (define (explode sf) (define (go nesting) (fmatch (case (SfRegular x) None) (case (SfPair (Box [l r])) (if (= nesting 4) (Some [(SfRegular 0) (Some (regular! l)) (Some (regular! r))]) (maybe/or (maybe/map (fun ([l' ladd radd]) [(mk-pair l' (maybe' r (fun (radd') (sf-map-leftmost (+ radd') r)) radd)) ladd None]) (go (inc nesting) l)) (nonstrict (maybe/map (fun ([r' ladd radd]) [(mk-pair (maybe' l (fun (ladd') (sf-map-rightmost (+ ladd') l)) ladd) r') None radd]) (go (inc nesting) r)))))))) (maybe/map car (go 0 sf))) (define (sf-map-leftmost f) (fmatch (case (SfRegular x) (SfRegular (f x))) (case (SfPair (Box [l r])) (mk-pair (sf-map-leftmost f l) r)))) (define (sf-map-rightmost f) (fmatch (case (SfRegular x) (SfRegular (f x))) (case (SfPair (Box [l r])) (mk-pair l (sf-map-rightmost f r))))) (define (mk-pair l r) (SfPair (box [l r]))) (define regular! (fmatch (case (SfRegular x) x) (case x (panic (str-append "regular!: not a regular number: " (show-sf-num x)))))) (define show-sf-num (fmatch (case (SfRegular x) (show-int x)) (case (SfPair (Box [l r])) (apps str-append "[" (show-sf-num l) "," (show-sf-num r) "]")))) (define parse-sf-num (define (p-sf-num inp) (let1 (Parser p) (parse/or (parse/map SfRegular parse/int) (parse/between (parse/string "[") (parse/string "]") (do parse/bind (<- a (Parser p-sf-num)) (parse/string ",") (<- b (Parser p-sf-num)) (parse/pure (SfPair (box [a b])))))) (p inp))) (parse! (Parser p-sf-num)))

Visa mer
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem ★
●

Dag: 18
SprÄk: Python

Har man inga pekare fÄr man fuska lite. Stoppar man siffrorna i en extra lista kan man manipulera dem genom att hÄlla reda pÄ listan de ligger i. Som bonus blev alla noder listor med antingen ett eller tvÄ element och man kan avgöra typen med len, vilket kanske Àr snyggare Àn en massa isinstance-anrop. Men baksidan Àr att det blir en massa extra [0] för att fiska ut vÀrdet.

from copy import deepcopy from functools import reduce def item(s): if s[0] == '[': return pair(s) return [int(s[0])], s[1:] def pair(s): i1, s = item(s[1:]) i2, s = item(s[1:]) return [i1, i2], s[1:] numbers = [pair(s.rstrip())[0] for s in open("input18").readlines()] def traverse(node, position): if len(node) == 1: return node return traverse(node[position], position) def explode(node, depth = 0, prev = None, next = None, parent = [], position = -1): if len(node) == 2: if depth > 3 and len(node[0]) == 1 and len(node[1]) == 1: if prev: traverse(prev, 1)[0] += node[0][0] if next: traverse(next, 0)[0] += node[1][0] parent[position] = [0] raise StopIteration explode(node[0], depth + 1, prev, node[1], node, 0) explode(node[1], depth + 1, node[0], next, node, 1) def split(node, parent = None, position = -1): if len(node) == 1: if node[0] > 9: parent[position] = [[node[0] // 2], [(node[0] + 1) // 2]] raise StopIteration else: split(node[0], node, 0) split(node[1], node, 1) def reduce_number(number): while True: try: explode(number) split(number) return number except StopIteration: pass def magnitude(node): if len(node) == 1: return node[0] return 3 * magnitude(node[0]) + 2 * magnitude(node[1]) print(magnitude(reduce(lambda x, y: reduce_number([deepcopy(x), deepcopy(y)]), numbers))) print(max(magnitude(reduce_number([deepcopy(n1), deepcopy(n2)])) for n1 in numbers for n2 in numbers if n1 != n2))

Dold text
PermalÀnk
Medlem
●

Dag: 18
Kod: C++

LÄngt och rörigt, sÄ postar bara lÀnk till lösning: https://github.com/gbroll/AoC-2021/blob/main/c%2B%2B/day_18/d...

Hade jÀttesvÄrt att fÄ ihop magnitudberÀkningen, eftersom jag sparade data i en vektor med par (nivÄ, vÀrde) och var tvungen att ge mig pÄ en iterativ lösning. Hade kanske varit mer intuitivt med en rekursiv lösning men dÄ hade jag vÀl behövt en för ÀndamÄlet bÀttre lÀmpad datastruktur...

Dold text
PermalÀnk
Medlem
●

Dag:18
SprÄk: C#

Lösning: https://github.com/langebangen/AOC/blob/main/2021/AOC2021/Puz...

JÀkligt rörigt, men fick till det till slut..

Dold text
PermalÀnk
Medlem ★
●

Dag: 19
SprÄk: Python

Nu börjar det bli knepigt...

Jag rÀknar ut avstÄnden mellan olika beacons, dessa Àr oberoende av sensorns rotation och position.
Hitta största snittet mellan avstÄnden för tvÄ sensorer (s1, s2)
Identifiera vilka punkter i s1 och s2 som matchar varandra genom att se vilka avstÄnd som hör till de olika punkterna.
Pröva alla rotationer tills vi hittar en dÀr man kan subtrahera s2s koordinater frÄn s1s och fÄ samma offset i x-, y- och z-led för alla koordinatpar.
Rotera, addera offset och slÄ ihop.
För uppgift tvÄ behöver man Àven hÄlla reda pÄ offset och transformera dessa pp samma sÀtt för att Manhattan-distansen skall bli rÀtt.

from collections import defaultdict, Counter from itertools import product, permutations, combinations import re import numpy as np def compute_beacon_distances(scanners): return [set(np.square(s[i2] - s[i1]).sum() for i1, i2 in combinations(range(len(s)), 2)) for s in scanners] def find_largest_intersection_pair(bds): return max((len(bds[i1] & bds[i2]), i1, i2) for i1, i2 in combinations(range(len(bds)), 2)) def find_common_beacons(s1, s2, bds): intersect = bds[s1] & bds[s2] shared = [defaultdict(list) for _ in range(len(bds))] for i in [s1, s2]: s = scanners[i] for i1, i2 in combinations(range(len(s)), 2): diff = np.square(s[i2] - s[i1]).sum() if diff in intersect: shared[i][tuple(s[i1])].append(diff) shared[i][tuple(s[i2])].append(diff) wanted_length = Counter([len(si[1]) for s in shared for si in s.items()]).most_common()[0][0] same = defaultdict(list) for s in shared: for k, v in s.items(): if len(v) == wanted_length: # Filter out spurious hits same[tuple(sorted(v))].append(k) # Only keep the ones with one coordindate from each set a = np.array([l for l in same.values() if len(l) == 2]) return a[:,0,:], a[:,1,:] def find_transform(c1, c2): for t in permutations(np.eye(3, dtype=int)): for s in product([-1,1],[-1,1],[-1,1]): rotated_c2 = np.array([np.dot(np.array(t) * np.array(s), i) for i in c2]) diffs = [Counter(coord) for coord in (c1 - rotated_c2).T] if sum(map(len, diffs)) == 3: # Unique diff in all 3 directions? return (np.array(t) * np.array(s), [o for i in diffs o]) def merge_beacons(s1, s2, rot, offset): set1 = set(tuple(b) for b in scanners[s1]) set2 = set(tuple(b) for b in np.array([np.dot(rot, i) for i in scanners[s2]]) + offset) set12 = np.array(list(set1 | set2)) scanners[s1] = set12 del scanners[s2] def transform_offsets(alloffsets, s1, s2, rot, offset): alloffsets[s1].append(np.array(offset)) for o in alloffsets[s2]: alloffsets[s1].append(np.array(np.dot(rot, o)) + offset) del alloffsets[s2] scanners = [np.array([list(map(int, b)) for b in re.findall("(\-?\d+),(\-?\d+),(\-?\d+)", blob)]) for blob in open("input19").read().split("\n\n")] alloffsets = [[] for _ in scanners] while len(scanners) > 1: bds = compute_beacon_distances(scanners) _, s1, s2 = find_largest_intersection_pair(bds) c1, c2 = find_common_beacons(s1, s2, bds) rot, offset = find_transform(c1, c2) merge_beacons(s1, s2, rot, offset) transform_offsets(alloffsets, s1, s2, rot, offset) print(len(scanners[0])) print(max(np.absolute(alloffsets[0][i1] - alloffsets[0][i2]).sum() for i1, i2 in combinations(range(len(alloffsets[0])), 2)))

Dold text
StÀdade lite i koden :)