🌟 Advent of Code (AoC) 2021 🌟

PermalÀnk
Medlem
●

Dag: 8

too much text. Nu ger jag mig.

Dold text
PermalÀnk
Medlem
●

Dag: 7
SprÄk: C#

using System; using System.Linq; namespace Aoc2021.Puzzles { internal class Day07 : Puzzle { public override object PartOne() => CalculateMinFuelCost(d => d); public override object PartTwo() => CalculateMinFuelCost(d => (d * d + d) / 2); private int CalculateMinFuelCost(Func<int, int> fuelCostFunc) { var positions = Utilities.GetInput(GetType()) .Split(",") .Select(int.Parse) .ToArray(); var (start, count) = (positions.Min(), positions.Max() - positions.Min() + 1); return Enumerable.Range(start, count) .AsParallel() .Min(position => CalculateFuelCostAtPosition(positions, position, fuelCostFunc)); } private static int CalculateFuelCostAtPosition(int[] positions, int position, Func<int, int> fuelCostFunc) { return positions .Select(p => Math.Abs(position - p)) .Sum(fuelCostFunc); } } }

Dold text

Dag: 8
SprÄk: C#

using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace Aoc2021.Puzzles { internal class Day08 : Puzzle { public override object PartOne() { return ReadInput() .SelectMany(x => x.Output) .Count(x => new[] { 2, 3, 4, 7 }.Contains(x.Length)); } public override object PartTwo() { return ReadInput() .Select(x => (x.Output, Map: DecipherSignalPatterns(x.Input))) .Sum(x => ConvertOutputSignalsToValue(x.Output, x.Map)); } private static int ConvertOutputSignalsToValue(string[] output, IDictionary<int, string> map) { return output.Select(p => GetOutputDigit(map, p)) .Select((x, i) => x * (int)Math.Pow(10, 3 - i)) .Sum(); } private static int GetOutputDigit(IDictionary<int, string> map, string pattern) { return map.Single(m => m.Value.ElementsEqual(pattern)).Key; } private static IDictionary<int, string> DecipherSignalPatterns(string[] patterns) { var map = new Dictionary<int, string> { { 1, patterns.Single(p => p.Length == 2) }, { 4, patterns.Single(p => p.Length == 4) }, { 7, patterns.Single(p => p.Length == 3) }, { 8, patterns.Single(p => p.Length == 7) } }; map.Add(3, patterns.Single(p => p.Length == 5 && map[7].All(p.Contains))); map.Add(9, patterns.Single(p => p.Length == 6 && map[3].All(p.Contains))); map.Add(0, patterns.Single(p => p.Length == 6 && map[7].All(p.Contains) && map.None(x => x.Value == p))); map.Add(6, patterns.Single(p => p.Length == 6 && map.None(x => x.Value == p))); map.Add(5, patterns.Single(p => p.Length == 5 && p.All(x => map[6].Contains(x)))); map.Add(2, patterns.Single(p => map.None(x => x.Value == p))); return map; } private (string[] Input, string[] Output)[] ReadInput() { return Utilities.GetInput(GetType()) .Split(Environment.NewLine) .Select(row => Regex.Matches(row, @\w{1,7}\b).Select(x => x.Value).ToArray()) .Select(x => (x.Take(10).ToArray(), x.TakeLast(4).ToArray())) .ToArray(); } } }

Dold text
PermalÀnk
Medlem
●

Dag: 8
SprÄk: Scala

Tittade pÄ dagens problem tidigare och stÀngde ner sidan direkt utan att ens börja lÀsa. De lÄnga beskrivningarna brukar göra att jag tröttnar ganska snabbt pÄ att lösa aoc dagligen. Dags för nÄgra dagars paus tror jag och sen kolla om det dykt upp nÄt problem som ser intressant ut.

val input = Using.resource(Source.fromFile("8.txt"))(_.getLines().toList) input.map { case s"$_ | $s" => s.split(' ').count(x => Set(2, 3, 4, 7)(x.length)) }.sum input.map { case s"$s1 | $s2" => val pat = s1.split(' ') val out = s2.split(' ') val one = pat.find(_.length == 2).get.toSet val four = pat.find(_.length == 4).get.toSet val mapping = pat.map { key => key.sorted -> (key.length, key.count(one), key.count(four)).match case (2, _, _) => 1 case (3, _, _) => 7 case (4, _, _) => 4 case (5, 1, 3) => 5 case (5, _, 2) => 2 case (5, _, _) => 3 case (6, 1, _) => 6 case (6, _, 3) => 0 case (6, _, _) => 9 case (7, _, _) => 8 }.toMap out.map(x => mapping(x.sorted)).mkString.toInt }.sum

Dold text
PermalÀnk
Medlem
●

Dag: 8
SprÄk: Rust

Lagomt segt med denna efter jobbet.
Min hjÀrna kÀndes halvgrillad innan jag sÄg mönstret pÄ del 2.

Dold text

use std::collections::HashMap; const ZERO: &[usize; 6] = &[0, 1, 2, 4, 5, 6]; const ONE: &[usize; 2] = &[2, 5]; const TWO: &[usize; 5] = &[0, 2, 3, 4, 6]; const THREE: &[usize; 5] = &[0, 2, 3, 5, 6]; const FOUR: &[usize; 4] = &[1, 2, 3, 5]; const FIVE: &[usize; 5] = &[0, 1, 3, 5, 6]; const SIX: &[usize; 6] = &[0, 1, 3, 4, 5, 6]; const SEVEN: &[usize; 3] = &[0, 2, 5]; const EIGHT: &[usize; 7] = &[0, 1, 2, 3, 4, 5, 6]; const NINE: &[usize; 6] = &[0, 1, 2, 3, 5, 6]; fn main() { let input = std::fs::read_to_string("input.txt").unwrap(); let input: Vec<_> = input .lines() .map(|s| s.split_once('|').unwrap()) .map(|t| { let mut a = t.0.split_whitespace().collect::<Vec<_>>(); let b = t.1.split_whitespace().collect::<Vec<_>>(); a.sort_by(|a, b| a.len().cmp(&b.len())); (a, b) }) .collect(); println!("part 1: {}", part1(&input)); // 318 println!("part 2: {}", part2(&input).unwrap()); // 996280 } fn part1(data: &[(Vec<&str>, Vec<&str>)]) -> usize { data.iter() .flat_map(|p| &p.1) .filter(|p| matches!(p.len(), 2 | 3 | 4 | 7)) .count() } fn part2(data: &[(Vec<&str>, Vec<&str>)]) -> Option<usize> { let mut total = 0; for (usp, out) in data.iter() { let segment_occurences: HashMap<char, u8> = usp.iter() .flat_map(|s| s.chars()) .fold(HashMap::new(), |mut map, v| { *map.entry(v).or_default() += 1; map }); let mut segments = [' '; 7]; for code in usp.iter() { // Samlar ihop sÄ vi slipper dubbelborrow let only_new_segments: Vec<_> = code .chars() .filter(|c| !segments.contains(c)) .map(|c| (c, segment_occurences.get(&c).unwrap())) .collect(); for (chr, occurences) in only_new_segments { match (code.len(), occurences) { (2, 8) => segments[2] = chr, (2, _) => segments[5] = chr, (3, _) => segments[0] = chr, (4, 6) => segments[1] = chr, (4, _) => segments[3] = chr, (7, 4) => segments[4] = chr, (7, _) => segments[6] = chr, _ => (), } } } // Bygg ihop talet total += out .iter() .fold(0usize, |acc, digit| acc * 10 + get_digit(&segments, digit)); } Some(total) } fn get_digit(segments: &[char; 7], digit: &str) -> usize { match digit.len() { 6 if chk_chrs(ZERO.iter().map(|&f| segments[f]), digit) => 0, 2 if chk_chrs(ONE.iter().map(|&f| segments[f]), digit) => 1, 5 if chk_chrs(TWO.iter().map(|&f| segments[f]), digit) => 2, 5 if chk_chrs(THREE.iter().map(|&f| segments[f]), digit) => 3, 4 if chk_chrs(FOUR.iter().map(|&f| segments[f]), digit) => 4, 5 if chk_chrs(FIVE.iter().map(|&f| segments[f]), digit) => 5, 6 if chk_chrs(SIX.iter().map(|&f| segments[f]), digit) => 6, 3 if chk_chrs(SEVEN.iter().map(|&f| segments[f]), digit) => 7, 7 if chk_chrs(EIGHT.iter().map(|&f| segments[f]), digit) => 8, 6 if chk_chrs(NINE.iter().map(|&f| segments[f]), digit) => 9, _ => panic!("brunsÄs"), } } fn chk_chrs<'a>(mut segments: impl Iterator<Item = char>, digit: &str) -> bool { segments.all(|chr| digit.contains(chr)) }

Dold text
Renskrivit lösningen
Visa signatur

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

PermalÀnk
●

Dag: 9
SprÄk: Scala

Idag blev det en del muterbara strukturer, för att det kÀndes enklare.

object Day9 { val data = readLines("9/data.txt") val lines = data.map(_.map(_.toString.toInt)) implicit class Adder(p: (Int, Int)) { def +(other: (Int, Int)) = (p._1 + other._1, p._2 + other._2) } val surrounding = Seq((-1,0), (0,-1), (1,0), (0,1)) val zeroTo100 = 0 until 100 def valid(p: (Int, Int)) = zeroTo100.contains(p._1) && zeroTo100.contains(p._2) def depth(p: (Int, Int)) = if (valid(p)) lines(p._2)(p._1) else 10 def extend(p: (Int, Int)) = surrounding.map(dp => p + dp) def lowPoint(p: (Int, Int)) = { val center = depth(p) surrounding.forall(dp => depth(p + dp) > center) } val lowPoints = for { y <- lines.indices x <- lines.head.indices if valid(x, y) && lowPoint(x, y) } yield (x, y) def extendToBasin(p: (Int, Int)) = { val pointsToExtend = mutable.Queue(p) val basin = mutable.Set(p) while(pointsToExtend.nonEmpty) { val p = pointsToExtend.dequeue() val candidates = extend(p).filter { p => valid(p) && depth(p) < 9 && !basin.contains(p) } basin.addAll(candidates) pointsToExtend.appendAll(candidates) } basin.toSet } def main(args: Array[String]): Unit = { // part 1 println(lowPoints.map(p => depth(p) + 1).sum) // part 2 val basins = ArrayBuffer[Set[(Int, Int)]]() for(lowPoint <- lowPoints if !basins.exists(_.contains(lowPoint))) { basins.append(extendToBasin(lowPoint)) } val res = basins.sortBy(-_.size) .take(3) .map(_.size) .product println(res) } }

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

Dag: 8
SprÄk: Python 3
Lösning: GitHub.

Del 1 var inga konstigheter, men jag hade problem med Del 2. Tyckte uppgiften pÄminde om vÀskuppgiften frÄn förra Äret, men som vanligt kunde jag inte omformulera mina vaga tankar i kod. Slutade med att jag gick för en lösning dÀr jag kollar överlappet mellan siffror tills jag hittat alla siffror. TÀnker att det mÄste finnas en snyggare lösning Àn min while-loop, men den gör ju jobbet...

Dold text

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

Kul med en BFS sÄhÀr en torsdagsmorgon.

Dold text
Visa signatur

:(){ :|:& };:

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

PermalÀnk
●
Skrivet av GLaDER:

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

Kul med en BFS sÄhÀr en torsdagsmorgon.

Dold text

Trodde du missat att slÄ ihop överlappande basins, men nu nÀr jag lÀser beskrivningen noggrannare sÄ Àr det jag som i onödan tog hÀnsyn till att flera low points kunde hamna i samma basin.

"The devil is in the details", som det heter

PermalÀnk
●

Dag: 9
SprÄk: Haskell

Fuskade lite och antog att det inte finns sadelpunkter och platÄer, sÄ slapp jag hÄlla reda pÄ vilka punkter jag kollat. Att anvÀnda Data.Set var nog onödigt sÄ hÀr i efterhand.

import Data.List import qualified Data.Set as Set main = interact solve solve input = "Problem 1: " ++ show (sum (map riskLevel lowPts)) ++ "\n" ++ "Problem 2: " ++ show ((product.(take 3).reverse.sort) (map ((Set.size).(getBasin heightmap)) lowPts)) ++ "\n" where riskLevel p = 1 + getHeight heightmap p lowPts = filter (isLowPoint heightmap) allPts allPts = [(x, y) | y <- [0..length heightmap-1], x <- [0..length (head heightmap)-1]] heightmap = lines input within heightmap (x, y) = x>=0 && x<length (head heightmap) && y>=0 && y<length heightmap getHeight heightmap (x, y) = read [((heightmap !! y) !! x)] :: Int isLowPoint heightmap (x, y) = all higher surroundingPts where surroundingPts = filter (within heightmap) [(x, y-1), (x-1, y), (x+1, y), (x, y+1)] higher (x', y') = getHeight heightmap (x', y') > getHeight heightmap (x, y) getBasin heightmap (x,y) = Set.union (Set.singleton (x,y)) (Set.union (if relevant (x, y-1) then getBasin heightmap (x, y-1) else Set.empty) (Set.union (if relevant (x-1, y) then getBasin heightmap (x-1, y) else Set.empty) (Set.union (if relevant (x+1, y) then getBasin heightmap (x+1, y) else Set.empty) (if relevant (x, y+1) then getBasin heightmap (x, y+1) else Set.empty)))) where relevant (x', y') = valid (x', y') && higher (x', y') && (not.tooHigh) (x', y') valid (x', y') = within heightmap (x', y') higher (x', y') = getHeight heightmap (x', y') > getHeight heightmap (x, y) tooHigh (x', y') = getHeight heightmap (x', y') >= 9

Dold text
PermalÀnk
Medlem
●

Dag: 9
SprÄk: C#

Idag kÀndes det enklare Àn gÄrdagen. Körde pÄ en rekursiv lösning för att rÀkna ut bassÀngstorlekarna.

internal class Puzzle9 : Puzzle<int> { private static readonly (int x, int y)[] NeighborOffsets = new[] { (-1, 0), (1, 0), (0, -1), (0, 1) }; private int _xLength; private int _yLength; private int[,] _map = default!; protected override void Solve(string[] lines) { _xLength = lines[0].Length; _yLength = lines.Length; _map = new int[_xLength, _yLength]; foreach (var (x, y) in Iterate(_map)) { _map[x, y] = lines[y][x] - '0'; } var lowPoints = Iterate(_map).Where(IsLowPoint).ToArray(); One = lowPoints.Sum(coord => 1 + _map[coord.x, coord.y]); Two = lowPoints .Select(c => GetBasinSize(c, new HashSet<(int x, int y)>())) .OrderByDescending(x => x) .Take(3) .Aggregate(1, (a,b) => a * b); } private bool IsLowPoint((int x, int y) coord) => NeighborOffsets .Select(offset => GetDepth(coord.x + offset.x, coord.y + offset.y, int.MaxValue)) .All(n => n > _map[coord.x, coord.y]); private int GetBasinSize((int x, int y) coord, ISet<(int x, int y)> visitedNodes) { if (!visitedNodes.Add(coord)) { return 0; } var depth = _map[coord.x, coord.y]; if (depth == 9) { return 0; } return 1 + NeighborOffsets .Select(offset => new { coord = (coord.x + offset.x, coord.y + offset.y), depth = GetDepth(coord.x + offset.x, coord.y + offset.y, -1) }) .Where(x => x.depth > depth) .Sum(x => GetBasinSize(x.coord, visitedNodes)); } private int GetDepth(int x, int y, int defaultValue) => IsOutOfRange(x, y) ? defaultValue : _map[x, y]; private bool IsOutOfRange(int x, int y) => x < 0 || x >= _xLength || y < 0 || y >= _yLength; private static IEnumerable<(int x, int y)> Iterate(int[,] arr) { for (int x = 0; x < arr.GetLength(0); x++) { for (int y = 0; y < arr.GetLength(1); y++) { yield return (x, y); } } } }

Dold text
PermalÀnk
Medlem
●

Dag: 9
SprÄk: Carth

Skönt att fÄ en mjukare boll idag efter gÄrdagens utslitning.

(import std) (define main (do io/bind (<- input (io/map unwrap! (read-file "inputs/day9.txt"))) (let ((dim (string/length-bytes (iter/first! (lines input)))) (height-array (array/collect (map (flip - ascii-0) (flat-map string/bytes (lines input))))) (heightmap (array/collect (array/chunks dim height-array))) (low-points (filter-map (fun (pt) (let ((h (array/lookup2d! pt heightmap)) (adjs (filter-map (flip array/lookup2d heightmap) (list/iter (adjecent-points pt))))) (if (all (< h) adjs) (Some pt) None))) (iter/cartesian (xrange (to-nat 0) (array/length heightmap)) (xrange (to-nat 0) dim)))))) (display (str-append "Part 1: " (show-nat (part1 heightmap low-points)))) (display (str-append "Part 2: " (show-nat (part2 heightmap low-points)))))) (define (part1 heightmap low-points) (sum (map (apps <o inc to-nat (flip array/lookup2d! heightmap)) low-points))) (define (part2 heightmap low-points) (define (cmp-pt [i1 j1] [i2 j2]) (match (num/cmp i1 i2) (case Eq (num/cmp j1 j2)) (case x x))) (define (basin-size seen) (fmatch (case LNil (set/count seen)) (case (LCons (Box [pt pts])) (if (set/member? cmp-pt pt seen) (basin-size seen pts) (if (= 9 (maybe' 9 to-int (array/lookup2d pt heightmap))) (basin-size seen pts) (basin-size (set/insert cmp-pt pt seen) (list/append (adjecent-points pt) pts))))))) (apps |> low-points (map (<o (basin-size set/nil) list/singleton)) array/collect (merge-sort num/cmp) array/iter-rev (take 3) product)) (define (adjecent-points [i j]) (list [(dec i) j] [i (inc j)] [(inc i) j] [i (dec j)]))

Dold text
Visa signatur

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

PermalÀnk
Medlem ★
●

Dag: 9
SprÄk: Python

import numpy as np a = np.array([list(map(int, s.strip())) for s in open("input09").readlines()]) xs, ys = a.shape def neighbors(p): x, y = p if x > 0: yield (x - 1, y) if x < xs - 1: yield (x + 1, y) if y > 0: yield (x, y - 1) if y < ys - 1: yield (x, y + 1) def low(p): return all(a[p] < a[n] for n in neighbors(p)) print(sum([a[p] + 1 for p in np.ndindex(a.shape) if low(p)])) b = a < 9 def find_basin(p, work, visited): if p in visited: return work visited.add(p) if b[p]: work.add(p) for n in neighbors(p): if b[n] and not n in work: find_basin(n, work, visited) return work visited = set() sets = [frozenset(find_basin(p, set(), visited)) for p in np.ndindex(a.shape)] print(np.prod(sorted(len(i) for i in sets)[-3:]))

Dold text
PermalÀnk
Medlem ★
●

Dag: 9
SprÄk: Go

type position struct { x, y, val int neighbours []position low bool } func main() { fileName := "" if len(os.Args) == 1 { fileName = "input.txt" } else { fileName = os.Args[1] } input, err := helpers.ReadLines(fileName) if err != nil { panic(err) } start := time.Now() sinks, grid, totalRisk := initGrid(input) basins := make([]int, 0) for _, sink := range sinks { basins = append(basins, finaBasinSize(sink, grid)) } sort.Ints(basins) sum := 1 for _, val := range basins[len(basins)-3:] { sum *= val } duration := time.Since(start) fmt.Println(totalRisk) fmt.Println(sum) fmt.Println(duration) } func initGrid(input []string) (sinks []int, grid map[int]position, risk int) { grid = map[int]position{} for y, line := range input { for x, depth := range line { val := int(depth - '0') pos := position{x: x, y: y, val: val} pos.neighbours = make([]position, 0) pos.low = true for x1 := -1; x1 <= 1; x1++ { if x1 != 0 && x+x1 >= 0 && x+x1 < len(line) { neighbourValue := int(rune(line[x+x1]) - '0') if neighbourValue <= val { pos.low = false } neighbour := position{x: x + x1, y: y, val: neighbourValue} pos.neighbours = append(pos.neighbours, neighbour) } } for y1 := -1; y1 <= 1; y1++ { if y1 != 0 && y+y1 >= 0 && y+y1 < len(input) { neighbourValue := int(rune(input[y+y1][x]) - '0') if neighbourValue <= val { pos.low = false } neighbour := position{x: x, y: y + y1, val: neighbourValue} pos.neighbours = append(pos.neighbours, neighbour) } } hash := hash(x, y) if pos.low { sinks = append(sinks, hash) risk += pos.val + 1 } grid[hash] = pos } } return } func finaBasinSize(sink int, grid map[int]position) (size int) { visited := make(map[int]interface{}) var queue []position root := grid[sink] queue = append(queue, root) visited[hash(root.x, root.y)] = nil for len(queue) > 0 { node := queue[0] queue = queue[1:] for _, neighbourNode := range node.neighbours { if neighbourNode.val != 9 { hash := hash(neighbourNode.x, neighbourNode.y) if _, ok := visited[hash]; !ok { visited[hash] = nil queue = append(queue, grid[hash]) } } } } return len(visited) } func hash(x, y int) int { if x >= y { return x*x + x + y } return x + y*y }

Dold text
PermalÀnk
Medlem
●

Dag: 9
SprÄk: C++

Första gÄngen jag anvÀnder Set i C++. Stark kÀnsla av att det finns bÀttre sÀtt att lösa detta pÄ. Om man inte anvÀnder Set eller motsvarande behöver man vÀl sjÀlv hÄlla reda pÄ vilka positioner som redan besökts. Kom inte pÄ nÄgot bra sÀtt att lösa det pÄ utan evinnerliga loopar...

grid parse(vector<string> str_data) { vector<vector<int>> data; int n_rows = str_data.size(); for (auto const row:str_data) { vector<int> row_data; for (char const num:row) { row_data.push_back(num-48); } data.push_back(row_data); } return data; } vector<coord> get_neighbours() { vector<coord> neighbours; neighbours.push_back(make_pair(1,0)); neighbours.push_back(make_pair(-1,0)); neighbours.push_back(make_pair(0,1)); neighbours.push_back(make_pair(0,-1)); return neighbours; } vector<coord> find_low_points(grid data, vector<coord> &neighbours) { vector<coord> low_points; int n = data[0].size(); int m = data.size(); neighbours = get_neighbours(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { bool low_point = true; int val = data[i][j]; for(const auto nghrb : neighbours) { int ip = i + nghrb.first; int jp = j + nghrb.second; if (ip >= 0 && ip < m && jp >= 0 && jp < n) { if (data[ip][jp] <= val) low_point = false; } } if (low_point) { low_points.push_back(make_pair(i,j)); } } } return low_points; } int solve_part1(grid data) { int count = 0; vector<coord> neighbours; vector<coord> low_points = find_low_points(data, neighbours); for (auto const &point:low_points) { count += (data[point.first][point.second]+1); } return count; } int solve_part2(grid data) { int n = data[0].size(); int m = data.size(); vector<coord> nghbrs; vector<coord> low_points = find_low_points(data, nghbrs); vector<int> b_sizes(3,0); vector<int> b_copy(4,0); set<coord>::iterator it; std::pair<set<coord>::iterator,bool> ret; for (auto const &low_point : low_points) { set<coord> basin; set<coord> coords,new_coords; new_coords.insert(low_point); do { coords = new_coords; new_coords.clear(); for (it = coords.begin(); it != coords.end(); ++it) { int i = it->first; int j = it->second; for (auto const &nghbr : nghbrs) { int ip = i + nghbr.first; int jp = j + nghbr.second; if (ip >= 0 && ip < m && jp >= 0 && jp < n) { if (data[ip][jp] < 9) { ret = basin.insert(make_pair(ip, jp)); if (ret.second == true) { new_coords.insert(make_pair(ip, jp)); } } } } } } while (new_coords.size() > 0); copy(b_sizes.begin(), b_sizes.end(),b_copy.begin()); b_copy.insert ( upper_bound(b_copy.begin(), b_copy.end(), basin.size(),greater<int>()), basin.size() ); copy(b_copy.begin(), --b_copy.end(), b_sizes.begin()); b_copy.erase(--b_copy.end()); } return b_sizes[0] * b_sizes[1] * b_sizes[2]; }

Dold text
PermalÀnk
Medlem
●

Dag: 9
SprÄk: Rust

type ColData<'a> = (Option<&'a usize>, Option<&'a usize>, Option<&'a usize>); type RowData<'a> = (ColData<'a>, ColData<'a>, ColData<'a>); fn main() { let input: Vec<Vec<_>> = std::fs::read_to_string("input.txt") .unwrap() .lines() .map(|s| { s.chars() .filter_map(|c| c.to_digit(10).map(|d| d as usize)) .collect() }) .collect(); println!( "{}", part1(&input).iter().map(|(r, _, _)| r + 1).sum::<usize>() ); println!("{}", part2(&input).unwrap()); } fn part1(data: &[Vec<usize>]) -> Vec<(usize, usize, usize)> { let mut hits = Vec::new(); for row in 0..data.len() { for col in 0..data[0].len() { if let Some(&risk_lvl) = part1_matcher(fetch_row(data, row, col)) { hits.push((risk_lvl, row, col)); } } } hits } fn part2(data: &[Vec<usize>]) -> Option<usize> { let lows = part1(data); let mut sizes = vec![]; for (_, row, col) in lows { sizes.push(solve(data, &mut vec![], row, col)); } sizes.sort_unstable(); Some(sizes.pop()? * sizes.pop()? * sizes.pop()?) } fn solve(data: &[Vec<usize>], res: &mut Vec<(usize, usize)>, row: usize, col: usize) -> usize { if res.contains(&(row, col)) { return 0; } let mut accum = 1; let (up, mid, down) = fetch_row(data, row, col); res.push((row, col)); for i in [ (up.1, if row > 0 { row - 1 } else { 0 }, col), (mid.0, row, if col > 0 { col - 1 } else { 0 }), (mid.2, row, col + 1), (down.1, row + 1, col), ] { accum += match i { (Some(&x), row, col) if x != 9 => solve(data, res, row, col), _ => 0, }; } accum } fn part1_matcher((up, mid, down): RowData) -> Option<&usize> { match (up.1, mid, down.1) { (None, (None, x @ Some(a), Some(b)), Some(c)) if [b, c].iter().all(|v| a < v) => x, (None, (Some(d), x @ Some(a), Some(b)), Some(c)) if a < b && a < c && a < d => x, (None, (Some(b), x @ Some(a), None), Some(c)) if [b, c].iter().all(|v| a < v) => x, (Some(c), (None, x @ Some(a), Some(b)), Some(d)) if [b, c, d].iter().all(|v| a < v) => x, (Some(c), (Some(d), x @ Some(a), Some(b)), Some(e)) if [b, c, d, e].iter().all(|v| a < v) => { x } (Some(c), (Some(b), x @ Some(a), None), Some(d)) if [b, c, d].iter().all(|v| a < v) => x, (Some(c), (None, x @ Some(a), Some(b)), None) if [b, c].iter().all(|v| a < v) => x, (Some(c), (Some(d), x @ Some(a), Some(b)), None) if [b, c, d].iter().all(|v| a < v) => x, (Some(c), (Some(b), x @ Some(a), None), None) if [b, c].iter().all(|v| a < v) => x, _ => None, } } fn fetch_row(input: &[Vec<usize>], row: usize, col: usize) -> RowData { ( row.checked_sub(1) .map(|v| fetch_col(input.get(v), col)) .unwrap_or((None, None, None)), fetch_col(input.get(row), col), row.checked_add(1) .map(|v| fetch_col(input.get(v), col)) .unwrap_or((None, None, None)), ) } fn fetch_col(row: Option<&Vec<usize>>, col: usize) -> ColData { if let Some(value) = row { ( col.checked_sub(1).map(|v| value.get(v)).flatten(), value.get(col), col.checked_add(1).map(|v| value.get(v)).flatten(), ) } else { (None, None, None) } }

Dold text
Kodformat
Visa signatur

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

PermalÀnk
●

Dag: 9
SprÄk: C

FörstÄr inte rykterna om att den hÀr skulle vara lÀttare Àn den igÄr. Mycket luddigare formulerat, fick prova flera tolkningar innan jag hamnade rÀtt.

#include <stdio.h> #include <stdlib.h> #define MAP_W 100 #define MAP_H 100 #define INDEX(x, y) ((x) + (y) * MAP_W) int g_height[MAP_W * MAP_H]; int *g_basin; int g_basins; int get_pos(int cur, int dx, int dy) { int cur_x, cur_y; cur_x = cur % MAP_W; cur_y = cur / MAP_W; cur_x += dx; cur_y += dy; if (cur_x < 0 || cur_x >= MAP_W) return 11; if (cur_y < 0 || cur_y >= MAP_H) return 11; return g_height[INDEX(cur_x, cur_y)]; } int basin_size(int i) { int cur_x, cur_y, size, here; cur_x = i % MAP_W; cur_y = i / MAP_W; if (g_height[i] == 9) return 0; here = g_height[i]; g_height[i] = 9; size = 1; if (cur_x > 0 && here <= get_pos(i, -1, 0)) size += basin_size(INDEX(cur_x - 1, cur_y)); if (cur_x + 1 < MAP_W && here <= get_pos(i, 1, 0)) size += basin_size(INDEX(cur_x + 1, cur_y)); if (cur_y > 0 && here <= get_pos(i, 0, -1)) size += basin_size(INDEX(cur_x, cur_y - 1)); if (cur_y + 1 < MAP_H && here <= get_pos(i, 0, 1)) size += basin_size(INDEX(cur_x, cur_y + 1)); return size; } void analyze_basin(int i) { int q; q = g_basins++; g_basin = realloc(g_basin, sizeof(*g_basin) * g_basins); g_basin[q] = basin_size(i); } int basin_cmp(const void *q1, const void *q2) { return *((int *) q1) - *((int *) q2); } int main(int argc, char **argv) { int i; int risk; for (i = 0; i < MAP_W * MAP_H; i++) fscanf(stdin, "%1d", &g_height[i]); for (i = risk = 0; i < MAP_W * MAP_H; i++) { if (get_pos(i, -1, 0) <= g_height[i]) continue; if (get_pos(i, 1, 0) <= g_height[i]) continue; if (get_pos(i, 0, -1) <= g_height[i]) continue; if (get_pos(i, 0, 1) <= g_height[i]) continue; risk += (g_height[i] + 1); analyze_basin(i); } qsort(g_basin, g_basins, sizeof(*g_basin), basin_cmp); printf("Solution A: %i\n", risk); printf("Solution B: %i (%i %i %i)\n", g_basin[g_basins - 1] * g_basin[g_basins - 2] * g_basin[g_basins - 3], g_basin[g_basins - 1], g_basin[g_basins - 2], g_basin[g_basins - 3]); return 0; }

Dold text
PermalÀnk
●

Dag: 9
SprÄk: Python

from typing import Generator, Tuple from math import prod data = [[int(x) for x in line.rstrip()] for line in open("9.in")] HEIGHT = len(data) WIDTH = len(data[0]) def generate_neighbours(i: int, j: int) -> Generator[Tuple[int, int], None, None]: for di, dj in ((0, 1), (1, 0), (0, -1), (-1, 0)): if 0 <= (n_i := i + di) < HEIGHT and 0 <= (n_j := j + dj) < WIDTH: yield n_i, n_j def measure_basin(i: int, j: int) -> int: seen = set() frontier = [(i, j)] while frontier: point = frontier.pop(-1) seen.add(point) frontier += [p for p in generate_neighbours(*point) if p not in seen and data[p[0]][p[1]] < 9] return len(seen) low_points = [ (i, j) for i in range(HEIGHT) for j in range(WIDTH) if all(data[n_i][n_j] > data[i][j] for n_i, n_j in generate_neighbours(i, j)) ] p1 = sum(data[i][j] + 1 for i, j in low_points) p2 = prod(sorted(measure_basin(*low_point) for low_point in low_points)[-3:]) print(p1, p2)

Dold text
PermalÀnk
Datavetare ★
●

Dag: 9
SprÄk: Rust

DFS var nÄgot snabbare Àn BFS. Lade en "ram" runt kartan med höjden satt till u8::MAX för att inte fÄ specialfall efter kanterna. Denna tar 810”s att köra pÄ en M1 MBA (inklusive inlÀsning frÄn fil).

use crate::solution::Solution; use std::collections::HashSet; struct Day9 { height_map: Vec<u32>, width: usize, height: usize, stride: usize, } impl Solution for Day9 { fn part1(&mut self) -> String { (1..=self.height) .into_iter() .fold(0, |risk, y| { risk + (1..=self.width).fold(0, |risk, x| risk + self.risk_level(x, y)) }) .to_string() } fn part2(&mut self) -> String { self.three_largest_basins() .iter() .product::<u32>() .to_string() } } impl Day9 { fn risk_level(&self, x: usize, y: usize) -> u32 { let height = self.height(x, y); for pos in adjacent(x, y) { if self.height(pos.0, pos.1) <= height { return 0; } } height + 1 } fn height(&self, x: usize, y: usize) -> u32 { self.height_map[x + y * self.stride] } fn three_largest_basins(&self) -> [u32; 3] { let mut basins = Vec::new(); for y in 1..=self.height { for x in 1..=self.width { if self.risk_level(x, y) != 0 { basins.push(self.basin_size(x, y)); } } } basins.sort_unstable(); basins[(basins.len() - 3)..].try_into().unwrap() } fn basin_size(&self, low_x: usize, low_y: usize) -> u32 { let mut visited = HashSet::new(); let mut stack = Vec::new(); let mut size = 1; stack.push((low_x, low_y)); while let Some((x, y)) = stack.pop() { for pos in adjacent(x, y) { let adj_height = self.height(pos.0, pos.1); if adj_height < 9 && adj_height > self.height(x, y) && !visited.contains(&pos) { size += 1; visited.insert(pos); stack.push(pos); } } } size } } fn adjacent(x: usize, y: usize) -> [(usize, usize); 4] { [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)] } pub fn new(input: &str) -> Box<dyn Solution> { let mut height_map = Vec::new(); let mut stride = 0; for (i, row) in input.lines().enumerate() { if i == 0 { stride = row.len() + 2; height_map.resize(stride, u32::MAX); } height_map.push(u32::MAX); row.chars() .for_each(|ch| height_map.push(ch.to_digit(10).unwrap())); height_map.push(u32::MAX); } height_map.resize(height_map.len() + stride, u32::MAX); let height = height_map.len() / stride - 2; Box::new(Day9 { height_map, width: stride - 2, height, stride, }) }

use crate::solution::Solution; use std::collections::{HashSet, HashMap}; type Pos = (u32, u32); struct Day9 { height_map: HashMap<Pos, u32>, } impl Solution for Day9 { fn part1(&mut self) -> String { self.height_map .keys() .fold(0, |risk, pos| risk + self.risk_level(pos)) .to_string() } fn part2(&mut self) -> String { self.three_largest_basins() .iter() .product::<u32>() .to_string() } } impl Day9 { fn risk_level(&self, pos: &Pos) -> u32 { let height = self.height(pos); for pos in adjacent(pos) { if self.height(&pos) <= height { return 0; } } return height + 1; } fn height(&self, pos: &Pos) -> u32 { *self.height_map.get(pos).unwrap_or(&u32::MAX) } fn three_largest_basins(&self) -> [u32; 3] { let mut basins = Vec::new(); for pos in self.height_map.keys() { if self.risk_level(pos) != 0 { basins.push(self.basin_size(pos)); } } basins.sort_unstable(); basins[(basins.len() - 3)..].try_into().unwrap() } fn basin_size(&self, low_pos: &Pos) -> u32 { let mut visited = HashSet::new(); let mut stack = Vec::new(); let mut size = 1; stack.push(*low_pos); while let Some(pos) = stack.pop() { for adj_pos in adjacent(&pos) { let adj_height = self.height(&adj_pos); if adj_height < 9 && adj_height > self.height(&pos) && !visited.contains(&adj_pos) { size += 1; visited.insert(adj_pos); stack.push(adj_pos); } } } size } } fn adjacent(pos: &Pos) -> [Pos; 4] { [(pos.0 + 1, pos.1), (pos.0 - 1, pos.1), (pos.0, pos.1 + 1), (pos.0, pos.1 - 1)] } pub fn new(input: &str) -> Box<dyn Solution> { let mut height_map = HashMap::new(); for (y, row) in input.lines().enumerate() { row.chars() .enumerate() .for_each(|(x, ch)| { height_map .insert((x as u32, y as u32), ch.to_digit(10).unwrap()); }); } Box::new(Day9 { height_map, }) }

Denna Àr nÄgot enklare, men ocksÄ 5-6 gÄnger lÄngsammare!
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: 8
SprÄk: Dart
Lösning: GitHub

Well, lÀs pÄ egen risk.

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

PermalÀnk
●

Dag: 8
SprÄk: Nim
Lösning: https://github.com/HugoGranstrom/AdventOfNim/blob/main/2021/9...

Idag var helt okej, blev lite för verbose kod för mitt tycke och man vet ju aldrig hur "snĂ€ll" datan Ă€r. Är ganska skönt att datan var ganska tillrĂ€ttalagd idag iaf.

PermalÀnk
Hedersmedlem ★
●

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

Mycket kod idag (igen), men jag försöker göra koden lÀtt att följa och möjlig att utöka istÀllet för kort.
PrestandatÀnk rök ocksÄ till förmÄn för lÀttlÀst (samt lÀtt-kodat). Trots allt slöseri med att skapa dubletter och filtrera bort dem sÄ tar det runt 30 ms att köra.

Sitter fortfarande fast pÄ del 2 av gÄrdagens, men hoppade till dag 9 sÄ jag inte har flera dagars jobb köat. Hade dÄligt med tid igÄr, och delvis Àven idag, och har fastnat i tÀnket.

Visa signatur

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

PermalÀnk
Medlem ★
●

Dag: 9
SprÄk: Python
Lösning: GitHub

Är ju uppenbart att det som vanligt finns ett smart sĂ€tt att lösa det pĂ„. Synd att man inte har koll pĂ„ sĂ„nt men det gick ju Ă€ndĂ„.
FrÄga mig dock inte hur det fungerar i detalj för det Àr jag inte riktigt med pÄ sjÀlv Àn

Visa signatur

StationÀra | Define 7 Compact | RM750x White | X570S AERO G | Ryzen 5 5600x | NH-D15 Chromax | Flare X 4x8GB 3200MHz | RTX 4070 Super | MP600 1TB | 980 1TB | A2000 1TB | 970 EVO 500GB | 850 EVO 500GB |
Acer X34A + 2x Dell U2719D | Wave 1 | Arctis Nova Pro Wireless |
Laptop | Macbook Air M1 2020 | 16GB | 256GB |
3dkatten.se

PermalÀnk
●

Dag: 10
SprÄk: Scala

object Day10 { val data = readLines("10/data.txt") def main(args: Array[String]): Unit = { case class LexerResult(unexpected: Option[Char], open: List[Char]) def check(remaining: String, open: List[Char] = Nil): LexerResult = { if(remaining.isEmpty) { LexerResult(None, open) } else { remaining.head match { case '(' => check(remaining.tail, ')' :: open) case '[' => check(remaining.tail, ']' :: open) case '{' => check(remaining.tail, '}' :: open) case '<' => check(remaining.tail, '>' :: open) case c if c == open.head => check(remaining.tail, open.tail) case unexpected => LexerResult(Some(unexpected), open) } } } // part 1 def score1(line: String) = check(line).unexpected match { case Some(')') => 3 case Some(']') => 57 case Some('}') => 1197 case Some('>') => 25137 case None => 0 } println(data.map(score1).sum) // part 2 val scores = data.map(line => check(line)) .filter(_.unexpected.isEmpty) .map { res => res.open.foldLeft(0L) { case (score, ch) => score * 5 + (ch match { case ')' => 1 case ']' => 2 case '}' => 3 case '>' => 4 }) } } .sorted println(scores(scores.length / 2)) } }

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

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

Kul med en BFS sÄhÀr en torsdagsmorgon.

Dold text

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

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

  • Missade att man skulle multiplicera med 5.

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

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

  • Sorterade inte listan med poĂ€ng.

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

Dold text
Visa signatur

:(){ :|:& };:

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

PermalÀnk
●

Dag: 10
SprÄk: Python

from typing import Tuple start_chars = "[{<(" end_chars = "]}>)" char_opposites = dict(zip(start_chars, end_chars)) | dict(zip(end_chars, start_chars)) char_scores = {")": 3, "]": 57, "}": 1197, ">": 25137, "(": 1, "[": 2, "{": 3, "<": 4} def score_line(line: str) -> Tuple[int, int]: valid_score = 0 invalid_score = 0 stack = [] for c in line: if c in start_chars: stack.append(c) elif stack.pop(-1) != char_opposites[c]: return 0, char_scores[c] while stack: c = stack.pop(-1) valid_score = valid_score * 5 + char_scores[c] return valid_score, invalid_score valid_scores, invalid_scores = zip(*((score_line(line.rstrip())) for line in open("10.in"))) valid_non_zero = [x for x in valid_scores if x > 0] print(sum(invalid_scores)) print(sorted(valid_non_zero)[len(valid_non_zero) // 2])

Dold text
PermalÀnk
●

Dag: 10
SprÄk: Nim
Lösning: https://github.com/HugoGranstrom/AdventOfNim/blob/main/2021/1...

Var en ganska behaglig uppgift dÀr det mest var min stundtals icke-existerande lÀsförmÄga som stÀllde till det bara. Tog gÄnger 10 istÀllet för gÄnger 5 pÄ del 2 bland annat

Dold text
PermalÀnk
Medlem ★
●

Dag: 10
SprÄk: Python

from functools import reduce matches = { "(" : ")", "[" : "]", "{" : "}", "<" : ">" } mismatch_scores = { ")" : 3, "]" : 57, "}" : 1197, ">" : 25137 } def parse(s, expect = ""): while s: if s[0] in matches: expect += matches[s[0]] elif s[0] == expect[-1]: expect = expect[:-1] else: return mismatch_scores[s[0]], "" s = s[1:] return 0, expect[::-1] def score(expect, s = 0): for e in expect: s = s * 5 + " )]}>".index(e) return s parsed = list(map(parse, [s.strip() for s in open("input10s").readlines()])) l = sorted(map(score, [expect for _, expect in parsed if expect])) print(sum(score for score, _ in parsed), l[len(l) // 2])

Dold text
PermalÀnk
Medlem ★
●

Dag: 10
SprÄk: C#

Lösning

int pt1sum = 0; List<long> pt2sums = new(); using (var sr = new StreamReader("input.txt")) { while (!sr.EndOfStream) { var line = sr.ReadLine()!.ToCharArray(); var stack = new Stack<char>(); bool corrupt_line = false; foreach (var item in line) { //Console.WriteLine( item); switch (item) { case '(': case '[': case '{': case '<': stack.Push(item); break; case ')': if (stack.Pop() != '(') { pt1sum += 3; corrupt_line = true; } break; case ']': if (stack.Pop() != '[') { pt1sum += 57; corrupt_line = true; } break; case '}': if (stack.Pop() != '{') { pt1sum += 1197; corrupt_line = true; } break; case '>': if (stack.Pop() != '<') { pt1sum += 25137; corrupt_line = true; } break; default: break; } if (corrupt_line) break; } if (corrupt_line) continue; long sum = 0; while (stack.Count > 0) { sum *= 5; switch (stack.Pop()) { case '(': sum += 1; break; case '[': sum += 2; break; case '{': sum += 3; break; case '<': sum += 4; break; default: break; } } pt2sums.Add(sum); } } pt2sums.Sort(); Console.WriteLine("Part 1 " + pt1sum); Console.WriteLine("Part 2 " + pt2sums[pt2sums.Count/2]);

Dold text

Kommentarer

Ganska rÀttframt idag, pushade öppningsparenteser av de olika slagerna pÄ en stack, poppade vid stÀngning och kollade om de stÀmmer överens. Tekniskt sett sÄ poÀngsÀtter jag ju sen öppnande istÀllet för stÀngande för del 2, men det Àr ju detsamma. Och som vanligt springer siffrorna ivÀg sÄ pass högt att man behöver köra long istÀllet för int.

Dold text
Visa signatur

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

PermalÀnk
Medlem
●

Dag: 10
SprÄk: C#

internal class Puzzle10 : Puzzle<long> { private static readonly string[] Chunks = new string[] { "()", "[]", "{}", "<>" }; protected override void Solve(string[] lines) { var corruptedLines = lines .Select((x, idx) => new { score = FindIllegalCharacter(x), idx }) .Where(x => x.score > 0) .ToList(); One = corruptedLines.Select(x => x.score).Sum(); var corruptedLineIndexes = corruptedLines.Select(x => x.idx).ToList(); var fixedLines = lines .Where((x, idx) => !corruptedLineIndexes.Contains(idx)) .Select(x => FixIncompleteLines(x)) .OrderBy(x => x) .ToList(); Two = fixedLines[fixedLines.Count / 2]; } private static long FixIncompleteLines(string line) => GetOpenChars(line, false, out _) .Reverse() .Select(GetClosedChar) .Aggregate(0L, (totalScore, b) => totalScore * 5 + b switch { ')' => 1, ']' => 2, '}' => 3, '>' => 4, _ => 0 }); private static int FindIllegalCharacter(string line) { _ = GetOpenChars(line, true, out var point); return point; } private static char? GetOpenChar(char @char) => Chunks.FirstOrDefault(x => x[1] == @char)?[0]; private static char GetClosedChar(char @char) => Chunks.Single(x => x[0] == @char)[1]; private static IEnumerable<char> GetOpenChars(string line, bool checkIllegal, out int illegalCharPoint) { illegalCharPoint = 0; var openChars = new List<char>(); foreach (var @char in line) { var openChar = GetOpenChar(@char); if (openChar == null) { openChars.Add(@char); } else if (checkIllegal && openChars[^1] != openChar) { illegalCharPoint = @char switch { ')' => 3, ']' => 57, '}' => 1197, '>' => 25137, _ => 0 }; break; } else { openChars.RemoveAt(openChars.Count - 1); } } return openChars; } }

Dold text
PermalÀnk
Medlem
●

Dag: 10
SprÄk: Carth

Jag tyckte om dagens. Lite mysigt sÄdÀr.

(import std) (define main (do io/bind (<- input (io/map unwrap! (read-file "inputs/day10.txt"))) (let1 [corrupteds incompletes] (partition-eithers (map execute (lines input)))) (display (str-append "Part 1: " (apps |> corrupteds list/iter (map corrupted-points) sum show-int))) (display (str-append "Part 2: " (apps |> incompletes list/iter (map incomplete-score) array/collect (merge-sort num/cmp) array/middle unwrap! show-int))))) (data Bracket Round Square Curly Angle) (define corrupted-points (fmatch (case Round 3) (case Square 57) (case Curly 1197) (case Angle 25137))) (define (incomplete-score missings) (foldl (fun (tot b) (+ (* 5 tot) (inc (bracket-to-int b)))) 0 (list/iter missings))) ;;? Returns Left with last token when corrupted, and Right with the missing brackets when incomplete (define (execute line) (define (go stack) (define (open bracket) (Right (list/cons bracket stack))) (define (close b2) (match (list/uncons stack) (case None (Left b2)) (case (Some [b1 stack']) (if (bracket-eq b1 b2) (Right stack') (Left b2))))) (fmatch (case None (Right stack)) (case (Some [symbol rest]) (match (match symbol (case "(" (open Round)) (case "[" (open Square)) (case "{" (open Curly)) (case "<" (open Angle)) (case ")" (close Round)) (case "]" (close Square)) (case "}" (close Curly)) (case _ (close Angle))) (case (Left bracket) (Left bracket)) (case (Right stack') (go stack' (next rest))))))) (go LNil (next (map string/singleton-byte (string/bytes line))))) (define (bracket-eq b1 b2) (= (bracket-to-int b1) (bracket-to-int b2))) (define (bracket-to-int b) (to-int (: (transmute b) Nat8)))

Dold text
Visa signatur

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

PermalÀnk
Medlem
●

Dag: 10
SprÄk: C++

Roligt och lagom svÄrt idag IMHO. Första gÄngen det kÀndes naturligt för mig att anvÀnda Stack för att lösa uppgiften.

#include <iostream> #include <iomanip> #include <stack> #include <map> #include <algorithm> #include "../utils/file_reader.cpp" typedef unsigned long long ull; map<char,char> delims; void set_delims() { delims['('] = ')'; delims['['] = ']'; delims['{'] = '}'; delims['<'] = '>'; } bool opens(char inp) { return delims.count(inp) > 0? true : false; } int calc_score(vector<char> const illegals) { map<char,int> points; points[')'] = 3; points[']'] = 57; points['}'] = 1197; points['>'] = 25137; int score = 0; int n_illegals = illegals.size(); for (int i = 0; i < n_illegals; i++) { score += points.at(illegals[i]); } return score; } int calc_score(vector<vector<char>> const missing) { vector<ull> scores; map<char,int> points; points[')'] = 1; points[']'] = 2; points['}'] = 3; points['>'] = 4; int n_rows = missing.size(); for (int i = 0; i < n_rows; i++) { ull row_score = 0; vector<char> row = missing[i]; int row_size = row.size(); for (int j = 0; j < row_size; j++) { row_score = row_score * 5 + points.at(row[j]); } scores.insert(upper_bound(scores.begin(), scores.end(),row_score),row_score); } return scores[scores.size()/2]; } void scan_lines(vector<string> str_data, vector<vector<char>> &missing, vector<char> &illegals) { set_delims(); int n_rows = str_data.size(); for (int row = 0; row < n_rows; row++) { stack<char> chunks; bool illegal = false; vector<char> row_miss; string row_d = str_data[row]; int n_chars = row_d.length(); for (int pos = 0; pos < n_chars; pos++) { char char_ = row_d[pos]; if (opens(char_)) { chunks.push(char_); } else { if (char_ != delims.at(chunks.top())) { illegals.push_back(char_); illegal = true; break; } else { chunks.pop(); } } } if (!illegal) { while(chunks.size()>0) { row_miss.push_back(delims.at(chunks.top())); chunks.pop(); } missing.push_back(row_miss); } } } vector<int> solve(vector<string> str_data) { vector<vector<char>> missing; vector<char> illegals; vector<int> results; scan_lines(str_data, missing, illegals); results.push_back(calc_score(illegals)); results.push_back(calc_score(missing)); return results; } int main() { string filename = "../../input/day_10.txt"; vector<string> string_data = read_file<string>(filename,true); vector<int> result = solve(string_data); cout << setw(30) << left << "Day 10 Part 1 solution: " << result[0] << endl; cout << setw(30) << left << "Day 10 Part 2 solution: " << result[1] << endl; }

Dold text