CPU: 7950X | RAM: 32GB | GPU: 3090 w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3
đ Advent of Code (AoC) 2022 đ
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
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.
Hemska flashbacks till den tiden man pluggade dÄtidens "AI"... Slag under bÀltet!
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
vilket verkade galet komplext och dÄ hade jag redan lagt mer tid Àn jag Àr beredd att lÀgga per dag.
GL
Att föresprÄka Mac pÄ Swec Àr som att föresprÄka hybridbilar pÄ en raggartrÀff i Mora.
Nuvarande stationÀr: 7800X3D, 128Gb ram, 4Tb nvme, 3x8Tb sata-ssd, 4070 Ti S
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
}
i5-7600k . GTX 1080 . 16 GB
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.
Tackar och bockar, ska titta pÄ nÀrmare pÄ det och se om jag kan fÄ ner tiden lite
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);
}
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]);
}
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
Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer
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
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.
:(){ :|:& };:
đđ»ââïž Â đŽđ»ââïž Â đđ»ââïž Â â
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;
}
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 == ÷r1).unwrap() + 1;
let pos2 = packets.iter().position(|p| p == ÷r2).unwrap() + 1;
let result = pos1 * pos2;
println!("Day 13, part 2: {:?}", result);
}
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 }
Dag: 13
SprÄk: Go
Lösning: GitHub
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
Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer
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;
}
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.
CPU: 7950X | RAM: 32GB | GPU: 3090 w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3
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));
}
}
}
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)
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))
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 }
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)
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)
};
}
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)
}
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
}
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)
}
}
}
}
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()
}
}
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!
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.
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...
:(){ :|:& };:
đđ»ââïž Â đŽđ»ââïž Â đđ»ââïž Â â
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
}
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
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())
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);
}
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;
}
}
CPU: 7950X | RAM: 32GB | GPU: 3090 w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3
- RTX 5080/5090 lagerstatus585
- BestĂ€llde Ryzen 7 9800X3D â fick 14 Ă„r gammal processor25
- gamingdator 30-35k - sista Ă„sikt15
- Smart lÄs för altandörrar5
- Redaktionens betyg pÄ RX 9070 XT Red Devil samt 9070 Hellhound157
- Vad har ni i lön?14k
- Kommer inte in i grÀnssnitt ASUS router.6
- [LEK] Gissa spelet17k
- 9070 / XT - Owners club117
- Geforce RTX 5050 fÄr inte nÀsta generations minne42
- SÀljes 2" UltraGear 32GQ950 4K Nano IPS 160 Hz HDR GamingskÀrm
- Köpes Enklare bÀrbar dator
- SĂ€ljes ZOTAC GeForce RTX 3080 Trinity OC
- Köpes 1070/1080
- SĂ€ljes MSI 3090 TRIO EKWB & vattenkylningspaket.
- SĂ€ljes Datordelar Asus ROG Strix Z390-F GAMING + I7 9700K
- Köpes Söker 360hz 1080p
- Köpes Söker en Bambu Lab p1s
- Köpes 4090, oavsÀtt modell
- Köpes Ram ddr5 16-32gb och NÀtaggregat 700w+
- BestĂ€llde Ryzen 7 9800X3D â fick 14 Ă„r gammal processor24
- Asus nya skÀrmar har inbyggd luftrenare22
- Kör Windows 11 pÄ Raspberry Pi9
- Testlabbet uppdaterar prestandaindexet59
- DÀrför funkar inte din Chromecast just nu65
- Geforce RTX 5050 fÄr inte nÀsta generations minne42
- Snabbkoll: AnvÀnder du VPN-tjÀnst privat?57
- USA slÄr fast: Google mÄste sÀlja Chrome81
- EFF-verktyg upptÀcker falska mobilmaster12
- Nykomlingen: VÄra grafikkort Àr 10 gÄnger snabbare Àn RTX 509059
Externa nyheter
Spelnyheter frÄn FZ
- Wanderstop slĂ€pps i dag â och betygen ser bra ut idag
- FZ High Score â Boom! Vi har ett Split Fiction-resultat idag
- Smygfilmer visar Las Vegas / New Vegas frÄn sÀsong tvÄ av Fallout-serien idag
- Split Fiction sÄldes i 1 miljon exemplar pÄ bara 48 timmar idag
- LÀckare: Indiana Jones PS5-slÀpps den 17 april idag