🌟 Advent of Code (AoC) 2022 🌟

PermalÀnk
●

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

Förra Äret gav jag upp efter dag 12, ska försöka kÀmpa lite lÀngre i Är.

PermalÀnk
Medlem
●

Dag: 12

Python
Hamnade Àven jag i en hemsk sökning som tog för lÄng tid att exekvera.

Lösningen blev:
1) rÀkna upp steg-nummer
2) Iterera över nuvarande position(er) och gÄ ett steg frÄn dessa Ät alla hÄll om möjligt
3) MÀrk dessa nya positioner (om dom inte redan Àr satta) med steg-nummer och börja om i steg 1 med dessa nya positioner
avbryt detta nÀr end-positionen fÄr ett vÀrde.

Av vad ni skriver hÀr verkar det vara en BFS lösning?

file = open("input")

dirs = {(1,0), (0,1),(-1,0),(0,-1)}

values={}
grid ={}
curr=[]

for x,line in enumerate(file):
for y,char in enumerate(line.strip()):
if char == "S" or char =="a":
grid[x,y] =1
curr.append((x,y))
elif char == "E":
grid[x,y] =26
end = x,y
else:
grid[x,y] = ord(char)-96

step = 0
while True:
step += 1
prep = []
for i in curr:
for d in dirs:
point = (i[0] + d[0]),(i[1] + d[1])
if point in grid:
if not point in values:
if grid[i]+1 >= grid[point]:
values[point] = step
prep.append(point)
if point==end:
print(step)
exit()
curr = prep

Dold text
PermalÀnk
Medlem ★
●
Skrivet av Pie-or-paj:

Jag fÄr nog titta pÄ eventuella optimeringar senare och tar gÀrna emot tips pÄ detta men just nu Àr jag sjukt nöjd att det gick att lösa. Riktigt kul uppgift tyckte jag som aldrig sett nÄgot liknande innan.

Det Àr ett standardproblem (som t.ex. sortering) som kallas "pathfinding" och precis som andra standardproblem finns det standardalgorithmer. Dijkstra Àr troligtvis den som Àr mest basic och Àr den "enklaste" lösningen. A* eller A-star kanske du har hört talas om i samband med spel vilket Àr en vanlig, mer optimerad optimerad, variant av Dijkstra.

En kodmÀssigt enklare lösning men lite mindre uppenbar (och ointressant om du pratar om optimeringar) Àr att se kartan som en graf och göra en BFS. Allt det hÀr Àr olika graf-sök/navigerings algorithmer dÀr Breadth-first search Àr en av de mest grundlÀggande och pathfinding ett specifikt subsÀtt. Om du pluggar coputer science kommer dÄ fÄ höra om och implementera ett helt gÀng olika och defiinitivt dessa tre.

SÄ Àr du sugen pÄ att lÀra dig lite mer och optimera koden rekommenderar jag varmt att försöka implementera Dijkstra utifrÄn pseudokoden pÄ Wikipedia Ett typexempel pÄ bra att ha gjort nÄgon gÄng sÄ att du vet vad du ska söka efter nÀr det kommer upp men definitivt inget som en behöver kunna utantill.

Tips/lösning till dag 12

Hemska flashbacks till den tiden man pluggade dÄtidens "AI"... Slag under bÀltet!

Visa signatur

CPU: 7950X 5GHz@1.1v | RAM: 32GB 6000MHz CL36 | GPU: KFAÂČ 3090 SG w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3 / Supreme CD-99

PermalÀnk
Medlem ★
●
Skrivet av Mickur:

Lite ledtrÄdar ifall du Ängrar dig!

Tack, jag tolkade det som att man skulle komma pÄ helt nytt sÀtt att hantera sin "oro"

och inte att man kunde köra modula med den gemensamma nÀmnaren

Dold text

vilket verkade galet komplext och dÄ hade jag redan lagt mer tid Àn jag Àr beredd att lÀgga per dag.

GL

Visa signatur

Att föresprÄka Mac pÄ Swec Àr som att föresprÄka hybridbilar pÄ en raggartrÀff i Mora.

PermalÀnk
Medlem ★
●

Dag: 12
SprÄk: Kotlin

Överkomplicerade ettan lite, dĂ„ jag trodde att uppgiften i tvĂ„an skulle anvĂ€nda vĂ€gen man gĂ„tt, men sĂ„ blev det inte. Jag funderade pĂ„ att skriva om till en minimum spaning tree för andra delen, men kör bara ettan frĂ„n alla startpositioner istĂ€llet 😅 Det var jobbiga krav med att den kan gĂ„ nedĂ„t men inte upp sĂ„ kĂ€nner inte för det.

val map = input.lines().flatMapIndexed { y, s -> s.mapIndexed { x, c -> Pair(Point(x, y), when(c) { 'S' -> 0 'E' -> 'z'.code - 97 else -> c.code - 97 }) }}.toMap() fun find(char: Char): Point { val y = input.lines().indexOfFirst {it.contains(char) } val x = input.lines()[y].indexOfFirst { it == char } return Point(x, y) } val goal = find('E') fun dijkstra(startNode: Point):Triple<Point?, Point, Int> { val queue = PriorityQueue<Triple<Point?, Point, Int>>(compareBy { it.third }) val visited = mutableSetOf<Point>() queue.add(Triple(null, startNode, 0)) while (queue.isNotEmpty()) { val thisNode = queue.poll() if (thisNode.second in visited) continue if (thisNode.second == goal) return thisNode visited.add(thisNode.second) val thisHeight = map[thisNode.second]!! for (point in thisNode.second.nearbyCardinal().filter { it in map.keys}) { val height = map[point]!! if (height - thisHeight <= 1) { queue.add(Triple(thisNode.second, point, thisNode.third + 1)) } } } return Triple(null, Point(0, 0), -1) } println(dijkstra(find('S')).third) // Part 1 println(map.filter { it.value == 0 }.map { dijkstra(it.key) }.map { it.third }.filter { it >0 }.minOf { it }) // Part 2 }

Dold text
Visa signatur

i5-7600k . GTX 1080 . 16 GB

PermalÀnk
●
Skrivet av Pie-or-paj:

Jag fÄr nog titta pÄ eventuella optimeringar senare och tar gÀrna emot tips pÄ detta men just nu Àr jag sjukt nöjd att det gick att lösa. Riktigt kul uppgift tyckte jag som aldrig sett nÄgot liknande innan.

Det Àr ett standardproblem (som t.ex. sortering) som kallas "pathfinding" och precis som andra standardproblem finns det standardalgorithmer. Dijkstra Àr troligtvis den som Àr mest basic och Àr den "enklaste" lösningen. A* eller A-star kanske du har hört talas om i samband med spel vilket Àr en vanlig, mer optimerad optimerad, variant av Dijkstra.

En kodmÀssigt enklare lösning men lite mindre uppenbar (och ointressant om du pratar om optimeringar) Àr att se kartan som en graf och göra en BFS. Allt det hÀr Àr olika graf-sök/navigerings algorithmer dÀr Breadth-first search Àr en av de mest grundlÀggande och pathfinding ett specifikt subsÀtt. Om du pluggar coputer science kommer dÄ fÄ höra om och implementera ett helt gÀng olika och defiinitivt dessa tre.

SÄ Àr du sugen pÄ att lÀra dig lite mer och optimera koden rekommenderar jag varmt att försöka implementera Dijkstra utifrÄn pseudokoden pÄ Wikipedia Ett typexempel pÄ bra att ha gjort nÄgon gÄng sÄ att du vet vad du ska söka efter nÀr det kommer upp men definitivt inget som en behöver kunna utantill.

Tips/lösning till dag 12

Tackar och bockar, ska titta pÄ nÀrmare pÄ det och se om jag kan fÄ ner tiden lite

PermalÀnk
Medlem ★
●

Dag: 12
SprÄk: C++

Kul med lite repetition av bfs

#include <queue> #include <vector> #include "../AoCHelper/AoCHelper.h" struct square { char height{}; bool visited{false}; bool isEnd{false}; std::vector<square *> neighbours{}; square *previous{nullptr}; }; int bfs(square *start) { std::queue<square *> q; q.push(start); start->visited = true; while (!q.empty()) { square *s = q.front(); q.pop(); if (s->isEnd) { int answer{}; while (s->previous != nullptr) { ++answer; s = s->previous; } return answer; } for (square *n : s->neighbours) { if (!n->visited) { n->visited = true; n->previous = s; q.push(n); } } } return INT_MAX; } void parseNeighbours(std::vector<std::vector<square *>> &squareMap) { for (int i = 0; i < squareMap.size(); ++i) { for (int j = 0; j < squareMap[i].size(); ++j) { square *s = squareMap[i][j]; if (i > 0 && (squareMap[i - 1][j]->height) <= (s->height + 1)) { s->neighbours.push_back(squareMap[i - 1][j]); } if (i < squareMap.size() - 1 && (squareMap[i + 1][j]->height) <= (s->height + 1)) { s->neighbours.push_back(squareMap[i + 1][j]); } if (j > 0 && (squareMap[i][j - 1]->height) <= (s->height + 1)) { s->neighbours.push_back(squareMap[i][j - 1]); } if (j < squareMap[i].size() - 1 && (squareMap[i][j + 1]->height) <= (s->height + 1)) { s->neighbours.push_back(squareMap[i][j + 1]); } } } } void resetNeighbours(std::vector<std::vector<square *>> &squareMap) { for (int i = 0; i < squareMap.size(); ++i) { for (int j = 0; j < squareMap[i].size(); ++j) { square *s = squareMap[i][j]; s->visited = false; s->previous = nullptr; } } } void delete_squareMap(std::vector<std::vector<square *>> &squareMap) { for (int i = 0; i < squareMap.size(); ++i) { for (int j = 0; j < squareMap[i].size(); ++j) { delete squareMap[i][j]; } } } void puzzle_one(std::vector<std::string> input) { int answer{}; square *start; std::vector<std::vector<square *>> squareMap; for (int i = 0; i < input.size(); ++i) { std::string row = input[i]; std::vector<square *> squares; for (int j = 0; j < row.size(); ++j) { char c = row[j]; square *s = new square(); if (c == 'S') { s->height = 'a'; start = s; } else if (c == 'E') { s->isEnd = true; s->height = 'z'; } else { s->height = c; } squares.push_back(s); } squareMap.push_back(squares); } parseNeighbours(squareMap); answer = bfs(start); std::cout << "Puzzle one: " << answer << std::endl; delete_squareMap(squareMap); } void puzzle_two(std::vector<std::string> input) { int answer{INT_MAX}; std::vector<square *> startingCandidates{}; std::vector<std::vector<square *>> squareMap; for (int i = 0; i < input.size(); ++i) { std::string row = input[i]; std::vector<square *> squares; for (int j = 0; j < row.size(); ++j) { char c = row[j]; square *s = new square(); if (c == 'S' || c == 'a') { s->height = 'a'; startingCandidates.push_back(s); } else if (c == 'E') { s->isEnd = true; s->height = 'z'; } else { s->height = c; } squares.push_back(s); } squareMap.push_back(squares); } parseNeighbours(squareMap); for (square *start : startingCandidates) { answer = std::min(answer, bfs(start)); resetNeighbours(squareMap); } std::cout << "Puzzle two: " << answer << std::endl; delete_squareMap(squareMap); } int main() { std::vector<std::string> exampleInput{"Sabqponm", "abcryxxl", "accszExk", "acctuvwj", "abdefghi"}; AoCHelper a1{"2022", "12"}; std::vector<std::string> result = a1.get_input(); puzzle_one(result); puzzle_two(result); }

Dold text
PermalÀnk
Medlem
●

Dag: 4
SprÄk: C
Lösning:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include "common.h" #define MAX_ROW_LEN 16 typedef struct _range { __uint8_t low; __uint8_t high; __uint8_t length; } range; range makeRange(char* strInOut) { range retVal; char *ptr; ptr = strtok(strInOut, "-"); retVal.low = atoi(ptr); ptr = strtok(NULL, "-"); retVal.high = atoi(ptr); retVal.length = retVal.high - retVal.low; return retVal; } __uint8_t rangeContainedInRange(range range1, range range2) { __uint8_t low = range1.low < range2.low? range1.low : range2.low; __uint8_t high = range1.high > range2.high? range1.high : range2.high; __uint8_t length = high-low; if (length == range1.length || length == range2.length) { return 1; } return 0; } __uint8_t rangesOverlap(range range1, range range2) { if (range1.low <= range2.high && range2.low <= range1.high) { return 1; } return 0; } __uint16_t* solve_day_04() { static __uint16_t result[2] = {0, 0}; FILE* inputFile; char lineBuf[MAX_ROW_LEN]; char *str1, *str2; inputFile = fopen("input/day_04.txt", "r"); while (fgets(lineBuf, MAX_ROW_LEN, inputFile)) { str1 = strtok(lineBuf, ","); str2 = strtok(NULL, ","); range elf1Sections = makeRange(str1); range elf2Sections = makeRange(str2); result[0] += rangeContainedInRange(elf1Sections, elf2Sections); result[1] += rangesOverlap(elf1Sections, elf2Sections); } fclose(inputFile); return &result[0]; } int main(void) { __uint16_t* res = solve_day_04(); printf("**AoC-2022 day 4 part 1: %d **\n", res[PART_ONE]); printf("**AoC-2022 day 4 part 2: %d **\n", res[PART_TWO]); }

Dold text
PermalÀnk
Datavetare ★
●

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

BFS med multicore anvÀndning i del 2...

goos: darwin goarch: arm64 pkg: aoc2022 BenchmarkDay12_parsing-10 119095 8559 ns/op BenchmarkDay12_part1-10 1850 641310 ns/op BenchmarkDay12_part2-10 24 49364207 ns/op PASS ok aoc2022 3.841s

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 ★
●
Skrivet av GLaDER:

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

Jag tycker att de hÀr uppgifterna borde bli lÀttare med tiden, men sÄ verkar inte vara fallet

Dold text

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

eval() gjorde parsningen trivial, sen skrev jag en rekursiv ordered() som spottade ur sig True | False | None beroende pÄ sortering. Det löste Del 1. I Del 2 fick jag nys om cmp_to_key() och efter att ha skrivit om min ordered() sÄ den returnerade -1 | 1 | 0 istÀllet var vi hemma

Kul uppgift Àven om jag inte hade koll pÄ cmp_to_key() och fick hjÀlp av bekanta pÄ Slack för att hitta den funktionen.

Dold text
Visa signatur

:(){ :|:& };:

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

PermalÀnk
●

Haha! Ligger lite efter

Dag: 2
SprÄk: Zig

const std = @import("std"); fn score_play(a: u8, b: u8) u8 { return b + 1 + (4 + b - a) % 3 * 3; } fn score_play2(a: u8, b: u8) u8 { return score_play(a, (a + (b + 2) % 3) % 3); } pub fn main() !u8 { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = arena.allocator(); const input = try std.fs.cwd().readFileAlloc(allocator, "input_day2", 12000); const stdout = std.io.getStdOut().writer(); var score : u32 = 0; var score2 : u32 = 0; var i : usize = 0; while (i < input.len) { const ia = input[i] - 'A'; const ib = input[i + 2] - 'X'; score += score_play(ia, ib); score2 += score_play2(ia, ib); i += 4; } try stdout.print("Score: {}\n", .{score}); try stdout.print("Score 2: {}\n", .{score2}); return 0; }

Dold text
PermalÀnk
●

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

Nim Àr kompilerat sÄ finns ingen "eval" sÄ jag parsade varje rad som JSON istÀllet. Var ren och skÀr tur att jag skrev del 1 pÄ rÀtt format för att kunna anvÀnda samma funktion för min sortering. Men jag klagar inte

Dold text
PermalÀnk
Medlem ★
●

Dag: 13
SprÄk: Rust
Lösing:

use serde_json::Value; use std::cmp::Ordering; fn parse(input: &str) -> Vec<(Value, Value)> { let mut pairs = vec![]; let mut first = None; for line in input.lines() { if line.is_empty() { continue; } let v: Value = serde_json::from_str(line).expect("not json"); if let Some(f) = first { pairs.push((f, v)); first = None; } else { first = Some(v); } } pairs } fn check_pair((a, b): (&Value, &Value)) -> Ordering { match (a, b) { (Value::Number(a), Value::Number(b)) => { let a = a.as_i64().unwrap(); let b = b.as_i64().unwrap(); a.cmp(&b) } (Value::Array(a), Value::Array(b)) => a .iter() .zip(b.iter()) .fold(Ordering::Equal, |res, (a, b)| { res.then_with(|| check_pair((a, b))) }) .then(a.len().cmp(&b.len())), (Value::Array(_), Value::Number(_)) => { check_pair((a, &Value::Array(vec![b.clone()]))) } (Value::Number(_), Value::Array(_)) => { check_pair((&Value::Array(vec![a.clone()]), b)) } _ => { panic!("not supported") } } } pub fn one() { let input = include_str!("input1.txt"); let pairs = parse(input); let mut result = 0; for (index, (a, b)) in pairs.iter().enumerate() { if check_pair((a, b)) == Ordering::Less { result += index + 1; } } println!("Day 13, part 1: {}", result); } pub fn two() { let input = include_str!("input1.txt"); let mut packets = parse(input) .into_iter() .flat_map(|(a, b)| vec![a, b]) .collect::<Vec<_>>(); let divider1: Value = serde_json::from_str("[[2]]").unwrap(); let divider2: Value = serde_json::from_str("[[6]]").unwrap(); packets.push(divider1.clone()); packets.push(divider2.clone()); packets.sort_by(|a, b| { check_pair((a, b)) }); let pos1 = packets.iter().position(|p| p == &divider1).unwrap() + 1; let pos2 = packets.iter().position(|p| p == &divider2).unwrap() + 1; let result = pos1 * pos2; println!("Day 13, part 2: {:?}", result); }

Dold text
PermalÀnk
Medlem ★
●

Dag: 9
SprÄk: Node (JS)

import { testData, data } from "../input/day9.js"; const directions = { 'R': [1, 0], 'L': [-1, 0], 'D': [0, -1], 'U': [0, 1] } function touching(x1, y1, x2, y2) { return Math.abs(x1 - x2) <= 1 && Math.abs(y1 - y2) <= 1 } function solveA(input) { let hx = 0, hy = 0, tx = 0, ty = 0; const visited = {}; const rows = input.split('\n'); for (let row of rows) { let [operation, num] = row.split(' '); num = parseInt(num); const [dx, dy] = directions[operation]; for (let i = 1; i <= num; i++) { hx += dx; hy += dy; if (!touching(hx, hy, tx, ty)) { const diffX = hx === tx ? 0 : (hx - tx) / Math.abs(hx - tx); const diffY = hy === ty ? 0 : (hy - ty) / Math.abs(hy - ty); tx += diffX; ty += diffY; } const str = `${tx} ${ty}`; visited[str] = 1; } } console.log(Object.keys(visited).length) } function solveB(input) { const knots = []; for (let i = 1; i <= 10; i++) { const knot = [0, 0]; knots.push(knot); } let hx = 0, hy = 0, tx = 0, ty = 0; function move(dx, dy) { knots[0][0] += dx; knots[0][1] += dy; for (let i = 1; i < 10; i++) { [hx, hy] = knots[i - 1]; [tx, ty] = knots[i]; if (!touching(hx, hy, tx, ty)) { const diffX = hx === tx ? 0 : (hx - tx) / Math.abs(hx - tx); const diffY = hy === ty ? 0 : (hy - ty) / Math.abs(hy - ty); tx += diffX; ty += diffY; } knots[i] = [tx, ty]; } } const visited = {}; const rows = input.split('\n'); for (let row of rows) { let [operation, num] = row.split(' '); num = parseInt(num); const [dx, dy] = directions[operation]; for (let i = 1; i <= num; i++) { hx += dx; hy += dy; move(dx, dy); const [x, y] = knots.at(-1); const str = `${x} ${y}`; visited[str] = 1; } } console.log(Object.keys(visited).length) } const solutionA = () => { solveA(data); } const solutionB = () => { solveB(data); } export { solutionA, solutionB }

Dold text
PermalÀnk
Datavetare ★
●

Dag: 13
SprÄk: Go
Lösning: GitHub

Kod

goos: darwin goarch: arm64 pkg: aoc2022 BenchmarkDay13_parsing-8 2804 426078 ns/op 750517 B/op 9023 allocs/op BenchmarkDay13_part1-8 478545 2459 ns/op 1 B/op 0 allocs/op BenchmarkDay13_part2-8 17823 67079 ns/op 28437 B/op 9 allocs/op PASS ok aoc2022 5.329s

Benchmark
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 ★
●

Dag: 13
SprÄk: C#

using System.Diagnostics; using AoCUtils; Console.WriteLine("Mickur's Advent of Code 2022 - Day 13!"); // Setup var input = File.ReadAllLines("input.txt"); var ParsedInput = new List<object>(); var PartOneAnswer = 0; var PartTwoAnswer = 0; var sw = new Stopwatch(); sw.Start(); // Parsing foreach (var line in input) { if(!string.IsNullOrWhiteSpace(line)) ParsedInput.Add(ParseArray(line)); } sw.Stop(); Console.WriteLine($"Finished parsing in {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} ticks)"); sw.Restart(); // Part One var rightIndicies = new List<int>(); for (var i = 0; i < ParsedInput.Count; i += 2) { var leftObjects = ParsedInput[i]; var rightObjects = ParsedInput[i + 1]; var result = CompareArrays((List<object>) leftObjects, (List<object>) rightObjects); if (result == -1) { rightIndicies.Add((i / 2) + 1); } } PartOneAnswer = rightIndicies.Sum(); sw.Stop(); Console.WriteLine($"Finished part one in {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} ticks)"); sw.Restart(); // Part Two /*var newStuff = new List<object>(); foreach (var line in input) { if(!string.IsNullOrWhiteSpace(line)) newStuff.Add(ParseArray(line)); }*/ var div1 = ParseArray("[[2]]"); var div2 = ParseArray("[[6]]"); //newStuff.Add(div1); //newStuff.Add(div2); ParsedInput.Add(div1); ParsedInput.Add(div2); ParsedInput.Sort(delegate(object arr1, object arr2) { return CompareArrays((List<object>) arr1, (List<object>) arr2); }); var div1Index = 0; var div2Index = 0; for (int i = 0; i < ParsedInput.Count; i++) { if (ParsedInput[i] == div1) { div1Index = i + 1; } if (ParsedInput[i] == div2) { div2Index = i + 1; } } PartTwoAnswer = div1Index * div2Index; sw.Stop(); Console.WriteLine($"Finished part two in {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} ticks)"); Console.WriteLine($"Part One answer: {PartOneAnswer}"); Console.WriteLine($"Part Two answer: {PartTwoAnswer}"); List<object> ParseArray(ReadOnlySpan<char> span) { var depth = 0; var objects = new List<object>(); var tempstring = ""; for (var i = 0; i < span.Length; i++) { char currChar = span[i]; // int is complete, parse it and save it! if (currChar == ',' || currChar == ']') { if (tempstring != "") { var value = AoCParsing.FastIntParse(tempstring); objects.Add(value); tempstring = ""; } } if (currChar == '[') // This is our array! { // If we find a new array on our level, parse it! if (depth == 1) { var toAdd = ParseArray(span.Slice(i)); objects.Add(toAdd); } depth++; } if (currChar == ']') // This is our array! { if (depth == 1) return objects; depth--; } if (char.IsDigit(currChar) && depth == 1) { tempstring += currChar; } } return objects; } int CompareArrays(List<object> array1, List<object> array2) { var maxLength = Math.Max(array1.Count, array2.Count); for (var i = 0; i < maxLength; i++) { // Left is empty, right order! if (i >= array1.Count) return -1; // Right is empty, wrong order! if (i >= array2.Count) return 1; // Both are Ints if (array1[i] is int && array2[i] is int) { var a = (int)array1[i]; var b = (int)array2[i]; if (a < b) { return -1; } if (a > b) { return 1; } } // Make sure both are lists else { var a = array1[i] is List<object> ? (List<object>)array1[i] : new List<object> { (int)array1[i] }; var b = array2[i] is List<object> ? (List<object>)array2[i] : new List<object> { (int)array2[i] }; var result = CompareArrays(a, b); if (result != 0) return result; } } return 0; }

Varning för hemsk kod

Amen fyfan. Spenderat flera timmar pÄ att leta fel i min kod och sÄ visar det sig att jag anvÀnt fel variabel i en check. Jaja, nu borde del 1 gÄ igenom!

Tji fick jag, testdatat gÄr utan problem, men inte min egen input.

Edit: Ah, det Àr inte bara 1-9 i input nu, attans, mer parsing!

Edit 2: SĂ„ja!

Edit 3: Verkar ha gjort precis rÀtt för del 2

Edit 4: Och dÀr blev bÄda klara! Koden Àr dock helt otroligt hemsk.

Hur det gick för mig...
Visa signatur

CPU: 7950X 5GHz@1.1v | RAM: 32GB 6000MHz CL36 | GPU: KFAÂČ 3090 SG w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3 / Supreme CD-99

PermalÀnk
Medlem
●

Dag: 13
SprÄk: C#

Ähh exempeldatan fungerade fint men inte nĂ€r jag testade med min input.. Precis som Mickur ovan sĂ„ tĂ€nkte jag inte pĂ„ att ett nummer kunde vara högre Ă€n 9. NĂ€r vĂ€l det var fixat sĂ„ gick det bĂ€ttre

namespace AOC2022.Puzzles; internal class Puzzle13 : Puzzle<int> { private static readonly string[] DividerPackets = new string[] { "[[2]]", "[[6]]"}; record Signal(int Value, List<Signal> Children) { public override string ToString() => Value >= 0 ? Value.ToString() : $"[{string.Join(",", Children)}]"; } protected override void Solve(string[] lines) { var comparer = new SignalComparer(); var signals = lines.Where(x => !string.IsNullOrWhiteSpace(x)).Select(Parse).ToList(); One = signals .Chunk(2) .Select((x, idx) => (first: x[0], second: x[1], idx: idx + 1)) .Sum(x => comparer.Compare(x.first, x.second) == -1 ? x.idx : 0); Two = signals .Concat(DividerPackets.Select(Parse)) .OrderBy(x => x, comparer) .Select((signal, idx) => (signal, idx: idx + 1)) .Where(x => DividerPackets.Contains(x.signal.ToString())) .Aggregate(1, (a, b) => a * b.idx); } private static Signal Parse(string signal) { var stack = new Stack<Signal>(); var brackets = new char[] { '[', ']' }; for (var i = 0; i < signal.Length; i++) { var s = signal[i]; if (s == '[') { stack.Push(new(-1, new())); } else if (s == ']') { var currSignal = stack.Pop(); if (!stack.TryPeek(out var parent)) { return currSignal; } parent.Children.Add(currSignal); } else { var remainingSignal = signal[i..]; var toIdx = remainingSignal.IndexOfAny(brackets); var values = remainingSignal[..toIdx] .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => new Signal(int.Parse(s), new())) .ToList(); if (values.Count > 0) { stack.Peek().Children.AddRange(values); i += toIdx - 1; } } } throw new Exception("Invalid signal"); } private static (Signal first, Signal second) Normalize(Signal first, Signal second) => (first.Value, second.Value) switch { (-1, >= 0) => (first, second with { Children = new() { new(second.Value, new()) }, Value = -1 }), (>= 0, -1) => (first with { Children = new() { new(first.Value, new()) }, Value = -1 }, second), _ => (first, second) }; class SignalComparer : IComparer<Signal> { public int Compare(Signal? x, Signal? y) { var (first, second) = Normalize(x!, y!); return first.Value >= 0 && second.Value >= 0 ? first.Value.CompareTo(second.Value) : first.Children.Zip(second.Children) .Select(x => Compare(x.First, x.Second)) .FirstOrDefault(x => x != 0, first.Children.Count.CompareTo(second.Children.Count)); } } }

Dold text
PermalÀnk
Medlem ★
●

Dag: 12
SprÄk: Python

import numpy as np g = np.array([[c for c in l.strip()] for l in open(name).readlines()]) s, e = tuple(zip(*np.where(g == 'S')))[0], tuple(zip(*np.where(g == 'E')))[0] g[s] = 'a' g[e] = 'z' def bfs(s, e, g0, allowed, success, sentinel): g = np.full(np.array(g0.shape) + 2, sentinel) g[1:-1,1:-1] = g0 bf, e, visited = [[(s[0] + 1, s[1] + 1)]], (e[0] + 1, e[1] + 1), set() while bf: path = bf.pop(0) p = path[0] if success(p, g, e): return path if p in visited: continue visited.add(p) bf += [[q] + path for q in [(p[0]+1,p[1]),(p[0]-1,p[1]),(p[0],p[1]+1),(p[0],p[1]-1)] if allowed(p, q, g) ] print(len(bfs(s, e, g, lambda p, q, g: ord(g[p]) + 2 > ord(g[q]), lambda p, g, e: p == e, '~')) -1, len(bfs(e, s, g, lambda p, q, g: ord(g[q]) >= ord(g[p]) - 1, lambda p, g, e: g[p] == 'a', ' ')) - 1)

Dold text
PermalÀnk
Medlem ★
●

Dag: 13
SprÄk: Python

Dagens fultrick: Returnera bool (true/false) eller None, dÀr None betyder att man ska kolla nÀsta element.

from itertools import chain from functools import cmp_to_key def compare(left, right): if isinstance(left, int): if isinstance(right, int): return None if left == right else left < right return compare([left], right) if isinstance(right, int): return compare(left, [right]) if not left: return True if right else None if not right: return False if (res := compare(left[0], right[0])) is None: res = compare(left[1:], right[1:]) return res ps = [tuple(eval(l) for l in ll.split('\n')) for ll in open("input13").read().split('\n\n')] s = sorted(chain(*[[l,r] for l, r in ps + [([[2]],[[6]])]]), key=cmp_to_key(lambda x, y: [1, -1][compare(x, y)])) print(sum([i + 1 for i, (l, r) in enumerate(ps) if compare(l, r)]), (s.index([[2]]) + 1) * (s.index([[6]]) + 1))

Dold text
PermalÀnk
Medlem ★
●

Dag: 10
SprÄk: Node (Js)

import { data, testData } from "../input/day10.js"; function solveA(input) { const interesting = [20, 60, 100, 140, 180, 220] const rows = input.split('\n'); let x = 1; let op = 0; let ans = 0; for (const row of rows) { const [left, right] = row.split(' '); if (right) { const num = parseInt(right) op++; if (interesting.includes(op)) { ans += op * x; } op++; if (interesting.includes(op)) { ans += op * x; } x += num; } else { op++; if (interesting.includes(op)) { ans += op * x; } } } console.log(ans) // -1 } function solveB(input) { const isHash = (x, screenX) => { return (x === screenX || x === screenX - 1 || x === screenX + 1); } let x = 1, screenX = -1, line = ''; const screen = []; const rows = input.split('\n'); for (const row of rows) { const [left, right] = row.split(' '); screenX++; line += isHash(x, screenX) ? 'O' : ' '; if (screenX === 39) { screen.push(line); line = ''; screenX = -1; } if (right) { const num = parseInt(right); screenX++; line += isHash(x, screenX) ? 'O' : ' '; if (screenX === 39) { screen.push(line); line = ''; screenX = -1; } x += num; } } for (let row of screen) { console.log(row); } } const solutionA = () => { solveA(data); } const solutionB = () => { solveB(data); } export { solutionA, solutionB }

Dold text
PermalÀnk
Medlem ★
●

Dag: 14
SprÄk: Python

import numpy as np stones = [[eval(p) for p in l.strip().split(" -> ")] for l in open("input14").readlines()] mx, my = (max(map(max,c)) + 1 for c in zip(*[(zip(*s)) for s in stones])) grid = np.full((mx + my, my + 2), '.') for line in [list(zip(stone[:-1], stone[1:])) for stone in stones]: for fr, to in line: if fr[0] == to[0]: for y in range(min(fr[1], to[1]), max(fr[1], to[1]) + 1): grid[fr[0], y] = "#" else: for x in range(min(fr[0], to[0]), max(fr[0], to[0]) + 1): grid[x, fr[1]] = "#" grid[:,my + 1] = '#' def fall(x, y, terminate): if terminate(x, y): return False for o in [0, -1, +1]: if grid[x + o, y + 1] == '.': return fall(x + o, y + 1, terminate) grid[x, y] = 'o' return True c1 = c2 = 0 while (fall(500, 0, lambda x, y: y + 1 == my)): c1 = c1 + 1 while (fall(500, 0, lambda x, y: grid[500, 0] == 'o')): c2 = c2 + 1 print(c1, c1 + c2)

Dold text
PermalÀnk
●

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

PermalÀnk
Medlem
●

Dag: 14
SprÄk: C#

namespace AOC2022.Puzzles; internal class Puzzle14 : Puzzle<int> { protected override void Solve(string[] lines) { var rockPaths = lines.Select(GetPath).ToList(); var cave = GenerateCave(rockPaths); One = DropSands(cave); rockPaths.Add(GetPath($"0,{cave.GetLength(1)} -> 666,{cave.GetLength(1)}")); cave = GenerateCave(rockPaths); Two = DropSands(cave) + 1; } private static IEnumerable<(int x, int y)> GetPath(string line) => line.Split(" -> ") .Select(path => { var coords = path.Split(",").Select(int.Parse).ToList(); return (x: coords[0], y: coords[1]); }); private static bool[,] GenerateCave(List<IEnumerable<(int x, int y)>> rockPaths) { var (width, depth) = rockPaths .SelectMany(x => x) .Aggregate((w: 0, d: 0), (max, cur) => (Math.Max(cur.x, max.w), Math.Max(cur.y, max.d)), x => (x.w + 1, x.d + 2)); return rockPaths .SelectMany(paths => paths.Zip(paths.Skip(1))) .SelectMany(x => Grid.IterateBetween(x.First, x.Second)) .Aggregate(new bool[width, depth], (a, b) => { a[b.x, b.y] = true; return a; }); } private static int DropSands(bool[,] cave) { var startPos = (x: 500, y: 0); var sandAmount = 0; while (!DropSand(cave, startPos)) sandAmount++; return sandAmount; } private static bool DropSand(bool[,] cave, (int x, int y) startPos) { var sandPos = startPos; while (true) { if (Grid.IsOutOfRange(cave, (sandPos.x, sandPos.y + 1))) { return true; } var newPos = GetNextPosition(cave, sandPos.x, sandPos.y); if (newPos == sandPos) { cave[newPos.x, newPos.y] = true; return newPos == startPos; } sandPos = newPos; } } private static (int x, int y) GetNextPosition(bool[,] cave, int sx, int sy) => cave switch { _ when !cave[sx, sy + 1] => (sx, sy + 1), _ when !cave[sx - 1, sy +1] => (sx - 1, sy + 1), _ when !cave[sx + 1, sy + 1] => (sx + 1, sy + 1), _ => (sx, sy) }; }

Dold text
PermalÀnk
Medlem ★
●

Dag 7 Kotlin

class Day7 { fun run() { val input = java.io.File("src/input/day7.txt").readLines(); val fileStructure = addChildren(input) var root = fileStructure while (root?.parentDirectory != null) { root = root?.parentDirectory } val part1Answer = root!!.part1() val part2Answer = root!!.part2(30000000).minByOrNull { it.totalSize }!! println(part1Answer) println(part2Answer.totalSize) println(root!!.part1test()) } private tailrec fun addChildren(instructions: List<String>, currentDirectory: Directory? = null): Directory? { if (instructions.isEmpty()) { return currentDirectory } val instruction = instructions.first() when { instruction.startsWith("dir ") -> { val directoryName = instruction.split(" ")[1] val newDirectory = Directory(currentDirectory, mutableListOf(), mutableListOf(), directoryName) currentDirectory?.subDirectories?.add(newDirectory) return addChildren(instructions.drop(1), currentDirectory) } instruction.split(" ")[0].all { it.isDigit() } -> { val fileParts = instruction.split(" ") val newFile = File(currentDirectory!!, fileParts[1], fileParts[0].toInt()) currentDirectory?.files?.add(newFile) return addChildren(instructions.drop(1), currentDirectory) } instruction == "$ ls" -> return addChildren(instructions.drop(1), currentDirectory) instruction.startsWith("$ cd") -> { val targetDirectory = instruction.split(" ")[2] if (targetDirectory == "/") { return addChildren( instructions.drop(1), Directory(null, mutableListOf(), mutableListOf(), targetDirectory) ) } if (targetDirectory == "..") { return addChildren(instructions.drop(1), currentDirectory?.parentDirectory) } return addChildren( instructions.drop(1), currentDirectory?.subDirectories?.find { it.name == targetDirectory }) } } throw IllegalArgumentException("nu blev det tokigt igen") } class Directory( val parentDirectory: Directory?, val subDirectories: MutableList<Directory>, val files: MutableList<File>, val name: String ) { val totalSize: Int by lazy { files.sumOf { it.size } + this.subDirectories.sumOf { it.totalSize } } fun part1(): Int { val size = if (totalSize < 100000) totalSize else 0 return size + this.subDirectories.sumOf { it.part1() } } fun part1test(): Int { println(this.name + ": " + this.totalSize) return totalSize + this.subDirectories.sumOf { it.part1test() } } fun part2( targetFreeSpace: Int, currentFreeSpace: Int = 70000000 - this.totalSize, directoriesForDelete: MutableList<Directory> = mutableListOf() ): List<Directory> { if (currentFreeSpace + this.totalSize >= targetFreeSpace) { directoriesForDelete.add(this) } for (childDirectory in this.subDirectories) { childDirectory.part2(targetFreeSpace, currentFreeSpace, directoriesForDelete) } return directoriesForDelete } } class File(val parentDirectory: Directory, val name: String, val size: Int) }

Dold text

Dag 8 Koltin

class Day8 { fun run(){ //val input = "30373\n25512\n65332\n33549\n35390".split("\n") val input = File("src/input/day8.txt").readLines(); val allTrees: List<List<Tree>> = input.mapIndexed { y, treeLine -> val trees = treeLine.split("").subList(1, treeLine.length+1) trees.mapIndexed { x, tree -> Tree(x, y, tree.toInt()) } } val forest = Forest(allTrees) println(forest.treesVisibleFromAnywhere) println(forest.highestScenicValue) } } class Forest(val trees: List<List<Tree>>) { val treesVisibleFromAnywhere: Int by lazy { var visibleTrees = 0 for (y in trees.indices) { for(x in trees[0].indices) { val currentTree = trees[y][x] val treeLineHorizontal = trees[y] val treeLineVertical = getVerticalTreeLine(x) val hasAnyHeigherLeft = treeLineHorizontal.filter { it != currentTree && it.x < currentTree.x }.all { it.height < currentTree.height } val hasAnyHeigheRight = treeLineHorizontal.filter { it != currentTree && it.x > currentTree.x }.all { it.height < currentTree.height } val hasAnyHeigherAbove = treeLineVertical.filter { it != currentTree && it.y < currentTree.y }.all { it.height < currentTree.height } val hasAnyHeigherBelow = treeLineVertical.filter { it != currentTree && it.y > currentTree.y }.all { it.height < currentTree.height } visibleTrees += when{ y == 0 || y == trees.size-1 -> 1 x == 0 || x == trees[0].size-1 -> 1 hasAnyHeigherLeft || hasAnyHeigheRight -> 1 hasAnyHeigherAbove || hasAnyHeigherBelow -> 1 else -> 0 } } } visibleTrees } val highestScenicValue: Int get(){ var highestScore = 0 val treeCounter = {treesToCount: List<Tree>, treeCountDirection: TreeCountDirection, currentTree: Tree -> val treesOnSpecifiedSide = when(treeCountDirection){ TreeCountDirection.LEFT -> treesToCount.filter { it != currentTree && it.x < currentTree.x}.reversed() TreeCountDirection.RIGHT -> treesToCount.filter { it != currentTree && it.x > currentTree.x } TreeCountDirection.UP -> treesToCount.filter { it != currentTree && it.y < currentTree.y }.reversed() TreeCountDirection.DOWN -> treesToCount.filter { it != currentTree && it.y > currentTree.y } }.takeWhile { it.height < currentTree.height } treesOnSpecifiedSide.count() + when(treeCountDirection){ TreeCountDirection.LEFT -> if (treesOnSpecifiedSide.lastOrNull()?.x != 0) 1 else 0 TreeCountDirection.RIGHT -> if (treesOnSpecifiedSide.lastOrNull()?.x != treesToCount.size-1) 1 else 0 TreeCountDirection.UP -> if (treesOnSpecifiedSide.lastOrNull()?.y != 0) 1 else 0 TreeCountDirection.DOWN -> if (treesOnSpecifiedSide.lastOrNull()?.y != trees.size-1) 1 else 0 } } for (y in 1 .. trees.size - 2) { for(x in 1 .. trees[0].size - 2) { val currentTree = trees[y][x] val treeLineHorizontal = trees[y] val treeLineVertical = getVerticalTreeLine(x) val scoreLeft = treeCounter(treeLineHorizontal, TreeCountDirection.LEFT, currentTree) val scoreRight = treeCounter(treeLineHorizontal, TreeCountDirection.RIGHT, currentTree) val scoreAbove = treeCounter(treeLineVertical, TreeCountDirection.UP, currentTree) val scoreBelow = treeCounter(treeLineVertical, TreeCountDirection.DOWN, currentTree) val score = scoreLeft*scoreRight*scoreAbove*scoreBelow if(score > highestScore) { highestScore = score } } } return highestScore } private fun getVerticalTreeLine(x: Int): List<Tree> { var verticalTrees: MutableList<Tree> = mutableListOf() for(treeLine in trees) { verticalTrees.add(treeLine[x]) } return verticalTrees.toList() } } data class Tree(val x: Int, val y: Int, val height: Int) enum class TreeCountDirection{ LEFT, RIGHT, UP, DOWN }

Dold text

Dag 9 Koltin

class Day9 { fun run() { val input = File("src/input/day9.txt").readLines() val moves = input.map { val moveParts = it.trim().split(" ") val moveDirection = when (moveParts[0]) { "U" -> MoveCommand.Direction.UP "D" -> MoveCommand.Direction.DOWN "L" -> MoveCommand.Direction.LEFT "R" -> MoveCommand.Direction.RIGHT else -> throw IllegalArgumentException() } MoveCommand(moveDirection, moveParts[1].toInt()) } println(Knots(2).moveAround(moves)) println(Knots(10).moveAround(moves)) } } class MoveCommand(val direction: Direction, val totalSteps: Int) { val isVertical: Boolean by lazy { direction == Direction.UP || direction == Direction.DOWN } enum class Direction(val step: Int) { UP(1), DOWN(-1), LEFT(-1), RIGHT(1) } } data class Knot(var current: Point, val isHead: Boolean = false) class Knots(numberOfKnots: Int){ private val allKnots: LinkedList<Knot> = LinkedList() init { val head = Knot(Point(0, 0), true) allKnots.addFirst(head) IntRange(1, numberOfKnots-1).forEach { _ -> allKnots.add(Knot(Point(0,0))) } } fun moveAround(commands: List<MoveCommand>): Int { val uniqueLocations: MutableSet<Pair<Int, Int>> = mutableSetOf(Pair(0, 0)) commands.forEach {command -> for (step in 0 until command.totalSteps) { allKnots.forEachIndexed{knotIndex, knot -> if(knot.isHead) { moveHead(knot, command) } else { val lastKnot = allKnots[knotIndex-1] moveTailPart(knot, lastKnot) } } val tailCurrentLocation = Pair(allKnots.last.current.x, allKnots.last.current.y) uniqueLocations.add(tailCurrentLocation) } } return uniqueLocations.size } companion object { private fun moveHead(head: Knot, command: MoveCommand) = if (command.isVertical) head.current.move(head.current.x, head.current.y + command.direction.step) else head.current.move(head.current.x + command.direction.step, head.current.y) private fun moveTailPart(tailPart: Knot, lastPart: Knot){ val currentPoint = tailPart.current val lastPoint = lastPart.current if(currentPoint.distance(lastPoint) == 2.0) { val newX = (lastPoint.x + currentPoint.x) / 2 val newY = (lastPoint.y + currentPoint.y) / 2 currentPoint.move(newX, newY) } else if (currentPoint.distance(lastPoint) > 2.0) { val newX = when{ lastPoint.x > currentPoint.x -> currentPoint.x+1 lastPoint.x < currentPoint.x -> currentPoint.x-1 else -> currentPoint.x } val newY = when{ lastPoint.y > currentPoint.y -> currentPoint.y+1 lastPoint.y < currentPoint.y -> currentPoint.y-1 else -> currentPoint.y } currentPoint.move(newX, newY) } } } }

Dold text

Dag 10 Koltin

class Day10 { fun run() { val input = File("src/input/day10.txt").readLines() val display = Display(input) println(display.runInstructions()) println(display.part2Sb.toString()) } } class Display(private val instructions: List<String>){ private var x: Int = 1 val part2Sb: StringBuilder = java.lang.StringBuilder() private var cycleNumber: Int by Delegates.observable(0){prop, oldValue, newValue -> if(newValue % 20 == 0 && newValue % 40 != 0) { signalStrengths.add(x*newValue) } val currentPositionOnRow = (newValue - 1) % 40 val spriteIsInView = currentPositionOnRow == x-1 || currentPositionOnRow == x || currentPositionOnRow == x+1 if (spriteIsInView) part2Sb.append("#") else part2Sb.append(".") if(currentPositionOnRow == 39) { part2Sb.append("\n") } } private val signalStrengths: MutableList<Int> = mutableListOf() fun runInstructions(): Int { for ( instruction in instructions) { when{ instruction == "noop" -> cycleNumber++ instruction.startsWith("addx") -> { val value = instruction.split(" ")[1].toInt() repeat(2){cycleNumber++} x += value } } } return signalStrengths.sum() } }

Dold text

Jag har inte lekt med Kotlin innan det hÀr sÄ om nÄgon ser nÄgot uppenbart jÀttekonstigt jag gör sÄ vill jag gÀrna veta Tyckte om observablen i del 10 i a f. Trevligt sprÄk!

PermalÀnk
Medlem ★
●
Skrivet av GLaDER:

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

eval() gjorde parsningen trivial, sen skrev jag en rekursiv ordered() som spottade ur sig True | False | None beroende pÄ sortering. Det löste Del 1. I Del 2 fick jag nys om cmp_to_key() och efter att ha skrivit om min ordered() sÄ den returnerade -1 | 1 | 0 istÀllet var vi hemma

Kul uppgift Àven om jag inte hade koll pÄ cmp_to_key() och fick hjÀlp av bekanta pÄ Slack för att hitta den funktionen.

Dold text

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

Jag trodde att dagens uppgift skulle vara svÄrare. Sen trodde jag den skulle vara lÀttare....

Det tog inte sÄ lÄng tid att lösa test-inputen, men det tog lÄng tid att köra. Jag förstod inte varför och jag brÄkade fram och tillbaka med massor av olika brytvilkor utan att fÄ bÀttre prestanda. Efter otaliga iterationer fick jag tillslut till en lösning som kör pÄ nÄgon sekund. Nyckeln verkar vara att sÀkerstÀlla att vi inte slÀnger ned sand i avgrunden som första steg i loopen, istÀllet för att kolla det pÄ slutet. Jag förstÄr inte riktigt varför, men men...

Dold text
Visa signatur

:(){ :|:& };:

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

PermalÀnk
Medlem ★
●

Dag: 14
SprÄk: Go

package main import ( "fmt" "math" "os" "strings" "time" "github.com/Kasidro/aoc2021/internal/helpers" ) type coordinate struct { x, y int } type line struct { coordinate1, coordinate2 coordinate } type cave map[int]rune func main() { input, err := helpers.ReadLines(os.Args[1]) if err != nil { panic(err) } lines := make([]line, 0) maxY := math.MinInt for _, line := range input { l, y := parseLine(line) if y > maxY { maxY = y } lines = append(lines, l...) } start := time.Now() c := make(cave) c.populate(lines) fmt.Println(c.runSimulation(maxY, true)) fmt.Println(time.Since(start)) c.drawCave(470, 530, 0, 50) fmt.Println() start = time.Now() c = make(cave) c.populate(lines) fmt.Println(c.runSimulation(maxY+2, false)) fmt.Println(time.Since(start)) c.drawCave(470, 530, 0, 50) } func (cave cave) runSimulation(maxY int, infinity bool) int { drops := 1 for !cave.dropSand(maxY, infinity) { drops++ } return drops } func (cave cave) dropSand(max int, infinity bool) bool { resting := false sand := coordinate{500, 0} for !resting { if sand.y == max && infinity { return true } if sand.y == max-1 && !infinity { cave[helpers.Hash(sand.x, sand.y)] = 'o' resting = true continue } hash := helpers.Hash(sand.x, sand.y+1) if _, ok := cave[hash]; !ok { sand.y++ continue } hash = helpers.Hash(sand.x-1, sand.y+1) if _, ok := cave[hash]; !ok { sand.x-- sand.y++ continue } hash = helpers.Hash(sand.x+1, sand.y+1) if _, ok := cave[hash]; !ok { sand.x++ sand.y++ continue } if !infinity && sand.x == 500 && sand.y == 0 { cave[helpers.Hash(500, 0)] = 'o' return true } cave[helpers.Hash(sand.x, sand.y)] = 'o' resting = true } return false } func (cave cave) populate(lines []line) { for _, line := range lines { if line.coordinate1.x == line.coordinate2.x { yMin := math.Min(float64(line.coordinate1.y), float64(line.coordinate2.y)) yMax := math.Max(float64(line.coordinate1.y), float64(line.coordinate2.y)) for y := yMin; y <= yMax; y++ { cave[helpers.Hash(line.coordinate1.x, int(y))] = '#' } } else { xMin := math.Min(float64(line.coordinate1.x), float64(line.coordinate2.x)) xMax := math.Max(float64(line.coordinate1.x), float64(line.coordinate2.x)) for x := xMin; x <= xMax; x++ { cave[helpers.Hash(int(x), line.coordinate1.y)] = '#' } } } } func (cave cave) drawCave(minX, maxX, minY, maxY int) { for y := minY; y <= maxY; y++ { for x := minX; x <= maxX; x++ { hash := helpers.Hash(x, y) if val, ok := cave[hash]; ok { fmt.Print(string(val)) } else { fmt.Print(".") } } fmt.Println() } fmt.Println() } func parseLine(input string) ([]line, int) { coords := strings.Split(input, " -> ") maxY := math.MinInt lines := make([]line, 0, len(coords)) for i := 0; i < len(coords)-1; i++ { c1, c2 := strings.Split(coords[i], ","), strings.Split(coords[i+1], ",") x1, y1, x2, y2 := helpers.GetInt(c1[0]), helpers.GetInt(c1[1]), helpers.GetInt(c2[0]), helpers.GetInt(c2[1]) if y1 > maxY { maxY = y1 } if y2 > maxY { maxY = y2 } coord1, coord2 := coordinate{x: x1, y: y1}, coordinate{x: x2, y: y2} line := line{coord1, coord2} lines = append(lines, line) } return lines, maxY }

Dold text
PermalÀnk
●

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

Del 1 gick att brute-force:a ganska lĂ€tt men efter att ha testat det pĂ„ del 2 och inte ens kommit förbi 1% progress gav jag upp pĂ„ den idĂ©n. SĂ„ jag var tvungen att komma pĂ„ nĂ„got sĂ€tt att utesluta punkter som definitivt inte kommer vara rĂ€tt svar. Kom till sist pĂ„ att, eftersom vi fĂ„r veta att det finns EXAKT EN punkt som inte Ă€r innanför nĂ„gon sensors radar, sĂ„ mĂ„ste det betyda att den ligger PRECIS UTANFÖR minst en sensors radar. För hade den inte gjort det hade det betytt att det funnits en annan punkt mellan punkten och radarn, och dĂ€rmed hade vi inte haft nĂ„gon unik lösning. SĂ„ psuedokod Ă€r typ:

for sOuter in sensors: let r = sOuter.maxDistance for pos in sOuter.circle(r + 1): if not pos.insideAny(sensors): # we have found solution

Dold text
PermalÀnk
Medlem ★
●

Dag: 15
SprÄk: Python

import re coords = [tuple(map(int, re.findall('\-?\d+', l.strip()))) for l in open("input15").readlines()] def gen(sx, sy, bx, by, line = 0): dist = abs(sx - bx) + abs(sy - by) for i in range(line, sy - dist): yield [] for l in range(max(line, sy - dist), sy): o = dist - (sy - l) yield [(sx - o, sx + o + 1)] for l in range(max(sy, line), sy + dist + 1): o = dist - (l - sy) yield [(sx - o, sx + o + 1)] while True: yield [] def merge(ranges): a, b = sorted(ranges), [] for begin, end in a: if b and b[-1][1] > begin - 1: b[-1][1] = max(b[-1][1], end) else: b.append([begin, end]) return b def one(line): l = [gen(*coord, line) for coord in coords] r = merge(list(r[0] for r in (map(next, l)) if r)) return r[0][1] - r[0][0] - len(set([bx for _, _ ,bx, by in coords if by == line])) def two(): l = [gen(*coord) for coord in coords] for y in range(4000000): if len(m := merge(r[0] for r in (map(next, l)) if r) ) > 1: return y + dim * m[0][1] print(one(2000000), two())

Dold text
Förenklade lite
PermalÀnk
Medlem
●

Dag: 15
SprÄk: C#

Inte helt optimal lösning, semi brute-force som tar 5,5s pÄ min maskin. I del 2 löste jag det sÄ att ifall jag hamnar i ett "sensorfÀlt " sÄ hoppar jag sÄ lÄngt jag kan i x-led för att sedan fortsÀtta igen. Det var tufft idag sÄ jag nöjer mig med denna lösningen tror jag.

using System.Data; using System.Numerics; using System.Text.RegularExpressions; namespace AOC2022.Puzzles; internal partial class Puzzle15 : Puzzle<int, string> { [GeneratedRegex(@Sensor at x=(-?\d+), y=(-?\d+): closest beacon is at x=(-?\d+), y=(-?\d+))] private static partial Regex Regex(); record struct Pair((int x, int y) Sensor, (int x, int y) Beacon) { public int Distance { get; } = ManhattanDistance(Sensor, Beacon); } protected override void Solve(string[] lines) { var beacons = lines .Select(x => Regex().Match(x).Groups.Values.Skip(1) .Select(x => int.Parse(x.Value)).ToList()) .Select(x => new Pair((x: x[0], y: x[1]), (x: x[2], y: x[3]))) .ToList(); var (from, to) = beacons .Aggregate((0, 0), (a, b) => { var from = Math.Min(a.Item1, b.Beacon.x - b.Distance); from = Math.Min(from, b.Sensor.x - b.Distance); var to = Math.Max(a.Item2, b.Beacon.x + b.Distance); to = Math.Max(to, b.Sensor.x + b.Distance); return (from, to); }); One = Enumerable.Range(from, to - from) .Where(x => CheckForBeacon(beacons, (x, 2000000), false) >= 0) .Count(); Two = FindBeacon(beacons); } private static string FindBeacon(IEnumerable<Pair> beacons) { for (var y = 0; y <= 4000000; y++) { for (var x = 0; x <= 4000000; x++) { var dist = CheckForBeacon(beacons, (x, y), true); if (dist == -1) { return BigInteger.Add(BigInteger.Multiply(x, 4000000), y).ToString(); } x += dist - 1; } } return "0"; } private static int CheckForBeacon(IEnumerable<Pair> pairs, (int x, int y) location, bool beaconCheck) { foreach (var pair in pairs) { if (!beaconCheck && pair.Beacon == location) { continue; } var pointDistance = ManhattanDistance(location, pair.Sensor); if (pointDistance <= pair.Distance) { return Math.Abs(pointDistance - pair.Distance) + 1; } } return -1; } private static int ManhattanDistance((int x, int y) first, (int x, int y) second) => Math.Abs(first.x - second.x) + Math.Abs(first.y - second.y); }

Dold text
PermalÀnk
Medlem ★
●

Dag: 15
SprÄk: C#
Den dÀr var inte nÄdig. Tog vÀldigt mycket tid för att hitta smÄfel jag gjort i koden, sÀkert lÄngtifrÄn optimalt.

using System.Diagnostics; using AoCUtils; Console.WriteLine("Mickur's Advent of Code 2022 - Day 15!"); // Setup var input = File.ReadAllLines("input.txt"); var sensors = new List<Sensor>(); var beacons = new List<Beacon>(); // Part one variables var partOneMinX = int.MaxValue; var partOneMaxX = int.MinValue; // Parse input var startTime = Stopwatch.GetTimestamp(); for(var i = 0; i < input.Length; i++) { input[i] = input[i].Replace("Sensor at x=", ""); input[i] = input[i].Replace(" closest beacon is at x=", ""); input[i] = input[i].Replace(" y=", ""); var split = input[i].Split(':'); var sensor = split[0].Split(','); var beacon = split[1].Split(','); var sensorX = AoCParsing.FastIntParse(sensor[0]); var sensorY = AoCParsing.FastIntParse(sensor[1]); var beaconX = AoCParsing.FastIntParse(beacon[0]); var beaconY = AoCParsing.FastIntParse(beacon[1]); var range = ManhattanDistance(sensorX, sensorY, beaconX, beaconY); // Set min and max if (sensorX - range < partOneMinX) partOneMinX = sensorX - range; if (sensorX + range > partOneMaxX) partOneMaxX = sensorX + range; sensors.Add(new Sensor(sensorX, sensorY, range)); beacons.Add(new Beacon(beaconX, beaconY)); } var stopTime = Stopwatch.GetTimestamp(); Console.WriteLine($"Finished parsing in {Stopwatch.GetElapsedTime(startTime, stopTime).TotalMilliseconds} ms"); startTime = Stopwatch.GetTimestamp(); var partOneAnswer = PartOne(2000000); stopTime = Stopwatch.GetTimestamp(); Console.WriteLine($"Part one answer: {partOneAnswer}"); Console.WriteLine($"Finished part one in {Stopwatch.GetElapsedTime(startTime, stopTime).TotalMilliseconds} ms"); startTime = Stopwatch.GetTimestamp(); var partTwoAnswer = PartTwo(4000000); stopTime = Stopwatch.GetTimestamp(); Console.WriteLine($"Part two answer: {partTwoAnswer}"); Console.WriteLine($"Finished part two in {Stopwatch.GetElapsedTime(startTime, stopTime).TotalMilliseconds} ms"); int PartOne(int y) { var counter = 0; for (var x = partOneMinX; x <= partOneMaxX; x++) { var isBeacon = false; foreach (var beacon in beacons) { if (beacon.X == x && beacon.Y == y) { isBeacon = true; break; } } if (!isBeacon) { foreach (var sensor in sensors) { if (sensor.IsInRange(x, y)) { counter++; break; } } } } return counter; } long PartTwo(int size) { long returnValue = -1; var cts = new CancellationTokenSource(); try { Parallel.For(0, size + 1, new ParallelOptions { CancellationToken = cts.Token }, y => { for (var x = 0; x <= size;) { var inRange = false; var xJump = x + 1; for (var i = 0; i < sensors.Count; i++) { if (sensors[i].IsInRange(x, y)) { inRange = true; // Find possible jump if (x < sensors[i].X) { var possibleJump = sensors[i].JumpForward(y); if (possibleJump > xJump) { xJump = possibleJump; } } } } if (!inRange) { returnValue = x * 4000000L + y; cts.Cancel(); } x = xJump; } }); } catch { // ignored } return returnValue; } int ManhattanDistance(int firstX, int firstY, int secondX, int secondY) { return Math.Abs(firstX - secondX) + Math.Abs(firstY - secondY); } class Sensor { public readonly int X; public readonly int Y; private readonly int _range; public Sensor(int x, int y, int range) { X = x; Y = y; _range = range; } public bool IsInRange(int x, int y) { return Math.Abs(X - x) + Math.Abs(Y - y) <= _range; } public int JumpForward(int y) { var yDiff = Math.Abs(Y - y); return X + _range - yDiff + 1; } } class Beacon { public readonly int X; public readonly int Y; public Beacon(int x, int y) { X = x; Y = y; } }

Dold text
Visa signatur

CPU: 7950X 5GHz@1.1v | RAM: 32GB 6000MHz CL36 | GPU: KFAÂČ 3090 SG w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3 / Supreme CD-99