🌟 Advent of Code (AoC) 2021 🌟

PermalÀnk
Datavetare ★
●
Skrivet av Bryal:

I new() skulle du kunna spara iteratorn i en variabel och anropa .next() manuellt en gÄng för att flytta ut undantagsfallet med den första raden frÄn innuti loopen. Lite oombett tips sÄhÀr pÄ kvÀllskvisten

let mut lines = input.lines(); let numbers = numbers_parse(lines.next().unwrap()); for line in lines { ...

Dold text

Helt korrekt! Det var inte det enda mÀrkliga med new(), började med en annan idé men Àndrade mig och det blev lite mishmash...

Finns egentligen ingen anledning för poÀngberÀkningen ska behöva &mut self, stÀdat lite.

Visa signatur

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

PermalÀnk
●

Dag: 4
SprÄk: Haskell

Usch, en sÄn röra.

import Data.List main = interact solve solve input = solution drawing boards ++ "\n" where drawing = parseDraw ((head.lines) input) :: [Int] boards = (parseBoards.tail.lines) input :: [[Int]] parseDraw line | elem ',' line = read draw:parseDraw (tail rest) | otherwise = read line:[] where (draw, rest) = break (\c -> c==',') line parseBoards (_:a:b:c:d:e:bs) = [(map read (words a ++ words b ++ words c ++ words d ++ words e))] ++ parseBoards bs parseBoards _ = [] solution drawing boards = "Quickest board has score " ++ show (chooseBoard drawing boards minimum) ++ "\nSlowest board has score " ++ show (chooseBoard drawing boards maximum) chooseBoard drawing boards strategy = sum remainingNumbers * last drawnNumbers where drawnNumbers = take (chosenFinishTurn+1) drawing remainingNumbers = boards !! (chosenBoard-1) \\ drawnNumbers chosenBoard = 1 + elemIndex' chosenFinishTurn finishTurnByBoard chosenFinishTurn = strategy finishTurnByBoard finishTurnByBoard = map finishTurn boards finishTurn board = minimum (map finishTurnRow (boardRows board)) finishTurnRow row = maximum (remapToDrawOrder drawing row) boardRows board = map (map ((!!) board)) rowIndices where rowIndices = [[0..4], [5..9], [10..14], [15..19], [20..24], [0,5..20], [1,6..21], [2,7..22], [3,8..23], [4,9..24]] remapToDrawOrder drawing row = map drawOrder row where drawOrder n = elemIndex' n drawing elemIndex' i xs = case elemIndex i xs of Just x -> x Nothing -> 999

Dold text
PermalÀnk
Medlem
●
Skrivet av Thomas:

... och Lisp antar jag? Ser ut att vara huvudsaklingen frÄn relaterade sprÄk.

Kollade upp hur Lisp ser ut och jag kan bara hÄlla med.

Visa signatur

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

PermalÀnk
Medlem
●

Dag 4 i C++ galenskapen:
Nu börjar det ta emot lite, intellisense har gett upp dÄ jag slog i taket för antal constexpr steps
Men jag fÄr rÀtt resultat Àn utan att starta programmen

https://godbolt.org/z/M7jbbvPbT

PermalÀnk
Medlem ★
●

Dag: 4
SprÄk: Go

type board struct { index int bingo bool gameBoard [][]int numberPosition map[int]position unmarkedScore int finalScore int } type position struct { x, y int } 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) } draws := helpers.GetInts(strings.Split(input[0], ",")...) boards := initBoards(input[1:]) //winner := play(draws, boards) loser := playAnti(draws, boards) fmt.Println(draws) //fmt.Printf("Winner board is: %v, Final result: %v\n", winner.index, winner.finalScore) fmt.Printf("Losing board is: %v, Final result: %v\n", loser.index, loser.finalScore) loser.Print() } func play(draws []int, boards []*board) board { for _, draw := range draws { for _, board := range boards { if checkBoard(draw, board) { return *board } } } return board{} } func playAnti(draws []int, boards []*board) board { for _, draw := range draws { for _, board := range boards { won := checkBoard(draw, board) if len(boards) == 1 && won { return *boards[0] } } for i := len(boards) - 1; i >= 0; i-- { if boards[i].bingo { boards = remove(boards, i) } } } return board{} } func checkBoard(draw int, board *board) (won bool) { if pos, ok := board.numberPosition[draw]; ok { board.gameBoard[pos.y][pos.x] = 1 board.unmarkedScore = board.unmarkedScore - draw if hasWon(pos, *board) { board.finalScore = draw * board.unmarkedScore board.bingo = true return true } } return } func hasWon(pos position, board board) bool { sum := 0 for x := 0; x < 5; x++ { sum += board.gameBoard[pos.y][x] } if sum == 5 { return true } sum = 0 for y := 0; y < 5; y++ { sum += board.gameBoard[y][pos.x] } if sum == 5 { return true } return false } func remove(boards []*board, i int) []*board { boards[i] = boards[len(boards)-1] return boards[:len(boards)-1] } func initBoards(input []string) (boards []*board) { index := 0 for i := 0; i < len(input); i = i + 6 { boardInput := input[i+1 : i+6] board := initBoard(boardInput, index) boards = append(boards, &board) index += 1 } return } func initBoard(input []string, index int) (board board) { board.gameBoard = make([][]int, 5) board.numberPosition = make(map[int]position, 25) board.index = index for y := 0; y < 5; y++ { board.gameBoard[y] = make([]int, 5) input[y] = strings.TrimSpace(input[y]) input[y] = strings.Replace(input[y], " ", " ", -1) row := strings.Split(input[y], " ") for x := 0; x < 5; x++ { if number, err := strconv.Atoi(row[x]); err == nil { board.unmarkedScore += number board.gameBoard[y][x] = 0 board.numberPosition[number] = position{x, y} } else { panic(err) } } } return } func (b board) Print() { fmt.Printf("---------------------\n") for i := 0; i < len(b.gameBoard); i++ { gameBoard := b.gameBoard[i] fmt.Printf("| %v | %v | %v | %v | %v |\n", gameBoard[0], gameBoard[1], gameBoard[2], gameBoard[3], gameBoard[4]) fmt.Printf("---------------------\n") } }

Dold text
PermalÀnk
Medlem
●

Dag: 4
SprÄk: C++

#include <iostream> #include <sstream> #include "../utils/file_reader.cpp" using namespace std; const int N = 5; struct board { int nums[N][N]; int checks[N][N] = {0}; int row_checks[5] = {0}; int col_checks[5] = {0}; int unchecked_total = 0; bool winner = false; }; vector<int> get_nums(string data, char delim) { vector<int> output; string str; int num; stringstream sstream(data); while (getline(sstream, str, delim)) { if (!str.empty()) { stringstream s(str); s >> num; output.push_back(num); } } return output; } vector<board> get_boards(vector<string> data) { vector<board> boards; board new_board; string line; int row = 0; int n_rows = data.size(); while (row < n_rows) { line = data[row]; //empty line signals new board if (line.empty()) { for (int i = 0; i < N; i ++) { row +=1; line = data[row]; vector<int> nums = get_nums(line,' '); for (int j = 0; j < N; j++) { new_board.nums[i][j] = nums[j]; } } boards.push_back(new_board); } row +=1; } return boards; } void play_bingo(vector<board> boards, vector<int> nums, board &winner_board, int &winner_num, bool return_first) { for (auto num:nums) { int n = boards.size(); for (auto &brd : boards) { if (brd.winner) { continue; } brd.unchecked_total = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (brd.nums[i][j] == num) { brd.checks[i][j] = 1; brd.row_checks[i] += 1; brd.col_checks[j] += 1; } if (brd.checks[i][j] == 0) { brd.unchecked_total += brd.nums[i][j]; } if ((brd.row_checks[i] == N || brd.col_checks[j] == N) && (!brd.winner)) { brd.winner = true; } } } if (brd.winner) { winner_board = brd; winner_num = num; if (return_first) { return; } } } } return; } int solve(vector<string> data, bool stop_at_first) { vector<int> nums = get_nums(data[0], ','); vector<board> boards = get_boards(data); int winner_num; board winner_board; play_bingo(boards, nums, winner_board, winner_num,stop_at_first); return winner_board.unchecked_total * winner_num; } int main() { string filename = "../../input/day_04.txt"; vector<string> data = read_file<string>(filename,false); int part_1 = solve(data,true); int part_2 = solve(data,false); cout << "Day 4 Part 1 solution: " << part_1 << endl; cout << "Day 4 Part 2 solution: " << part_2 << endl; return 0; }

Dold text

Lite kÀmpigt med denna.

PermalÀnk
Medlem ★
●

Dag: 4
SprÄk: Dart
Lösning: GitHub

SjĂ€lva problemet var inte jĂ€ttesvĂ„rt att lösa - dĂ€remot att lĂ€sa av filen och mappa om till modell korrekt. Är fan inte alls nöjd med den hĂ€r röran:

final numbersFromInput = input .replaceAll('\r\n', ' ') .split(' ') .where((e) => e.isNotEmpty) .map((e) => int.parse(e)) .toList();

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

Dag: 4
SprÄk: Python, eller rÀttare sagt list comprehensions och numpy. Under 20 rader, inklusive whitespace och en kommentar

NÀr jag sÄg uppgift tvÄ skrotade jag min första lösning och löste bÄda pÄ en gÄng.

import numpy as np l = [l.strip() for l in open("input04").readlines()] numbers = [int(n) for n in l[0].split(",")] lines = [[int(i) for i in line.split()] for line in l[2:] if line] boards = [np.array(lines[i:i + 5]) for i in range(0, len(lines), 5)] def turns_to_win_and_score(board): for i, n in enumerate(numbers): board[np.where(board == n)] = -n # any line or column where all the numbers are negative? if any([line.all() for x in [board < 0, board.transpose() < 0] for line in x]): return i, sum(board[board >= 0]) * n bingos = list(map(turns_to_win_and_score, boards)) print(min(bingos)[1], max(bingos)[1])

Dold text

Det dÀr var snyggt som fan

Visa signatur

ASRock X870E Nova WIFI / Ryzen 9800X3D (CO: -45 AC) / Corsair Vengance 64GB DDR5 6000MHz CL30 / Crucial T705 1TB Gen5 + 5.5TB sekundÀra / ASUS TUF 4080 Gaming OC / Seasonic Focus GX 850W ATX 3.1 / Acer Predator XB273UGX 1440p 270 Hz G-Sync / FD Torrent Compact / Thermalright Phantom Spirit 120 SE / Evo 4 / Sennheiser IE 300 / Rode NT1-A
Synology 1621+ 6*16 / 1513+ 5*8 / LG CX 65" / XBox Series X

PermalÀnk
Skrivmaskin ★
●

Dag 4:
SprÄk C++
Lösning: Nej, dĂ€r fĂ„r jag nog kasta in handduken pĂ„ grund av tidsbrist, en (upplevd) snabb stegring i svĂ„righetsgrad och för dĂ„liga C++-kunskaper. Lade ner nĂ„gon timme pĂ„ att parsea rĂ€tt och utforma funktioner för att hitta vinnare pĂ„ ett smidigt sĂ€tt, bara för att inse att AoC-gĂ€nget inte hĂ„ller sig till 1-99-bingo utan ocksĂ„ anvĂ€nder 0:or, som Ă€r en stor del av min lösning. Hinner inte stöpa om mina strategier om det ska bli nĂ„gra artiklar och julkalenderluckor framöver Återkommer kanske med Python nĂ€r det lugnat ner sig lite

PermalÀnk
Medlem
●

Dag: 4
SprÄk: Scala

val input = Using.resource(Source.fromFile("4.txt"))(_.getLines().toVector) class Board(rows: Vector[Vector[Int]], cols: Vector[Vector[Int]]): def mark(num: Int): Board = Board(rows.map(_.filter(_ != num)), cols.map(_.filter(_ != num))) def checkBingo: Boolean = rows.exists(_.isEmpty) || cols.exists(_.isEmpty) def score: Int = rows.flatten.sum val nums = input.head.split(",").map(_.toInt) val boards = input.tail .filter(_.nonEmpty) .grouped(5) .map(_.map(_.trim.split("""\D+""").map(_.toInt).toVector)) .map(xss => Board(xss, xss.transpose)) .toVector val scores = nums .foldLeft((boards, Vector.empty[Int])) { case ((boards, score), num) => val (finished, active) = boards.map(_.mark(num)).partition(_.checkBingo) (active, score ++ finished.map(_.score * num)) } ._2 scores.head // part1 scores.last // part2

Dold text
PermalÀnk
Medlem ★
●

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

from pathlib import Path from re import findall from math import sqrt input = Path(__file__).with_name('day4.txt') lines = input.open('r').read().split('\n\n') class bingo_board(): def __init__(self, numbers, index) -> None: self.index = index self.marked = [False] * 25 self.numbers = findall('\d+', numbers) for i in range(0, len(self.numbers)): self.numbers[i] = int(self.numbers[i]) self.size = int(sqrt(len(self.numbers))) # Method to mark a number on the board. def mark(self, num): if num in self.numbers: self.marked[self.numbers.index(num)] = True # Evaluate if the board has a row och column fully marked def bingo(self): bingo = [] for i in range(0, self.size): bingo.append(all(self._mrow(i))) bingo.append(all(self._mcol(i))) assert len(bingo) == self.size * 2 return any(bingo) # Get all unmarked numbers in the board def all_unmarked(self): board = dict(zip(self.numbers, self.marked)) return [num for num, marked in board.items() if not marked] # Return marked row number n def _mrow(self, n): start = n * self.size end = start + self.size return self.marked[start:end] # Return marked column number n def _mcol(self, n): return self.marked[n::self.size] # Draw the balls and mark the numbers drawn on each board def play_bingo(balls, boards): for ball in balls: ball = int(ball) for board in boards: board.mark(ball) if board.bingo(): return sum(board.all_unmarked()) * ball def play_last_bingo(balls, boards): winning_boards = set() for ball in balls: ball = int(ball) for board in boards: board.mark(ball) if board.bingo(): winning_boards.add(board.index) if len(winning_boards) == len(boards): return sum(board.all_unmarked()) * ball # Create bingo boards boards = [] for i in range(1, len(lines)): boards.append(bingo_board(lines[i], i - 1)) # Create balls balls = lines[0].split(',') print('Score part 1: ' + str(play_bingo(balls, boards))) print('Score part 2: ' + str(play_last_bingo(balls, boards)))

Dold text
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: 5
SprÄk: Python

import re from collections import defaultdict from itertools import zip_longest pos_count = defaultdict(int) for line in open("5.in"): x1, y1, x2, y2 = map(int, re.split("\D+", line.rstrip())) xd = 1 if x2 > x1 else -1 yd = 1 if y2 > y1 else -1 for x, y in zip_longest(range(x1, x2 + xd, xd), range(y1, y2 + yd, yd), fillvalue=y1 if y1 == y2 else x1): pos_count[(x, y)] += 1 print(sum(1 for v in pos_count.values() if v >= 2))

Dold text
PermalÀnk
●

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

Idag kÀndes inte sÄ farligt svÄrt ÀndÄ, var ganska liknande en av dom tidigare uppgifterna. Tog sin lilla stund att fÄ till rÀtt loopar för diagonalerna dock.

import std/[strutils, strscans, sequtils, tables] proc parseLines(s: seq[string]): seq[(int, int, int, int)] = for line in s: let (success, x1, y1, x2, y2) = scanTuple(line, "$i,$i -> $i,$i") doAssert success, "Failed to parse: " & line result.add (x1, y1, x2, y2) proc part1(lines: seq[(int, int, int, int)]): int = var counts = initCountTable[(int, int)]() for (x1, y1, x2, y2) in lines: if x1 == x2 or y1 == y2: for i in min(x1, x2) .. max(x1, x2): for j in min(y1, y2) .. max(y1, y2): counts.inc (i, j) result = len(counts.values.toSeq.filterIt(it >= 2)) proc part2(lines: seq[(int, int, int, int)]): int = var counts = initCountTable[(int, int)]() for (x1, y1, x2, y2) in lines: if x1 == x2 or y1 == y2: for i in min(x1, x2) .. max(x1, x2): for j in min(y1, y2) .. max(y1, y2): counts.inc (i, j) elif x1 <= x2 and y1 <= y2: for (i, j) in zip(countup(x1, x2).toSeq, countup(y1, y2).toSeq): counts.inc (i, j) elif x1 > x2 and y1 <= y2: for (i, j) in zip(countdown(x1, x2).toSeq, countup(y1, y2).toSeq): counts.inc (i, j) elif x1 > x2 and y1 > y2: for (i, j) in zip(countdown(x1, x2).toSeq, countdown(y1, y2).toSeq): counts.inc (i, j) elif x1 <= x2 and y1 > y2: for (i, j) in zip(countup(x1, x2).toSeq, countdown(y1, y2).toSeq): counts.inc (i, j) result = len(counts.values.toSeq.filterIt(it >= 2)) let input = "input.txt".lines.toSeq.parseLines echo "Part 1: ", part1(input) echo "Part 2: ", part2(input)

Dold text
felstavade spoiler
PermalÀnk
●

Dag: 5
SprÄk: Scala

object Day5 { val data = readLines("5/data.txt") case class Coord(x: Int, y: Int) case class Line(x1: Int, y1: Int, x2: Int, y2: Int) { val length = max(abs(x2 - x1), abs(y2 - y1)) val coords = (0 to length).map(i => Coord(x1 + (x2 - x1) * i / length, y1 + (y2 - y1) * i / length)) def horizOrVert = x1 == x2 || y1 == y2 } val lines = data.map { case s"${int(x1)},${int(y1)} -> ${int(x2)},${int(y2)}" => Line(x1, y1, x2, y2) } def main(args: Array[String]): Unit = { def countDangers(lines: Seq[Line]) = { val allZeroMap = Map.empty[Coord, Int].withDefaultValue(0) val cellCount = lines.foldLeft(allZeroMap) { case (map, line) => map ++ line.coords.map(c => (c, map(c) + 1)).toMap } cellCount.values.count(_ > 1) } // part 1 println(countDangers(lines.filter(_.horizOrVert))) // part 2 println(countDangers(lines)) } }

Dold text
PermalÀnk
●

Fin lösning!
Tack för att du lÀrde jag mig transpose ocksÄ.

Skrivet av jclr:

Dag: 4
SprÄk: Scala

val input = Using.resource(Source.fromFile("4.txt"))(_.getLines().toVector) class Board(rows: Vector[Vector[Int]], cols: Vector[Vector[Int]]): def mark(num: Int): Board = Board(rows.map(_.filter(_ != num)), cols.map(_.filter(_ != num))) def checkBingo: Boolean = rows.exists(_.isEmpty) || cols.exists(_.isEmpty) def score: Int = rows.flatten.sum val nums = input.head.split(",").map(_.toInt) val boards = input.tail .filter(_.nonEmpty) .grouped(5) .map(_.map(_.trim.split("""\D+""").map(_.toInt).toVector)) .map(xss => Board(xss, xss.transpose)) .toVector val scores = nums .foldLeft((boards, Vector.empty[Int])) { case ((boards, score), num) => val (finished, active) = boards.map(_.mark(num)).partition(_.checkBingo) (active, score ++ finished.map(_.score * num)) } ._2 scores.head // part1 scores.last // part2

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

Dag: 4
SprÄk: Python 3
Lösning: GitHub, men mycket av spelandet sker i Utils.

Bra dag, men det var lÀngesedan jag anvÀnde numpy sÄ en hel del tid gick Ät till att söka i dokumentationen. Detta till trots fick jag ihop en lösning jag tycker Àr lÀttlÀst och vÀlfungerande. Det gÄr sÀkerligen att hitta svaret snabbare eller pÄ fÀrre rader kod, men jag ser inte riktigt vitsen med att skriva den sortens kod.

SÀrskilt nöjd blev jag med Del 2.

Det enda som skiljer min Del 1 frÄn min Del 2 Àr:

bingos[mx] = True if all(bingos):

pÄ raderna 30 och 31.

Dold text

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

Bytte telefon igÄr och nÄgonting gick snett med alarmet sÄÄÄÄÄÄÄ, det blev Ärets lÀngsta sovmorgon! Uppgiften i sig var OK, tycker jag. Som vanligt hade jag svÄrt att vÀlja ett spÄr att följa, men det gick bra tillslut.

Visa signatur

:(){ :|:& };:

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

PermalÀnk
Medlem
●

Dag: 4
Lösning: Golang

DÄ har vi redan börjat hamna efter.. Bingospelet var inte helt enkelt, fick dessutom för mig att försöka mig pÄ lite bit operationer - vilket gjorde att det tog Ànnu lÀngre tid, men kanske blev en lite kortare lösning.

package main import ( "bufio" "fmt" "math/bits" "os" "strconv" "strings" ) type Bingo struct { Balls []int Boards []Board BoardSize int } type Board struct { BingoFound bool Rows []uint NumberPosition map[int]Position PositionNumber map[string]int } type Position struct { X int Y int } type Result struct { Sum int Ball int Product int } func findBingoScores(bingo Bingo) []Result { var results []Result for _, ball := range bingo.Balls { if len(results) == len(bingo.Boards) { break } for j, board := range bingo.Boards { if board.BingoFound { continue } pos, ok := board.NumberPosition[ball] if !ok { continue } board.Rows[pos.Y] = setBit(board.Rows[pos.Y], reversePosX(bingo.BoardSize, pos.X)) if isBingoHorizontal(bingo, board, pos) || isBingoVertical(bingo, board, pos) { sum := findUnmarked(board, bingo.BoardSize) score := sum * ball results = append(results, Result{ Sum: sum, Ball: ball, Product: score, }) bingo.Boards[j].BingoFound = true } } } return results } func isBingoHorizontal(bingo Bingo, board Board, pos Position) bool { return bingo.BoardSize == bits.OnesCount(board.Rows[pos.Y]) } func reversePosX(boardSize int, x int) uint { return uint(boardSize - 1 - x) } func isBingoVertical(bingo Bingo, board Board, position Position) bool { allVerticalOnes := true for y := 0; y < bingo.BoardSize; y++ { if y == position.Y { continue } if !hasBit(board.Rows[y], reversePosX(bingo.BoardSize, position.X)) { allVerticalOnes = false break } } return allVerticalOnes } func findUnmarked(board Board, boardSize int) int { var sum int for y, row := range board.Rows { for x := 0; x < boardSize; x++ { if !hasBit(row, reversePosX(boardSize, x)) { ball := board.PositionNumber[getPositionNumberKey(x, y)] sum += ball } } } return sum } func setBit(n uint, pos uint) uint { n |= 1 << pos return n } func hasBit(n uint, pos uint) bool { val := n & (1 << pos) return val > 0 } func getPositionNumberKey(x int, y int) string { return fmt.Sprintf("%d,%d", x, y) } func getPartOne(bingo Bingo) int { return findBingoScores(bingo)[0].Product } func getPartTwo(bingo Bingo) int { scores := findBingoScores(bingo) return scores[len(scores)-1].Product } func getRows(filename string) Bingo { file, err := os.Open(filename) if err != nil { panic(err) } defer file.Close() scanner := bufio.NewScanner(file) var bingo Bingo rowIndex := 0 y := 0 var board Board for scanner.Scan() { row := scanner.Text() if rowIndex == 0 { numbers := strings.Split(row, ",") for _, number := range numbers { val, err := strconv.Atoi(number) if err != nil { panic(err) } bingo.Balls = append(bingo.Balls, val) } } else { if len(row) == 0 { if board.NumberPosition != nil { bingo.Boards = append(bingo.Boards, board) } board = Board{} board.NumberPosition = map[int]Position{} board.PositionNumber = map[string]int{} y = 0 } else { fields := strings.Fields(row) for x, field := range fields { val, err := strconv.Atoi(field) if err != nil { panic(err) } board.NumberPosition[val] = Position{ X: x, Y: y, } board.PositionNumber[getPositionNumberKey(x, y)] = val } board.Rows = append(board.Rows, 0) y++ } } rowIndex++ } bingo.Boards = append(bingo.Boards, board) bingo.BoardSize = y return bingo } func main() { fmt.Println("Part one:", getPartOne(getRows("../input.txt"))) fmt.Println("Part two:", getPartTwo(getRows("../input.txt"))) }

Dold text
PermalÀnk
●

Dag 5
SprÄk: C
Lösning: GitHub

Dag 5 kÀndes inte sÄ svÄr nÀr jag lÀste uppgiften, sÄ jag var tvungen att skoja till det lite. GÀller att hÄlla sina ternÀrer och parenteser rÀtt i mun!

PermalÀnk
Medlem ★
●
Skrivet av survivalcode:

Dag: 5
SprÄk: Python

import re from collections import defaultdict from itertools import zip_longest pos_count = defaultdict(int) for line in open("5.in"): x1, y1, x2, y2 = map(int, re.split("\D+", line.rstrip())) xd = 1 if x2 > x1 else -1 yd = 1 if y2 > y1 else -1 for x, y in zip_longest(range(x1, x2 + xd, xd), range(y1, y2 + yd, yd), fillvalue=y1 if y1 == y2 else x1): pos_count[(x, y)] += 1 print(sum(1 for v in pos_count.values() if v >= 2))

Dold text

Den hÀr var ju mycket klurigare Àn min lösning. Ett regexp istÀllet för en obegriplig list comprehension med 4(!) for. Sedan blir det en del brus för att översÀtta koordinaterna till nÄgot som numpy gillar sÄ defaultdict var nog ett smartare val. Tack för lektionen.

Dag: 5
SprÄk: Python

import numpy as np lines = [tuple([tuple([int(i) for i in p.split(",")]) for p in l2]) for l2 in [l1.split(" -> ") for l1 in [l.strip() for l in open("input05").readlines()]]] def coords(line, diag): (x1, y1), (x2, y2) = line xstep = (x2 - x1) / abs(x2 - x1) if x1 != x2 else 0 ystep = (y2 - y1) / abs(y2 - y1) if y1 != y2 else 0 return [(int(x1 + i * xstep), int(y1 + i * ystep)) for i in range(max(abs(x1 - x2), abs(y1 - y2)) + 1) if xstep == 0 or ystep == 0 or diag] for diag in [False, True]: bottom = np.zeros((1000,1000)) for l in lines: bottom[[*np.array(coords(l, diag)).T]] += 1 print((bottom > 1).sum())

Dold text
PermalÀnk
Datavetare ★
●

Dag: 5
SprÄk: Rust

use crate::solution::Solution; use std::{ cell::RefCell, ops::AddAssign, collections::HashMap }; type Canvas = HashMap<Pos, u32>; struct Day5 { axis_aligned_lines: Vec<Line>, diagonal_lines: Vec<Line>, ocean_floor: RefCell<Canvas>, } impl Solution for Day5 { fn part1(&self) -> String { let mut canvas = self.ocean_floor.borrow_mut(); self.axis_aligned_lines .iter() .for_each(|line| line.draw(&mut canvas)); num_overlaps(&canvas).to_string() } fn part2(&self) -> String { let mut canvas = self.ocean_floor.borrow_mut(); self.diagonal_lines .iter() .for_each(|line| line.draw(&mut canvas)); num_overlaps(&canvas).to_string() } } pub fn new(input: &str) -> Box<dyn Solution> { let mut axis_aligned_lines = Vec::new(); let mut diagonal_lines = Vec::new(); for input_line in input.lines() { let (x1, y1, x2, y2) = scan_fmt!(input_line, "{d},{d} -> {d},{d}", i32, i32, i32, i32) .expect("Invalid line specification"); let line = Line{from: Pos{x: x1, y: y1}, to: Pos{x: x2, y: y2}}; if line.is_axis_aligned() { axis_aligned_lines.push(line); } else { diagonal_lines.push(line); } } Box::new(Day5{ axis_aligned_lines, diagonal_lines, ocean_floor: RefCell::new(Canvas::new()), }) } fn num_overlaps(canvas: &Canvas) -> usize { canvas .values() .filter(|&&overdraw| overdraw > 1) .count() } #[derive(Clone, Copy, Eq, Hash, PartialEq)] struct Pos { x: i32, y: i32, } impl AddAssign for Pos { fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; } } impl Pos { fn delta_step(self, rhs: Self) -> Self { let cmp = |a, b| { if a == b { 0 } else if a < b { 1 } else { -1 } }; Pos{x: cmp(self.x, rhs.x), y: cmp(self.y, rhs.y)} } } struct Line { from: Pos, to: Pos, } impl Line { fn is_axis_aligned(&self) -> bool { self.from.x == self.to.x || self.from.y == self.to.y } fn draw(&self, canvas: &mut Canvas) { let mut cur_pos = self.from; let step = cur_pos.delta_step(self.to); loop { *canvas.entry(cur_pos).or_insert(0) += 1; if cur_pos == self.to { break } cur_pos += step; } } }

Dold text

Hmm, den hÀr spenderade 11 ms av budget:en (mÄlet Àr att lösa alla 25 dagar pÄ <1s). "Put-pixel" suger prestandamÀssigt...
FÄr fundera pÄ potentiell optimering.

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: 5
SprÄk: C++

#include <iostream> #include <regex> #include "../utils/file_reader.cpp" struct line { int x1; int y1; int x2; int y2; }; vector<line> parse(vector<string> data, vector<vector<int>> &grid) { vector<line> output; int x_max_grid = 0, y_max_grid = 0; int x1, x2, y1, y2; std::string regex_string = "^([0-9]+),([0-9]+)\\s->\\s([0-9]+),([0-9]+)$"; regex regex(regex_string); smatch matches; int n_rows = data.size(); for (int i = 0; i < n_rows; i++) { bool match = regex_search(data[i],matches,regex); if (match) { int x1 = stoi(matches[1]); int y1 = stoi(matches[2]); int x2 = stoi(matches[3]); int y2 = stoi(matches[4]); line new_line = {x1, y1, x2, y2}; output.push_back(new_line); if (x1 > x_max_grid){x_max_grid = x1;} if (x2 > x_max_grid){x_max_grid = x2;} if (y1 > y_max_grid){y_max_grid = y1;} if (y2 > y_max_grid){y_max_grid = y2;} } } //output.push_back(grid_diagonal); grid.resize(x_max_grid + 1, vector<int> (y_max_grid + 1,0)); return output; } int draw_lines(vector<line> lines,vector<vector<int>> grid, bool skip_diagonals = true) { int count = 0; int n_lines = lines.size(); int row_step,col_step; for (auto line : lines) { if (line.x1 == line.x2) { //vertical line line.y1 > line.y2? row_step = -1 : row_step = 1; int row = line.y1; while (row != (line.y2+row_step)) { if (grid[line.x1][row] == 1) { count++; } grid[line.x1][row]++; row += row_step; } } else if (line.y1 == line.y2) { //horizontal line line.x1 > line.x2? col_step = -1 : col_step = 1; int col = line.x1; while (col != (line.x2+col_step)) { if (grid[col][line.y1] == 1) { count++; } grid[col][line.y1]++; col+= col_step; } } else { if (skip_diagonals) { continue; } //45 degree diagonal line int col = line.x1; line.x1 > line.x2? col_step = -1 : col_step = 1; int row = line.y1; line.y1 > line.y2? row_step = -1 : row_step = 1; while (col != (line.x2 + col_step)) { if (grid[col][row] == 1) { count++; } grid[col][row]++; col += col_step; row += row_step; } } } return count; } int main() { string filename = "../../input/day_05.txt"; vector<string> data = read_file<string>(filename,true); vector<vector<int>> grid; vector<line> lines = parse(data, grid); int part_1 = draw_lines(lines, grid, true); int part_2 = draw_lines(lines, grid, false); cout << "Day 5 Part 1 solution: " << part_1 << endl; cout << "Day 5 Part 2 solution: " << part_2 << endl; return 0; }

Dold text
PermalÀnk
Datavetare ★
●

Day: 5
SprÄk: Rust (med Rayon sÄ alla CPU-trÄdar anvÀnds)

use crate::solution::Solution; use rayon::prelude::*; use std::{ ops::AddAssign, sync::atomic::{AtomicU32, Ordering}, sync::Arc, }; const CANVAS_DIM: usize = 1000; const ATOMIC_ZERO: AtomicU32 = AtomicU32::new(0); struct Canvas { buf: [AtomicU32; CANVAS_DIM * CANVAS_DIM], } struct Day5 { axis_aligned_lines: Vec<Line>, diagonal_lines: Vec<Line>, ocean_floor: Arc<Canvas>, } impl Solution for Day5 { fn part1(&mut self) -> String { self.axis_aligned_lines .par_iter() .for_each(|line| line.draw(&mut self.ocean_floor.clone())); num_overlaps(&self.ocean_floor).to_string() } fn part2(&mut self) -> String { self.diagonal_lines .par_iter() .for_each(|line| line.draw(&mut self.ocean_floor.clone())); num_overlaps(&self.ocean_floor).to_string() } } pub fn new(input: &str) -> Box<dyn Solution> { let mut axis_aligned_lines = Vec::new(); let mut diagonal_lines = Vec::new(); for input_line in input.lines() { let (x1, y1, x2, y2) = scan_fmt!(input_line, "{d},{d} -> {d},{d}", i32, i32, i32, i32) .expect("Invalid line specification"); let line = Line{from: Pos{x: x1, y: y1}, to: Pos{x: x2, y: y2}}; if line.is_axis_aligned() { axis_aligned_lines.push(line); } else { diagonal_lines.push(line); } } Box::new(Day5{ axis_aligned_lines, diagonal_lines, ocean_floor: Arc::new(Canvas{buf: [ATOMIC_ZERO; CANVAS_DIM * CANVAS_DIM]}), }) } fn num_overlaps(canvas: &Canvas) -> usize { (&canvas.buf) .into_iter() .filter(|&overdraw| overdraw.load(Ordering::Relaxed) > 1) .count() } #[derive(Clone, Copy, Eq, Hash, PartialEq)] struct Pos { x: i32, y: i32, } impl AddAssign for Pos { fn add_assign(&mut self, rhs: Self) { self.x += rhs.x; self.y += rhs.y; } } impl Pos { fn delta_step(self, rhs: Self) -> Self { let step = |a: i32, b: i32| { match a.cmp(&b) { Ordering::Equal => 0, Ordering::Less => 1, Ordering::Greater => -1, } }; Pos { x: step(self.x, rhs.x), y: step(self.y, rhs.y), } } } struct Line { from: Pos, to: Pos, } impl Line { fn is_axis_aligned(&self) -> bool { self.from.x == self.to.x || self.from.y == self.to.y } fn draw(&self, canvas: &mut Arc<Canvas>) { let mut cur_pos = self.from; let step = cur_pos.delta_step(self.to); loop { let idx = cur_pos.y as usize * CANVAS_DIM + cur_pos.x as usize; canvas.buf[idx].fetch_add(1, Ordering::Relaxed); if cur_pos == self.to { break } cur_pos += step; } } }

Dold text

Fick ned det till 1,3 ms för att lösa bÄda delarna. Fast givet negativ skalning med CPU-trÄdar frÄn 3 trÄdar och uppÄt misstÀnkte jag att det kommer vara Ànnu snabbare att kör pÄ en trÄd och skippa overhead frÄn atomÀra variabler och dra igÄng flera trÄdar.

Mycket riktigt, kör man allt enkeltrÄdat gÄr det att fÄ ned det till 0,9 ms. SÄ behÄller den varianten

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: 5
SprÄk: Halftafflig F#

open System.IO open System let DrawHorizontal startX startY length = [for i in 0..length -> (startX, (startY+i))] let DrawVertical startX startY length = [for i in 0..length -> ((startX+i), startY)] let DrawDiagonal startX startY endX endY = let drawLineRising startX startY length = [for i in 0..length -> (startX+i, startY+i)] let drawLineFalling startX startY length = [for i in 0..length -> (startX-i, startY+i)] let direction = ((startX-endX),startY-endY) let data = match direction with | (x,y) when abs x <> abs y -> failwith "Not a 45 deg angle" | (x,y) when x < 0 && y < 0 -> drawLineRising startX startY -x | (x,y) when x < 0 && y > 0 -> drawLineFalling endX endY -x | (x,y) when x > 0 && y < 0 -> drawLineFalling startX startY x | (x,y) when x > 0 && y > 0 -> drawLineRising endX endY x | _ -> failwith "Unexpected movement" data let task1 map (input,output) = let (outx, outy) = output match input with | (inx, iny) when inx=outx && iny < outy -> DrawHorizontal inx iny (outy-iny) @ map | (inx, iny) when inx=outx && iny > outy -> DrawHorizontal outx outy (iny-outy) @ map | (inx, iny) when iny=outy && inx < outx -> DrawVertical inx iny (outx-inx) @ map | (inx, iny) when iny=outy && inx > outx -> DrawVertical outx outy (inx-outx) @ map | _ -> map let task2 map (input,output) = let (outx, outy) = output match input with | (inx, iny) when inx=outx && iny < outy -> DrawHorizontal inx iny (outy-iny) @ map | (inx, iny) when inx=outx && iny > outy -> DrawHorizontal outx outy (iny-outy) @ map | (inx, iny) when iny=outy && inx < outx -> DrawVertical inx iny (outx-inx) @ map | (inx, iny) when iny=outy && inx > outx -> DrawVertical outx outy (inx-outx) @ map | (inx, iny) -> DrawDiagonal inx iny outx outy @ map let calculateScore = List.countBy id >> List.filter (fun (_,y) -> y > 1) >> List.length let parseData = let parseRow (str:string) = let parseCoordinates (str:string) = let parts = str.Split(",", StringSplitOptions.TrimEntries) |> Seq.map int (parts |> Seq.head, parts |> Seq.skip 1 |> Seq.head) let parts = str.Split("->", StringSplitOptions.TrimEntries) |> Seq.map parseCoordinates (parts |> Seq.head, parts |> Seq.skip 1 |> Seq.head) File.ReadLines "Day5.txt" |> Seq.map parseRow let drawpipes pipefunc = parseData |> Seq.fold pipefunc [] printfn "task 1: %i" (drawpipes task1 |> calculateScore) printfn "task 2: %i" (drawpipes task2 |> calculateScore)

Dold text
Visa signatur

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

PermalÀnk
Medlem ★
●

Dag: 5
SprÄk: C# 10

Blev ÀndÄ en del pyssel med dagens lösning. Fick börja om lite i del 2 nÀr jag fick rÀtt svar pÄ exempeldatat men fel pÄ det som gÀller. SÄ jÀkla drygt att felsöka nÀr det blir sÄ.

Edit: Var inte helt nöjd med föregÄende lösning, och kom pÄ en jag gillar bÀttre under en lÄngpromenad.

var vents = new int[1000, 1000]; using (var sr = new StreamReader("input.txt")) { while (!sr.EndOfStream) { var line = sr.ReadLine()!.Split(" -> "); (string[] point1, string[] point2) = (line[0].Split(','), line[1].Split(',').ToArray()); (int x1, int x2, int y1, int y2) = (int.Parse(point1[0]), int.Parse(point2[0]), int.Parse(point1[1]), int.Parse(point2[1])); int xstep = x1 == x2 ? 0 : (x1 < x2 ? 1 : -1); int ystep = y1 == y2 ? 0 : (y1 < y2 ? 1 : -1); int xstop = x2 + (xstep == 0 ? 1 : xstep); int ystop = y2 + (ystep == 0 ? 1 : ystep); for (int x = x1, y = y1; x != xstop && y != ystop; x += xstep, y += ystep) { vents[x, y]++; } } } Console.WriteLine(vents.Cast<int>().Count(x => x > 1));

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: 5
SprÄk: Carth

Har ingen map/dictionary/tabell-typ i Carth Àn, sÄ det börjar bli smÀrtsamt. Fick anvÀnda array och sortering istÀllet. Hittade ocksÄ en kodgenereringsbugg dÀr min foldl inte tail-call optimerades och gav stack overflow, sÄ behövde jobba mig runt det.

(import std) (define main (do io/bind (<- input (io/map unwrap! (read-file "inputs/day5.txt"))) (let (([ortho-points diag-points] (map-both array/collect-list (partition-eithers (flat-map (<o line-points parse-line) (lines input))))) (ortho-sorted (merge-sort point-cmp ortho-points)) (all-sorted (merge-sort point-cmp (array/append ortho-sorted diag-points))) )) (display (str-append "Part 1: " (show-int (count-intersections ortho-sorted)))) (display (str-append "Part 2: " (show-int (count-intersections all-sorted)))))) ;; The boxing of the accumulation is a hack to work around a bug in the codegen. `foldl` should ;; always be tail call optimized, but apparently it is not when the type of the accumulation is too ;; big or complex or something like that. No TCO => stack overflow / segfault for long ;; iterators. Boxing reduces the type to a simple pointer, which does not break TCO. (define (count-intersections ps) (define (point-eq p1 p2) (match (point-cmp p1 p2) (case Eq True) (case _ False))) (let (([p0 ps] (next! (array/iter ps))) ([p1 ps] (next! ps)) (init (if (point-eq p0 p1) 1 0))) (car (deref (foldl (fun ((Box [n p0 p1]) p2) ;; Don't count more than one intersection when more than one duplicate (box [(if (and (point-eq p2 p1) (not (point-eq p2 p0))) (+ n 1) n) p1 p2])) (box [init p0 p1]) ps))))) (define parse-line (<o unwrap! (parse (do parse/bind (<- x1 parse/nat) (parse/string ",") (<- y1 parse/nat) (parse/string " -> ") (<- x2 parse/nat) (parse/string ",") (<- y2 parse/nat) (parse/pure [[(to-int x1) (to-int y1)] [(to-int x2) (to-int y2)]]))))) (define (line-points [[x1 y1] [x2 y2]]) (if (= x1 x2) (map Left (zip (repeat x1) (range (min y1 y2) (max y1 y2)))) (if (= y1 y2) (map Left (zip (range (min x1 x2) (max x1 x2)) (repeat y1))) (let ((mag (abs (- x2 x1))) (dx (sign (- x2 x1))) (dy (sign (- y2 y1)))) (map (fun (i) (Right [(+ x1 (* dx i)) (+ y1 (* dy i))])) (range 0 mag)))))) (define (point-cmp [x1 y1] [x2 y2]) (match (int/cmp x1 x2) (case Lt Lt) (case Gt Gt) (case Eq (int/cmp y1 y2))))

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
●

Dag: 5
SprÄk: Haskell

Följer Yoshmans exempel och syntaxfÀrgar kodsnutten. Hittade ett program kallat highlight i apt, som kan spotta ut bbcode. Den missar operatorerna men vad gör vÀl det sÄ hÀr innan jul?

import qualified Data.Set as Set main = interact solve solve :: String -> String solve input = "Problem 1: " ++ show (countOverlaps (filter (not.isDiagonal) measurements)) ++ "\n" ++ "Problem2: " ++ show (countOverlaps measurements) ++ "\n" where measurements = map splitNumbers (lines input) :: [[Int]] splitNumbers line = read num : if null rest then [] else splitNumbers rest where (num,rest) = span isNum (dropWhile (not.isNum) line) isNum c = elem c "0123456789" countOverlaps measurements = length (snd (foldr countPts (Set.empty, Set.empty) measurements)) where countPts line (allPts, dups) = (allPts', dups') where allPts' = Set.union allPts newPts dups' = Set.union dups (Set.intersection allPts newPts) newPts = Set.fromList (points line) points line@(x1:y1:x2:y2:[]) = if isDiagonal line then zip xs ys else [(x,y) | x<-xs, y<-ys] where xs = listPts x1 x2 ys = listPts y1 y2 listPts p1 p2 | p1 > p2 = reverse [p2..p1] | otherwise = [p1..p2] isDiagonal (x1:y1:x2:y2:[]) = x1/=x2 && y1/=y2

Dold text
PermalÀnk
Hedersmedlem ★
●

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

Tog rÀtt mycket tid. Spenderade nog 45+ minuter efter att jag löst bÄda delarna, med att skriva om det jag visste var en fullösning (tre cases: vertikal, horisontell, diagonell) till en mer generell lösning som kan hantera alla tre.
Det blev klart kortare med den generella (se diff för senaste commit).

Edit: Uppdaterade lite; elegant kod fick ta över trots sannolikt lÀgre prestanda:

let total_overlaps = 0; for (let y = 0; y < GRID_SIZE; y++) { for (let x = 0; x < GRID_SIZE; x++) { if (grid[y][x] >= 2) total_overlaps++; } } return total_overlaps;

blev

return grid.flat().filter(entry => entry >= 2).length;

Stör mig dock pÄ den sista yield som Àr utanför i *points(). Ser ingen snyggare lösning... Kan ha den före, efter, eller ha en while(true) som jag manuellt bryter efter yield-raden, om motsatsen till nuvarande while-expression Àr sant. Gillar ingen av de tre.

Hur gör man det snyggare?

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"
NAS: 6700K/16GB/Debian+ZFS | Backup (offsite): 9600K/16GB/Debian+ZFS

PermalÀnk
●

Dag: 4
SprÄk: Rust
Lösning: Github

use std::fs; pub fn run() { let data = fs::read_to_string("dec_04.txt").expect("unable to read file"); let mut cards = vec![vec![vec![]]]; let mut card = vec![vec![]]; let mut bingo_balls = vec![0]; for line in data.lines().rev() { match line.len() { i if i > 16 => { bingo_balls = line.split(",").map(|s| s.parse().unwrap()).collect(); } i if i == 14 => { let bingo_line: Vec<i32> = line.split(" ").filter_map(|s| s.parse().ok()).collect(); card.push(bingo_line); } 0 => { cards.push(card.clone()); card.clear(); } _ => println!("Bad data"), } } let mut high_score = 500; let mut winning_card = 0; let mut winning_line = vec![]; for (card_index, card) in cards.iter().enumerate() { let mut row = vec![0; 6]; let mut col = vec![0; 6]; let mut score_line = vec![]; for (score, ball) in bingo_balls.iter().enumerate() { for (x, line) in card.iter().enumerate() { for (y, n) in line.iter().enumerate() { if n == ball { row[x] += 1; col[y] += 1; score_line.push(*ball); if (row[x] == 5) || (col[y] == 5) { if score < high_score { high_score = score; winning_card = card_index; winning_line = score_line.clone(); } } } } } } } let sum1: i32 = winning_line.iter().sum(); let mut sum2 = 0; for card in &cards[winning_card] { for n in card { sum2 += n; } } let awnser = (sum2 - sum1) * winning_line.last().unwrap(); println!("Awnser {}", awnser); }

Dold text

Lite dÄligt med tid / d börjar ta lÀngre tid att lösa :P. Hann inte fÄ in i tid för första stjÀrnan ens. PÄ det igen nÀsta Är, hÀnga med lte lÀngre varje gÄng. Kanske löser nÄn dag till fast utanför tidsramen.

PermalÀnk
Medlem
●

Dag: 4
SprÄk: C#

internal class Puzzle4 : Puzzle<int> { private class Square { public int Number { get; } public bool IsMarked { get; set; } public Square(int number) => Number = number; } private readonly List<int> _bingoResults; public Puzzle4() { var lines = File.ReadAllLines("Inputs/Puzzle4.txt"); var numbers = lines[0].Split(',') .Select(int.Parse) .ToArray(); var boards = lines.Skip(1) .Where(x => !string.IsNullOrWhiteSpace(x)) .Select(boardLine => boardLine .Split(' ', StringSplitOptions.RemoveEmptyEntries) .Select(x => new Square(int.Parse(x))) .ToArray()) .Chunk(5) .ToArray(); _bingoResults = PlayBingo(numbers, boards); } public override int One() => _bingoResults.First(); public override int Two() => _bingoResults.Last(); private static List<int> PlayBingo(int[] numbers, Square[][][] boards) { var winningResults = new List<int>(); var playingBoards = boards.ToList(); foreach (var number in numbers) { foreach (var board in playingBoards.ToList()) { var numbersToCheck = board .Select(line => line.FirstOrDefault(s => s.Number == number)) .Where(s => s != null); foreach (var numberToCheck in numbersToCheck) { numberToCheck!.IsMarked = true; } if (HasRowWin(board) || HasColumnWin(board)) { var score = board.Sum(line => line.Where(s => !s.IsMarked).Sum(s => s.Number)) * number; winningResults.Add(score); playingBoards.Remove(board); } } if (playingBoards.Count == 0) { break; } } return winningResults; } private static bool HasRowWin(Square[][] board) => board.Any(line => line.All(s => s.IsMarked)); private static bool HasColumnWin(Square[][] board) { for (int col = 0; col < board.Length; col++) { var hasColumnWin = true; for (int row = 0; row < board[col].Length; row++) { if (!board[row][col].IsMarked) { hasColumnWin = false; } } if (hasColumnWin) { return true; } } return false; } }

Dold text
PermalÀnk
Medlem ★
●

Kastar in handduken för idag. FÄr rÀtt pÄ exemplet, men fel pÄ faktiska inputen och jag har ingen aning om varför.

Jag jÀmför alltsÄ mellan en lista med alla coordinates mot en annan likadan efter en toSet() operation dÀr den tar bort alla dubbletter, som stÀmmer in pÄ min overridade operator kollen i Coordinate klassen.

Koden: GitHub

Jag har i alla fall lÀrt mig att toSet() Àr en krÀvande operation.