🌟 Advent of Code (AoC) 2021 🌟

PermalÀnk
Medlem ★
●

Dag: 10
SprÄk: Go

var chars map[rune]rune = map[rune]rune{ '(': ')', '[': ']', '{': '}', '<': '>', } type stack []rune func main() { fileName := "input.txt" input, err := helpers.ReadLines(fileName) if err != nil { panic(err) } fmt.Println(syntaxChecker(input)) } func syntaxChecker(input []string) (incorrect, incomplete int) { incompleteScores := make([]int, 0) for _, line := range input { result, faulty := checkLine(line) if faulty { incorrect += result } else { incompleteScores = append(incompleteScores, result) } } sort.Ints(incompleteScores) return incorrect, incompleteScores[len(incompleteScores)/2] } func checkLine(input string) (result int, incomplete bool) { stack := make(stack, 0) for _, r := range input { if _, ok := chars[r]; ok { stack.push(r) } else { opening, _ := stack.pop() if chars[opening] != r { return getIncorrectScore(r), true } } } return getStackScore(stack), false } func getStackScore(s stack) (result int) { for i := len(s) - 1; i >= 0; i-- { result *= 5 result += getIncompleteScore(s[i]) } return } func getIncompleteScore(r rune) int { switch r { case '(': return 1 case '[': return 2 case '{': return 3 case '<': return 4 default: return 0 } } func getIncorrectScore(r rune) int { switch r { case ')': return 3 case ']': return 57 case '}': return 1197 case '>': return 25137 default: return 0 } } func (s *stack) isEmpty() bool { return len(*s) == 0 } func (s *stack) pop() (rune, bool) { if s.isEmpty() { return ' ', true } element := (*s)[len((*s))-1] *s = (*s)[:len((*s))-1] return element, false } func (s *stack) push(element rune) { *s = append(*s, element) }

Dold text
PermalÀnk
Hedersmedlem ★
●

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

Klart lÀttare Àn gÄrdagens för mig, och vÀldigt mycket lÀttare Àn dag 8 del 2. Ska försöka ge mig pÄ den sistnÀmnda nu, kÀnns inte bra att ha nÄt gammalt ligga kvar, och idag har jag Àntligen tid att faktiskt göra mer Àn minimum.

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: 10
SprÄk: Rust

const PAIR: &[char; 4] = &['<', '(', '[', '{']; const SCORE: &[u32; 4] = &[25137, 3, 57, 1197]; const SCORE2: &[usize; 4] = &[4, 1, 2, 3]; fn main() { let input = std::fs::read_to_string("input.txt").unwrap(); println!( "Part 1: {}", input .lines() .filter_map(|f| process(f, false).err()) .map(|chr| match_with(chr, SCORE)) .sum::<u32>() ); // 411471 let mut scores = input .lines() .filter(|f| process(f, false).is_ok()) .filter_map(|f| process(f, true).ok()) .map(|f| { f.iter() .fold(0usize, |acc, &chr| acc * 5 + match_with(chr, SCORE2)) }) .collect::<Vec<_>>(); scores.sort_unstable(); println!("Part 2: {}", scores[scores.len() / 2]); // 3122628974 } fn process(s: &str, repair: bool) -> Result<Vec<char>, char> { let mut acc = vec![]; for value in s.chars() { if matches!(value, '>' | ')' | ']' | '}') { if repair { acc.pop(); } else { acc.pop() .filter(|&p| p == match_with(value, PAIR)) .ok_or(value)?; } } else { acc.push(value) } } acc.reverse(); Ok(acc) } fn match_with<T: Copy>(chr: char, m: &[T; 4]) -> T { match chr { '>' | '<' => m[0], ')' | '(' => m[1], ']' | '[' => m[2], '}' | '{' => m[3], _ => panic!("brunsÄs"), } }

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: 8
SprÄk: JavaScript
Jag blir knÀpp, suttit en bra stund med AoC dag 8 uppgift 2.

Med testinput sÄ stÀmmer varje delvÀrde och summan.
FÄr reda pÄ att mitt svar Àr för lÄgt med den riktiga datan, och jag kan inte begripa varför.

https://pastebin.com/qS2WQuNf

Hittade felet sjÀlv, i min matchning för nollan hade jag missat att checka av en sista
0 Àr det nÀr den inte matchar 6 eller 9, jag hade missat sexan

PermalÀnk
Medlem ★
●

Dag: 10
SprÄk: F#

let parse = System.IO.File.ReadAllLines >> Seq.map (Seq.toList) let findCorrupted input = let opposite = function | ')' -> '(' | ']' -> '[' | '}' -> '{' | '>' -> '<' | x -> failwithf "Wrong input" let rec findCorrupted' tokens input = match input with | [] -> None | '('::rest -> findCorrupted' ('('::tokens) rest | '['::rest -> findCorrupted' ('['::tokens) rest | '{'::rest -> findCorrupted' ('{'::tokens) rest | '<'::rest -> findCorrupted' ('<'::tokens) rest | closing::rest -> match tokens with | char::queue when char = opposite closing -> findCorrupted' queue rest | _ -> Some closing findCorrupted' [] input let findUnmatched = let opposite = function | '(' -> ')' | '[' -> ']' | '{' -> '}' | '<' -> '>' | _ -> failwithf "Got unexpected character" let findUnmatched' tokens char = match char with | '(' | '[' | '{' | '<' -> (opposite char::tokens) //Here we assume that we have filtered any invalid combinations before | _ -> (tokens |> List.tail) List.fold findUnmatched' [] let task1 = let scorer = function | ')' -> 3 | ']' -> 57 | '}' -> 1197 | '>' -> 25137 | _ -> failwithf "Not expected" Seq.choose findCorrupted >> Seq.sumBy scorer let task2 input = let scorer = let scorer' char = match char with | ')' -> 1L | ']' -> 2L | '}' -> 3L | '>' -> 4L | _ -> failwithf "Not expected" Seq.fold (fun state cur -> (state*5L+(scorer' cur))) 0L let points = input |> Seq.filter (findCorrupted >> Option.isNone) |> Seq.map findUnmatched |> Seq.map scorer |> Seq.sort let middleIndex = (points |> Seq.length)/2 points |> Seq.item middleIndex let data = parse "input.txt" printfn "Task 1: %i" (data |> task1) printfn "Task 2: %i" (data |> task2)

Dold text
Visa signatur

Jag Àr en optimist; det Àr aldrig sÄ dÄligt sÄ att det inte kan bli sÀmre.

PermalÀnk
Hedersmedlem ★
●

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

"Löste" Àntligen dag 8 del 2. KÀnner dock fortfarande inte att jag löst den, eftersom jag i slutÀndan körde brute force för att testa alla möjliga mappings mellan de olika kopplingarna (5040 st per rad att testa).

Nu nÀr jag fÄtt fram rÀtt svar kÀnns det dock mer OK att kolla in andras lösningar. Vill lösa alla sjÀlv utan hints, men denna gÄngen fick det bli en fullösning för att jag inte skulle ge upp helt.
Har helt fastnat i mitt tÀnk och kanske kommer fÄ en "men för fan..."-upplevelse nÀr jag ser andras lösningar.

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:

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

"Löste" Àntligen dag 8 del 2. KÀnner dock fortfarande inte att jag löst den, eftersom jag i slutÀndan körde brute force för att testa alla möjliga mappings mellan de olika kopplingarna (5040 st per rad att testa).

Nu nÀr jag fÄtt fram rÀtt svar kÀnns det dock mer OK att kolla in andras lösningar. Vill lösa alla sjÀlv utan hints, men denna gÄngen fick det bli en fullösning för att jag inte skulle ge upp helt.
Har helt fastnat i mitt tÀnk och kanske kommer fÄ en "men för fan..."-upplevelse nÀr jag ser andras lösningar.

Renskrev precis min dag 8 del 2 lösning. Kanske gÄr att förstÄ bÀttre nu. Ingen brute force lösning.

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: 9
SprÄk: C#

internal class Day09 : Puzzle { private static int _xMax; private static int _yMax; public override object PartOne() { var map = GetLocations().ToDictionary(p => (p.X, p.Y)); return map.Where(p => GetAdjacentLocations(map, p.Key.X, p.Key.Y).All(a => a.Height > p.Value.Height)) .Sum(p => p.Value.Height + 1); } public override object PartTwo() { var map = GetLocations().ToDictionary(p => (p.X, p.Y)); return map.Where(p => GetAdjacentLocations(map, p.Key.X, p.Key.Y).All(a => a.Height > p.Value.Height)) .Select(x => GetBasinSize(map, x.Key.X, x.Key.Y)) .OrderByDescending(x => x) .Take(3) .Aggregate(1, (current, basin) => current * basin); } private static IEnumerable<Location> GetAdjacentLocations(IDictionary<(int, int), Location> map, int x, int y) { return new (int X, int Y)[] { (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1) } .Where(a => a.X.IsBetween(0, _xMax) && a.Y.IsBetween(0, _yMax)) .Select(a => map[(a.X, a.Y)]); } private static int GetBasinSize(IDictionary<(int, int), Location> map, int x, int y) => GetBasin(map, x, y).Distinct().Count() + 1; private static IEnumerable<Location> GetBasin(IDictionary<(int, int), Location> map, int x, int y) { var higherAdjacentLocations = GetAdjacentLocations(map, x, y) .Where(a => a.Height != 9 && a.Height > map[(x, y)].Height) .ToArray(); return higherAdjacentLocations.Concat(higherAdjacentLocations.SelectMany(a => GetBasin(map, a.X, a.Y))); } private IEnumerable<Location> GetLocations() { var rows = Utilities.GetInput(GetType()) .Split(Environment.NewLine); _yMax = rows.Length - 1; _xMax = rows[0].Length - 1; for (var y = 0; y < rows.Length; y++) for (var x = 0; x < rows[y].Length; x++) yield return new Location(x, y, (int)char.GetNumericValue(rows[y][x])); } private record Location(int X, int Y, int Height); }

Dold text

Dag: 10
SprÄk: C#

internal class Day10 : Puzzle { public override object PartOne() { return GetChunks() .Select(x => ValidateChunk(x, new Stack<char>())) .Where(x => x.Status == ChunkStatusEnum.Corrupted) .Sum(x => GetChunkOperator(x.FirstInvalidCharacter).FirstScore); } public override object PartTwo() { var scores = GetChunks() .Select(x => ValidateChunk(x, new Stack<char>())) .Where(x => x.Status == ChunkStatusEnum.Incomplete) .Select(x => CalculateScore(x.RemainingCharacters)) .OrderBy(x => x) .ToArray(); return scores[(scores.Length - 1) / 2]; } private static (ChunkStatusEnum Status, char? FirstInvalidCharacter, Stack<char> RemainingCharacters) ValidateChunk(Queue<char> chunk, Stack<char> openings) { if (chunk.Count == 0) return openings.Count == 0 ? (ChunkStatusEnum.Valid, null, openings) : (ChunkStatusEnum.Incomplete, null, openings); var currentChar = chunk.Dequeue(); if (IsClosingCharacter(currentChar)) return openings.Pop() == GetChunkOperator(currentChar).Opening ? ValidateChunk(chunk, openings) : (ChunkStatusEnum.Corrupted, currentChar, openings); openings.Push(currentChar); return ValidateChunk(chunk, openings); } private static long CalculateScore(IEnumerable<char> characters) => characters.Aggregate<char, long>(0, (sum, c) => sum * 5 + GetChunkOperator(c).SecondScore); private static ChunkOperator GetChunkOperator(char? op) => ChunkOperators.Single(x => x.Opening == op || x.Closing == op); private static bool IsClosingCharacter(char op) => ChunkOperators.Any(x => x.Closing == op); private static ChunkOperator[] ChunkOperators => new[] { new ChunkOperator('(', ')', 3, 1), new ChunkOperator('[', ']', 57, 2), new ChunkOperator('{', '}', 1197, 3), new ChunkOperator('<', '>', 25137, 4) }; private IEnumerable<Queue<char>> GetChunks() { return Utilities.GetInput(GetType()) .Split(Environment.NewLine) .Select(x => new Queue<char>(x.ToCharArray())); } private record ChunkOperator(char Opening, char Closing, int FirstScore, int SecondScore); private enum ChunkStatusEnum { Valid, Incomplete, Corrupted } }

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

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

Snabbaste Del 1 för i Är, sÄhÀr lÄngt (1719) men sen gjorde jag varenda fel i boken pÄ Del 2.

  • Missade att man skulle multiplicera med 5.

  • Hade gjort fel pĂ„ min filtrering av inkompletta rader.

  • Gjord fel pĂ„ "att hĂ€mta mitten-vĂ€rdet" i listan.

  • Sorterade inte listan med poĂ€ng.

Allt som allt tog det 30 minuter extra för Del 2, vilket givetvis var för mycket för att fÄ nÄgon nÀmnvÀrd placering.

Dold text

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

VÀldigt straight-forward idag, imho. Det var dock en hel del kod att skriva -- för mig -- sÄ trillade in runt plats 4 000. Blev ocksÄ rejÀlt biten av att jag inte kunde göra:

grid[np.argwhere(grid > 9)] = 0

IstÀllet var jag tvungen att göra:

for (cx, cy) in np.argwhere(grid > 9): grid[cx, cy] = 0

@MultiMike, @survivalcode eller @Ingetledigtnamn kanske vet varför? (Och har kanske allmÀna tips kring hur jag kan banta ner min lösning!?)

Dold text
Visa signatur

:(){ :|:& };:

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

PermalÀnk
●
Skrivet av GLaDER:

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

VÀldigt straight-forward idag, imho. Det var dock en hel del kod att skriva -- för mig -- sÄ trillade in runt plats 4 000. Blev ocksÄ rejÀlt biten av att jag inte kunde göra:

grid[np.argwhere(grid > 9)] = 0

IstÀllet var jag tvungen att göra:

for (cx, cy) in np.argwhere(grid > 9): grid[cx, cy] = 0

@MultiMike, @survivalcode eller @Ingetledigtnamn kanske vet varför? (Och har kanske allmÀna tips kring hur jag kan banta ner min lösning!?)

Dold text

FörvÀntade mig mer kod Àn sÄ nÀr jag klickade pÄ lÀnken, jag har sjÀlv nÄgonting liknande :).

AngÄende np.argwhere sÄ ger det tillbaka en matris dÀr varje rad innehÄller index för den cell som uppfyller vilkoret. Dvs

[[i1,j1],[i2,j2],[i3,j3],[i4,j4]]

NÀr du sen försöker indexera med dessa gör du nÄgot som kallas "advanced indexing", vilket Àr en generalisering av hur indexering med integers sker om jag förstÄr det rÀtt. Precis som nÀr du indexerar med M[row_idx, col_idx] sÄ kommer M[row_matrix, col_matrix] indexera M genom att kombinera row & col. I ditt fall skickar du bara in row_matrix, vilket gör att du bara indexerar i första dimensionen och fÄr tillbaka alla kolumner för de rader som matchar.

Ett alternativ Àr np.nonzero(condition) som ger tillbaka tvÄ matriser pÄ formatet

([i1,i2,i3,i4],[j1,j2,j3,j4])

, dessa kan du sedan anvÀnda för indexering.

Min personliga favorit Àr dock att anvÀnda boolmasken direkt för indexering;

grid[grid > 9] = 0

PermalÀnk
Medlem
●

Dag: 11
SprÄk: Rust

const ADJACENT: &[(i64, i64); 8] = &[ (-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1), ]; const WIDTH: i64 = 10; const HEIGHT: i64 = 10; macro_rules! check_and_update { ($input:expr, $arr:expr, $count:expr, $x:expr, $y:expr) => {{ $input[$y][$x] += 1; if $input[$y][$x] > 9 { $input[$y][$x] = 0; $count += 1; $arr.push(($x, $y)) } }}; } fn main() { let mut input: Vec<Vec<_>> = std::fs::read_to_string("input.txt") .unwrap() .lines() .map(|s| { s.chars() .filter_map(|c| c.to_digit(10).map(|d| d as usize)) .collect() }) .collect(); println!("{}", part1(&mut input.clone())); // 1665 println!("{}", part2(&mut input)); // 235 } fn part1(input: &mut Vec<Vec<usize>>) -> u64 { (0..100).fold(0, |acc, _| acc + calc_step(input)) } fn part2(input: &mut Vec<Vec<usize>>) -> u64 { let mut steps = 0; while !input.iter().all(|a| a.iter().all(|&b| b == 0)) { calc_step(input); steps += 1; } steps } fn calc_step(input: &mut Vec<Vec<usize>>) -> u64 { let mut flashes = vec![]; let mut count = 0; for y in 0..input.len() { for x in 0..input[0].len() { check_and_update!(input, flashes, count, x, y); } } while !flashes.is_empty() { for flash in flashes.drain(0..).collect::<Vec<_>>() { flashes.append( &mut adjacent(flash).iter().fold(vec![], |mut acc, &(x, y)| { if input[y][x] != 0 { check_and_update!(input, acc, count, x, y); } acc }), ) } } count } fn adjacent((x, y): (usize, usize)) -> Vec<(usize, usize)> { ADJACENT .iter() .filter(|&(dx, dy)| { let x = x as i64; let y = y as i64; x + dx >= 0 && y + dy >= 0 && x + dx < WIDTH && y + dy < HEIGHT }) .map(|&(dx, dy)| ((x as i64 + dx) as usize, (y as i64 + dy) as usize)) .collect() }

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
●

Dag: 11
SprÄk: Scala

object Day11 { val data = readLines("11/data.txt") case class Elem(idx: Int, value: Int, affect: Seq[Int]) { def reset = copy(value = 0) def inc(count: Int) = copy(value = value + count) } def main(args: Array[String]): Unit = { def idx(x: Int, y: Int) = y * 10 + x val elems = for(y <- 0 until 10; x <- 0 until 10) yield { val value = data(y)(x).toString.toInt val valid = (0 until 10).toSet val affect = for { dy <- -1 to 1 dx <- -1 to 1 if dx != 0 || dy != 0 if valid(x + dx) && valid(y + dy) } yield idx(x + dx, y + dy) Elem(idx(x, y), value, affect) } def step(elems: Seq[Elem], toIncrease: Seq[Int]): (Seq[Elem], Int) = { if(toIncrease.isEmpty) { (elems, 0) } else { val plusOne = elems.map { e => e.inc(toIncrease.count(_ == e.idx)) } val (flashed, other) = plusOne.partition(_.value > 9) val affected = flashed.flatMap(_.affect) val (subSeq, subFlashed) = step(other, affected) (subSeq ++ flashed.map(e => e.reset), flashed.size + subFlashed) } } // part 1 var es: Seq[Elem] = elems var totFlashes = 0 for(_ <- 0 until 100) { val (newEs, flashes) = step(es, 0 until 100) totFlashes += flashes es = newEs } println(totFlashes) // part 2 es = elems val allFlashStepOpt = Iterator.from(1).find { i => val (newEs, flashes) = step(es, 0 until 100) es = newEs flashes == 100 } println(allFlashStepOpt) } }

Dold text
PermalÀnk
Medlem
●

Dag: 11
SprÄk: C#

Roligt pussel idag. Skapade en hjÀlpklass för att hantera iteration av ett rutnÀt, och en punkts grannar etc.

internal class Puzzle11 : Puzzle<int> { private int[,] _grid = default!; protected override void Solve(string[] lines) { _grid = Grid.CreateGrid(lines); int step = 0, totalFlashCount = 0; while (true) { step++; var flashedSquids = new HashSet<(int x, int y)>(); var flashCount = Grid.Iterate(_grid).Sum(c => Flash(c, flashedSquids)); if (step <= 100) { totalFlashCount += flashCount; } if (flashCount == _grid.Length) { break; } } One = totalFlashCount; Two = step; } private int Flash((int x, int y) coord, ISet<(int x, int y)> flashedSquids) { if (flashedSquids.Contains(coord)) { return 0; } if (_grid[coord.x, coord.y] < 9) { _grid[coord.x, coord.y]++; return 0; } _grid[coord.x, coord.y] = 0; flashedSquids.Add(coord); return 1 + Grid.GetNeighbours(_grid, coord, true) .Sum(n => Flash(n, flashedSquids)); } }

Dold text
PermalÀnk
●

Dag: 11
SprÄk: Nim
Lösning: Github

KÀnner inte att jag behÀrskar vektorisering riktigt Àn, sÄ blev lite mÄnga for loopar istÀllet.

Dold text
PermalÀnk
Medlem
●

Dag: 11
SprÄk: Carth

(import std) (define main (do io/bind (<- input (io/map unwrap! (read-file "inputs/day11.txt"))) (let ((flat-array (array/collect (map (<o to-int (flip - ascii-0)) (flat-map string/bytes (lines input))))) (grid (array/collect (array/chunks (to-nat 10) flat-array))))) (display (str-append "Part 1: " (show-int (part1 grid)))) (display (str-append "Part 2: " (show-int (part2 1 grid)))))) (define (part1 grid) (car (foldl (fun ([n grid] _) (map-car (+ n) (step grid))) [0 grid] (xrange 0 100)))) (define (part2 n-steps grid) (let1 [n grid] (step grid) (if (= n 100) n-steps (part2 (inc n-steps) grid)))) (define (step grid) (define (filter-flashing grid ixs) (filter (<o (= 10) (flip array/lookup2d! grid)) ixs)) (define (flash-octopuses n grid) (fmatch (case None [n (array/map (array/map (fun (x) (if (> x 9) 0 x))) grid)]) (case (Some [ix rest]) (let ((as (adjecents (map-both to-int ix))) (grid (foldl (fun (grid a) (array/modify2d! inc a grid)) grid as))) (flash-octopuses (+ n 1) grid (next (iter/chain rest (filter-flashing grid as)))))))) (let ((grid (array/map (array/map inc) grid)) (flashing (filter-flashing grid (iter/cartesian (range (to-nat 0) (to-nat 9)) (range (to-nat 0) (to-nat 9))))) ([n grid] (flash-octopuses 0 grid (next flashing)))) [n grid])) (define (adjecents [i j]) (iter/cartesian (range (to-nat (max 0 (- i 1))) (to-nat (min 9 (+ i 1)))) (range (to-nat (max 0 (- j 1))) (to-nat (min 9 (+ j 1))))))

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: 11
SprÄk: Python

from numpy import array, full, where, logical_and, logical_not from itertools import product, count, takewhile a = array([list(map(int, [d for d in s.strip()])) for s in open("input11s").readlines()]) xs, ys = a.shape def neighbors(x, y): coords = [(x + xi, y +yi) for xi, yi in product(range(-1, 2), range(-1, 2)) if (xi or yi) and 0 <= x + xi < xs and 0 <= y + yi < ys] return tuple(map(array,zip(*coords))) def step(a, flashed = full(a.shape, False)): a += 1 while (new := logical_and(a > 9, logical_not(flashed))).any(): flashed = a > 9 for p in zip(*where(new)): a[neighbors(*p)] += 1 a[where(flashed)] = 0 return flashed.sum() l = list(takewhile(lambda x: x < 100, map(lambda _: step(a), count()))) print(sum(l[0:100]), len(l) + 1) # +1 for iteration where takewhile stopped

Dold text
PermalÀnk
●

Dag: 11
SprÄk: Python 3

import numpy as np from scipy.signal import convolve2d grid = np.array([[int(x) for x in line.rstrip()] for line in open("11.in")]) flash_count = 0 step = 0 while grid.any(): step += 1 grid += 1 has_flashed = np.zeros_like(grid, dtype=bool) while not np.all((could_flash := (grid > 9)) == has_flashed): grid += convolve2d(could_flash & ~has_flashed, [[1, 1, 1], [1, 0, 1], [1, 1, 1]], "same") has_flashed[could_flash] = True flash_count += np.sum(has_flashed) grid[could_flash] = 0 if step == 100: print(flash_count) print(step)

Dold text
PermalÀnk
Medlem
●
Skrivet av survivalcode:

Dag: 11
SprÄk: Python 3

import numpy as np from scipy.signal import convolve2d grid = np.array([[int(x) for x in line.rstrip()] for line in open("11.in")]) flash_count = 0 step = 0 while grid.any(): step += 1 grid += 1 has_flashed = np.zeros_like(grid, dtype=bool) while not np.all((could_flash := (grid > 9)) == has_flashed): grid += convolve2d(could_flash & ~has_flashed, [[1, 1, 1], [1, 0, 1], [1, 1, 1]], "same") has_flashed[could_flash] = True flash_count += np.sum(has_flashed) grid[could_flash] = 0 if step == 100: print(flash_count) print(step)

Dold text

Snyggt, tÀnkte inte alls pÄ att man kunde lösa det med faltning.

Dold text
PermalÀnk
Medlem
●

Dag: 11
SprÄk: C++

#include <set> #include <climits> #include <chrono> #include "../utils/file_reader.cpp" #include "../utils/result_printer.cpp" typedef pair<int,int> coord; typedef vector<vector<int>> grid; grid parse(vector<string> str_data) { vector<vector<int>> data; int n_rows = str_data.size(); for (auto const row:str_data) { vector<int> row_data; for (char const num:row) { row_data.push_back(num-48); } data.push_back(row_data); } return data; } vector<coord> get_neighbours() { vector<coord> neighbours = {{1,-1},{1,0},{1,1},{0,1},{0,-1},{-1,-1},{-1,0},{-1,1}}; return neighbours; } int solve(grid data, bool part2) { int n_flashes = 0; int step_flashes; int n_steps = part2? INT_MAX : 100; int n = data[0].size(); int m = data.size(); int nm = n*m; set<pair<int,int>> flash_coords; vector<coord> nbs = get_neighbours(); for (int step = 0; step < n_steps; step++) { if (part2 && step_flashes == nm) { return step; } step_flashes = 0; //first substep for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (data[i][j] == 9) { data[i][j] = 0; n_flashes++; step_flashes++; flash_coords.insert(make_pair(i, j)); } else { data[i][j]++; } } } //second substep while (flash_coords.size() > 0) { set<pair<int, int>> coords(flash_coords); flash_coords.clear(); for (const auto &coord : coords) { for (const auto &nb:nbs) { int ip = coord.first + nb.first; int jp = coord.second + nb.second; if (ip >= 0 && ip < m && jp >= 0 && jp < n) { if (data[ip][jp] == 9) { data[ip][jp] = 0; n_flashes++; step_flashes++; flash_coords.insert(make_pair(ip,jp)); } else if (data[ip][jp]>0) { data[ip][jp]++; } } } } } } return n_flashes; } int main() { int day = 11; auto start = chrono::high_resolution_clock::now(); string filename = "../../input/day_" + to_string(day) + ".txt"; vector<string> string_data = read_file<string>(filename,true); grid data = parse(string_data); auto parsed = chrono::high_resolution_clock::now(); int part_1 = solve(data, false); int part_2 = solve(data, true); auto solved = chrono::high_resolution_clock::now(); vector<chrono::high_resolution_clock::time_point> time_stamps{start , parsed, solved}; print_results<int>(day, part_1, part_2, time_stamps); }

Dold text
PermalÀnk
Medlem ★
●

dag 11
sprÄk C#
lösning github

slogs alltför lÀnge mot edge cases idag, sÄ del 1 tog en vÀldans tid. men att de synkroniserar sig efter ett tag, som del 2 handlade om, det blev jag ju varse tidigare Àn tÀnkt dÄ iaf... sÄ del 1, timmar; del 2, knappt en minut.

Dold text
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
Hedersmedlem ★
●

Dag: 11
SprÄk: TypeScript (med Node.js)
Lösning: day11.ts, common.ts (klasserna GenericGrid samt Coordinate ligger hÀr)

Mycket kod men inga större svÄrigheter, tack och lov. Skönt med en del 2 som gick att lösa pÄ rÀtt kort tid nÀr del 1 var fÀrdig.

Borde kanske faktorera ut Square, Grid och Coordinate sÄ de Àr delade mellan olika dagars pussel, har anvÀnt nÄgot vÀldigt snarlikt pÄ minst tvÄ andra uppgifter nu... men jag vet inte om jag orkar. Vill Àven göra om Dag 8 del 2 och optimera Dag 9 -- och ska jag faktorera ut klasserna bör jag Àven uppdatera uppgifterna som anvÀnde dem...

Edit: Jag gjorde sÄ, koden ovan uppdaterad. Har inte tagit mig an de Àldre uppgifterna som anvÀnder nÀstan identisk Grid-klass Ànnu dock.

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
●

Lade rÀtt mycket tid pÄ uppgift 8 men jag fick till den till slut.
Det gÄr antagligen att göra det Ànnu bÀttre dock men den ger mig i alla fall rÀtt svar sÄ det kan inte vara helt tokigt.
Det lÀr visa sig om jag kommer ikapp men det Àr ju ingen brÄdska direkt.
SÄ detta Àr alltsÄ min lösning för dag 8 i Dyalog APL.

]dinput decodenumbers←{ ⍝ digits contain proper segments for each digit (0-9) digits←'abcefg' 'cf' 'acdeg' 'acdfg' 'bcdf' 'abdfg' 'abdefg' 'acf' 'abcdefg' 'abcdfg' ⎕IO←0 allsegments←'abcdefg' segment←' '(≠⊆⊱)⊃'|'(≠⊆⊱)⍔ numbers←' '(≠⊆⊱)1⊃'|'(≠⊆⊱)⍔ (cf bcdf acf abcdefg)←,segmentâŒżâ€1⍚2 4 3 7∘.=,≱¹segment (adg abfg)←∩/segmentâŒżâ€1⍚5 6∘.=,≱¹segment a←acf~cf aeg←abcdefg~bcdf bd←bcdf~cf ce←abcdefg~abfg,adg bd←bcdf~cf d←adg~abfg b←bd~d eg←aeg~a c←ce~eg e←ce~c f←cf~c g←eg~e position←∊a b c d e f g 10⊄{digits⍳↓allsegments/⍚position∊↑⍔}šnumbers } ⎕IO←0 ⍝ Read data digitnotes←⊃⎕NGET 'data/2021_dag8.txt'1 ⍝ Check length of all output values, 2=1, 4=4, 3=7,7=8 (segments = number) 'Part one:',+/+⌿2 4 3 7∘.=,≱¹↑1⌷[1]' '(≠⊆⊱)¹↑'|'(≠⊆⊱)šdigitnotes 'Part 2:',+/decodenumbers šdigitnotes

Dold text
Kom pÄ ett snyggare sÀtt att hantera funktionen
PermalÀnk
Hedersmedlem ★
●

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

Skam den som ger sig.
6.2 ms, till skillnad frÄn originalet med brute force (inlÀgg hÀr) som tog 5810 ms. Inte sÄ lÄngt ifrÄn 1000 ggr snabbare.

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: 11
SprÄk: Go

type position struct { x, y, charge, hash int neighbours []int flashed bool } type Grid map[int]*position func main() { fileName := "input.txt" input, err := helpers.ReadLines(fileName) if err != nil { panic(err) } start := time.Now() grid := initGrid(input) flashes := 0 allFlashed := false index := 0 for !allFlashed { newFlashes := grid.calculateFlashes() if newFlashes == 100 { fmt.Println(time.Since(start)) fmt.Println(index + 1) allFlashed = !allFlashed } if index < 100 { flashes += newFlashes } index++ } fmt.Println(flashes) } func initGrid(input []string) (grid Grid) { grid = make(Grid) for y, line := range input { row := make([]position, len(line)) for x, val := range line { charge := int(val - '0') pos := position{charge: charge, x: x, y: y} pos.neighbours = make([]int, 0) for x1 := -1; x1 <= 1; x1++ { if x+x1 >= 0 && x+x1 < len(row) { for y1 := -1; y1 <= 1; y1++ { if y+y1 >= 0 && y+y1 < len(input) { if x1 != 0 || y1 != 0 { pos.neighbours = append(pos.neighbours, hash(x+x1, y+y1)) } } } } } hash := hash(x, y) pos.hash = hash grid[hash] = &pos } } return } func (grid *Grid) calculateFlashes() (flashes int) { flashed := make([]position, 0) for _, position := range *grid { position.charge = (position.charge + 1) % 10 position.flashed = false if position.charge == 0 { flashes++ position.flashed = true flashed = append(flashed, *position) } } for len(flashed) > 0 { newFlashed := make([]position, 0) for _, pos := range flashed { for _, neighbourHash := range pos.neighbours { neighbour := (*grid)[neighbourHash] if !neighbour.flashed { neighbour.charge = (neighbour.charge + 1) % 10 if neighbour.charge == 0 { flashes++ neighbour.flashed = true newFlashed = append(newFlashed, *neighbour) } } } } flashed = newFlashed } return } func hash(x, y int) int { if x >= y { return x*x + x + y } return x + y*y }

Dold text
PermalÀnk
99:e percentilen ★
●
Skrivet av Yoshman:

Dag: 9
SprÄk: Rust

Gillar skarpt syntax highlighting i foruminlÀgg, men man skulle vÀl kunna sÀga att det finns teman som blir mer lÀsbara med @Soitoras mörka tema.

Visa signatur

Skrivet med hjÀlp av Better SweClockers

PermalÀnk
Medlem ★
●
Skrivet av GLaDER:

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

VÀldigt straight-forward idag, imho. Det var dock en hel del kod att skriva -- för mig -- sÄ trillade in runt plats 4 000. Blev ocksÄ rejÀlt biten av att jag inte kunde göra:

grid[np.argwhere(grid > 9)] = 0

IstÀllet var jag tvungen att göra:

for (cx, cy) in np.argwhere(grid > 9): grid[cx, cy] = 0

@MultiMike, @survivalcode eller @Ingetledigtnamn kanske vet varför? (Och har kanske allmÀna tips kring hur jag kan banta ner min lösning!?)

Dold text

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

Jag har svÄrt för det hÀr med rekursion. Jag ser ju direkt att en uppgift som denna lÀmpar sig vÀldigt vÀl för en rekursiv DFS, men trots det sitter jag lÀÀÀÀnge och försöker göra en iterativ variant. Tillslut fick jag ge upp och ge mig ut pÄ rekursionsjakt pÄ Internet. Aja. TillrÀckligt mÄnga sÄdana hÀr uppgifter sÄ kanske jag ger med mig och lÀr mig gilla rekursion.

Dold text
Visa signatur

:(){ :|:& };:

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

PermalÀnk
●

Dag: 12
SprÄk: Python

Nej, den Àr inte optimerad för lÀsbarhet eller prestanda.

from collections import defaultdict from typing import List neighbours = defaultdict(list) for line in open("12.in"): a, b = line.rstrip().split("-") neighbours[a].append(b) neighbours[b].append(a) def explore(cave: str, seen: List[str], allow_double_visits: bool) -> int: return int(cave == "end") + sum( explore(neighbour, seen + [cave] if cave.islower() else seen, not_seen and allow_double_visits) for neighbour in neighbours[cave] if ((not_seen := (neighbour not in seen)) or allow_double_visits) and cave not in ("start", "end") ) print(sum(explore(start, [], False) for start in neighbours["start"])) print(sum(explore(start, [], True) for start in neighbours["start"]))

Dold text
PermalÀnk
●
Skrivet av GLaDER:

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

Jag har svÄrt för det hÀr med rekursion. Jag ser ju direkt att en uppgift som denna lÀmpar sig vÀldigt vÀl för en rekursiv DFS, men trots det sitter jag lÀÀÀÀnge och försöker göra en iterativ variant. Tillslut fick jag ge upp och ge mig ut pÄ rekursionsjakt pÄ Internet. Aja. TillrÀckligt mÄnga sÄdana hÀr uppgifter sÄ kanske jag ger med mig och lÀr mig gilla rekursion.

Dold text

Började ocksĂ„ pĂ„ en iterativ variant men gav upp rĂ€tt snabbt nĂ€r det blev för svĂ„rt :). Är sjĂ€lv ett fan av rekursionslösningar; identifiera mĂ„ldefinition samt hur du tar dig till nĂ€sta steg sĂ„ Ă€r problemet löst mer eller mindre.

Dold text
PermalÀnk
●

Dag: 12
SprÄk: Scala

Tips till de som tycker rekursion Àr jobbigt:
Börja frÄn "andra sidan"! TÀnk ut avbrottsvillkoret först, dvs dÄ funktionen inte ska anropa rekursivt.
DÄ brukar det lösa sig automatiskt hur man ska bryta ner data för att nÀrma sig avbrottsvillkoret.
Och sen Àr det ju som vanligt, övning ger fÀrdighet.

object Day12 { val data = readLines("12/data.txt") val links = data.flatMap { case s"$from-$to" => Seq(from -> to, to -> from) } .groupMap(_._1)(_._2) def large(cave: String) = cave.head.isUpper def small(cave: String) = !large(cave) def main(args: Array[String]): Unit = { type Path = Seq[String] // part 1 def explore1(path: Path): Seq[Path] = { if(path.last == "end") { Seq(path) } else { val paths = for { cave <- links(path.last) if large(cave) || !path.contains(cave) } yield explore1(path :+ cave) paths.flatten } } println(explore1(Seq("start")).size) // part 2 def explore2(path: Path, allowDuplicates: Boolean = true): Seq[Path] = { if(path.last == "end") { Seq(path) } else { val paths = for { cave <- links(path.last) duplicate = small(cave) && path.contains(cave) if cave != "start" if large(cave) || !duplicate || allowDuplicates } yield explore2(path :+ cave, allowDuplicates && !duplicate) paths.flatten } } println(explore2(Seq("start")).size) } }

Dold text
PermalÀnk
Datavetare ★
●

Dag: 12
SprÄk: Rust

Postar en lite enklare version Ă€n den som jag valt att spara. Siktar sjĂ€lv pĂ„ att minimera körtiden för att lösa alla 25 dagar sĂ„ mycket som möjligt. Den slutgiltiga Ă€r ~4 gĂ„nger snabbare Ă€n den postade. ÄndĂ„ första dagen det tar mer Ă€n 1,0 ms att lösa bĂ„da delproblemen (det inkluderar inlĂ€sning och utskrift av resultat)

Den postade löser problemet pÄ ~9,1 ms pÄ en M1

use crate::solution::Solution; use std::collections::HashMap; struct Day12 { steps: HashMap<Cave, Vec<Cave>>, } impl Solution for Day12 { fn part1(&mut self) -> String { self.count_paths(VisitOnce::default()).to_string() } fn part2(&mut self) -> String { self.count_paths(VisitOneTwice::default()).to_string() } } impl Day12 { fn count_paths(&self, visited: impl Visited) -> u32 { let mut num_paths = 0; let mut stack = Vec::new(); for step in self.steps.get(&Cave::Start).unwrap() { stack.push((step, visited)); } while let Some(step) = stack.pop() { let (cave, mut visited) = step; if let Cave::Small(cave_id) = cave { visited.insert(*cave_id); } for next_step in self.steps.get(cave).unwrap() { match *next_step { Cave::Small(cave_id) => { if visited.contains(cave_id) { continue; } }, Cave::Large(_) => (), Cave::End => { num_paths += 1; continue; }, Cave::Start => continue, } stack.push((next_step, visited)); } } num_paths } } pub fn new(input: &str) -> Box<dyn Solution> { let mut large_caves = Vec::new(); let mut small_caves = Vec::new(); let mut steps = HashMap::new(); for step_desc in input.lines() { let mut parts = step_desc.split('-'); let cave0 = to_cave(parts.next().unwrap(), &mut large_caves, &mut small_caves); let cave1 = to_cave(parts.next().unwrap(), &mut large_caves, &mut small_caves); steps.entry(cave0).or_insert(Vec::new()).push(cave1); steps.entry(cave1).or_insert(Vec::new()).push(cave0); } Box::new(Day12{ steps, }) } fn to_cave(desc: &str, large_caves: &mut Vec<String>, small_caves: &mut Vec<String>) -> Cave { if desc == "end" { return Cave::End; } if desc == "start" { return Cave::Start; } let is_small_cave = desc.chars().next().unwrap().is_ascii_lowercase(); let caves = if is_small_cave { small_caves } else { large_caves }; let id = if let Some(id) = caves.iter().position(|d| d == desc) { id } else { caves.push(desc.to_string()); caves.len() - 1 } as CaveId; if is_small_cave { Cave::Small(id) } else { Cave::Large(id) } } type CaveId = u32; #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] enum Cave { Start, End, Large(CaveId), Small(CaveId), } trait Visited: Copy { fn contains(&self, cave_id: CaveId) -> bool; fn insert(&mut self, cave_id: CaveId); } #[derive(Default, Clone, Copy)] struct VisitOnce { visited: CaveId, } impl Visited for VisitOnce { fn contains(&self, cave_id: CaveId) -> bool { (self.visited & (1 << cave_id)) != 0 } fn insert(&mut self, cave_id: CaveId) { self.visited |= 1 << cave_id; } } #[derive(Default, Clone, Copy)] struct VisitOneTwice { visited: CaveId, something_visited_twice: bool, } impl Visited for VisitOneTwice { fn contains(&self, cave_id: CaveId) -> bool { self.something_visited_twice && (self.visited & (1 << cave_id)) != 0 } fn insert(&mut self, cave_id: CaveId) { if (self.visited & (1 << cave_id)) == 0 { self.visited |= 1 << cave_id; } else { self.something_visited_twice = true; } } }

Dold text
Skrivet av GLaDER:

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

Jag har svÄrt för det hÀr med rekursion. Jag ser ju direkt att en uppgift som denna lÀmpar sig vÀldigt vÀl för en rekursiv DFS, men trots det sitter jag lÀÀÀÀnge och försöker göra en iterativ variant. Tillslut fick jag ge upp och ge mig ut pÄ rekursionsjakt pÄ Internet. Aja. TillrÀckligt mÄnga sÄdana hÀr uppgifter sÄ kanske jag ger med mig och lÀr mig gilla rekursion.

Dold text

För DFS Àr det trivialt att konvertera den rekursiva versionen till en iterativ variant, bara stoppa in en stack-variabel och pusha argumenten dit i stÀllet för att göra anropet.

Den iterativa varianten har flera fördelar över den rekursiva:

  • I alla sprĂ„k utom Go (finns det andra?) Ă€r storleken pĂ„ stacken en fix storlek, dĂ€rför inte generellt OK att köra den rekursiva versionen medan den iterativa bara begrĂ€nsas av tillgĂ€nglig mĂ€ngd RAM (förutsatt att det finns en heap)

  • den iterativa varianten kommer i de flesta fall vara nĂ„got snabbare, CPU slipper sĂ€tta upp/ta ned "call-frames"

Rekursion ger ofta enklare och mer intuitiva lösningar jÀmfört med iterativa varianter, och i praktiken fungerar det sÀker riktigt bra i de flesta fall.

För egen del har jag blivit biten tillrÀckligt mÄnga gÄnger av rekursiva lösningar för att undvika dem sÄ lÄngt som möjligt. Men det beror en hel del pÄ att jag jobbat mycket med OS-kernels samt resurssvaga inbyggda-system, dÀr kan man inte kosta pÄ sig stora anropsstackar!

Dold text
Visa signatur

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