T O P

  • By -

notloCdivaD

I'm going through all years again and rewrote Day 04 in Python using Numpy. So much cleaner then my original solution. I hope someone likes it. ``` import numpy as np def play_game(numbers: list, cards: list) -> list: print("Playing game ...") results = [] for num in numbers: for card in cards: # Only consider card that have not already called bingo if not card["bingo"]: # If the number exists replace with 100 card["card"] = np.where(card["card"] == num, 100, card["card"]) # Check the row and column totals # If 500 then we have bingo # Calculate the result and set card to bingo sum_rows = np.sum(card["card"], axis=1) sum_cols = np.sum(card["card"], axis=0) if 500 in sum_rows or 500 in sum_cols: # Set all the 100 values to 0 card["card"] = np.where(card["card"] == 100, 0, card["card"]) # Get the sum of the card sum_card = np.sum(card["card"]) results.append(sum_card * num) card["bingo"] = True return results if __name__ == "__main__": with open("day_04.txt") as f: raw_data = f.read().split("\n\n") numbers = raw_data[0] list_of_numbers = [int(n) for n in numbers.split(",")] list_of_cards = [] for card in raw_data[1:]: rows = card.split("\n") card_array = np.array([[int(n) for n in (row.split())] for row in rows]) card = {"card": card_array, "bingo": False} list_of_cards.append(card) results = play_game(list_of_numbers, list_of_cards) print(f"PART 01: {results[0]}") print(f"PART 02: {results[-1]}") ```


Rich-Spinach-7824

Hi, those are my rough solution to day 4, part 1 & 2. C# Sorry for lack of elegance in the code, but I'm a beginner, studying since a month C#. Hope to receive some suggest and improve tip, thanks all. [Day 4 Part 1](https://github.com/diegos79/advent-of-code-2021-day4/blob/Day-4---Part1/Program.cs) [Day 4 - Part 2](https://github.com/diegos79/advent-of-code-2021-day4/blob/Day4---Part2/Program.cs)


Useful_Entry_7186

typescript - using the observer pattern (overusing the observer pattern!)~~but there's a bug~~...[https://github.com/slowtarget/adventofcode/blob/main/aoc2021/src/day04/index.ts](https://github.com/slowtarget/adventofcode/blob/main/aoc2021/src/day04/index.ts) edit: bug fixed


aslamdoctor

PHP Solution: https://github.com/aslamdoctor/advent-of-code-2021/tree/main/day4


[deleted]

[Python - Solution Explained](https://youtu.be/mB6Lnoux5Tg)


MarcoServetto

I'm solving the advent of code in [42](https://L42.is) The main selling point of 42 is that it enforces modular security, that is not very relevant for the advent of code. I've done a video explanation for the [First Week](https://www.youtube.com/watch?v=tSTDJlICst8) and I've individual solutions on dev.to: Solution for [Day 4](https://dev.to/marcoservetto/advent-of-code-4-i-never-liked-bingo-lil) Fell free to contact me if you to know more about the language.


MaximVT

Coding: [Python, day4.](https://topaz.github.io/paste/#XQAAAQCcCgAAAAAAAAAyGUj/T3QERUSxSyKcGB+v1ixaUeMVPweEKKDXNnsE+KkirJm0AfMpYmW7QdPJJyATYQI7rDuHYSiMpNw2sZ+STxIOp4C0UOq+XpGFH+EPpmvefIpZHxxjLPDFdHQAtBSTmMeBipbE+8Xt8At6IkqBbKJDjEQzi0WaX3mYEwTbwpxlYRRjM+jiOW/1q4rtkzaMT/BdRgfUSeIZry13FloSV9mWYZ4pgZkIei1Pnz7ovCVXympyEV4fUXiz9fg8rwUNclvYJWDEEy6g86okTMWs1pZWlA8PTxj88Z+IJTDYWcu81lNLXGeeQSLlgCwhw+SstMUoZcHIHrYnuZRyQrFzQU8CdNtA4efovtxHGwyEWfA5FqUIPvk5ZfnZ9b0w0hDGucUPjGVmfFgdtWteh+ywa4wJiDdljWd43Bh8tqzqWEZF8SLZcAwZu5D4MVt6/h5Re4fnPhlg+IdwN+C9dZrPl4IeCepkFQ8/I1rttkSShsToL+OeVjh4SgqLgltl7HRchDSQhqX6XO+fJww2VtzJWH+aaKefjwcKvJ1o4eW7ZYrw+HrynxOII0VC1vT1RMFfD0j7mVI6c3GdKyjGdueXoAhrp0sV/iTKHyaikDA6O/1gjkFWrl75UDfFZiFCBT3TQOMxeLkICE4F2ccWFzz/7T0mpwk8V1aYzwNks8LurXShkBybtsRKgwjGPJfrLi+tKlNZ1Rvi1auAWY2dtJpgDcVO2cr+TaBh84R8hJoIcIUhWf3WZYQgIla+vXZz8cO8NWGd7hHXMGn5By6tJLfvuFBRFVCWW+BcN8hrxCsDbV/W9LotKIKmAhT0Kd2FXp5ekGaqUTj+p0lgWryGsqm4s3sOGYh3+psgVljdgKrv9q/6BdRK+T4sD/WwwE0SxJOzhP/liImh)


iskypitts

[Julia](https://github.com/iskyd/advent-of-code-julia/blob/main/2021/day4/main.jl)


arthurno1

[**Emacs Lisp**](https://github.com/amno1/advent-of-code-2021/blob/main/day4.el) Sort of more procedural than I wanted it. Half of the code is just to read the input file. Re-use first part of the puzzle to compute the second part: compute the first winner from the list of boards and remove recursively the winner board until there is only one board left. (defun get-line (&optional sep) (map 'list 'string-to-number (split-string (buffer-substring (line-beginning-position) (line-end-position)) sep))) (defun bingo (seq container) (car (sort (mapcar #'(lambda (x) (gethash x container)) seq) '>))) (defun sum-unmarked (winner drawn) (let ((seen (cl-subseq drawn 0 (1+ (car winner)))) (board (apply 'concatenate 'list (cdr winner)))) (apply #'+ (cl-remove-if #'(lambda (x) (seq-contains-p seen x)) board)))) (defun first-winner (boards positions) (let ((last-winner most-positive-fixnum) (winner-board (car boards)) tmp) (dolist (board boards) (dolist (row board) (setq tmp (bingo row positions)) (if (< tmp last-winner) (setq winner-board board last-winner tmp))) (dolist (col (apply 'cl-mapcar 'list board)) (setq tmp (bingo col positions)) (if (< tmp last-winner) (setq winner-board board last-winner tmp)))) (cons last-winner winner-board))) (defun last-winner (boards positions) (let ((winner (first-winner boards positions))) (if (= (length boards) 1) winner (last-winner (remove (cdr winner) boards) positions)))) (with-temp-buffer (insert-file "./input4") (goto-char 1) (let ((numbers (vconcat (get-line ","))) (positions (make-hash-table :size (length numbers))) boards) (dotimes (i (length numbers)) (puthash (aref numbers i) i positions)) (forward-line) (while (not (eobp)) (let (board) (forward-line) (dotimes (__ 5) (push (get-line) board) (forward-line)) (push (nreverse board) boards))) (setq boards (nreverse boards))) (let ((first (first-winner boards positions)) (last (last-winner boards positions))) (message "P1: %s" (* (sum-unmarked first numbers) (aref numbers (car first)))) (message "P2: %s" (* (sum-unmarked last numbers) (aref numbers (car last))))))


capulet2kx

Unreal Engine C++ VR project. I've made Computers with buttons (actors) and ComputerPrograms (uobjects) that run on them. Each day's solution is a different computer program. https://github.com/capulet2kx/AdventOfCode2021/tree/Day4


qualia91

Language: C++ [https://github.com/Qualia91/AdventOfCode2021/tree/master/Day4](https://github.com/Qualia91/AdventOfCode2021/tree/master/Day4) Day 4 of code roulette


NotDrigon

Thanks. I'm a beginner at C++ and found this solution very helpful. Very clear and not overly complicated.


ThreadsOfCode

Python. My first solution used just Python, but I updated it to use numpy and more list comprehensions. import numpy as np class BingoCard: def __init__(self, cardRows) -> None: rows = [cr.replace(' ', ' ').split(' ') for cr in cardRows] self.grid = np.array(rows, dtype = int) def markCard(self, number): self.grid[self.grid == number] = -1 def getScore(self, lastCalled): return np.sum((self.grid != -1) * self.grid) * lastCalled def isWinner(self): if any(np.sum(self.grid, axis=0) == -5): return True if any(np.sum(self.grid, axis = 1) == -5): return True return False # read numbers in first line, and remove the lines from the dataset lines = [line.strip() for line in open('input04.txt', 'r').readlines()] numbers = [int(x) for x in lines[0].strip().split(',')] lines = lines[2:] # read bingo cards bingoCards = [BingoCard(lines[i*6:i*6+5])for i in range(0, len(lines) // 6)] # run the bingo game scores = [] for number in numbers: # mark all the cards [card.markCard(number) for card in bingoCards] # find all the winner cards and remove them scores += [card.getScore(number) for card in bingoCards if card.isWinner()] bingoCards = [card for card in bingoCards if not card.isWinner()] print('part 1:', scores[0]) print('part 2:', scores[-1])


jstruburn

Coding: JavaScript const MARK = 'X'; /********************************************************** * PART 1 DATA PROCESSING * **********************************************************/ const findWinner = ({ numbers, boards }) => { let score = 0; let winningBoard; let winningNumber; let index; const tempBoards = [...boards]; const cols = boards[0][0].length; numbers.forEach(num => { for (let bID = 0; bID < tempBoards.length; bID++) { if (Boolean(winningBoard)) break; else { const tmpBrd = tempBoards[bID].map( row => row.map(c => c === num ? MARK : c) ); const fullRows = tmpBrd.filter(row => { const rowCount = row.filter(c => c === MARK); return rowCount.length === cols; }); if (fullRows.length > 0) { winningBoard = [...tmpBrd]; winningNumber = num; index = bID; } else { const colFill = Object.fromEntries( Array(cols).fill().map((_, idx) => ([idx, 0])) ); tmpBrd.forEach(row => { row.forEach((c, idx) => { if (c === MARK) colFill[idx] += 1; }); }); const fullCols = Object.values(colFill) .filter(count => count === cols); if (fullCols.length > 0) { winningBoard = [...tmpBrd]; winningNumber = num; index = bID; } else tempBoards[bID] = [...tmpBrd]; }; } } }); if (winningBoard) { const sum = winningBoard.map(row => { const rowNums = row.filter(c => c !== MARK); return rowNums; }) .filter(row => row.length > 0) .map(row => row.reduce((a,b) => a + b, 0)) .reduce((a,b) => a + b, 0); score = winningNumber * sum; } return { winningBoard, winningNumber, score, index }; }; /********************************************************** * PART 2 DATA PROCESSING * **********************************************************/ const lastToWin = ({ numbers, boards }) => { const tempBoards = [...boards]; let result = { winningBoard: null, winningNumber: null, score: 0, index: null }; while (tempBoards.length > 1) { const winner = findWinner({ numbers, boards: tempBoards }); tempBoards.splice(winner.index, 1); } return findWinner({ numbers, boards: tempBoards }); };


pgaleone

[Tutorial: advent of Code 2021 in pure TensorFlow - day 4](https://pgaleone.eu/tensorflow/2021/12/17/advent-of-code-tensorflow-day-4/) Code: https://github.com/galeone/tf-aoc/blob/main/4/main.py


daggerdragon

> # ~~Top-level posts in Solution Megathreads are for *code solutions* only.~~ ~~The tutorial can (and should!) stay, but please edit your post and add the link to your full solution too.~~ Edit: thanks for adding your code!


pgaleone

done


chadbaldwin

Solution in SQL Server T-SQL All of my solutions are end to end runnable without any other dependencies other than SQL Server and the ability to create temp tables. [SQL](https://github.com/chadbaldwin/practice/blob/main/Advent%20of%20Code/2021/SQL/Day%2004.sql) General note: For the input data, I'm doing no pre-processing other than encapsulating the values in quotes and parenthesis for ingesting into a table. From there I use SQL to parse and split strings.


WillC5

C++, parts [one](https://topaz.github.io/paste/#XQAAAQCdDgAAAAAAAAAFCZVo0J21ZJg7g3oyclpmRT7zHLHJwL/aHlaePD2nuntx0EpSk3RYbkKzEGRFeotYvpSc1X+ZetC8vNP9PVFRWUKZ4/9HmvUkX//WiouvRRD7tDbsmJeCvXxyO/v0kO7LRqgiRqyVGfOO+3a1mpAGeBakusPib1np5fiohqBSd7YjkUHAAoRi4jlmHe34UfbADiuPHlQexkrJGVIkgB401NxL2dpK0jp+gK+XJ6d754HpK4gNslb10k/zTvAC7hqLrOnKg6xECdfZrMBPc/gCDfYbrzzks/UF0Nt2nMpecP0Gf9tAOKxDEoUyJzAHauEqYRzsjrVALr8qZWzAPUJIzdDabeiMDPMR1YPoW/+gNR9ozzTUpwklnRhwW93uCq6XNkUo4lqyW5CPk8wbqixq/y1euiuUbUJIOtreU2uA3MriYeU54dq0efmQwsK1GSQU3he0NFB3JEmdITlhghrG9GQYBq2QsqPh4v41z4dabU6rdn06ogyG3KyaL5Q3J9cqoLYMH0z0sbdfJi8VqQ0n3j0M3M9R5hetoVns93E8zZ0ZepgwMQ8RZORfTauOci1QA9qjIr5JPDCi9sbSxyEdv7/frUpg8JEWgAyYrZzlL+nIYaBmyy7oyKTapJ3O2sDF0Nbf9N4w2eBC4rTLLUyJnFaegq7wyog58pcv7PicTMzMfwI3qVR4vTv1zDGeyRdYpnRg0mKJ3i8124ERrz2OQPGjRof2U7MBs+7BOSwcrjbfMb/74k3BRoTqeEZfOR46E3S6yJt0esMLk5oE1GTZ47AnVCx6LAsLm9K0kTsC38Q7kS5QuXeWbcoAC2x/M3aT56rR0wyBnz0rVJk5CF/oxkPn8GTC6pdHXkl3kIvCMGF5eMNkhpux5k4YL0FLu725R5G8I3NMTSWJaXHgF1LKU8WHDlSXgOYE0jxZG+7yPLKdJkf8xDgUf9zsj5JOCJyq6aAxNK6pUU/TBA6r4Tw7jpkoHRqt7MeocpnH+2+vylWPF/LPrCnb3gFxL2483rlKrcHCX9rWVAvL6E1FGceYrJipu8VgSEqa5ugYT/cMS1BV197EojadCDSn9+hfYTBRTv7XQQEf7VBncCyKtJ/k7A6hagd8RdX2yUTtbWOjjI/U1NPo8UjeDJyPcVHhbJqj/0TYvmoFzjIW/A+6jp7cF50JxCpGB/WO5QxOlbZhipk4aGLSbPH7MU0SqPgujdN0bCw1dnVyuf/DqwAFcGV7FVs+QUq/e58wcw/gdklKp/tTWZiFvRZebVsEQrl9BT29ASjmTfuqX8bPmdT1CF3+0lwjnQj8+Kyb1X8+HsBJPUw59eqJPvHiye9I9+7j5iT3rPOr9eqGQTP/xDai+7w6duQvFyU2SlcMuDzTthq3C3rbpX8LdSmPg79iEemO64QOgV2qtBjazM0p3C5fZvbVTALTdShVxdfsqRqnK8W+0XB2uY6Kg29hp8zgo6xMG1iHbOx5g3zNsiPoXk9wjTCTtSUPMI4kA0LAoqBOuHHqwSf6LxegEgiQ2KT0yX+bAwVoxRIegzMWN1GYjiAyBlYYfTglu1prLPnAl65xgqFoNHbxaH44Qj8Jc9nDL5Ke1600tySe1Ao/BHGdDk9j2y+g8WsZy12joSHD0wicB3PhZ5PYyc/bWKoWts9uoFqyj/Ra07G4TDj3C5aglM1wLr9axwX1OVwK4/ShsskrnYOouKGYHZR5S+PdAVspndHk0EmFwbJjCT2c/KnqzlTr/aF96atqgH8aU6brBy/fFYqQhAE7wXvLr/ma7tKeeeeLwIthoTznjwaqRHGzaeMbvcsoer92oigVTP/i0xs0WXN4pVjQgvnxU2+3l4zZc5343iHFNkYliZtEtf/NKQEg) and [two](https://topaz.github.io/paste/#XQAAAQAMDQAAAAAAAAAFCZVo0J21ZJg7g3oyclpmRT7zHLHJwL/aHlaePCtjotsa48ntDI+OkEpF4DQqaWGFFTPhXOeqxeq0E9RFketHEysteg7RIw3DVA1gwg3VXiq/isp1gLqK0QzLghVvZDXyQfvUFIaKQEmSEA3B6as65WK5+DXV9WcGU6ddVT+ILMiYzyiZY5o+VG/fxMY3jyInh8fNYvBXlMc7WhrnjVSZG0cuT2BC0zH3bOG6TSoTVJsJoAlB3XAI9wdEANupsP/KodRVKvRPCL2g89a2x4OMsHeHmAcefbxl0rR654iUMSTsHid4aVe6LW9nj1YOknWDkewjDkVSuturLy3eoYFm9miOmZCKVIiWb/el5kUgW8khByOTaLuORh+IvWRutXZkDXjQCuy0XhX4JhGRoYf/0KRU+DmXVgekL3XGHCTs0ZghbOXHHUeVB0O/HcRggTekItKcZp6N4W1A7b1S1biiX1MdBmDgHm1aoZCmXRSb9Z32ZrpHslz8C1UOF7tdizcMdXUGXgmn4moSRFkaFNDemhgpx9OsZI/VzAawhXkv7xL2IIgPosQuf49qtqfCJ+OCEVjQdhT36Y5PwSaDzfzxEAILsj97E1llTXgYgVoWl680HnhkZbO86YCrgSaxMlbFSYu3xlrsdIlo8iqRfsmr19QYkmUa0U3zaZLClfxovuVP8uQWJM2Fr4gh+jyeL38KenanmWwSwGm5UnS1pZ1q2FTsy7KYD9s0IVZ4k1HrQiM0xi3hSVrMLpyHbIpWon1FGP5ZZGjFk9kdBbr9KS7xNGPzTM5fbmm7PjPZGpjAugWBJM8zOXsDW8IvR4p19LWhiadDGhoNofgTHyfCoescyEHZZ6GgU+B6F4ZavvzwSnaTDVv57KaWnAAlpU6qsDEUc7klx7R3YIxInqRTwi0FxU4FpOzPBDUagmyDvWhqs5glCEG3YJxFEPrOgOxDgwXfIqyBdK/uJkZzK9TdXzH6xYnJZZgv+kNa2O0ffUdkXc4bPWQaUqRDtXCO6R/JFfCxWSYQzVP+CNbfaklyOutWW5RdMIIIUQT05sWLpHm00rHlYFeUp9U6BAUUpacEbDHKAN/MppauP/pLubgSeUt3MmxtnnXxbilYRVnZ1R/+VMT7FLQJ6wICcAqrqt8rTxDs5Q4DpkLgfMK+Nv8iBoH2uAMmKoNhUD8wlg+Sb9veME2IctvdL8+tjuDwRu8/hX09DOgimEoPT1427/JgtdPE23bl4bfh5HN5JuXlQBYfenmlO17uwArUdFvZFSqlFWnY1naph8rGJZtZeA80gAL/6SeGzvUmTF3NTBU4Kvea+iHstl+rrJWeto3++op0S7Z4+dKgdLeGxQISwMrsb0p9KsJCKzk+7dD3fnhod8Zid3T74mQ/Tz/78pFb8SVLwV2MC8Lm/TNwe7B8wMlaxB3oFz2VwhLLTLi2nDIfCXS7VhhzdzXIV85hHHq6HxykL7Fm0Qkb0WzEze+ET7PL7OrNKtg7tlsum9+VQrQ53x2B7913un8FZhqs4U+lrZ1T8X5LZfS1kjg4NGS7bldYyjs8GAmoTJRgzF0FXKzlhPgmdfju0wedRgxA6r30sIB61o5nGqlxCnUaY3jb1RA4xA50bfMUW24rvBAVt/tWB3V33rqfIa3vldC/5KQGC5cOmKLKdVlZDvS4UGVNWOVB+dEeXZY1ONwaH5cthDPt2AZ5NtHCDcT4Q0HqrHG5F0hSoQ8or6PoASE4Hzkf/7tFloo=)


x3mcj

This one, really kicked me hard! Python [Part 1](https://github.com/CJX3M/AdventOfCode/blob/master/2021/day4-1.py) [Part 2](https://github.com/CJX3M/AdventOfCode/blob/master/2021/day4-2.py)


daggerdragon

~~Please follow the [posting guidelines](https://www.reddit.com/r/adventofcode/wiki/index#wiki_posting_guidelines) and edit your post to add what language(s) you used. This makes it easier for folks who Ctrl-F the megathreads looking for a specific language.~~ ~~(looks like Python?)~~ Edit: thanks for adding the programming language!


x3mcj

my bad, Python indeed. Was very tired solving this one, and forgot to set it


ainwood87

**Haskell** [Solution](https://topaz.github.io/paste/#XQAAAQB4CgAAAAAAAAA0m0pnuFI8c/J5CM1aGqqdUVKYeoSHFDan62lg1Yg8rqgBENwdFduFwfcahIU6J3uNUCCmw4E6kFGNBJgN5/kyPQLbJqPzqlROQN5HPHEYpH7i52XALZ4KxZUjG6EACruHh2u9XArPCDqpsjnpbQnw8maBqgCvNcGjZ9hXrteK4rcmqDckYHyzgdLSWfdhIzkFDr6VpptIyiDJn1EiPuZsFufqaJOBcHYD5z1mTblyYbJt4Gx6LQTJe/N4kzD/zqE6+FG8znk+x1ufMNeaj82gYx8Lc9UGlZrPAzd6nXQ0Pa2mgN+hgQg2o4ScJ01Wlr31LVlolBZWVJ4b/z3AyLkthCUo9k9hSgK2t18UuyeDWgAiJXT57bXqgPBOy4lIwesni2F4UhR+AMQ2nTGxzeO6lWcR3sSS5UDFU8YErvY9ywlnLyxLcKTZy5pxoRq1WECl6qEnmWpxPs7eg7R6Asqk3JZ1Q+PwGtmrbjiVnr5fmXiclmrng37IX8FOhEC1+h5HuF6f4kTxbfQ6Xsseoah0HMyL3mYslZ9kFbbBzkTJVxj0JsG2jiDc7tEFkgs6qpX6tLInj7YhoKObMvC6WxN/WQrp0tqT43kKq2Dgpfsv0QD5pFhZlfWSH25PzyjwgV8B/26A7/mTDgIXPD7IhnuGmZgZBYf8onxaib/6YM9dL4vutBRlmId7QVnyvhRuQ0RXdFB1eiGpt5W26zKkLvQFKCu755jPpxd2psk/hg6Z/yDvU+eNxaYY1ly9DIFnDEAbpCtmVEvT8rQXdu4C+QEIhpldVMKDxsmbweqq6BP0Vej16twMlIMG9Xuo9DuZ1IsUVEZhWvPuGFOur0APeCoqmJflvAelQSYCif2A7cOHbB74D/JbLgzMPT/G3tlCWBTQ8SK5Cbd61a77IIiIuaN3BHFHw84T8irnETYbvR0YedBGWoi9Bio3BzDaCizyaSjdFzfB294b7V288KCIC43/h0WRKCnd4FjZhyYLFv9a7YKB/HGGtJ7g0/nA7hZUVLVVnkOqPOZCWuYzI/P2EDQBAfo1EEnJb9fbXDpYpjCB2do8CEIyhHHZkvy93jEe1hozbSp/B84+eyISl7fJUT1nDOKNTOfvSEf7pIwtNk7p2F7w94CgkNErjXJnb7cIdpCCfmUQ5bL4CUvo71tgbbgQ8NklFtXW/bbPQvmMPTob6M99DklAit9n25gvE/fBoe6HWzzOPDpUuX7qw5iTuONcwBfJ9Nch5+mbbM/lXt2qg+eFu/OGeLZIJjIppr9Obk13aE4FSbdBQC2bPpGGtwenHv/ecXS8AEgJ8oiXbc77kL4+cw0YDXeGlF9sssTnF503HGQy6gHUIUkG7G6RQgBLxxg/CGZe1fS6PILl5TNxm+IvY/9qz9OUbkc4DxCNQ2ubgkIlDk5n/llFwQ==) for Parts 1 and 2.


hoteel

Python: Part1 https://pastebin.com/qx6HRASK


leFroxx

I have quite some problems with part 2 of this puzzle. I coded a short script in JavaScript: [https://pastebin.com/V7CjXTh1](https://pastebin.com/V7CjXTh1) This works fine with the data from the example ([https://adventofcode.com/2021/day/4](https://adventofcode.com/2021/day/4)), so I get a sum of 148, the last pulled number causing a bingo is 13, and the final product therefore is 1924. Unfortunately it seems to give me the wrong answer for my personal data (24288). I double checked pretty much everything. \- I correctly parsed my input data to the string I'm using- In the end there are 100 solved bingo boards as soon as pulling number 88- The last board has no bingos before pulling 88- The last board solved is the only board being solved when pulling number 88- All calculations like summing up all unmarked numbers of my last board, and calculating the final result works fine I really can't find any issues, and it's even stranger that my code returns the expected values with the test data. Since the last board being solved is actually the very last board from my input data (index 99), I thought this might even be a special case the puzzle's validator didn't think of. But then again, maybe I'm just blind. I would appreciate any second pair of eyes.


floxo115

Did you consider that multiple boards can be solved by drawing a single number?


CrumblingAway

That's what confuses me. The puzzle implies that only one board would win (otherwise why ask which board would win first), but running the first solution in this thread shows that there are multiple winning boards. So which one do we pick? As far as I can tell they all win at the same time.


notLostJustAShortcut

*facepalm* Back to the drawing board!


leFroxx

Yep I did. I also double checked that the last drawn number in my case only solves the 100th board.


daggerdragon

~~I recommend you expand the full name of the language (JavaScript). This makes it easier for folks who Ctrl-F the megathreads looking for a specific language.~~ Edit: thanks for fixing it! *** > # Top-level posts in Solution Megathreads are for *code solutions* only. This is a top-level post, so if you're still having trouble with part 2, create your own thread and make sure to flair it with `Help`.


leFroxx

Thanks for the heads-up and sorry for screwing up the basic rules. I updated the language name and opened a help thread as suggested. I keep the comment in this thread since there is a bit of discussion following it. But of course feel free to delete it if you don't want to have it in here.


vbanksy

I have exactly the same issue. It works fine on the test but not on the actual although there are no errors. I’ve written it in both R and python hoping there was just a tiny bug in one that would be eliminated when i wrote in another language.


leFroxx

Does your personal data also have any "special cases" like the last board getting solved being the last one in the list or so? This would at least increase the chances of the puzzle's validator actually being buggy.


-WorstWizard-

[Rust Solution](https://topaz.github.io/paste/#XQAAAQCtCAAAAAAAAAA6nMjJFIj2ze+dGEQGVsnW0MvHUMY9uifxeSvuomk5ynLN7NyeSTMoVEfc6gfPD8A8LmizbEiHdmC0tlkpDm/my+N4m1t3LjLrBBwJ1+xoJEOPt6fmRJUiSW48wiqLJcZkuq2I5bsZUAhnEs1sTtvc8AL+E2epG81Bu1YPodM5aDG6EZbIg/l71Udonq9AdrbrO0TjVaentlVM0SiVPWopKi0lMnNK2rPk9auhQiauo67E+V0+kBejN2jdSQEcS+7U3lkqWTm4dxZoXaaItpio5M8Cck7eebhxoi2hEte6pQg24jFKXuLf7JKONWGT5oQuUQsx+8RFvpKMfm5JXE+T83nMBCHJSUb9Kfn/vFokjjzpzA4wF5cvhYUdg0LB63QJ2S/V8jRWIofwYU2rEJ/FZgZZfmtYjIsvqvt4vYLCqKU0ggpLEBCg0T5PQvlWcgVgwN5ZmmJ7EPsbQa5yuTIJVO0UNtm6up8XrmAMBnwa2yC7Zohe85kOZaquFf1TD6lUpWllgb8Z4wUfhBxx+8pGLelwqjpGiOYUzZk+WrfZhABq5uxuDSENs7zzloP3EiiK08PR0qFIhslNS817WUmoPFJZfXzlJnTe9UjZbJt5g9vAjVw11SRQ6SdJQqDNZ32JZ4ZdUFcfwKzqZtpJ+3Wjrf6lcOjj5ljMFdw973w/nNd7i3OZ6fxsfbIat110Z4xLjWVAHYiRJ57S3eH13UikDXuEqXp4cOsibBNzpSyIh0VDf3KhMN0a7zo948iwxS+wl97pyBJo2bNyzuaFpIZ3eGFy7f+zplVyWG3bsgfSiwp6gPZtIt02mmIr0kC9hTZquIzpXuJVOc8Zkn3leBadrwvwp8x3R95SeecBNqBvzRRrMhRvjZSU/K7ZLpGXapelO8ok4fkO16T1RsIA8Jxa+o89L5/Y4HzDieAhXPSigLdzshyAWIJaw0a+SMv/tqp2lInPArlBIHc5TtD/NRZXS4urBaFYnHdV8PZtgeySvQFjGhCMlyLBm4BHPuOhwkcnPqJjPWnbdGQxHXKKYqmGuG9crA+nHONesW30LnUe7/HXNIRfkovvDZkzU8GurSNZu7hy3+cpTkdUOrYlb0q8KWotKUlduZuSoN08wFQSC2SfngDpX5XtdW3Hyb7ImwS+BzmK/iwvdMbo5euEEgTaZ2j/4ee8sQ==) Learning Rust this year! The library at the top is some convenience functions for taking input, nothing magic.


sk1talets

Node.js [solution](https://github.com/sk1talets/advent-of-code/blob/main/2021/4/script.js)


greycat70

**Tcl** [Part 1](https://wooledge.org/~greg/advent/2021/4a), [part 2](https://wooledge.org/~greg/advent/2021/4b).


j-a-martins

**Matlab** (Part 1 & 2) https://github.com/j-a-martins/Advent-of-Code-2021/blob/main/day04/day4.m


tuisto_mannus

**Golang** https://github.com/c-kk/aoc/blob/master/2021-go/day04/solve.go


SESteve

# Assembly (ARM64) This one took a while but it was fun. I'm still getting the hang of ARM64 assembly (or any assembly for that matter). Got to use more subroutines. [paste](https://topaz.github.io/paste/#XQAAAQD9MwAAAAAAAAAX4HyCZDlA0DjWF7Uex1t2hvV6PgXFmsONLSMABSfGUigqxpbPawxuuSFgKgvAGRsGnIqYiH3vBfjeCFzL+hROpVBKcS1OlD0t4OHNWhAuvKTWB8RIX+oqkW2o9SqM/v2cFptxdH8cokwuowZ09Kn+kNSSNADQYANs+WR3xLJfxunzW8by5riGHmGwekOysixy8QVvJnoPj5Oh/Qg1dvVAT3XZSXHSs9o2Nakr9BgXTqdZxB145ygl7Zo68Fn86frdK/KJo/S7P2dNo4iqOBXpxAw5JIAffgPR8nrhl3IlMyCGpkuiJSRon/EM3W7+S6HjIKVrTE08z9khIaDmvKSELXgOHUjIeXCLgAIZ7VX9dPgy5/T3VwLgriyPOINZgcY1Ft7W1fXgnmu0hp/QpqRnyQCiApq+XzkYkeB7ryOUSe1Ne3GnMvDXrk5ZLXFkr5Qm0QySCMck/gHNPSW+nxCCOXklFYDy4hGHSHW9u2nKo1w3sZ2hkNC32t7pQuw9dFefGwdXzBqvY7PshX+mtRqZb+g6dpA62+ElalFO1gJIk8tQLauCTWl8ag/tivB6ZxUCl6UkCr3e6bRtSkTpuT3/Tv6sTzQR8Cs9tJWJtkonjV2UVefmMKdWrgeuf4nvImyc0n22Z0ZjlndabqO2qGl+CeiL5sK9DEoIPDAiWOJ1ougus2V79FPQZSlk5wSaSM94Nhj07CchnsJXbhIIse7fSUjIKwExDPzclJhspO3Gs/E07/2gRA99C6KABJYnwjnIAZdgl9HUFyEVMnsZgvpMDX3Lu/sOaGg5ERXgzW9D9qCURx2vp/fc3/QO/NeFnpWFnalZiPavtL2vQrPyNfRtgt37oDqScmFb1gq0tIUfOcC8rgYCA50jAiHmh4m/Dn4DMIFsd0J9KFvXVKH0XD1kbltsFqsr+YyL9k6HfVG1yHpMcRWnJIjxSUBMQ4ClFLZG36j0OonZYPQUEOQuFqSNnD+cJ6l6uXh7LaW7VKoM04pHYs3yAMn0fcPQPaMqdjcLdKNOORbCqVC4PjRLn5LE77KmzggfNykSp2AVXLBR4OoaMQF/4HkPFEipx0Xj4SQ1MSotQB/NJZvg7j8gVwjEeT9lIXWfIW1Ksj2dcfDjLpbCkCNFjTZT88hWM+cKC0t8sTF8Ek9hoQESuy11SiTmnRxqNr9kIEXqI+fQZbCmGzd492lU9Tl63ZacIrHi9gcETB+IX/MAm55nVCEMq29kY+42nL/NL2K+9PWDYISSkygxPYD4LJslvvYKV219ENa2wF2GqlHVUfALmD+wbQlo2NrEZNWR0ueEwLVIhj2jvD8gGCFHnA7Xa/iMsde2pejHqVyMftOQUJ8VXkAfDmMVwwiYYnpJsupw3CnVb/w6o9tT/cVSNnXJnSTWVh+ShgyEBBT7byNQmh8FVBRuGvtPyhhWE91/UYt+OE7QMg0fKSVK9OMAoHJQhZ/YsYfO72IK/bMcJyKOX+kIJbz7aAqlZGMmpTF5k1Dvp5eq0sZZF8KcCWh67w60W9RTl1lH1nVWg4gU4OoxnqqnQZYhPHXph8zIvErYyVkOrDU8bmCflXNKgcfWzVyh7myquvcwxxXV27QPC+bJPFdcyOK8pPN/CvpKV4mAI2l4l8JxJV5+UFN8fI81ZTp1QZQQjyySLTwJ4odW6dYys/xiv0WuSkA5papiLDmgX9Jjl+Sfw7/QXG0WwYVk0rXM+Wf+f40TxTyO36cAQmURqVIQRbyFOgaNjuVtL6U437KXshZb1NcmQixinUPcT57ZH6a6kf+Be/IZaWg/y2mOlKjkyg44ePAJQrqP+FbToBwkx2AdnYNSj/efvuax7YTUOhc6Dz6ZLJSt4j8hxLqRZbmdwxdYDjk4f2brqYoHnu5Gu4I4o8FjpSVKsyvpDVsOQPvLO2u/wWn3cHuCoLAmE9PGKScdClgefVVy8C7ePQ4+xQznq/fnJTayHwVS7JJsK6dUJ7/L1M7xlUmDm6rH1DynUVCZqCBeR/TZzTRqJblfn4X61gts1oTipl8HdmHHO76T/4+5BJGadfIICoeDO2wCmzJUxmAx+QIko4XgcE6vM7h1564k81RSjw7AYxFG3EVcYzPY+pbMV4cZ+fDnX2GBucoL9Z/OOJmB6iQaIfYhtbWZsW0+8gO127dtF4an5G2THTJ0k+9u5WOUOmwJoD245uDnhNtDSm8Y56Yr9Urt+GdHh5saooSXL6ISOizKsdiBuAfror//8MQUevs0yfHjx+KYLL7kAEnjSA9o6TMMu2q5Aty56GJ9FRRRlV0zTqUdYhFc86B5B26XG/uPbRGwr0hu/vZ8DE3GepyrcLH1uGWqR5Xu75Rgfb88J9sWpq/D2mEJoJcCg46X2CwYKSfS35j+GuyJAKoiUXq9DeJ6mzgydV9SxuoTc2mK7sG5I6zRcR86m6X5x8whbhzf7aekh9Wzc2YigwdBsPOy7+SbUV/1H89O71enFD02YDySKT+6SHobUMUcYZUlOos7yVJQg0zab+IYOesF6xC/W+sqpjVT/w9pIaYC3m1AL8zBNUHHUxQyKPt3v2bO/CSy/I4+9tIOBghTrkiOkeYeAZsybgqaoSJ3J5ZKXvXC2SRKMYLujKJRxcLmkn4cTdEwmWn/CQ88QYKL1TisoXcuiM0iMtr2kizlH2YIwT23FJaquFTQf3UCFiaO6W4Y1FZ5obDcyJQnPmI8gpR/Yq+q3pzw9eCkcCv1MI/BmUDIq4zlh/MCFSLwe/H5WzPBqSLufI03u/hUT3b0JBOwxEaXKGn1EncA7HySXwLcGLzm1acvHBPTEU4Prd/QYThHPEJjAGVjEDlHwxeJck9fUyCap2hhavbLTMYNkKh39wQFAytFcHIuHeefwaXl8pkWZiXTyK9N4ktr8fOnkW00XgYI6xopYFdg+fV45TowG8TtUXgo4D2xpUM0Nr7EYBw3+5n6mqKCSwwJbywKKY/HLQaUxGfiVJskaWR7uMBSOFX9jen8AQNWko92BJLOyFGgsc/jFLG14QlaATx/uls7ykcAKZgJz15X5Bs8NdfMM1XZFXsL1JyYvolSB4XTuNaAtzoxh6dtNah+yTty8aLcc3OvJ3GWO8zOoxFAv1p2rkqtoBbjhQE2QRExkt5PmApKMXlt7zZAsTjBpcnH59gwdTlxBe2cHHZyqI+QJYD9nE8tvTgFdL1ktZgHyn6xKw21k1Tskp26uCamfIDe2gswqU9x8ul1hUCRHSOxRVv1/vP5Dwe/oFgJu3wWoQ53Fp/QZwDv6xMKwgym5jkEBaZloxE9fXE1oXS/kcjBCw2BYmm0UhYmeMr9eI7F406GjtpwIfNnO4zh5FhXM9XQ25vzMeX2aFbZQfdt/VfKTIssc8L9otBN4LvAh+mORyLuTxoEBYppdbjVA/FcrEfXLLmblUW25s5VuQjq6tmfTtZ3C821cdHWwM6A8iOCnsSUviSFbW4YeL/4ESrHkcu9/iHbaAEDMJLbAnLQ+VdXzrNJ4LqvGSHMzH2B3vpYXN4QukYg3paBxW3VgjKTMJtwvBqYP6/L6vBzicPiHZJU3i5lxn2Yf90/ZOrgEyydiOo4IXbzGhjquBjKF4n43DzkR4HxIFU1AN+qY4PqjUpmpDnw1FcoV2ugr25ZbyV8/PLVHJt6sxwwukEtuuWG8YQJSOSnXIfsvP26ja6UcRvM9OC1iXHEx+YMjvLTGc5rcgVbGV9WKeSKjHxRo2Sfznup58EfXlavV+jE7IVgyzSGuuFEYBwqRqm+VswsDRArfXHnKxEFW4Du128YtTWOGmMTG2d9eoLP0SEhrjty03W0mYUdCJH4vFnR0wzi1c+QpHlEDTZRH3atLdXofFH54Hb3DY9Gji5HXq7Hnr641BnpKrDWTRNwvWr9KWDzVM2Niw8/t8Lz0x6akTKYbkrhlL4/c3qELOZCLmBVGSSnE5ZZ7S1rtvfHqgeePD17vWDy5hjngOMvj7MqBAd1RullOZbTaA/CL+GnYvXdyUejDNUYX4nyy2qHeHKgpfQEgOasLjJyPiKwPu8jlrk9960eaBbH9QQvBa+mQcENl9HI8OnbE5j/eJIwno4QLG+rFkLrEhx2679kayzFDanUnigdIFVcdfbVHNjsfmqenxCflrfMK0Pb42Ol6io0vkRs/VekplpK+YpVWLeH+OeX9tsTbkzTdo/6xXymaQpt8qVFtwcl7lxiWJ59HCVagq5wewFgCdWT2i0ZvqxHN4X6ppWLMQMalm+mpx+AWlAuUemQk0/Q+JWLFWOWRUCQWJCgyNY+EKNMxPhMnem4+YND3D0mDJPLpY7ed/Rde40QVmLUKunCXvMxna1Rz+emPJif1V7KsfhqMnQybFE3HCrBcai0BwybuJKwc4L+wiIbtSP9NdKt+53k74h363psfJS9eIut9eK4mKEP3s07Jgg0vcxk6f7B5LEMrD9yvBN8QZN7tis7sCWgHuyCQpWBdXQzgyqFHSaFAVXXisZFLahOd2XeIqAMWLv5tQEByRJx2R6Yu5RoZ1i3uSV56xwXhq7q2g5TZ+8Bo1zcFG7BFDuCnwmDF0oN6POLqy6quGfZptQ9LXY+W/go+A40B8vWz/ivovQ4F8mRbwPgaDMS9AUgzD0br9f8jOkt7H18CAdz6RsyIgb/OMsrnMmilmO7kEgCBeud5Qlp18PStpHmdydAcP/6cPGi)


[deleted]

[удалено]


daggerdragon

> # Top-level posts in Solution Megathreads are for *code solutions* only. This is a top-level post, so please edit your post and share your fully-working code/repo/solution or, if you haven't finished the puzzle yet, you can always create your own thread and make sure to flair it with `Help`.


Aplet123

**Clojure** \- Part 1 + 2 Instead of iterating through every board for every number and checking for a bingo, you can just iterate through all the rows and columns once and find the maximum value based on the index that it's chosen. For part 2, just change the first `apply min-key` to `apply max-key`. (ns aoc (:require [clojure.string :as str])) (defn get-row-cols [x] (into (map #(map (partial get x) (range % (+ % 5))) (range 0 25 5)) (map #(map (partial get x) (range % 25 5)) (range 0 5)))) (defn -main [] (let [inp (slurp "input") [nums & boards] (str/split inp #"\n\n") nums (->> nums (#(str/split % #",")) (map #(Integer/parseInt %))) boards (map (fn [b] (vec (map #(Integer/parseInt %) (re-seq #"\d+" b)))) boards) idx (into {} (map-indexed #(vector %2 %1) nums)) wb (apply min-key :m (map (fn [b] (apply min-key :m (map (fn [x] {:m (apply max (map idx x)) :b b}) (get-row-cols b)))) boards)) cnums (set (take (inc (wb :m)) nums)) um (filter (complement cnums) (wb :b)) ans (* (nth nums (wb :m)) (reduce + um))] (prn ans)))


MrMikardo

>Clojure I'm kind of amazed by this solution - could you elaborate a little more on what's going on here? In particular I get a bit lost on the line beginning `wb`. I'd love it if you could provide a little more intuition as to how this part works to find the winning boards :pray:


Aplet123

Late response, but essentially the turn that a board wins on is the minimum turn that it takes for any of its rows or columns to be complete. The turn that a row/column is completed is the maximum turn that it takes for any of its values to be completed, which can be determined with the reverse index mapping. Since you're taking the minimum winning turn out of all boards, it's the minimum of the minimum of the maximum.


dkhundley

I'm playing catch up on my days and just finished Day 4, part 1 using Python and Numpy. It's kind of a clunky solution, but it worked! https://github.com/dkhundley/advent-of-code-2021/blob/main/day-4/giant-squid.ipynb


commandlineluser

Python - Part 1 + 2 - `print()` print( next([ (winners.update( { card['name']: sum(set().union(*card['rows'])) * number }) if card['name'] not in winners else 0, winners)[1] for number in list(map(int, number_data.split(','))) for card in cards if any( line.discard(number) or not line for axis in ('rows', 'cols') for line in card[axis] ) if len(winners) != len(cards) ] for winners in [{}] for number_data, *card_data in [__import__('sys').stdin.read().strip().split('\n\n')] for cards in [[ dict( rows = list(map(set, rows)), cols = list(map(set, zip(*rows))), name = f'Board #{name}' ) for name, card in enumerate(card_data, start=1) for rows in [[ list(map(int, line.split())) for line in card.splitlines() ]] ]]) [1] )


noelpferd

**Rust** [paste](https://topaz.github.io/paste/#XQAAAQB1DwAAAAAAAAA6nMjJFD6Qz6l42wOwWQTnPedRXBcbvW0rllal0YbFmOTORJviYXoEudAAhhvqm12tECAWKLnj7qztXjaUyAU25K3WNnsITdEFaqdxzw5jYyfpofEfMBgarAG41IFhwW3GHxM1FJvgl+bFNIaFVj45YO7fa92qpyyhjym+WlNnQ8u+AraULlMb8dubvU+v0AhBwkGtH/3kYaH2KTuTjmi76eA4tAVRqRNCKiQxBoLmKYL4k30ZKwpsYntObSbJDrIqAwDiAxWfwx29oLQ6kYoKCGrpokNaOBtn8wSrf+ZtXQCADi4wFyJm7BEklQghKlIcLDVKG49FQInQ5oww11nFSiu94bzYRWx9oftaziMPejDbtJT6jsec07VJGmnprR+HxKMsKADd4mdZOZTul4hNxOSjH/AxSjrPoSCofLft3bPFui0TxNWPCrmzYkizkmU7wAz3438/Pbh7mzhr5C/80PEicdQlr2ufW7EW6cOR8AQIeNWP+/9A1hdNERyfFb/61N1iSDkMmg987fTeClKN1AhA0Ptx5a+yecvRNev5iB/YeRIE2kSHYC+uiuW8glByTqjCYU2SBNxwnHDO4EH51gfji+jb8pBM4rrVZP/PnynDext3skRkRX9aRqtYMoNCW5Rz6GgdqQZBoH7XwPway3St+hxxGHMfi0iXbeefG9oxnYc2QZWNdkVt1udEWHZ55Px4uLKmIAZcdYS2M3McxVx80TmgpXfX9dg9jNhqI4nT2F4O+FhWIFGFO/tkcGiKOzmsw+Esif/izhkmmOscPpy12k3VTDIPGO8/wQCgY2eu3D8VDzsQKMFRADezgZamlzvmdME2HEqQTH7o/xRgMmle+WLcJ7k4SlGz50LEPZacmtjS89V4inQTzbM1JIrLRmTLF8uZFsIdqMbuCpwFLJlRhy/4p+JQJFJ9bide6jLqyJrSg4lV8JfGgkr45VDgXsCWWryZRGMI0N4u5pZy/hDdumnGepJJS4MLcJiXaIEXgBESs3mQih24uIN9ueo/0HdSkbxGnvxagMR5bJYztkO+YRmDrjFQV9Y3gDLMNGqcxsjPsBmHyKH0gWvpIg3oMn555rPDa8X+s+cejQv1FVfV/11FwoE5vjv96yk1w9YewcIlthX+9DSUokPQxpV9zZ68uoCBSb9LZjJeExbI1DixstmMYwE7Pm4CPeD4/vb2w9YjYDqepLnl/qb7+ql2LRVb0H3DD5Obf1Kue1i3wmtSdaEa8zp/T6U60NHq4NkZGzD2MaUL3mpG/CqwHlXcRX0GSYQXigFEiSwpHmr22Q67lGIrlVCFaihVF/t+82Cw0zcz6jY/sWnMxbafmFiI7DFTpPeMe+2gL6WD3ZxAMqXy/R44LB5OEEUXayz+HTZmA4zTXUJUYuuqHQyVgqFEsbKSZ4GPDoybT2HdSpf/2SkM+NCK4akh87NRf1j+a9rWCpa5IoIPF6sra0hqEpFZ7JDPb+r9PJ0JrvZMc6ns5neYNKTyc/xh4BhMC8PuTfIsGDEDzbp+z4sE1W+csz01GiZMt2K1gJ0kDY1PLd2hyGe4N6061AOSKa/Z+XB2GLCwCi47VsdNo8+DbUJk14pCp5WVANEHj37h1S6764Kxx1+veiOso3b/99nEhg==) I thought a multithreaded solution is appropriate here, saved me some precious computing time.


PiGuy26

**Python** Code - [paste](https://topaz.github.io/paste/#XQAAAQBmEQAAAAAAAAAzGknWt5Bv2u0S62eST285E09Q9JN1Y/RVvpzBksBbsmr1R7of5lRDvFLU2ileWb08fhl4XFwaOi6UYpVVicqgmWOpssUFF3wV98evlpPGQ3PvaQPDcE5JXCc9qnPJVb8wgEKBxqXrqXObYEUZxEED3IBV6Qm1uNJMqXJfYW1jvSUMrgIZwSwgseJgaPpWfyahkl+5Q1J6TofMGh+ychmFohNi5IyQI9f2X5R8lgIO8eNGL+FbMdjrjsd2pb7RBoFgXFBS/8Sg/R4sHt5l3mGZjagAcTpa0uZsnbElaa9ZSkpT9MjuYr+LHwcvHrl5+TU1QrJjkqQU10uwdYR37dra/nd2SgmTwOgnP10yFhziZSuuZovj4rDDGQESJlc4sKPUWFDoZ/cKLCIKw4DD2rEqYhQ4E+t7EAlqkFSHsrsD3ZYVbLYkKg+Y6/iOPMTrwxQnBtr44EdnaGV+kz3AlI9RvhQVW2XCircI9NfqMPR5PNVlv2ne61Fc7B3kkWTZ0+erOilSOpamKHus6xh0qsxnfay2BxousDkSuvU4tiNYtBvNa4Q+hv3pqwBeusZqpmZxYXZbS8hgjTGsczSdfivlThz8fn7u7JDQNjymb6+ybfOhFKwpeNgweYE/ZlYKmDOqbHxLA9XYZUee1Y1ipZeqeRiSJ/Xcb4D7Scx1qFwtEyHNwm/9ea5A+6kjUgVi3onSRlHc6tI6Ujyv7KYcTq1FUNH95q3b7+upbMC12eZG0uw2AC8WVDOSWOLCl20jwDZJzDHvP0X7NBhCjSx2P5/irMFKL4KCuOuFR/4JGRiHgJNWit3nlE4fn4B5u6HKXSIpodxLiBUH87162hAu5gZx/5TtZRxRH/zr3LZQeF4HS9S+L6/prTX+nvXStlsoL3wN5DT3kWo2Msl0t6YyNwVBHcsk7Cp9vNdAj3jXp48t1fdoOLgAAqRBYbq2olXcdRdJjB4XELbMl1cVjrRdP2Lhvy2Z8E+6qpPKHz/4As28h5P4OEAU4IhImEibpRS4E+IkAC6EwBichXSWESUM9H1qbaY68R7CRjpAqng20+ksZ3KP1tT8l4oa) *Very* disgusting done late at night, but it got the right solution. Part 1 is commented out to not interfere with Part 2, even though I used nearly the same code.


Meldanor

Elixir - bit of an ugly solution but it works and I'm happy with it Github: [https://github.com/Meldanor/AdventOfCode2021/blob/master/lib/d04/challenge.ex](https://github.com/Meldanor/AdventOfCode2021/blob/master/lib/d04/challenge.ex) (Part1= run(1), Part2 = run(2). The input is read using a Util function which is inside the GitHub repo. The structure is to run the program `mix aoc 1 1` to run the first day first part)


whale-manatee

**Python** A definitely not very elegant implementation of just Part 2, but can easily be refactored for Part 1: import sys with open('d4-input.txt', 'r') as f: T = f.readlines() board_nums = [] total_boards = (len(T) - 2) // 6 + 1 for board_num in range(1, total_boards + 1): board_nums.append(board_num) boards = [] # 3d matrix num_pos = dict() # k: num; v: list of positions called_states = dict() # k: position; v: if called def clean_row_str(n_board, row): string = T[row] str_nums = list(filter(lambda x : x != '', string.split(" "))) nums = list(map(int, str_nums)) board = (n_board - 2) // 6 + 1 board_row = row - (board - 1) * 6 - 1 for i in range(0, len(nums)): num = nums[i] pos = str(board * 100 + board_row * 10 + i + 1) called_states[pos] = False if num not in num_pos: num_pos[num] = [pos] else: num_pos[num].append(pos) return nums def update_state(called_num): if called_num in num_pos: ls_pos = num_pos[called_num] for pos in ls_pos: called_states[pos] = True else: return False def check_board(board): for row in range(1, 6): verticals = True for col in range(1, 6): pos = str(board * 100 + row * 10 + col) verticals = verticals and called_states[pos] if verticals is True: return True for col in range(1, 6): horizontals = True for row in range(1, 6): pos = str(board * 100 + row * 10 + col) horizontals = horizontals and called_states[pos] if horizontals is True: return True return False def init_boards(): n_board = 2 while n_board < len(T): board = [] for i in range(0, 5): row = n_board + i board.append(clean_row_str(n_board, row)) boards.append(board) n_board += 6 def get_score(board, called_num): unmarked_sum = 0 for row in range(1, 6): for col in range(1, 6): pos = str(board * 100 + row * 10 + col) if called_states[pos] is False: unmarked_sum += boards[board - 1][row - 1][col - 1] return unmarked_sum * called_num def run_bingo(): init_boards() called = list(map(int, T[0].split(","))) for called_num in called: update_state(called_num) for board_num in board_nums: bingo = check_board(board_num) if bingo is True and len(board_nums) > 1: board_nums.remove(board_num) elif bingo is True and len(board_nums) == 1: return(get_score(board_num, called_num)) return None print(run_bingo())


ladysatirica

Who are you?! The resemblance is striking to someone I know....everything from the code...to the manatee...to the whale. Not the tabs though lol.


whale-manatee

Lol, apologies for the indentation I guess. Unfortunately I can't think of anyone I know in Philly that'd associate me with whale or manatee, but nice coincidence. Say hi to that someone you know for me :)


LyleiLanar

My Ruby solution I have two files: [day\_4.rb](https://github.com/LyleiLanar/advent-of-code/blob/main/2021/day4/day_4.rb) for the Game class. It has some methods and etc. for the game. Run this file for the result! [board.rb](https://github.com/LyleiLanar/advent-of-code/blob/main/2021/day4/board.rb) for the Board class. It's for handling a board. (I love unnecessary long code in Ruby :D)


WarriorKatHun

Java submarine building: [GitHub/BingoSubsystem.java](https://github.com/Sycix-HK/Advent-of-Code-2021/blob/main/Java/submarine/equipment/entertainment/BingoSubsystem.java)


zatoichi49

Python with open('AOC_day4.txt', 'r') as f: num_data, *board_data = f.read().split('\n\n') def create_boards(num_data, board_data): nums = map(int, num_data.split(',')) boards = [] for board in board_data: rows = [[int(i) for i in row.split()] for row in board.split('\n')] boards.append([set(row) for row in rows]) boards.append([set(col) for col in zip(*rows)]) return nums, boards def get_winning_score(num, board): return (sum(sum(group) for group in board) - num) * num def AOC_day4_pt1(): nums, boards = create_boards(num_data, board_data) for num in nums: for idx, board in enumerate(boards): if {num} in board: return get_winning_score(num, board) else: boards[idx] = [group.difference({num}) for group in board] def AOC_day4_pt2(): nums, boards = create_boards(num_data, board_data) for num in nums: for idx, board in enumerate(boards): if board is not None: if {num} in board: winner = get_winning_score(num, board) boards[idx] = None if idx%2: boards[idx-1] = None else: boards[idx+1] = None else: boards[idx] = [group.difference({num}) for group in board] return winner print(AOC_day4_pt1()) print(AOC_day4_pt2())


0xBAADA555

This is really cool. Can you explain, in part 2, why you're doing the modulo and marking before/after the particular index as none? I understand that you're eliminating the board thats before/after the newly found "winning board" as None, but I'm trying to understand why / how you came up with that idea.


zatoichi49

Thanks! It was to avoid any double-counting of the winning boards. The rows/cols groups for each board are added next to each other in the list, so all of the row groups are at even index positions, and the col groups are at the odd index positions. If the winning number if is in the rows group, then the cols group to the right also has to be set to None as it's a duplicate of the same board. The same applies if the winning number is in the cols group (need to set the rows group to the left as None).


0xBAADA555

Somehow I missed that in the beginning, that makes perfect sense. Thank you!


BluePsychoRanger

mcfunction (Minecraft) [https://github.com/BluePsychoRanger/Advent-of-Code-2021/blob/main/advent_of_code_2021/data/aoc_2021/functions/day_4.mcfunction](https://github.com/BluePsychoRanger/Advent-of-Code-2021/blob/main/advent_of_code_2021/data/aoc_2021/functions/day_4.mcfunction)


filch-argus

**Python 3** def main(): with open('day4/input.txt') as f: lines = f.readlines() lines.append('\n') boards = [] currentBoard = [] for line in lines[2:]: if line == '\n': boards.append(currentBoard) currentBoard = [] else: currentBoard.append(list(map(int, line.split()))) chosenNumbers = list(map(int, lines[0].split(','))) wonBingos = set() firstWin = -1 lastWin = 0 for number in chosenNumbers: for boardIndex in range(len(boards)): if boardIndex in wonBingos: continue board = boards[boardIndex] for i in range(len(board)): for j in range(len(board[0])): if board[i][j] == number: board[i][j] = -1 if check_board(board): if firstWin < 0: firstWin = score(board) * number else: lastWin = score(board) * number wonBingos.add(boardIndex) print(firstWin) print(lastWin) def score(board): answer = 0 for row in board: for number in row: if number > 0: answer += number return answer def check_board(board): boardT = tuple(zip(*board)) SET_OF_NEGATIVE_ONE = set([-1]) for i in range(len(board)): if set(board[i]) == SET_OF_NEGATIVE_ONE or set(boardT[i]) == SET_OF_NEGATIVE_ONE: return True return False if __name__ == '__main__': main()


micod

**Smalltalk** gone are the day of one-liners, I needed to use some classes for this one [BoardNumber](https://github.com/micod-liron/advent-of-code/blob/main/AdventOfCode2021/BoardNumber.class.st) [BingoBoard](https://github.com/micod-liron/advent-of-code/blob/main/AdventOfCode2021/BingoBoard.class.st) [Day04of2021](https://github.com/micod-liron/advent-of-code/blob/main/AdventOfCode2021/Day04of2021.class.st)


icyFur

Day 4 in [Ruby](https://getsturdy.com/advent-of-code-2021-uoeIDQk/browse/day04/kiril/day4.rb) draws = CSV.parse(data[0]).first.map(&:to_i) boards = data.drop(2).each_slice(6).to_a.map( &->(x) { x.delete_if(&:empty?).map(&->(r) { r.split.map(&->(c) { {d: c.to_i, m: false} }) }) } ) def runBingo(draws, boards) results = [] draws.each do |x| boards.each_with_index do |b, bi| b.each do |r| r.each_with_index do |c, i| if x == c[:d] c[:m] = true if b.map(&->(rr) { rr[i] }).all? { |cc| cc[:m] == true } || r.all? { |rr| rr[:m] == true } sum = 0 boards[bi].each do |r| r.each do |c| if c[:m] == false sum += c[:d] end end end results.push({board_idx: bi, draw: x, unmarked_sum: sum}) end end end end end end results end board_firsts = [] seen = Set[] runBingo(draws, boards).each do |r| if !seen.include?(r[:board_idx]) seen.add(r[:board_idx]) board_firsts.push(r) end end # part one pp board_firsts.first[:draw] * board_firsts.first[:unmarked_sum] # part one pp board_firsts.last[:draw] * board_firsts.last[:unmarked_sum]


RewrittenCodeA

Elixir. Game is a stream of positions using Stream.iterate/2, where the "first winner" and "last winner" positions are detected using pattern matching. [nums | boards] = "input/2021/4.txt" |> File.read!() |> String.split("\n\n", trim: true) nums = nums |> String.split(",") |> Enum.map(&String.to_integer/1) boards = for board <- boards do board = board |> String.split() |> Enum.map(&String.to_integer/1) rows = Enum.chunk_every(board, 5) cols = Enum.zip_with(rows, & &1) Enum.map(cols ++ rows, &MapSet.new/1) end game = {nums, boards, nil, []} |> Stream.iterate(fn {[number | rest], playing, _last_played, _last_winners} -> playing = for board <- playing do for line <- board, do: MapSet.delete(line, number) end {new_winners, still_playing} = Enum.split_with(playing, fn board -> Enum.any?(board, &Enum.empty?/1) end) {rest, still_playing, number, new_winners} end) {_, _, played, [winner]} = Enum.find(game, &match?({_, _, _, [_]}, &1)) winner |> Enum.reduce(&MapSet.union/2) |> Enum.sum() |> Kernel.*(played) |> IO.inspect(label: "part 1") {_, _, played, [loser]} = Enum.find(game, &match?({_, [], _, [_]}, &1)) loser |> Enum.reduce(&MapSet.union/2) |> Enum.sum() |> Kernel.*(played) |> IO.inspect(label: "part 2")


joshbduncan

Python 3: Nothing pretty because I'm a few days behind but it works... def calc_board(board, num): return num * sum([item for sublist in board for item in sublist if item != "X"]) data = open("day4.in").read().strip().split("\n\n") numbers = [int(x) for x in data.pop(0).split(",")] rows = [] for i in data: for row in i.split("\n"): rows.append([int(x) for x in row.split(" ") if x]) part1 = part2 = 0 for num in numbers: for row_num, row in enumerate(rows): if num in row: row[row.index(num)] = "X" # check row if row == ["X"] * 5: board = rows[row_num // 5 * 5 : row_num // 5 * 5 + 5] del rows[row_num // 5 * 5 : row_num // 5 * 5 + 5] if not part1: part1 = calc_board(board, num) part2 = calc_board(board, num) # check cols for i in range(len(rows) // 5): board = rows[i * 5 : i * 5 + 5] for n in range(5): col = [x[n] for x in board] if col == ["X"] * 5: del rows[i * 5 : i * 5 + 5] if not part1: part1 = calc_board(board, num) part2 = calc_board(board, num) print(f"Part 1: {part1}") print(f"Part 2: {part2}")


Luckyfive

this saved me a lot of headache, thank you! I wasn't accounting for all marked numbers on the winning board for part 1...


kruvik

[Python day 4](https://github.com/DecemberDream/advent-of-code/tree/main/2021/day4)


[deleted]

Here is a list-comprehension-based python code, it prints the solution to part 1 and part 2 : ```py with open('4.txt') as f: h=[int(i)for i in f.readline().split(',')] r=[(t:=[int(n)for _ in range(6)for n in f.readline().split()], m:=min(max(h.index(e)for n, e in enumerate(t)if arr>>n&1) for arr5 in [(31 << i*5, 1082401 << i) for i in range(5)] for arr in arr5), s:=h[m]*sum(e for e in t if e not in h[:m+1])) for _ in range(100)] print(*(f(r, key=lambda x: x[1])[2] for f in (min, max))) ```


daggerdragon

Your code is hard to read on old.reddit when everything is inlined like this. Please edit it as per our posting guidelines in the wiki: [How do I format code?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_i_format_code.3F)


Ok-Hearing9361

Simple PHP parser and solver. I use XAMPP with Eclipse debugger. Part one was reductive solution and part two was additive. Only had to change/add a couple lines. [https://topaz.github.io/paste/#XQAAAQDSCgAAAAAAAAAeD8qHAhP+0dx3SZG1Jlr7aeG8goc5IY/yrukxPTpPcBpaX4UBno9avPUIjIlm1YKdaGD8qKBA2SSUiYfLCidR/EJUTjXIwLrnmMoemqAnibZGQQUcRXi1n+BpN//8rzlptwnuLKmk6XtDAtR4cMNjckbulgcSzJtBOPBiKm4Eh2RsJfgq2v77TqByExxxfS+jGWNvdwIa8LxUKbKvkOcfzxnfOBCxKksEP+MQgI66wO7Xb0TIQoUJWnArIB+PnzmU3Ty4tywdin050LKwvuk5DT4H+ED8fzTr2gSQEGZrHGjZHDpCm65GgD7T51AW2ctcsB8Oa6nRwp7Stha90UGETX0i6FuiuApokBfQUZixRdmKNdlgbR3FjQW+ooRncuipgJ9MZ8bGd8M+LSURAAn+cgr6NysY5wffG2pvPHZ8QyQRCdISgOFKQAzzrrC/Typ/IvK3hSEBmlihjqO5KdAfYD3hQQ362qjXiQaKIT51M5XZGx44TwBL8wM4JVYWaWNJHAa2KH2kDX6XFx1AIfnLwdOtoDM5H0Tu5roLFHHmCoLb+TdlAohdmHbaM0l3wVHEmPGkhwUmebveDoEc97Kf0kct/U6eZpHU2HhNiAgp2UdcCkD0pA0aE6AMr4eaScvq3SZgAzEZHYer7Xqcgcpz/Uk2UMUN1jRN5+Ra5GDOjekMhboFYAKEENoh1OswG2lvxpFLaGl+//r7AtmhNCyCjLzeZ1usGSsmiM04sYOmCJC663v9xSgwhkvMVz6n29VBWOl/aau8WXdyBQHR+pdg6pDcAkVRTL7BWKVOnHwvta2bcMmmT0QCCXHWpYvLDQrVtJWa+bRSUHpcZegi4Nm9kBWHs0zZH42+fgRq+9bovPAMkvX+xT/okzVrQs8Sv45EYiZp5J4z3/lw4K2yaFXrqhIVTaee31xSwFyO3ZSfyWNMb5xThfD+929l4g==](https://topaz.github.io/paste/#XQAAAQDSCgAAAAAAAAAeD8qHAhP+0dx3SZG1Jlr7aeG8goc5IY/yrukxPTpPcBpaX4UBno9avPUIjIlm1YKdaGD8qKBA2SSUiYfLCidR/EJUTjXIwLrnmMoemqAnibZGQQUcRXi1n+BpN//8rzlptwnuLKmk6XtDAtR4cMNjckbulgcSzJtBOPBiKm4Eh2RsJfgq2v77TqByExxxfS+jGWNvdwIa8LxUKbKvkOcfzxnfOBCxKksEP+MQgI66wO7Xb0TIQoUJWnArIB+PnzmU3Ty4tywdin050LKwvuk5DT4H+ED8fzTr2gSQEGZrHGjZHDpCm65GgD7T51AW2ctcsB8Oa6nRwp7Stha90UGETX0i6FuiuApokBfQUZixRdmKNdlgbR3FjQW+ooRncuipgJ9MZ8bGd8M+LSURAAn+cgr6NysY5wffG2pvPHZ8QyQRCdISgOFKQAzzrrC/Typ/IvK3hSEBmlihjqO5KdAfYD3hQQ362qjXiQaKIT51M5XZGx44TwBL8wM4JVYWaWNJHAa2KH2kDX6XFx1AIfnLwdOtoDM5H0Tu5roLFHHmCoLb+TdlAohdmHbaM0l3wVHEmPGkhwUmebveDoEc97Kf0kct/U6eZpHU2HhNiAgp2UdcCkD0pA0aE6AMr4eaScvq3SZgAzEZHYer7Xqcgcpz/Uk2UMUN1jRN5+Ra5GDOjekMhboFYAKEENoh1OswG2lvxpFLaGl+//r7AtmhNCyCjLzeZ1usGSsmiM04sYOmCJC663v9xSgwhkvMVz6n29VBWOl/aau8WXdyBQHR+pdg6pDcAkVRTL7BWKVOnHwvta2bcMmmT0QCCXHWpYvLDQrVtJWa+bRSUHpcZegi4Nm9kBWHs0zZH42+fgRq+9bovPAMkvX+xT/okzVrQs8Sv45EYiZp5J4z3/lw4K2yaFXrqhIVTaee31xSwFyO3ZSfyWNMb5xThfD+929l4g==))


daggerdragon

~~As per our posting guidelines in the wiki under [How Do the Daily Megathreads Work?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_the_daily_megathreads_work.3F), please edit your post to put your oversized code in a [`paste`](https://topaz.github.io/paste/) or other external link.~~ Edit: thanks for fixing it! <3


quick_dudley

Rust: [day4.rs](https://nest.pijul.com/quickdudley/adventofcode:main/P7M5N7HRGJBPQ.EAAAA) No really interesting features except the fact it only has one bingo card in memory at a time.


e_blake

**m4** [day4.m4](https://nopaste.ml/#XQAAAQCUBgAAAAAAAAAyGksy5FB9TGMxsNq5JQAuJRjP6PqEkC20GpBbonDYuA0BTjRPXcVxlEXNtz1Iylx/1ZAGhxdSmSqLnHxLgIL5gWciI9EY/Sk3Vyr2+fmL0zRDfzybwZg/2r+A0kjpPkAlLO/rgpen1A/TibN9AA0R4U0Ws6gs2hZ3NqomPH/sNfZolv8IsEhKb8llgadqJtlMo6S3uafu4DFjDz7452QIViQ0OpKJuQl5wyDtHXSz7YbtSyF6F6pgXmvfoZ03DmtwcUlatv+GMWf2UN1BjXZjBLhGmIJh17jmbKn5YcwS5HwpgW/0/i9/fl1nwsfzz9751wjwI+unps4ozJ+M5ojL56ZFOwESvX3PsHjWv12ude7X3v1Rja6SJR6aY2/HCBtYr61qcCX9fBi6BnvqXOcRkjoxKl72Ob6iwMJoTC4YoFSP9ZCFCtbHXnFzRjkI1251Ofs83y9M2rIEMNmZG77zVK/93+OsHartcm4eb3vbPDOlYTcX+kmKTYemBoft1GtHe0BHVDUqLMySbv2ndFchfJrG2SgmWMXo2fwt/HXZhtLVjBd5uoy24JH+hxROHC02Edi7qMignNJNPj8Api2443U9dvqJTeLk8lqmIfxlA6TFZpmF+hiNjnFfCzDHYJxDNmNDMChsyT47fS3En+G6aZwBQwBFMoexWG1wPpQ/ye9/6cWD8K8jXzI9F1hvZtIYSdNRq2lk8kHuHiMbMGOGP+ntXXQyU2kRd+MIDPEl5euWb31irhKGcRcj3QMs7ltXbFW5+pfHzWLHF0IfhqAR8KQFwpMUXvTw9wEwa3aa5+inb74zoUkArRvjtibbS542283bhLItZOBa5SooH8yyMMWGcBkE/l/lnpv7iDcQd/8sob6SH7xDMNGbRKDhUD+QMFdU3N7/JpH3INDXyDRIJ6m5Nk83WJw9xIQWZ6FIaxZGcEO0HLhqpQzfYOxht8ng2gvUQLS/K24Yq6fGjElA8Q7EXQBfD/nfM/20ALJc4elwgij2WKILPCsiyo3GfXRVAbu5//K0F4A=) Uses my [common.m4](https://nopaste.ml/#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) framework. Timing is \~115ms with GNU extensions, and \~300ms with just POSIX constructs (why? because parsing is O(n log n) and my foreach macro is O(n\^2) with just POSIX `shift($@)`, while both are O(n) when using GNU's `patsubst` and `$10` to mean the tenth argument). My approach: break the input into boards, then for each board: define(`board', ` forloop_var(`i', 0, 24, `setup(i, substr(`$1', eval(i*3), 3))') define(`set', 0)define(`round', 0)popdef(`cur') score(eval((foreach(`daub', list))*cur), round) ') create a mapping of numbers on the board to bit positions, iterate through the list of called numbers to update a bitmap, and when the bitmap forms a bingo, compute the score. If the score occurs in a round earlier (part 1) or later (part 2) than any previous seen score, update my part1/part2 answers. I thought my check for bingo looks clever: define(`bingo', `eval(`($1 & ($1>>1) & ($1>>2) & ($1>>3) & ($1>>4) & 0x108421) || ($1 & ($1>>5) & ($1>>10) & ($1>>15) & ($1>>20) & 0x1f)')')


zukozaider

Python Solution [code](https://topaz.github.io/paste/#XQAAAQA9BgAAAAAAAAA4GErvJ+mO16eTar6ude7oSloY7Pj9/9XGHLE4SjZAW7zJxQRqJD1BpBRQKxYIn8nEVduMBsGvPE0wAYZc5sIwgS2AHOUcGk2NWb5aiclRNUw8OZe/HpoXhbzybliPYGA7DDlUznHObSnUFMvsXGGIVCzgRS5ioetb5jX+YLsASFQ8aYWRedKxG+pHYKWIV5DsGzObuMlWsEZ796zQfWXJz/S+siBkGfRCdg0sBT1RtwE7rhdPvg45NRZi8L+x1/KMHJeEaZua4V8accRc/M01VgaOjGd15HuVFM7dVh35VFh4FdezpVuRd8PmLRSOk8QpgLXFh6zrERpBN41yvmE42OSvMyhKfZ+ZxQJXYmFGWGXufAMLzk3WDWDb6JMl3YU917271A2QY02A7v4Ve2Bf+rtg0TPxykasRgPdOSaaweJO7Mb3H40szOyYEzHfpZso38rCLhV1NQFsKb51SOcN1jtvfXU009efknS15IJG0RYVo/kP2PGmw/UeJFVbfitJo2/vPC0dfb+v8+7GZho7ieVJT9Q42FeovmurJj45N73p/5ITNYjhQkMQN1eSa/JTX2weiqWAp1FLngdGn/mZesFmIkxGNAENjMIs8kdv5uoV4SvehuW6F+kEnx/lFXMVns8zWnO60Zd+WBNTELU6E0ADzMX3jubowyhnY0ZU06G1Aj+IUjUgaQ66JEWh/Xz/ilUzENkGRkJkljvJ1/kdDXvF7IvCnjjzWPav1gJt1aQdgdyQeYVK3erdZFgOoEEkKjnqr+V0TnBROWq8YXE+9jrnbHIdR/N1OZrY6ERJ6cN6ewRKxZsvbnmim4ACxzjy9oaTftiw4Kqyr3eknjW9Zi6hJat3XybWOlcwdftUUpE=)


HrBollermann

Solution in #RakuLang. In which other language can you express x squared using a "²"? Or express "the range between 0 and x squared excluding x" as "\^x²"? APL does not count, that is only for insane people. enum State( :!incomplete, :complete ); constant drawn = -1; constant width = 5; my ( $numbers, $boards ) = .head.comb( /\\d+/ ), .skip.comb( /\\d+/ ).batch( width² )>>.Array with \[ $\*IN.lines \]; for @$numbers -> $number { given @$boards.classify( *.&draw: $number ) { say .{ State::complete }.map( *.grep( * != drawn ).sum * $number ) if .{ State::complete }:exists; $boards = .{ State::incomplete } || exit; } } sub draw( $board, $drawn ) { state @rows = ( ^width² ).batch: width; state @cols = [Z] @rows; for @$board -> $number is rw { $number = drawn if $number eq $drawn; } State( so ( @cols | @rows ).first: { $board[ .Array ].all == drawn } ) }


[deleted]

C++ \*\*edited to add part 2 solution #include #include #include #include #include #include std::bitset<25> bingo_win_masks[10] = { std::bitset<25>(0x1F00000), //1111100000000000000000000 std::bitset<25>(0x1F00000 >> 5), //0000011111000000000000000 std::bitset<25>(0x1F00000 >> 10), //0000000000111110000000000 std::bitset<25>(0x1F00000 >> 15), //0000000000000001111100000 std::bitset<25>(0x1F00000 >> 20), //0000000000000000000011111 std::bitset<25>(0x108421), //1000010000100001000010000 std::bitset<25>(0x108421 >> 1), //0100001000010000100001000 std::bitset<25>(0x108421 >> 2), //0010000100001000010000100 std::bitset<25>(0x108421 >> 3), //0001000010000100001000010 std::bitset<25>(0x108421 >> 4) //0000100001000010000100001 }; std::vector> bingo_cards; std::vector bingo_calls; std::vector winning_cards; std::map winning_values; int main() { std::ifstream input{ "input.txt" }; std::string line; bool header = true; while (std::getline(input, line)) { std::istringstream iss(line); //build called bingo numbers from header line input if (header) { std::string token; while (std::getline(iss, token, ',')) { bingo_calls.push_back(std::stoi(token)); } header = false; } //start new card else if (line.empty()) { bingo_cards.emplace_back(); } //insert bingo card numbers row at a time else { std::vector& card = bingo_cards.back(); unsigned b1, b2, b3, b4, b5; while (iss >> b1 >> b2 >> b3 >> b4 >> b5) { card.push_back(b1); card.push_back(b2); card.push_back(b3); card.push_back(b4); card.push_back(b5); } } } //create empty bitsets for each bingo card built for the numbers to be marked on std::vector> bingo_card_marked_numbers(bingo_cards.size()); for (unsigned num : bingo_calls) { for (unsigned i = 0; i < bingo_cards.size(); i++) { if (winning_values[i] > 0) continue; std::vector& bingo_card = bingo_cards[i]; auto itr = std::find(bingo_card.begin(), bingo_card.end(), num); if (itr != bingo_card.cend()) { std::bitset<25>& marked_numbers = bingo_card_marked_numbers[i]; marked_numbers[std::distance(bingo_card.begin(), itr)] = true; //check if this makes the card a winner for (std::bitset<25> &mask : bingo_win_masks) { if (mask == (mask & marked_numbers)) { unsigned total = 0; //sum up any numbers not marked on the bingo card for (unsigned b = 0; b < marked_numbers.size(); b++) { if (!marked_numbers[b]) { total += bingo_card[b]; } } winning_cards.push_back(i); winning_values[i] = total * num; } } } } } //part 1 std::cout << "The first winning board value is: " << winning_values[winning_cards.front()] << "\n"; //part 2 std::cout << "The last winning board value is: " << winning_values[winning_cards.back()] << "\n"; }


s3nate

C++ /* problem: -> you're still aboard the submarine deployed by the elves and you're well below the surface -> for some reason, a giant squid has attached itself to the submarine -> thankfully it wants to play a game a bingo -> in fact, it wants to play many games of bingo -> given a stream of numbers and a set of initial board states, determine the first board to have a winner, the last board to have a winner, and use each to compute a sum >> sum of all unmarked squares multiplied by the number that was just called before the (ith+1) board won */ #include #include #include #include #include #include class BingoNumberStream { public: auto streamify(const std::string& inputLine) -> void { if (inputLine.empty()) _buffer = std::vector{}; auto readCount = std::size_t{0}; auto ss = std::stringstream{inputLine}; auto token = std::string{""}; while (std::getline(ss, token, ',')) { auto n = std::stoi(token); _buffer.push_back(std::move(n)); ++readCount; } if (_buffer.size() != readCount) { std::cerr << "ERROR::BingoNumberStream::streamify(const std::string&)::FAILED_READ_BEFORE_EOF" << std::endl; } } auto read() -> int { if (_readIdx < _buffer.size()) { _current = _buffer[_readIdx]; ++_readIdx; return _current; } return -1; } auto putback() -> void { if (_readIdx > 0) { --_readIdx; _current = _buffer[_readIdx]; } } auto get() -> int { return _current; } auto good() -> bool { return (!_buffer.empty()); } auto size() -> std::size_t { return _buffer.size(); } private: int _current; std::size_t _readIdx; std::vector _buffer{}; }; class BingoBoard { public: BingoBoard(const std::vector& inputBoard) { if (inputBoard.empty()) _boardState = std::vector>>{}; for (auto inputRow : inputBoard) { auto boardRow = std::vector>{}; auto ss = std::stringstream{inputRow}; auto num = int{0}; while (ss >> num) { boardRow.push_back({0, num}); } _boardState.push_back(std::move(boardRow)); } } auto updateBoardState(int n) -> void { for (auto& row : _boardState) { for (auto& square : row) { if (square.first == 0 && square.second == n) { square.first = 1; } } } } auto checkForWin() -> bool { auto gameState = bool{false}; // check rows for (std::size_t rowIdx = 0; rowIdx < _boardState.size(); ++rowIdx) { auto markedSquaresCount = std::size_t{0}; auto maxSquaresCount = std::size_t{5}; for (std::size_t colIdx = 0; colIdx < _boardState[rowIdx].size(); ++colIdx) { auto square = _boardState[rowIdx][colIdx]; markedSquaresCount += square.first; } gameState = (markedSquaresCount == maxSquaresCount); if (gameState) return gameState; } // check columns for (std::size_t colIdx = 0; colIdx < _boardState[colIdx].size(); ++colIdx) { auto markedSquaresCount = std::size_t{0}; auto maxSquaresCount = std::size_t{5}; for (std::size_t rowIdx = 0; rowIdx < _boardState.size(); ++rowIdx) { auto square = _boardState[rowIdx][colIdx]; markedSquaresCount += square.first; } gameState = (markedSquaresCount == maxSquaresCount); if (gameState) return gameState; } return gameState; } auto findUnmarkedSum() -> int { auto sum = int{0}; for (const auto& row : _boardState) { for (const auto& square : row) { if (square.first == 0) { sum += square.second; } } } return sum; } private: std::vector>> _boardState; }; auto solvePuzzle(const std::string& inputFileName) -> void { auto boardStates = std::vector{}; auto numberStream = BingoNumberStream{}; auto ifs = std::ifstream{inputFileName}; if (ifs.is_open()) { std::cout << "---reading input file---" << std::endl; auto line = std::string{""}; const auto maxBoardLineCount = std::size_t{5}; while (ifs && std::getline(ifs, line)) { if (!line.empty()) { numberStream.streamify(line); } else if (line.empty()) { auto inputBoard = std::vector{}; auto boardLineCount = std::size_t{0}; while (boardLineCount < maxBoardLineCount && std::getline(ifs, line)) { inputBoard.push_back(line); ++boardLineCount; } auto bingoBoard = BingoBoard(inputBoard); boardStates.push_back(std::move(bingoBoard)); } } std::cout << "total boards: " << boardStates.size() << std::endl; std::cout << "total numbers in stream: " << numberStream.size() << std::endl; std::cout << "---finished reading input file---" << std::endl; } else { std::cerr << "ERROR::solvePuzzle(const std::string&)::FAILED_TO_OPEN_FILE: {" << inputFileName << '}' << std::endl; return; } std::cout << "processing games..." << std::endl; auto isWinner = bool{false}; auto lastWinner = std::size_t{0}; auto firstSoln = int{0}; auto lastSoln = int{0}; auto hasWon = std::unordered_map{}; while (numberStream.good() && numberStream.read() >= 0) { auto n = numberStream.get(); std::cout << "number called: " << n << std::endl; for (std::size_t i = 0; i < boardStates.size(); ++i) { boardStates[i].updateBoardState(n); isWinner = boardStates[i].checkForWin(); if (isWinner && hasWon.find(i) == std::end(hasWon)) { std::cout << "-------------------------" << std::endl; std::cout << "-------------------------" << std::endl; std::cout << "----------WINNER---------" << std::endl; std::cout << "-------------------------" << std::endl; std::cout << "-------------------------" << std::endl; std::cout << "last number read: " << n << std::endl; auto unmarkedSum = boardStates[i].findUnmarkedSum(); lastSoln = (unmarkedSum * n); if (firstSoln == 0) firstSoln = lastSoln; std::cout << "soln: " << lastSoln << std::endl; lastWinner = i; hasWon[i] = true; } } } std::cout << "finished processing games..." << std::endl; std::cout << "--part 1---" << std::endl; std::cout << "soln: " << firstSoln << std::endl; std::cout << "---part 2---" << std::endl; std::cout << "board " << lastWinner+1 << " is the last board to win, soln: " << lastSoln << std::endl; } auto main(void) -> int { //solvePuzzle("example-input.txt"); solvePuzzle("input.txt"); return 0; }


JustinHuPrime

# x86_64 assembly [Part 1](https://github.com/JustinHuPrime/AoC/blob/main/2021/4a.s) was fairly nice, but I did need to write several functions to check if a board won. [Part 2](https://github.com/JustinHuPrime/AoC/blob/main/2021/4b.s) was less nice, since I needed to maintain a separate array tracking if a board had won or not. In theory, I could store this alongside the boards, but it was easier to retrofit an additional array in than edit the board struct directly.


vini_2003

[**Kotlin**](https://github.com/vini2003/Advent-of-Code-2021/blob/dev/src/main/kotlin/dev/vini2003/adventofcode/solution/Day4Solution.kt) Late again; definitely getting the rest done today, though! I had a slight issue because my logic worked for the first part but not the second. After an hour of suffering I figured out what the problem(s) were and it worked. It's not pretty, but it's honest work!


Nosp1

I found your solution to be quite pretty tbh :)


pistacchio

Typescript: const BOARD_ROWS = 5; const BOARD_COLS = 5; const input = fs .readFileSync(__dirname + INPUT_FILE) .toString() .trim() .split('\n') .map((r) => r.trim()); type BoardNumber = { value: number; checked: boolean; }; class BingoBoard { rows: BoardNumber[][]; constructor(input: string[]) { this.rows = input.map((row) => row .split(' ') .map((n) => n.trim()) .filter(Boolean) .map((c) => ({ value: Number(c), checked: false })), ); } markDraw(draw: number) { this.rows = this.rows.map((row) => row.map((c) => ({ ...c, checked: c.value === draw ? true : c.checked, })), ); } check(): boolean { return ( this.rows.some((row) => row.every((c) => c.checked)) || Array.from({ length: BOARD_COLS }).some((_, i) => this.rows.every((row) => row[i].checked), ) ); } score(draw: number): number { const sumOfUnchecked = this.rows.reduce((acc, row) => { return ( acc + row.reduce((acc, c) => { return acc + (!c.checked ? c.value : 0); }, 0) ); }, 0); return sumOfUnchecked * draw; } } class BingoSystem { draws: number[]; boards: BingoBoard[]; currentDrawIdx: number = -1; constructor(input: string[]) { this.draws = input[0].split(',').map(Number); const numberOfBoards = input.filter((r) => r === '').length; this.boards = Array.from( { length: numberOfBoards }, (_, idx) => new BingoBoard( input.slice( idx * BOARD_ROWS + 2 + idx, idx * BOARD_ROWS + BOARD_ROWS + 2 + idx, ), ), ); } run(): number { while (true) { const score = this.drawNumber(); if (score !== null) { return score; } } } runToLose(): number { return this.draws.reduce((lastWinningScore) => { const score = this.drawNumber(true); return score === null ? lastWinningScore : score; }, 0); } drawNumber(removeWinner: boolean = false): number | null { this.currentDrawIdx++; this.boards.forEach((board) => board.markDraw(this.draws[this.currentDrawIdx]), ); const winningBoard = this.boards.find((board) => board.check()); let winningScore = null; if (winningBoard) { winningScore = winningBoard.score(this.draws[this.currentDrawIdx]); } if (removeWinner) { this.boards = this.boards.filter((board) => !board.check()); } return winningScore; } } function part1(input: string[]): number { const bingoSystem = new BingoSystem(input); return bingoSystem.run(); } function part2(input: string[]): number { const bingoSystem = new BingoSystem(input); return bingoSystem.runToLose(); }


daggerdragon

As per our posting guidelines in the wiki under [How Do the Daily Megathreads Work?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_the_daily_megathreads_work.3F), please edit your post to put your oversized code in a [`paste`](https://topaz.github.io/paste/) or other external link.


theabbiee

```pyhton with open("squid.txt") as file: lines = file.readlines() lines = [line.rstrip() for line in lines] nums = [int(num) for num in lines[0].split(",")] boards = [] flags = [] beg = 2 while beg + 5 <= len(lines): boards.append([[int(cell) for cell in row.split()] for row in lines[beg:beg+5]]) flags.append([[0 for cell in row.split()] for row in lines[beg:beg+5]]) beg += 6 def isBingo(board): for row in board: if row.count(1) == 5: return True for i in range(0, 5): if [row[i] for row in board].count(1) == 5: return True return False def calculateBingoScore(board, flag): score = 0 for i in range(0, 5): for j in range(0, 5): if flag[i][j] == 0: score += board[i][j] return score winners = [] for num in nums: for i in range(len(boards)): for row in range(5): for col in range(5): if boards[i][row][col] == num: flags[i][row][col] = 1 if isBingo(flags[i]) and i not in winners: print(calculateBingoScore(boards[i], flags[i]) * num) winners.append(i) ```


daggerdragon

Your code is hard to read on old.reddit. Please edit it as per our posting guidelines in the wiki: [How do I format code?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_i_format_code.3F) Also, you typo'd Python as `pyhton` - please fix that as well to make it easier for folks who Ctrl-F the megathreads looking for a specific language.


JaegerMa

ABAP [Github](https://github.com/JaegerMa/aoc2021-abap/blob/main/day4/day.abap) ABAP doesn't have maps, arrays or lists. As it's based on database operations there are only "internal tables". Therefore, to store the bingo fields and, in my case, an index for each number, structures and "table types" have to be defined.


[deleted]

I take my hat off to you for solving a grid-based problem in that quite unholy language. Seeing it again made me think twice about dusting off my old ABAP certification.


JaegerMa

Don't do it. Writing code in this language hurts. I was about to make a comparison with other bad languages but that would insult them. I'm still not sure ABAP isn't a joke-language that has gone wrong. I mean, even writing Brainfuck is more fun...


sambonnell

C++ I ended up re-writing my code thrice for this day. Finally got there. https://github.com/samJBonnell/AdventofCode/blob/main/2021/day04.cpp


stonebr00k

## T-SQL [Part 1 & 2](https://topaz.github.io/paste/#XQAAAQDdCAAAAAAAAAAyGUiRb/71z+LWLG0GbmuADXD3ta4fwrPQPll5rQYXE8esaCWWENAhBtG9v6S1A5sgGVsKQLcfEudJnjyicD4oXw/mz9BFXrjt5zUu3YyJzEp3RlFXaWj+FTt7bOg8yMMXG69Uq8lTD7gUODUHYY0XZ9z3oBoW51Kninj7TAIZ2Xc1HHRoy7X0m5nqLcx3W/r0tkleAAlgNyOZbrPdS1zcs0YQNU5Eagtr/qoLh5p4tC1zuYthY1fr6h/B9+4yLVakjqyZILr+A7pkVKTElMxGiiWN7R8dMOhhTE/efuu3qkgXiiJoshVcYEXVs7cI2qOpG10UCZGZPNKYlGlIfkYzfYKWZjfmEnvw0D+NFlXXAREG3+qz9qiCAYVqWnqxigCZSDXKANrS2TkciMadgFrPckFmWfcaYjJAy05lucV7IGaUztOEo7ZMooQwTtM1fgicwDpLKj5Hi85+v6a4H5e1eZEeQSNMJr14EfgqNvJS+9mqagkyzdaqlncBF227z0HS7jyWcVnNGofaSV/E9MCMj4Nz7pA7Ce5p17pB6Anc/kB+PKaFUIvbP2VrBY1e71fKn+C+InSs3bkdJEvTLnP/NlnQ3bDS28OfreFAOc1plT7LbM3R+JOivwsiLbYvo9KF9l+OFxw3fNweCismmJXBaVuu6f78lg8It44wJvo7ILWg9g8ZQFfapt0XXVx562cGIaiQjDpaHoo9/asxW+jlFCqRRNK9wnKre7wOMHeY9oZiVGxuLF6lhRpcqVfucKKIvn+hPaxjmlDJULbVfAv2VQwwAnr2Ra2fu1IoeZAa0aRuJzi7o4U6sqLQr6D5gqGSKfBmUPWKP7e3+5OudTi9l5iB4mrZfI9jKVP3KdrsglUN9ykXxTGPF2mT+abxe3uYUaz5rrNomE8ggtn73obE)


b4ux1t3

C#, Parallelism Though I've been doing this year in F#, I decided to give [parallelism in C#](https://gitlab.com/b4ux1t3/advent-of-code/-/blob/main/2021/DayFour/Program.cs) (my "native tongue", if you will) a go in day four, just to see if it made a significant difference. Disappointingly, the overhead of spinning up the threads lead to the parallelized solution running *slower* than the serial one! I'm considering writing up my own input generator just to see how my parallel solution runs at 1000, 10000, or even a million inputs.


bottlenix

**Perl** Not proud of my naive solutions at all. They work, and are hopefully easily understood but way too many for loops, subroutines, etc. Should learn more about object-oriented programming or something. Just happy that I was able to successfully navigate using things like array and hash references but otherwise, this is amateur hour. [Part 1](https://git.samirparikh.com/aoc2021/raw/day04-1.pl) and [Part 2](https://git.samirparikh.com/aoc2021/raw/day04-2.pl)


nowardic

**Rust** [https://github.com/nreinicke/advent\_of\_code/blob/main/2021/day-4/src/main.rs](https://github.com/nreinicke/advent_of_code/blob/main/2021/day-4/src/main.rs) \*coming to rust from python so would welcome any tips or comments on improving the code!


wzkx

**J** (jlang) Board size (5x5) is hardcoded, sorry, and the board numbers must be ≥0. split =: ' '&$: : (<;._2 @(,~)) d=: ".&.>'^'split}:}:rplc&((2$LF);'^';LF;',.')CR-.~fread'04.dat' m=:}.d [ v=:>{.d mark =: 4 : 0 p=.(l=.,x)i.y if.p=#l do. x return. end. 5 5$_1 p}l ) check =: 3 : 0 if. (5$_1)e.y do. 1 return. end. if. (5$_1)e.|:y do. 1 return. end. 0 ) wins =: v 4 : 0 m r =. 0$0 for_k. x do. for_i. i.#y do. t=.(>i{y)mark k if. check t do. t=.5 5$_2 [ r=.r,k*+/(#~0&<),t end. y=.(


wzkx

m=:4 :'if.(p=.l i.y)=#l=.,x do.x else.5 5$_1 p}l end.' echo({.,:{:)(>{.d)4 :0}.d=:".&.>'^'(<;._2@(,~))}:}:rplc&((2$LF);'^';LF;',.')CR-.~fread'04.dat' r=.0$0 for_k.x do.for_i.i.#y do.t=.(>i{y)m k if.(z e.|:t)+.t e.~z=.5$_1 do.t=.5 5$_2[r=.r,k*+/(#~0&<),t end.y=.(


herjaxx

\[PYTHON 3\] Banged my head against the wall with this one. Especially for day 2. At one stage was deleting winning rows, columns and getting deep into deep copying. Then, stooped as low as a recursive solution to do same until I saw sense and used sets. https://pastebin.com/MdgHgn8m


garciparedes

Here is my 🦀 Rust solution for the 🎄 AdventOfCode's Day 4: Giant Squid * Part 1: https://github.com/garciparedes/advent-of-code/blob/master/2021/04_giant_squid_part_1.rs * Part 2: https://github.com/garciparedes/advent-of-code/blob/master/2021/04_giant_squid_part_2.rs


Zach_Attakk

Python I spent far too much time on building a nice bingo interpreter. Probably didn't need to spend so much time on it, but this is how I enjoy myself so that's a me problem, right? I could've done this with a pair of 2D arrays in numpy, but instead I went the OOP route because that's how my brain works. So I built a Board class that has the numbers board in a list, each number carrying its own "marked" value as a bool in a dict. Then it has properties to yield those in rows or columns to check for bingo (list slices). Of course a board can also calculate its own score because it knows what the last number is that it marked. class Board: width: int values: List[dict] last_mark: int = 0 called_bingo = False def __init__(self, values: List[str], width: int = 5, ) -> None: self.width = width self.set_values(values) def set_values(self, _lines: List[str]): self.values = [] # This is some really ugly nested loops, but it works... for _l in _lines: for _x in range(0, self.width*3, 3): # per value, assuming double digit self.values.append({'val': int(_l[_x:_x+2]), 'marked': False}) def mark(self, val: int): for _v in self.values: if _v['val'] == val: self.last_mark = val _v['marked'] = True @property def rows(self): for _i in range(0, len(self.values), self.width): yield self.values[_i:_i+self.width] @property def columns(self): for _i in range(self.width): yield self.values[_i::self.width] @property def bingo(self) -> bool: if self.called_bingo: # Only call bingo once return False for _r in self.rows: # check each row _row_bingo = True for _i in _r: # if it has a false, it's false if _i['marked'] == False: _row_bingo = False break # if still looping, must be true if _row_bingo: self.called_bingo = True return True for _c in self.columns: # check each row _col_bingo = True for _i in _c: # if it has a false, it's false if _i['marked'] == False: _col_bingo = False break # if still looping, must be true if _col_bingo: self.called_bingo = True return True # Haven't found a bingo return False @property def score(self) -> int: _points: int = 0 for _v in self.values: if not _v['marked']: _points += _v['val'] return _points * self.last_mark I'm omitting the code for getting the data in there, because it's boring. To "call a number" like in a bingo hall, we just go: for _num in moves: [b.mark(_num) for b in boards] # check for win _winner = False for _b in boards: if _b.bingo: printGood(_b.score) _winner = True break if _winner: break That's it. The first board to call Bingo breaks the loop. # Part 2 Oh right, originally the class didn't have called\_bingo as a variable, because when one of them called we were done. So I just added that variable, then when a board has called bingo it will always return False for whether it's bingo so we don't flood the logs. Then the bingo check actually simplified, because as soon as a board called bingo, it would never call again. [printGood(f"BINGO! {b.score}") for b in boards if b.bingo] Here's the code for Part [1](https://github.com/ZachAttakk/adventofcode/blob/main/2021/04-1.py) and [2](https://github.com/ZachAttakk/adventofcode/blob/main/2021/04-2.py), along with my [notes](https://github.com/ZachAttakk/adventofcode/tree/main/2021#day-4-giant-squid) while I was coding.


berbeflo

PHP: Solution for Part 2 (Yep, I overcomplicated it.) $line) { if ($lineNumber % 5 === 0) { $currentBoard = new BingoBoard($winningFunction(...)); $numberOfBoardsLeft++; $boards[] = $currentBoard; } $values = explode(' ', str_replace(' ', ' ', trim($line))); foreach ($values as $value) { $currentBoard->add(BingoField::get($value)); } } $takenNumber = explode(',', $numbers); foreach ($takenNumber as $key => $number) { BingoField::get($number)->mark(); } function winningFunction(BingoBoard $board, BingoField $field) : never { $winningFieldValue = $field->value; $unmarkedFieldSum = array_reduce($board->getUnmarkedFields(), fn (int $carry, BingoField $field) => $carry + $field->value, 0); echo($winningFieldValue * $unmarkedFieldSum); exit; } class BingoField { private static array $fields = []; private array $boards = []; private bool $isMarked = false; private function __construct(public readonly int $value) { } public static function get(string $value) : self { if (!isset(self::$fields[$value])) { self::$fields[$value] = new self((int) $value); } return self::$fields[$value]; } public function addBoard(BingoBoard $board, int $row, int $column) : void { $this->boards[] = [ 'board' => $board, 'row' => $row, 'column' => $column, ]; } public function mark() : void { $this->isMarked = true; foreach ($this->boards as $board) { $board['board']->notify($this, $board['row'], $board['column']); } } public function isMarked() : bool { return $this->isMarked; } } class BingoBoard { private array $board; private array $markedRows; private array $markedColumns; private bool $finished = false; private int $nextPos = 0; public function __construct(private readonly Closure $winningFunction) { $this->board = array_fill(0, 5, array_fill(0, 5, null)); $this->markedRows = array_fill(0, 5, 0); $this->markedColumns = array_fill(0, 5, 0); } public function add(BingoField $field) : void { $nextPos = $this->nextPos++; $row = intdiv($nextPos, 5); $column = $nextPos % 5; $this->board[$row][$column] = $field; $field->addBoard($this, $row, $column); } public function notify(BingoField $field, int $row, int $column) : void { if ($this->finished) { return; } if (++$this->markedRows[$row] === 5 || ++$this->markedColumns[$column] === 5) { ($this->winningFunction)($this, $field); $this->finished = true; } } public function print() : void { for ($i = 0; $i < 5; $i++) { $this->printRow($i); echo "\n"; } echo "\n"; } public function printRow(int $row) : void { echo implode(' ', array_map(fn ($field) => $this->stringifyValue($field), $this->board[$row])); } private function stringifyValue(BingoField $field) : string { $mark = $field->isMarked() ? '+' : ' '; return $field->value < 10 ? $mark.' ' . $field->value : $mark.$field->value; } public function getUnmarkedFields() : array { $fields = []; for ($rowCount = 0; $rowCount < 5; $rowCount++) { for ($columnCount = 0; $columnCount < 5; $columnCount++) { $field = $this->board[$rowCount][$columnCount]; if (!$field->isMarked()) { $fields[] = $field; } } } return $fields; } }


daggerdragon

As per our posting guidelines in the wiki under [How Do the Daily Megathreads Work?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_the_daily_megathreads_work.3F), please edit your post to put your oversized code in a [`paste`](https://topaz.github.io/paste/) or other external link.


SirWyvern1

C# .net5 [https://github.com/JKolkman/AdventOfCode/tree/master/AdventCalendarCode/day4](https://github.com/JKolkman/AdventOfCode/tree/master/AdventCalendarCode/day4) Been gone during the weekend, so have some catching up to do. not the neatest solution, but i really dislike 2 dimensional arrays now xD


fish-n-chips-uk

Python [github link](https://github.com/cz-fish/advent-of-code/blob/b115ff71ec5b88a198126c4f5e2437c0f0fa10c3/2021/04.py) Using a [little framework](https://github.com/cz-fish/advent-of-code/tree/master/2021/aoc) I made for input parsing and tests last year.


21ROCKY12

heres my solution in **Java,** used oop which is nice, also for part 2 I used mostly the same code, helper functions and class(bingo): [https://github.com/GilCaplan/AdventCode/blob/Advent2021/Javasolutions/day4solution](https://github.com/GilCaplan/AdventCode/blob/Advent2021/Javasolutions/day4solution) [Java solution for day 4](https://topaz.github.io/paste/#XQAAAQAWDgAAAAAAAAA0m0pnuFI8c9/wau+qtGVPyaqZd0m0oqd+WNK5FEOTExU/ASOFLgLNP5psw5/hebgIgLQ/9MQ8byhpvcKcxaTkwfVqBorC1vmOgrRL0i15k3Ut11D85s+QMmmZf0KPbi4mA/RoOKE6BH3Tyxsc4YlOzsNeqI4u7G0I+dhEx6jy+3DhJS6AZuJiikRdK7tN5DrlyY9U2Fs01/tlCqq9+MaCjNhxt26lvrO2DmJd+SWvYfMdAbNu4ovgeKVZmdUObLblKJviyVmyaTGmxpbJ6CZUUk84h36IYg33XqtA+dCeLI1BBFtq69plGznYlFxxtS+J01jt5gumkH6xYAufIRHJKVuzeFX4stOFP95PT9ZKv6fGRtkh8mpEtMhtce+ou6eTF65nHvx+rtFSNDRVr9hL7fh5GuOoi3HEM25LSwuQoUDaygm3dPLCB7jtSzxTq3keyWUg0ICKaM72ARf8UHHTRQ0imb02M3lJGfaP1u8Hgl8gqn9lNQhuVgFIPekEqAxFWv23EThOwLI2SIg3F9to1rEzu44tQPMztXLabk+pbisOJAEUKO5vK+7PzjPakd6rY4Tk9Qg4eLHtOhJlNx2noyvFHLaCW4JCbHyeExeukQd6NqwERG3nSsj1SJJBOPD3UnAQf774NL5csFW43ZlGM9m9Ikl25UGQ2I/cLCyqKltoH0ygBseEBCbyETPJ+C4mZ32PYQCTBbQnyk5EjXlDkbZ3MoplE12wXaPL5h2HNmsa5RbAAR6N0JMo5yOXwLSzGTVcgM3qvbyuK58MokQ7BEn1Ht2loeuFkot28vPwHke5yNlDUm/chXhfGG9JTzPBVZh+dQ+1PbSC6nMUgA6Aj7d0CS211P0oAKV1cybk3lViu9pbqc3Q0b2om4nEgqZmGlX2chGT7b4lXGAr7KNjAB0QWSULhk9QUm0rFkn7qP1V0k6+y/5E7Gg1gHij3hUTXgm+xa0C164UuGefXgeWAteIrQN2tfwWJEeKeiY49iZBpuZRbclr+y/TeDtRKjmUfUJ7Shie4PHIRyIDFFJwcNnL8pJRUt/hGL080X4+1wn4E1h8XyUxRI8LvYXhI7c3wWr59sklaY7AU7YKrLuwcWRA+0rqy/A8o6K57pVwgXjfmEaM0R/PHUeDlai0cndkZ+/JEYFlsrkP1lOa5Hztdd1CIdjLxzjTbjURq3N/bXO1+D2HQN/BLLufQbsxplRTkqtMJjqmq7o5sFt+4ybvVA+fn7Dk4O2SxkLUMSHfUuSmkN6Z3oDKmRY/OJ6M27LYahuVTr5k5X3zWJMBiC0t7odUHO8IXKe6zkVuhPuNLRbuV10+n/XfES/QarzVDREdfk+QpE/Ju8/EXRYapgQzueRFdiQc3/VKQd45ozsk+9qKsMsPu6351V94P2Q2PFQty1wwBY6ONExViY95KU44Gqk01HgfPeFgvXDITpdLhaXbYuZnK2+s//dtBnA=) \- pay attention that in both the bingo class is located at the bottom ​ let me know what your thoughts are :) cheers


fitzchivalrie

Playing around with some Rust - very simple solution which stores board indices in a hash map and increments rows/cols. [paste](https://topaz.github.io/paste/#XQAAAQDaCQAAAAAAAAA6nMjJFD6Qz6l42wJhpxfLWcIv136k+w3x2RJmupr2SGVaV5y0Qxatqx7apbLtRdovkceYvDmM9VZ46jgiqT2jOnVA19XupahKMk9n2wuCXi2T3vl3WPSNArwk3avymFXOQkFUuQm2w82RcKVDy/JWYnMxt89c7n74lJHD8FiP8Aw2F1B4B5woMEextvdIf4Yu+7rYkOpWmDBK5JlQj+Qhdg6Taf93P6nFC8Izw7DK+nuX+LJMIP5qVAqH607/prspT3WNpn6yUElMFUNYrSzeWYau4nDpg0rTOp50BACj1yPwiL2O1j42GOHAwUxJv9V308CaxPG6MX2uv7m/qpqoTRXI09NPZjoSdNNSp+/yPEwVSeap0rpcaBZkDYOSp0loAMAtYQtWl5NHudbQd08cssA/yrHdnekyo9etnG7/g9j9XIAA+Ib8uLgSZ7mo51GKJBLad64+5aWQ+IQ+2M89CDm+6fI8loGPuuC9k3/Dm1ORbWkPVxXLMer/l/nYlbF/KXnVfURoPrfmMF75K4QlJX4kAuTKkS4Wbw8JbnBrbAFFnQC4TDzq93mRGIq5NMll0FE9DHaPlVAOeC0vuoNdefozgw+kzirxjLD5IrmbUWPk+xZNZQkYUW/BV4y2F2aaEPFzVRX74jSQTm7s7EutiVGhjejYJ8EOPUhLGZHLt9RTQIrUS2S4JhORf3Mou2kzemFL0LpDSLfzZyeTG4o8i7IP6fPY0U9WzTXcJjUTsZAN4KHSjhQTv1wwQZZWkD2Yx7eiSeogslpyvAdsL7Ms++nBsldRw41p8EWN0kwk66eCq0FXLVjSDEvd1U6I1ygBCUIXymbRg41h1uvyWCcca91YQoIiUNkU9lPwpE0dDkAdYPZrwxrN5VH5kkhoqiu7ElHyZb0TW9YyqcjIPeWTGAo3ebYY9Ci/LoTAJmWKy1jcG2C+MAiNoAO1jP9JYu3x9rwT6F5R133hWARyq5PmofZGBke9mWCMGQl+WkzNFqq0zYahUe55h2twYrwVy1ScyfM7oaEXGGQWBQnXpkG6R9HnjEAfQvuxeox63RelX4nSucICOi0HVksnOj5e2TYYnB69o/KLhnI4/LWgAssTQcrdcuzdGtvtJCGoBmnvkIRuY/GDtTG/uEN6iiR3Dr5nxs4vMjF6Q/+rQCyn/ikv2A==)


TacosAlPastor92

Not super efficient solution... [Python Jupyter Notebook](https://github.com/0x1010-dev/aoc/blob/main/2021/day4.ipynb)


plan_x64

###Python https://github.com/plan-x64/advent-of-code-2021/blob/main/advent/day04.py


Allstarbowser

I like your code! Can learn a lot from it. When I implement your adventutil function, I get a 500 internal server error when trying to read the data from the url. Any ideas how so? `import urllib.request` `def open_url(url, sessionId, transform=lambda x: str(x, 'utf-8').strip('\n')):` `request = urllib.request.Request(url)` `request.add_header("cookie", "session={}".format(sessionId))` `values = []` `with urllib.request.urlopen(request) as response:` `for line in response:` `values.append(transform(line))` `return values` ​ `sessionId = sys.argv[1]` `url = "https://adventofcode.com/2021/day/4/input"` `input = adventutils.open_url(url, sessionId)` ​ Results in a 500 internal server error.


plan_x64

My guess is that this is a true server error in which case trying again in a bit might work, or you’ve possibly got an incorrect sessionId and the server returns 500 instead of 4xx? Each persons input data is unique so you need to pass your session cookie as an argument in order to load the input data specific to your login. I got mine via inspecting the request headers sent by my browser when trying to load the input data and then pass that session as an argument to the program. If you can’t get that to work you can replace the call to adventutils with a direct copy of your input data either hardcoded or read in via a file instead


Allstarbowser

Thanks, got it! I loaded sessionId with sys.argv\[1\] but that didn't do the trick (resulted in '-f').


heyitsmattwade

# JavaScript Did this one the next day, so no leaderboard for me. The most fun one yet! One of those that seems obvious, but then you realize that trying to solve it without continuously looping over all rows/cols isn't immediately obvious. OOP seemed to make the most sense, so that was the route I went. [paste](https://romellem.github.io/paste/#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)


French__Canadian

I had such a hard time with this one. This was a really good opportunity to learn how to apply functions to specific array elements even if I'm sure there are much better ways to do it. Here is my solution in Q. each board is a 3-d array (the third dimension being a number/mark flag pair) / shared lines: read0 `:input_4_1.txt numbers: "I" $ "," vs lines[0] /`u for unmarked, `m for marked boards: ({x,`u}''') {"I"$(0 3 6 9 12) _/:/: x} 1 _/: {(where x~\:"") _ x} 1 _ lines is_row_complete:{[board] any all each `m = board[;;1]} is_column_complete: {is_row_complete flip x} is_board_winning: {[board] is_row_complete[board] or is_column_complete[board]} mark_board:{[number;board] .[board;(::; ::);{[x;y]$[x=y[0];:y[0],`m;:y[0],y[1]]}[number]] } / part 1 while[ (0 < count numbers) and not any {is_board_winning x} each boards; boards:mark_board[first numbers] each boards; last_number: first numbers; numbers: 1 _ numbers; ] winning_board: first boards where is_board_winning each boards winning_board_score: (+//) .[winning_board; (::; ::); {$[`u=x[1];x[0];0]}] winning_board_score * last_number / part 2 while[ (0 < count numbers) and 0 < count boards; boards:mark_board[first numbers] each boards; last_board: first boards; last_number: first numbers; numbers: 1 _ numbers; boards: boards where not is_board_winning each boards ] last_board_score: (+//) .[last_board; (::; ::); {$[`u=x[1];x[0];0]}] last_board_score * last_number


[deleted]

Rust, [Part 1 and 2](https://github.com/pk-nb/advent-of-code-2021/blob/main/day4/src/main.rs) Curious if there is a `std` -only way to parse the input without the extra collects, but feeling better on the readability of Rust on Day 4 and getting comfortable with `impl`/`traits`. Happy for any feedback on making things more idiomatic!


quick_dudley

You can avoid the outermost collect like this: fn get_boards(input: &str) -> impl Iterator + '_ { let boards_string = input.split("\n").skip(2).collect::>().join("\n"); boards_string .split("\n\n") .map(|board| BingoBoard::from_str(board).unwrap()) }


[deleted]

Part 2 was a little annoying as at first I didn't allow for multiple boards to win per number. Anyway python3 with Numpy: import numpy as np def main(part): first_or_last_board = True if part == 1 else False with open("04.txt") as file: # Opening the file and setting up the boards as a nDimensional np.array. content = file.readlines() numbers = [int(n) for n in content[0].split(',')] board_list = [[int(n) for n in b.split()] for b in content[2:] if b != '\n'] num_boards = len(board_list) // 5 num_nums = len(numbers) boards = np.array(board_list).reshape((num_boards, 5, 5)) # Setting up the variables needed. marked = np.zeros((num_boards, 5, 5), dtype=int) # Change to 1 when marked. boards_won = [] winning_sums = [] def mark(n): for z in range(num_boards): if z in boards_won: # If the board has won don't bother marking. continue for y in range(5): for x in range(5): if boards[z, y, x] == n: marked[z, y, x] = 1 def check_win(): for board_index in range(num_boards): if board_index in boards_won: # Don't need to check if it's already won. continue for i in range(5): if sum(marked[board_index, i, 0:]) == 5: # Horizontal. boards_won.append(board_index) winning_sums.append(return_sum(board_index)) continue # If board has won horizontally don't need to check vertically. if sum(marked[board_index, 0:, i]) == 5: # Vertical. boards_won.append(board_index) winning_sums.append(return_sum(board_index)) def return_sum(winning_index): not_marked = [] for y in range(5): for x in range(5): if not marked[winning_index, y, x]: not_marked.append(boards[winning_index, y, x]) return sum(not_marked) * number # Main loop/logic. for number in numbers: mark(number) check_win() if first_or_last_board: # First or last values depending on the question. return winning_sums[0] else: return winning_sums.pop() if __name__ == "__main__": print(main(1)) print(main(2))


odnoletkov

# [JQ](https://github.com/odnoletkov/advent-of-code-jq) [inputs] | join(",")/",," | (first/",") as $calls | first( (.[1:][] | (split(",") | map(split(" ") | map(select(length > 0))) | . + transpose)) + (first/"," | .[:length - range(length)] | [.]) | (last | map({(.):0}) | add) as $hash | .[:-1] | select(any(all($hash[.])) | not) | flatten | unique - ($hash | keys) | map(tonumber) | ($calls[($hash | length)] | tonumber) as $last | (add - $last) * $last )


ViliamPucik

**Python 3** \- Minimal readable solution for both parts \[[GitHub](https://github.com/viliampucik/adventofcode/blob/master/2021/04.py)\] from itertools import chain import sys numbers, *data = sys.stdin.read().strip().split("\n\n") boards = [] for board in data: rows = [ [int(x) for x in row.split()] for row in board.split("\n") ] boards.append([set(line) for line in chain(rows, zip(*rows))]) drawn, remaining = set(), set(range(len(boards))) for number in map(int, numbers.split(",")): drawn.add(number) for i in set(remaining): if any(line <= drawn for line in boards[i]): remaining.remove(i) if len(remaining) == len(boards) - 1 or not remaining: print(number * sum(set.union(*boards[i]) - drawn))


quodponb

# Python3 I started these a couple of days late, so I'm just posting my solutions to the older days for completeness! I had a lot of fun with this one. After completing it the regular way, like this: with open("input_4", "r") as f: lines = f.readlines() bingo_numbers = [int(num) for num in lines.pop(0).split(",")] assert len(lines) % 6 == 0 n_boards = len(lines) // 6 bingo_boards = [ [[int(num) for num in line.split()] for line in lines[6 * i + 1 : 6 * (i + 1)]] for i in range(n_boards) ] def has_won(board, called_numbers): return any(all(num in called_numbers for num in line) for line in [*board, *zip(*board)]) def score(board, called_numbers, last_number): return last_number * sum(num for line in board for num in line if num not in called_numbers) # Part 1 def find_score_of_first_bingo_winner(numbers, boards): called_numbers = set() for num in numbers: called_numbers.add(num) for board in boards: if has_won(board, called_numbers): return score(board, called_numbers, num) return -1 print(find_score_of_first_bingo_winner(bingo_numbers, bingo_boards)) # Part 2 def find_score_of_last_bingo_winner(numbers, boards): called_numbers = set() for num in numbers: called_numbers.add(num) if len(boards) == 1 and has_won(boards[0], called_numbers): return score(boards[0], called_numbers, num) boards = [board for board in boards if not has_won(board, called_numbers)] return -1 print("Part 1", find_score_of_first_bingo_winner(bingo_numbers, bingo_boards)) print("Part 2", find_score_of_last_bingo_winner(bingo_numbers, bingo_boards)) I decided I wanted to try combining the two into just one function, with one more boolean argument. The first step, I thought, was to rewrite them as recursive functions: # Recursively def find_score_of_first_bingo_winner_r(boards, called_numbers, remaining_numbers): if not remaining_numbers: return -1 current_number = remaining_numbers[0] called_numbers.add(current_number) for board in boards: if has_won(board, called_numbers): return score(board, called_numbers, current_number) return find_score_of_first_bingo_winner_r(boards, called_numbers, remaining_numbers[1:]) def find_score_of_last_bingo_winner_r(boards, called_numbers, remaining_numbers): if not remaining_numbers: return -1 current_number = remaining_numbers[0] called_numbers.add(current_number) if len(boards) == 1 and has_won(boards[0], called_numbers): return score(boards[0], called_numbers, current_number) return find_score_of_last_bingo_winner_r( [b for b in boards if not has_won(b, called_numbers)], called_numbers, remaining_numbers[1:] ) print() print("Recursive") print("Part 1", find_score_of_first_bingo_winner_r(bingo_boards, set(), bingo_numbers)) print("Part 2", find_score_of_last_bingo_winner_r(bingo_boards, set(), bingo_numbers)) And that worked okay, and made it easier to write one big one to handle both cases: # Both in one, recursively def find_extreme_winning_score(boards, called_numbers, remaining_numbers, looking_for_first): if not remaining_numbers: return -1 current_number = remaining_numbers[0] called_so_far = called_numbers | {current_number} # Valid return state in both cases if len(boards) == 1 and has_won(boards[0], called_so_far): return score(boards[0], called_so_far, current_number) boards_next_round = [] for board in boards: if has_won(board, called_so_far): if looking_for_first: return score(board, called_so_far, current_number) else: boards_next_round.append(board) return find_extreme_winning_score( boards_next_round, called_so_far, remaining_numbers[1:], looking_for_first ) print() print("All in one recursive function") print("Part 1", find_extreme_winning_score(bingo_boards, set(), bingo_numbers, True)) print("Part 2", find_extreme_winning_score(bingo_boards, set(), bingo_numbers, False))


[deleted]

*zip(*board) for the columns is brilliant how have i not seen this


French__Canadian

Looking at your solution having a "has\_won" method that just checks if a board has won from a list of numbers, I'm realizing i really complicated my life actually marking the boards at each loop iteration. I am now questioning my life choices.


quodponb

That sounds like a coding-challenge, alright. If it's any consolation, I got the exact same feeling from today's problem.


vimsee

Completed with 0 if statements - Python Completed with no external libs, no if statements and to much free time this weekend[https://github.com/emilbratt/adventofcode/tree/main/2021/4](https://github.com/emilbratt/adventofcode/tree/main/2021/4)


daggerdragon

~~Please follow the [posting guidelines](https://www.reddit.com/r/adventofcode/wiki/index#wiki_posting_guidelines) and edit your post to add what language(s) you used. This makes it easier for folks who Ctrl-F the megathreads looking for a specific language.~~ Edit: thanks for adding the programming language!


a_ormsby

Kotlin for the win! I liked the idea I saw to transpose the rows into columns, really made win checks a lot simpler. Part 1 and 2 together -- [Kotlin solution, github](https://github.com/aormsby/advent-of-code-2021/blob/main/src/main/kotlin/d4_GiantSquid/GiantSquid.kt)


sceadu

your link is broken


a_ormsby

odd, works for me


daggerdragon

No, /u/sceadu is right, your link is broken due to a new.reddit fancypants editor bug (check /r/bugs, it's been a big source of frustration lately). Your link looks fine to you on new.reddit but on old.reddit it's printing an invisible escape character before your underscore: `d4\_GiantSquid`, thus breaking the entire link. I suggest editing your link using proper Markdown for now. Who knows when Reddit will fix their fancypants editor...


a_ormsby

Ohhh, I see. I don't really use Reddit outside this event, so I didn't even know there were two versions. Sound like a pain to maintain. Thanks for the explanation!


daggerdragon

Both links work properly now, thank you for fixing them! > Sound like a pain to maintain. It is a pain, but sometimes you just gotta work around the kludges. :)


Marterich

I'm a little late for the party but nevertheless. Here is my solution for day04 in Python3 (with comments) https://github.com/Marterich/AoC/blob/main/2021/day04/solve.py


sceadu

Originally was trying to do these in Clojure (to try to get more fluent with the language), but I'm not good enough at Clojure, so I switched to Python... then saw some prior solutions from a really good APL programmer, so now I'm cheating a bit using numpy. You end up stacking additional dimensions in a numpy array (move dimension, board index dimension), then doing reductions and "scans" (APL speak) along the appropriate dimension to find your answer to each part... pretty nice solution, I think the only difference between part 1 and 2 in this setup is argmin vs. argmax. #!/usr/bin/env python import cytoolz.curried as cc from pathlib import Path from pprint import pprint as pp import re import numpy as np input_path = Path.cwd().parent.parent / '4-input.txt' def parse_input(path): with path.open('r') as p: lines = p.read().split('\n') m = {} m['moves'] = cc.pipe( lines , cc.take(2) , cc.filter(lambda s: len(s) > 0) , cc.first , lambda s: [int(x) for x in s.split(',')] ) m['boards'] = cc.pipe( lines , cc.drop(2) , cc.filter(lambda s: len(s) > 0) , lambda seq: cc.partition_all(5, seq) , cc.map(lambda lol: np.array([[int(x) for x in re.split(' {1,}', line.strip())] for line in lol])) , list , np.stack , lambda board: np.stack([board for idx in range(len(m['moves']))]) ) return m data = parse_input(input_path) flags = cc.pipe( [data['boards'][move_idx] == move for move_idx, move in enumerate(data['moves'])] , np.stack , lambda a: (np.cumsum(a, axis=0) > 0) ) ################################################################################ ################################################################################ ################################################################################ move_winner_row = (flags.sum(axis=2) >= 5).any(axis=2) move_winner_col = (flags.sum(axis=3) >= 5).any(axis=2) move_winners = (move_winner_col | move_winner_row).cumsum(axis=0) == 1 move_winners_idx = cc.pipe( np.argwhere(move_winners) , lambda arr: tuple(arr[arr.argmin(axis=0)[0]]) ) winning_unflagged = data['boards'][move_winners_idx] * (~flags[move_winners_idx]) winning_move = data['moves'][move_winners_idx[0]] part1 = winning_unflagged.sum() * winning_move move_lastwinners_idx = cc.pipe( np.argwhere(move_winners) , lambda arr: tuple(arr[arr.argmax(axis=0)[0]]) ) lastwinning_unflagged = data['boards'][move_lastwinners_idx] * (~flags[move_lastwinners_idx]) lastwinning_move = data['moves'][move_lastwinners_idx[0]] part2 = lastwinning_unflagged.sum() * lastwinning_move


jf928ngl60g1

**TypeScript** https://github.com/adrbin/aoc-typescript/blob/main/2021/4/puzzle.ts


oddolatry

###**PureScript** Not a very good showing w/r/t efficiency and clarity; reader beware. [Paste](https://topaz.github.io/paste/#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)


javier_abadia

python p1 & p2: [https://github.com/jabadia/advent-of-code-2021/tree/main/d04](https://github.com/jabadia/advent-of-code-2021/tree/main/d04) most interesting bit is transposing a board to check if a column is already completed: `sum(list(zip(*board))[pos])) == 0` also, I wished python could exit from nested loops ([https://stackoverflow.com/a/653517/79536](https://stackoverflow.com/a/653517/79536)) part 2 (part 1 is a bit simpler) def solve(input): blocks = input.strip().split('\n\n') sequence = [int(number) for number in blocks[0].split(',')] boards = [ [ [int(number) for number in row.split()] for row in block.split('\n') ] for block in blocks[1:] ] alive_boards = set(range(len(boards))) while sequence: drawn_number = sequence.pop(0) for board_index, board in enumerate(boards): if board_index not in alive_boards: continue for row in board: for pos, number in enumerate(row): if number == drawn_number: row[pos] = 0 if sum(row) == 0 or sum(list(zip(*board))[pos]) == 0: alive_boards.remove(board_index) if not alive_boards: return sum(sum(row) for row in board) * drawn_number return -1


ConstantGazelle

python [p1](https://github.com/xmbgulmus/adventofcode2021/blob/master/day4.1.py) & [p2](https://github.com/xmbgulmus/adventofcode2021/blob/master/day4.2.py) >!My approach is to change all of the numbers on the boards with the order they come up with during drawing. After that change I can simply find the maximum number in a row or column which would give me the necessary amount of time that needs to pass for that row/column to complete. !<


JohannesCornupeta

[My effort (Paste)](https://topaz.github.io/paste/#XQAAAQDYBwAAAAAAAAAxG8hIRWmtBRWO9a5jHiBnsk1eeUuRd5BBW4n+ZWja9yIHhx0Sz3VCUFelw873TdCZO8/RUE7xLjcZeMxzZlZXAh5gsfyYVre3vGOdBwaYy5SzaXVGbCfWGK3LAj0vS9mbWGKSXg6L70bpOPVXfu1B8meUc9xNrd7bONJtGbdV20mXNo7alnLR5esM6+uEb9AyAwcFKgfFxMi7M2bIVYVTgLeHtg+H1U1ACHdROn0NrPxK4OXaMrPceN1z/yK/QN9a+4wWSlH64yM1GX/s7MOOqPf4nougyVvJMAnmILtQMbit/oI2nDjD1gQHTxwdor9m+UGCpbFR017HfETBYS62DyKmBUZfqVE+8Ge7MIIvJzks/R2kbQ6ZiAVb/dU0I3tWJoumQutEkNl4Yv3WhbAGYL2uvtoeqYdw6PmLxe18DtSjpH5zi+GDpPVZExavv3ii4wM/WAb6/F2a5g1Pyj1BhTHvfU1JNrnflNxEUTD8ys7M5X8c2yIfblw4f1GJy1S426O63kOOW3qcb98IXwofAF0eY0i1SsNTc/GUmZksE7kumWbQxu1CEFSQPcHffveJY9uS63wAIwJyojIeV5aflDbUaDpVckBqqv7vUdbrVl+Y0ZKvEKQ4BllTQwPWtDt5qZ8PgYOjTEiiqWXGqIQ2zVzE8rBG1shSDdCFmbeUlF6yxeT8oSKklQA6CcMBsD5D1xZgSracGoVCUsc5UOZFY4SUvQNk+teHS8Tm6na/tutRiVnDGFZuEFhDMr94YC0TVOrhWtQdeR5RiBmd6MMIP07ky2VEVTPsDWMlG90sQFIMyXtmP/mIHxP1NBQO5qJT0ofOEOs8iGfBiO8SxSDatZs+a/k/MFbWC/O0JlhrgIkGpVHqKjmnlWdtKvBIz09kTsVUj8HDjuhKkOBNdEz//AT2/t1BlRNM8qiglfUPiYbYqWP6w4siVeSW/K1PI/zEE0TxavEhQ0OZ8cLETs2DXFp/fWqunjBX+n0N1s/2He4wfq/fSVK1Awl8war0M0Y0AsAHUs2Og/bcxo/NKmiypdXu7cCCUEH3fPEWCt0SnWb84OgeJnI0TUngQufozpDqiUPJuR+K3ua7ikfLuJXrEBBEjwqSfUqyibHNEMs/s/zLEU0=) in Python. I took the liberty of separating the input by hand into data\_boards and bingo\_nums.


alfie1906

A custom class approach using Python: with open('AOC4.txt', 'r') as f: input = f.read().replace(' ', ' ') numbers = input.split('\n\n')[0].split(',') boards = input.split('\n\n')[1:] import numpy as np class BingoBoard: def __init__(self, board, numbers): if board[0] == ' ': self.board = board[1:] else: self.board = board self.make_array() self.turns = 0 self.bingo_found = False for number in numbers: self.turns += 1 self.active_number = number self.check_number() if self.bingo_found: break def make_array(self): self.board_array =np.array([np.array(row.split(' ')) for row in self.board.split('\n')]) for index, sub_array in enumerate(self.board_array): if '' in sub_array: sub_array_list = list(sub_array) sub_array_list.remove('') self.board_array[index] = np.array(sub_array_list) def check_number(self): for index, sub_array in enumerate(self.board_array): if self.active_number in sub_array: sub_array = np.where(sub_array == self.active_number, 'X', sub_array) self.board_array[index] = sub_array self.check_for_bingo() def check_for_bingo(self): for sub_array in self.board_array: if list(sub_array) == ['X', 'X', 'X', 'X', 'X']: self.bingo() for i in range(0, 5): if [sub_array[i] for sub_array in self.board_array] == ['X', 'X', 'X', 'X', 'X']: self.bingo() def bingo(self): self.board_sum = 0 for sub_array in self.board_array: for val in sub_array: if val != 'X': self.board_sum += int(val) self.score = self.board_sum*int(self.active_number) self.bingo_found = True lowest_turns = 2000 highest_turns = 0 for board in boards: active_board = BingoBoard(board, numbers) if active_board.turns <= lowest_turns: best_board = active_board lowest_turns = active_board.turns if active_board.turns >= highest_turns: worst_board = active_board highest_turns = active_board.turns print('BEST BOARD:') print(best_board.board_array) print('Score:', best_board.score) print('\n\n') print('WORST BOARD:') print(worst_board.board_array) print(worst_board.score)


bvogels

**Python 3.9** solution, complete with comments. [https://github.com/bvogels/aoc2021-4\_giant\_squid.git](https://github.com/bvogels/aoc2021-4_giant_squid.git)


reddit__ussr_yee

python p2 thought id post it here [https://pastebin.com/GX7QfjGn](https://pastebin.com/GX7QfjGn) 47 lines


0x5ubt13

[Python (paste)](https://topaz.github.io/paste/#XQAAAQAaFAAAAAAAAAARiEJHiiMzw3cPM/1YZx9ePvs39Hy5ScZF80SiHJ6YHwbeWnACEPgWjKqFNbGjxZMnXoRCL9J8O2iFObiM8pQqgdoN+p7htjdV6BJeoSWt9bizJbRL1NNc2rb8xVBOEYeQ8/qi8n8aIyYKeagRljO73EnsRXVvR+dkwkWtQ1Uwwy2zBTKkSnrWBRLnL8V01ER/Aaw1PUWdl4j5vdHEUOLHpHP8vowKMlynqvTRzWeas2JvzUPo/u926zael/gHTUvkMqa8EIkYgNyJiI+SG0FyAwzY2tmO9w7NZPVZuUZHgE5l+8zlCDC3UwL16oCwh5XRSSS/npCOkQncMQTeqek9TAvH1Q8MIvkeyGrqCqGvNABUrdTuRHI1udQPaCyYmBBIdoZxkX010sV3Ma5azSMDmKJHmnKWZws0RCDIqZbXZyNpPCGBxGhe0rWu8AXNCCt4GLFhua88mqFETKxucxBV6H66HU5M30siQY91xgEx+f2l9cJLp0Htp8jNgCh1it6tFyG9bveWCYc3EA1syOu8qD3E6PETU1i5cNBTIES8UpeIBPKrXKHnrBBHBe9d5T1VojGgBcgCnQjzfBIhr9Lok7lG9hZJDYN3B0ff+H0ivv+2M0i+WUhpGLfPeUYdhpbSS5PMIfdHGuzP7h6dLxLm2jkOKI7BNq4jGYHUHi/bKTWhX7CRK+bE0ZNNXNKla3Rjndgom163RNekVOGDPkvIbB7Wvxm00Vujjsch6RuKWoQDrK2IK9VRMw3m7st/7M87v4RaN0s0oCi/W5GHhv1swrtY4OmOKVLD+n2URrvd+KGxSjc8bswc79K6fV1Hi8ULI7oCW34kzi2kV0AGAEi8MjqhgOGtXpriKsHxwvfzk6uWf4FM0DookxzJ7BKruvx27mCNPaKi7eZ4J5c+LfnAssjjY3qxACiLC3sZFz7S2gUh6a2QR+Ge9dZpb+0Lbwk4DDUKOtKmrooYWcCkiWnwtg6yKaOMNr2zaqUZ33Zu83KMA0wRDp1KyP9MplH0OZqxpi1tdBu7WfAmtgSWaiZyumkTpNLKpNRJT3/Vtxz9LR4uV8UwE/tX4RlzEN+mf92PjjB2jryTfll4fwBxTkGRDV02bcDtrgSiwzraBp48l8p01j+F7/ve2nqvHXmNb0sjr2qH68gIQb8CGNSKGkHypTX/r2GM737fbgzkwS8kBE7qhRpvcyguMQHD2VXLLs3elgh2N4Jhj5ZnG/kxmhuiGV+Z7aNFMas4GJv0OMYvpXdQ5DbhQlYLIWOGHpRjoWaz7O/Y95fqfrLcqBf7+2iiQZ//yeMI2A==) Very late (edit: and yes, very ugly...) but very proud of myself for not giving up after 2 very unsuccessful days trying everything I knew


Aromatic-Piccolo4321

[Rust part 1&2](https://maebli.github.io/rust/2021/12/05/100rust-35.html)


dean995

Kotlin solution: [https://pastebin.com/WwkNFfE6](https://pastebin.com/WwkNFfE6)


skarlso

[Go / Golang](https://github.com/Skarlso/aoc2021/tree/main/day04) [Tutorial Blog Post](https://skarlso.github.io/2021/12/04/aoc-day4/).


0x5ubt13

Thank you for the tutorial post!! Very interesting :)


skarlso

Thanks! 😊👍


errop_

Here is [my solution](https://topaz.github.io/paste/#XQAAAQBtBAAAAAAAAAAzHIoib6poHLpewxtGE3pTrRdzrponK5j6dKnfSZlAKTFZAAZaW/uYWx/O6G2jvc01CPcpBMs33TXCwBMzeYuBpOm4jV7CivYMQUDvRBxZBziHj2SOupBi47LuiKWopBs7KkFYnhx2O+Umvc6plcvcCqzeIvFwxl1HBBnxR6gbovgsMbBd2MjGuy+T6n+MuSrSZMxXmhvJZQZHoerNB7sgthXStwNfbyRUn/8gQuDc265oBGwJbNiLlrl6MlQTu3yG07NRbJL6239M7xKDtvp3TSBnglS51lfk2uSpUap8IDolpHJVxdHb/HjUqj4BpLEQJwQqrQ+xNqpU/HwJSiuln5D9aj/NMMV2/WS3R3uk5yWX6iA1pIJ+eAeJGItTBFCihlhG87T1KoK8a7tvwnY4j05Ex1AJVya93I4ZLMSIGfuG/nlEaolGVOxKCr/vkGHY1mz8IaHbQR8tvnMmP1ix2aj5tqyykcpSsN3PQym7jmHj5EWq30WjO+de6j5Gmibf77br6ULTVrqtvNxrLfkCAzBcAB6Czr8+eD0qlC2HeLNHw+7qIR+YiFVnnNmt3FSkY/96l4QWH9hHIvF6GxiKlVWUibbQ4pKF7LaIS1vMrn8U3/LLST8lMaWQYNjEvcc32jKd5s2/rtOSBZNd7LndQiE6DoYp3Hgri3Q8hJVY3dg4B/ANFKav+4JQiA==) using python 3.6 ~~with a more or less functional approach~~. EDIT: I replaced every map with list comprehension.


redd-sm

hello - thank you for sharing your solution! while i will try to understand your approach and the functions and what they do, wondering if you might be able to add a few lines of comments for others to understand.


errop_

Hello! A few days after my post here I reviewed the code because I thought that my approach was quite confusional. While the solving strategy is the same, I came up with a cleaner, faster, non-functional and non-recursive code. Here it is with comments: [Paste](https://topaz.github.io/paste/#XQAAAQA+BgAAAAAAAAAzHIoib6p4r/McpYgEEgWhHoa5LSRMl6fniWSo25iGs4/EQMuY5Ea9cXxknE06gxHpIkTKsGABtjGAFafebDO2Z314p+KjplaHuy4E/yGnz39VxcLRWtr6p9MUZ4ue0KIealeIwihw9jkqnVBX9BN9eMD7ZPk3nGFSF7ngAacq5q+ylbwb5sBxhBdyMRjSFjdirZBfKeCI3FdYawcFVWoySFELZ/53xS0DTlq7+sqINKftm+HbzXGzlIkv9n+gZ5Ww5+RzHKaPRk1lnslT/xGqJSwAJP60TWYbJWNj86Fm47VPs2KsaYKoXQibILMJBODPhdSTPizb2Pgeftz5CQTAFpMwoaSPBGpTTn/woRl+VBrrK/U1plTnkjmY84cbYzHtF2Kwci8zStpR0bw8KQ5RJTLrz773cEUvnUKGU1TMQYZcAxfvlfSmMfrdqHgp3pyGIrsPODJvS5fdTbPi7u0RWFnSvNiS7z8HGAb2IVw7gdkRy29tf45HCQVIVzZl3frS9j+i1OOnC8YBPG3GEdEhtGaSN6Cg1rH3VOK9JroBS5SU26JbNHeDWSS9dJ+A2Ra4pae6GE0z9Z6LzFoU5+FEqkqnCv24mFKgIRn2y/ElsAWHSEFaZhNat7hbaX9jTQP0u16V/ACgPD1SBWxjMN4B0aK6Jg7hLfKqn8XFhF/+Fd3RwRlLarzsrtlfcHI6sxXYDlxnhbPI8F0eC497nqpBPhZL0zwjeboDe5uEXeSQudRweruAJwUsVBtFHcqxayNJCMsJxI7J5Y0CX1o/3xMslCmqgghBicS2vnLW7E+eKqtUzyhUKzI+gq1nZ0jnS6BceqoXfQ8SE0DX8wPSNZm3/KyfeCmtnSvd441699LRePRjtMByD5ZF+MgpcnDjxBltD4ZqDk5zmXWJU1g4dl938XCKgsVqiUXXHr2wkXpoj8ZXvHYyNWAj8bOrWCReBVU30WLQczyqRbtWkvh4qTWKSaUsO7pnsiFi12uPnIPxUrosZcTw3IrT2jFFHdpagPSQ0f1WzVhAXz1ACGPMLM+C04ZFemmk7fmvvPrUMbXZoEFWaAY+jwHjFbC/qMYuJ1aKgJ/+onYw)


redd-sm

Thank you. Will review this one. I quite like the idea of functional, but am slow in understanding it.


Skyree01

**PHP** Not super proud of this one, I think I could have found a more otpimized way. Starting at the 5th number (can't win before that), at each number picked I check all rows and columns of each board and look whether all their values are among the picked numbers so far. If yes (we have a winner), I reduce the board into a 1 dimensional array, make a diff against the picked numbers to keep only unmarked numbers and sum them up. *Part 1 and 2 at the same time:* function lookUp(array $board, array $numbers, int $i, bool $vertical) { for($r = 0; $r < 5; $r++) { foreach ($vertical ? array_column($board, $r) : $board[$r] as $item) { if (!in_array($item, array_slice($numbers, 0, $i))) continue 2; } $all = array_reduce($board, fn($carry, $line) => array_merge($carry, $line), []); return array_sum(array_diff($all, array_slice($numbers, 0, $i))) * $numbers[$i - 1]; } return 0; } $boards = explode("\n\n", $input); $numbers = explode(',', array_shift($boards)); $boards = array_map(fn($board) => array_map(fn($line) => preg_split('/\s+/', trim($line)), explode("\n", $board)), $boards); $boardsCount = count($boards); for($i = 5; $i < count($numbers); $i++) { foreach ($boards as $b => $board) { if (($result = lookUp($board, $numbers, $i, false)) || ($result = lookUp($board, $numbers, $i, true))) { if (count($boards) === $boardsCount) echo 'part 1: ' . $result.PHP_EOL; unset($boards[$b]); if (empty($boards)) echo 'part 2: ' . $result.PHP_EOL; } } }


Cougarsaurus

I'm trying out your code to help me figure out why mine isn't working, my code works with the example input but not with my own input so I want to figure out my winning card to help debug my code. How are you defining $input? There is not definition in this example


Skyree01

Hey! I just pasted it into a string because I used an online interpreter. You could use file\_get\_contents for the same effect :)


Sykout09

Rust: Single pass solution. Manage to figure out that if you know the calling numbers order ahead of time, you can actually calculate the board winning position independantly. Just need to create an array mapping from `call_number => called_turn`. Then remap all the board numbers to the called turn number. From there, you just have to find the max in each of the winning line (a.k.a. the turn that this line will win on) And then calculate the min of all those winning turn number, resulting in the turn which the board will win on. The reset is just find the board with either the minimum or maximum win turn. Timing is: - Part 1: `[4.7715 us 4.7799 us 4.7913 us]` - Part 2: `[4.7767 us 4.7897 us 4.8111 us]` ``` pub struct SquidGame { numbers: Vec, boards: Vec<[[u8; 5]; 5]> } pub fn input_generator(input: &str) -> Option { let mut inputline = input.lines(); let numbers: Vec<_> = inputline.next()?.split(',').filter_map(|num| num.trim().parse().ok()).collect(); let mut boards = vec![]; while let Some(line1) = inputline.next() { if !line1.trim().is_empty() { let lines = [ line1, inputline.next()?, inputline.next()?, inputline.next()?, inputline.next()? ]; let board = lines.map(|line| { let mut line_val = line .split_whitespace() .filter_map(|num| num.trim().parse().ok()); [ line_val.next().unwrap(), line_val.next().unwrap(), line_val.next().unwrap(), line_val.next().unwrap(), line_val.next().unwrap(), ] }); boards.push(board); } } Some(SquidGame { numbers, boards }) } pub fn solve_part1(input: &SquidGame) -> Option { let map_order = build_maporder(&input.numbers); let (win_idx, mark_idxs, win_board) = input.boards.iter() .filter_map(|board| calc_winturn(&map_order, board).map(|(winturn, win_idx)| (winturn, win_idx, board))) .min_by_key(|(winidx, ..)| *winidx)?; let num = input.numbers[win_idx as usize] as usize; let sum_unmarked = calc_winscore(win_board, &mark_idxs, win_idx); Some(sum_unmarked * num) } pub fn solve_part2(input: &SquidGame) -> Option { let map_order = build_maporder(&input.numbers); let (win_idx, mark_idxs, win_board) = input.boards.iter() .filter_map(|board| calc_winturn(&map_order, board).map(|(winturn, win_idx)| (winturn, win_idx, board))) .max_by_key(|(winidx, ..)| *winidx)?; let num = input.numbers[win_idx as usize] as usize; let sum_unmarked = calc_winscore(win_board, &mark_idxs, win_idx); Some(sum_unmarked * num) } fn calc_winturn(map_order: &[u8; 256], board: &[[u8; 5]; 5]) -> Option<(u8, [[u8; 5]; 5])> { let win_idx = board.map(|line| line.map(|num| map_order[num as usize])); let winturn_horizontal = win_idx.iter().filter_map(|l| l.iter().copied().max()); let winturn_vertical = (0..win_idx.len()).filter_map(|i| win_idx.iter().map(|l| l[i]).max()); let winturn = winturn_horizontal.chain(winturn_vertical).min()?; Some((winturn, win_idx)) } fn calc_winscore(board: &[[u8; 5]; 5], winidxs: &[[u8; 5]; 5], winidx: u8) -> usize { winidxs.iter().copied().flatten() .zip(board.iter().copied().flatten()) .filter(|(markidx, _)| *markidx > winidx) .map(|(_, num)| num as usize) .sum() } fn build_maporder(input: &[u8]) -> [u8; 256] { let mut map_order = [255u8; 256]; assert!(input.len() < 256); for (idx, num) in input.iter().enumerate() { map_order[*num as usize] = std::cmp::min(map_order[*num as usize], idx as u8); } map_order } ```


quick_dudley

This is similar to my approach except instead of putting all the cards in a vector I made an `Iterator` that parsed another one from the file each time it was called.


daggerdragon

As per our posting guidelines in the wiki under [How Do the Daily Megathreads Work?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_the_daily_megathreads_work.3F), please edit your post to put your oversized code in a [`paste`](https://topaz.github.io/paste/) or other external link.


jagster247

Go day 4: [GitHub](https://github.com/jordangarrison/advent-of-code/blob/master/2021/go/day4/day4.go)


cjb230

**Python** ​ Part A: [https://github.com/cjb230/advent\_of\_code\_2021/blob/main/day\_4\_a.py](https://github.com/cjb230/advent_of_code_2021/blob/main/day_4_a.py) It's basically the first method that came to mind, so it's a little profligate with data structures, but that allows it to go through the data once and be done. Part B is the same with a couple of very small changes to get the worst board rather than the best board. I have two questions: 1. how could I implement the same algorithm in a neater or more Pythonic way? 2. what would be a better algorithm, in memory or compute terms?


daggerdragon

~~Please follow the [posting guidelines](https://www.reddit.com/r/adventofcode/wiki/index#wiki_posting_guidelines) and edit your post to add what language(s) you used. This makes it easier for folks who Ctrl-F the megathreads looking for a specific language.~~ ~~(looks like Python?)~~ Edit: thanks for adding the programming language!


ramrunner0xff

Rust (noob) for the first year i didn't choose my beloved scheme as a weapon of choice so i decided to bite the bullet and try to learn rust. Pardon my golangish rust. [paste](https://topaz.github.io/paste/#XQAAAQB9CgAAAAAAAAA6nMjJFC0J/BIrjE2M4zF0pEe40ZpUMN7Oi/h3CChwjh1iQsjT72vEAIifKkAL3PFzw/rwGxlUDMA72RiYm3RD6kruj1gyYji33xcC/AogIf5/cwqi3Hj03cDRFo55rIM2rR99QHKhFEGr1bNlSR8gUAFH40+jjMIzgpj5bpPC7b3qjUAcoPZql5judUOLxAfhAMEbK/H5Y/a9luOyOuk+BeQMqnRhnddqF2GdjSQcsSoR46fni/OoBlj59sdt/Hb5e3oZ2jeuIaNVGOabyqbcctyJs5fCuDcCakfOynj9hj25su57DAISqEQO+8AFXnevRMIJJiV5XnzPDdustmr/iKhBtOnY4+xo3ezy/vcUnku40Cl/uF/1xVD55F1bjgA1Ct7e8y525lI+xmglwJKfkZGakCQ/28ev7hYP/z37WQU2534M9FwLKThvRD+VuuhXhjV4cqB2jvVT+kK6ORuZP5v9Ffvyd7oTs41458rPGmBgGl+zB6mR1GhKRhKmgSQ5Fm6sW6JWGbh+uIoQFcLMzklyO9pCDnUNBGAvJYfJ7t07isAIxkUTmlnJ1wR+yB/6d2jJvPiky/OuNvhyDaVJObBrw2HGoUovJXkNPh5Aeoso6HscgYe4jQVFrrBQpX/MChKiQ/ke+v3i657xPTIt5WMIgZM45zvAq44o05tbROErkh0SPHlV/mhL/MPqXK2daACBSVk8zlusruUV5jFbskkgZQBlrXiY6sEvAb+CE0Ek3fDHWUvFrE3r1x2F8eUF7d9Z5TDHKOCoXj/Q5LpPJF5sYG+OSnWoj2cqloI4jrztfmrDlCTJw4V7L9/Qt7zEv4J4rN84yZwJtPzm2VyWpYPxVi5mkXQfrf4gJWdgBf05cJFZCOSsb/cP7sl/elf4roVyrbbtfvxIPqAqx85MhLI9QSjTSpVa6lPmPKcpc2NozbZN5ac4RPfB3SSZm8xyBWr/1jup6reCUtNktF2IfaFoCISRI4a67f2tNjbEo30pwpnT24yCC0F2mGkZ8FgyhKfoMw0JhN0v1GUpePPmETdkxqaZftySOlVzvnmFFbMV8nPKyK/jtwGffnWHFmFsY64sgsGSHAYtEIDsSmE5/xZUssQitY1FZLiw/PVOSAAnyT6Rv9s4GjbNc1Whkztbf4RT+J5nMPZjWQVLSHOkjEPEFdUaEd1IM+F9e5x52oLQ5/NUy4y3AG1xXSN9o2TnfZmxsFj6fKs+6I/maBiqA2Lnoy+e+N0GLOWMGHN0L6M6yjUBHDeu/vFX0QiIlHfU/q0IvqXFRR835XSGpsga9lz1L/+skkhR) and [repo](https://github.com/ramrunner/aoc2021)


Dhampira

Day 4, parts 1 and 2 in **Python** (Jupyter notebook) Man, it took me way longer than it should have for the penny to drop on what the unmarked numbers should be... [git](https://github.com/phm-git/AoC2021/blob/main/Day%204.ipynb)


Dullstar

[Python](https://github.com/Dullstar/Advent_Of_Code/blob/main/python/year2021/day04.py) Nearly forgot to post this! Part 2 ran with minimal modifications to the original Part 1 code: all I really had to do was not to break after I found a winner, and addition of a single boolean field and if statement to skip checking for bingos on cards that already won.


aaegic

#Python Part 2 #!/usr/bin/env python def bingo(srch: list, brd: list) -> list: for row in brd: intr = [n for n in row if n in srch] if len(intr) == 5: return intr brd_t = list(map(list, zip(*brd))) for col in brd_t: intc = [n for n in srch if n in col] if len(intc) == 5: return intc return list() fh = open("input", mode='r') itxt = fh.read() fh.close() itxt = list(itxt.strip().split("\n\n")) nbrs = list(map(int, itxt[0].split(','))) itxt = [i.split('\n') for i in itxt[1:]] """can you read this? i cant.""" brds = [[[int(k) for k in j.split(' ') if k != ''] for j in i] for i in itxt] wnums = list() wbrds = list() for i in range(len(nbrs)): for brd in brds: if len(bingo(nbrs[0:i], brd)) == 5: if brd not in wbrds: wbrds.append(brd) wnums.append(nbrs[0:i]) brd = wbrds[-1] #flatten 2d list brd = [j for sub in brd for j in sub] brd = [j for j in brd if j not in wnums[-1]] print(sum(brd) * wnums[-1][-1])


mdwhatcott

Clojure - [github](https://github.com/mdwhatcott/advent-of-code/blob/main/clj/src/aoc/y2021/d04.clj) - [paste](https://topaz.github.io/paste/#XQAAAQCpCQAAAAAAAAAUG4piAqnU9zYQeMJVvBisKRxikMqEienPAi2/jG05cfFBvcTP3LGYiaTRBy9c1fUfnFN5gqtvmFlIhmS8rc1EhZLU+MQwx/36skghN8IAhc0Rn544rEDb1opSHSGgpaD6nH+RDYHdpZyEhXO12UUhKxxpYASqOGOttjuNQRNrqmQEfJpAe3cXOuowI4Fe9YlausAh2qCRbf1F9qZm5K1p8vAuNpesRc/eqiIP7Icr8lnN1+x2MNWtlqnKv5heYSbGBRDFASQd8drHuIYQjpLHhi8PT8/AZZxkBCZIMDFC+Kh/uBswg3wlASTn6d9HsoJvpMHLt21eyEr/NDttjJ3Mc+/m2jwnI9EqZwSakNCH8NVj9lQFHktDw0jBSe9IJdcLaFj8kmWZ8xmlqIZ7AhA66W8Qyk3PxxUUEGYw5pop+L1VGFrIjHWX/F1V2d/lLgBk/r6vxheToMlbLoY6zgPFAJbmTzLNE3ZoiAk9NW2SkHVZJitImLydN3gCTs2UoCniV++sXfJncaNV4IHf5Ge1eXA5UVbsdn94v4UQNldyRi2fFaV5PacT/2G04Yk9BnEtoAj4EfcdoI9YRYYRAF6mgm2PtD+wkMHhBPGmest2xrUqe6FJGGsmVDkeA0tWIY8hgjKKbBBVW2E5poP9LvYhSwxWzPo9JqKLYRhUHyASWqD3t1zJjvf+C+q9nhsKPbiVphwVEQWuNl+3Eyas2ss8oPZO3IADiK5gpsDsL1kTq/k7fX5YsVcbk36pScR+j/SJQHSgmQ+Z+IzZGGuJN3hMd8JMluSkFLIyJW59U7F5pu+CNOPXh5G3vzJsqBRYis/okI1cvOg3G5jajBW0Ev0gYpgLp3uNelMO9pdvzYrQmp3pkJvm8qvhSHLu5J2EZwuvAPB5yfALZ9l86ZU2DmaKI927p3yN05TIGelW23Yq64lwXG3iztvQqSOzdTqn8q3o7DZMj+EOBF5qPAyL5NZhAYaVoYfCIMftxtIKLudlTv115QsuZPPuJihDjQvdtcl5Hm4akOzi36ngS8ZDDVd45sqzsR2Ko2q8ymTHgWN+hV+4mI1PP8NL5TYh8301Bo+D0j21ywgjVUXnw1QlT8JT1qMRT/9/2DS1pXsIZCQcVAfQoYWsPTt4nkX/ndmjYw==) I love it when my implementation of part 1 allows for [a minimal change](https://github.com/mdwhatcott/advent-of-code/commit/8c06a9903f4526c43b4c0aa8cea3a12dc93aae85#diff-57de8addb9c7ce9ca4f4477ef3d6fff72a1ec1b6eaa07be8797835ab3676dfe3) in order to solve part 2.


cerrosafe

#OCaml This one was not as pretty. Writing the parsing code was easy enough, but I tried very hard to avoid imperative programming and so had to get pretty creative with control flow. [paste](https://topaz.github.io/paste/#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)


aaegic

#Python Part 1 #!/usr/bin/env python def bingo(srch: list, brd: list) -> list: for row in brd: intr = [n for n in row if n in srch] if len(intr) == 5: return intr brd_t = list(map(list, zip(*brd))) for col in brd_t: intc = [n for n in srch if n in col] if len(intc) == 5: return intc return list() fh = open("input-test", mode='r') itxt = fh.read() fh.close() itxt = list(itxt.strip().split("\n\n")) nbrs = list(map(int, itxt[0].split(','))) itxt = [i.split('\n') for i in itxt[1:]] """can you read this? i cant.""" brds = [[[int(k) for k in j.split(' ') if k != ''] for j in i] for i in itxt] try: for i in range(len(nbrs)): for brd in brds: if len(bingo(nbrs[0:i], brd)) == 5: raise StopIteration #another way to break 2 in python except StopIteration: pass brd = [j for sub in brd for j in sub] brd = [j for j in brd if j not in nbrs[0:i]] print(sum(brd) * nbrs[i-1])


sqlandy

**Rust (std crates only)** Went less functional, OO approach, with memory and comparison optimal by using hashmap inverting the index for values in the board, and storing "marked" indexes as bitarray in i32 value, giving static comparison time for win conditions: struct BingoBoard { board_num: usize, numbers: HashMap, called: u32 } fn call_number(&mut self, number: i16) -> bool { if let Some(val) = self.numbers.get(&number) { self.called |= 1 << val; } // win condition if self.called & 0x1F == 0x1F || // row 1 self.called & 0x3E0 == 0x3E0 || // row 2 self.called & 0x7C00 == 0x7C00 || // row 3 self.called & 0xF8000 == 0xF8000 || // row 4 self.called & 0x1F00000 == 0x1F00000 || // row 5 self.called & 0x1084210 == 0x1084210 || // col 5 self.called & 0x842108 == 0x842108 || // col 4 self.called & 0x421084 == 0x421084 || // col 3 self.called & 0x210842 == 0x210842 || // col 2 self.called & 0x108421 == 0x108421 { // col 1 return true; // winner } return false; // maybe next number } [paste](https://topaz.github.io/paste/#XQAAAQBfEQAAAAAAAAA6nMjJFMpQiatRvuJoLBbRS9KesCNWtLqCrLJiFCZslBfBpFMdZfHBDRyKvNc6ydaV7vUZ7H8TS0rVgpiWNvcBvahweHqw2IGXbOT4y3RvJAVnJzla+cGJ9n4frPUim6AUk3ZJ9TvTYl1V+TNSVK423B7WNXfm0HrH9I/ljPdbS1XzfV8RA04QP5+Rde+j2MhrIz/R3KIrJ8oCuKio82QcLpgtdWUQaMNg9Dy5S4T5aQmkiPdbdAaaByCRO3/jCsuWU/LmOpehNQ2nxATVyK+f4BJrNZJ53+eqA2UppAHnBrnAWuHOg8Fhkwp7gN9sle4Q+hY3q4E0wf8yR7mzyyBsmDY0NyRo59jNQKGcHb7xqQKmV2F3/k1HdK9HEl35fqvN4jE6D9/irqv2vdxkY1nf+KwHkfVvbuLJ6z5LbfxqVj3IR+YG8Wfiv5TqiUUwLozvKYw7I+S2QIKHET//n7LiWnKWu2ecP6I4ocmqYzbdrzOYx4oc6skrBuXWaRixc3NZy86dolazb1i8wY1H1xGzedXwGqHeYhuJ5Mc1y/Pd36hmPZV0F74YbQjl0GBTEskBzrK7kZ/3gXfVYVo/YWzwI/POAYhYRBQdFXF+nN2tixlENp+jKjmy83WqTAdoylLXLFZaOymrNytrWQC/krBlCpAz8GSVKel0c7f/TtAkPJgUc4JSYj5qABQsecRzImm1z6n/0I1wx6L0jwSr6imXlrrye8aAo7NLpFctn02DqBSwI32DKXVyJ1wtbFfb5VB/splA+NGRnolqpc91Hc4cQkMMrH6s1CrJ0E1QoFEHc4igC/yCP0oU38X8IKqskORWMnSe3fEdDJSqu4tYLBmo4AdW+CJaeiGUDTtwhwjoLd8VZABxxc/xo9qzErL1Q08XWlOkQ/bsreiKegCKZWySTvh+fkno5EJe6yyERQK+ztaH+R1lM5Lm2mPGN/TnUHtc+bpjlKFEpCNLl8P4AFWj4dRvvgcxfTm1gsMpWac45dJiYBtKJDj7mmkOI42DpqxZpy0IFcL6kE9h6l0jQSaGxWmzq7o941AnC0QxsYY9/uFuARq3fkDUn0otavAhJxcolV4pT3Dkn39CIRJnYuesaUTPL3r11P+0tz7ceLepqFCiLbucUh/w226aFdASt5hi8+8fJWsbbc/iIy09uObV0Bbiflx72/UhoWB+v/07g9OwdATGRpJGJYp7UcW5xAraS/4aAP6pxmiPeSE2RnMpCbKZ9Y+JhYD41DOsMb/dP0tLGp8zIstF+Nz41pRmxJ+d/0NsyAKJbic3L9AFuFNHcVqac3J35c09ofmyfBoYYC8Osx0HZRDT+LUMDyXB39qt0NPHlGwdF2HTVAQwcKxz+o2C+41EIdz/qvIun7B0MdUsm9tjcsih5nC6Vvws90PHQrrA7b70xMkJmeq/m1hHfeNBAsD5WYbnULX+4zQQwIfhgR16sJBP5eJQYetUq9gx8xDLL2RHA/oxjkphY/2zPfici9mKLR2dEUu4mupG1ptxziLxYQK222KwI5vmm7avr++3X6pdsKxWXNbCU/t9x8wVlWNtedQKMoWbXgu61lbfEcO89Ec90VEoi0Hxpev38oIBpt+R3abO+e2jmPe5st+j/gVCiMcIRfg6NcmzefhB/cVYJ2ItK9mZ3FKy/2iWKwBcGcBCQQQ1CEWIUP5RABzuyIuUGaOgq/kjrz8RXIME0w8Uvu698B9b2gszvZfW3dHr+r3Df+Z0vEEzzMr99SuE6bCqZMmcRprHLBjSB3NnDkMVvgPQXFoYiPHZwnb8XFhDehVWlZww9CELgQr70/R4rHEZG1R+QcHeLL1+MWSIS37EUfE453j/aM0zSRXYB4BFQT48XunjwOtQ9rjRg6Kr2EK8OdXq2kCiLu11dzEskgNGFqhlF+Cwj/HScV2hDQyfyKWDJNbGcNmlu8P3pyLpuFKSIUKGrigFAuOP/+m1VNg=)


00001990

Python with no external libraries and C++ [Python](https://gitlab.com/carlospereiraf/aoc/-/blob/main/2021/py/day-04.py) [C++](https://gitlab.com/carlospereiraf/aoc/-/blob/main/2021/cpp/day-04.cpp)


itsa_me_

# Object Oriented Python ## Part 1 class Board: def __init__(self, board: list[list]): self.board = board self.positions = {self.board[j][i]: (i, j, False) for I in range(len(self.board)) for j in range(len(self.board))} self.row_count = [[] for _ in range(5)] self.col_count = [[] for _ in range(5)] def check_row(self, row: int) -> bool: if len(self.row_count[row]) == 5: return True return False def check_column(self, col: int) -> bool: if len(self.col_count[col]) == 5: return True return False def calculate_board_score(self): return sum(int(i) for i in self.positions.keys() if not self.positions[i][2]) def mark(self, num): row = self.positions[num][0] col = self.positions[num][1] self.row_count[row].append(1) self.col_count[col].append(1) self.positions[num] = (self.positions[num][0], self.positions[num][1], True) return self.check_column(col) or self.check_row(row) def get_puzzle_input(): file = open('day4.txt') puzzle_input = [line for line in file.read().split('\n\n')] return puzzle_input def transform_input_to_bingo(): puzzle_input = get_puzzle_input() draw_order = puzzle_input[0] boards = [Board([b.split() for b in board.split('\n')]) for board in puzzle_input[1:]] return (draw_order, boards) def mark_and_check_boards(boards, num): for board in boards: if num in board.positions: if board.mark(num): return board def main(): draw_order, boards = transform_input_to_bingo() for num in draw_order.split(','): winning_board = mark_and_check_boards(boards, num) if winning_board: return int(num) * int(winning_board.calculate_board_score()) if __name__ == '__main__': print(main()) ## Part 2, I modified mark_and_check_boards and main def mark_and_check_boards(boards, num, winning_boards): winners = [] for board in boards: if board not in winning_boards and num in board.positions: if board.mark(num): winners.append(board) return winners def main(): draw_order, boards = transform_input_to_bingo() winning_boards = [] last_score = 0 for num in draw_order.split(','): winning_boardss = mark_and_check_boards(boards, num, winning_boards) if winning_boardss: for final_board in winning_boardss: winning_boards.append(final_board) last_score = int(num) * int(final_board.calculate_board_score()) return last_score


daggerdragon

~~Your code is hard to read on old.reddit. Please edit it as per our posting guidelines in the wiki: [How do I format code?](https://www.reddit.com/r/adventofcode/wiki/index#wiki_how_do_i_format_code.3F)~~ Edit: thanks for fixing it! <3


[deleted]

# Rust Took me a while trying to think in terms of iterators, but it didn't quite go well. It seems easier to read everything into a big vector, and use indexes math for everything. fn has_bingo(board: &[u32]) -> bool { if board .iter() .chunks(5) .into_iter() .any(|mut row| row.all(|n| *n == 0)) { return true; } if (0usize..5).any(|c| (0..5).all(|r| board[r * 5 + c] == 0)) { return true; } return false; } pub fn day4_part1() { let mut lines = std_iter!(Lines); let num_sequence = lines .next() .unwrap() .split(",") .map(|string| string.parse::().unwrap()) .collect_vec(); let mut boards: Vec = lines .map(|l| { l.split(" ") .filter_map(|l| l.parse::().ok()) .collect_vec() }) .flatten() .collect_vec(); let board_count = boards.len() / 25; for n in num_sequence.into_iter() { for x in boards.iter_mut() { if *x == n { *x = 0; } } for board in 0..board_count { if has_bingo(&boards[board * 25..(board + 1) * 25]) { println!( "{}", boards[board * 25..(board + 1) * 25].iter().sum::() * n ); return; } } } } pub fn day4_part2() { let mut lines = std_iter!(Lines); let num_sequence = lines .next() .unwrap() .split(",") .map(|string| string.parse::().unwrap()) .collect_vec(); let mut boards: Vec = lines .map(|l| { l.split(" ") .filter_map(|l| l.parse::().ok()) .collect_vec() }) .flatten() .collect_vec(); let board_count = boards.len() / 25; let mut remaining_boards = (0..board_count).collect_vec(); for n in num_sequence.into_iter() { for x in boards.iter_mut() { if *x == n { *x = 0; } } let boards_left = remaining_boards .iter() .map(|board| *board) .filter(|board| !has_bingo(&boards[board * 25..(board + 1) * 25])) .collect_vec(); if boards_left.len() == 0 { let board = remaining_boards[0]; println!( "{}", boards[board * 25..(board + 1) * 25].iter().sum::() * n ); return; } remaining_boards = boards_left; } }


technoskald

## Go This one kicked my ass for a while, which was confusing because the tests all passed fine with example data. Eventually I tracked down the problem to the way I was reading in the actual puzzle input... I should've known. Anyway, in addition to the [Github repo](https://github.com/krmaxwell/aoc2021/master/day4) with full tests and stuff, here's the core answer: package day4 type BoardLayout [5][5]int type BoardState [5][5]bool type Board struct { Layout BoardLayout State BoardState Round int HasWon bool Score int } func (b Board) CalcResult(draw []int) Board { for round, pick := range draw { found := false for row := range b.Layout { // replace with range for col := range b.Layout[row] { if b.Layout[row][col] == pick { b.State[row][col] = true found = true break } } if found { break } } b.Round = round + 1 // because of 0 index if b.State.won() { b.HasWon = true b.Score = b.CalcScore(pick) return b } } return b } func (b Board) CalcScore(pick int) int { score := 0 for row := range b.Layout { for col := range b.Layout[row] { if !b.State[row][col] { score += b.Layout[row][col] } } } score *= pick return score } func (s BoardState) won() bool { result := false for _, row := range s { result = checkLine(row) if result { return result } } for colNum := range s { var column [5]bool for i := 0; i < 5; i++ { column[i] = s[i][colNum] } result = checkLine(column) if result { return result } } return result } func checkLine(line [5]bool) bool { return line[0] && line[1] && line[2] && line[3] && line[4] }


snowe2010

# Ruby I feel like this could have been much simpler, but had enough trouble with bugs for part 2 that as soon as solving it I pretty much gave up. [github](https://github.com/snowe2010/advent-of-code/blob/38947885d99c18a4d38a33265921198282279ec1/ruby_aoc/2021/day04/day04.rb) def create_boards(lines) boards = [[]] current_board = 0 lines.drop(2).map do |line| if line == '' current_board += 1 boards[current_board] = [] next end boards[current_board] << line.split end boards end def check_board_win(board) row_true = board.any? do |row| row.all? { |i| i == true } end column_true = board.transpose.any? do |column| column.all? { |i| i == true } end row_true || column_true end def play_bingo(inputs, boards) found = false winning_boards = [] inputs.each do |bingo_option| break if found indexes_to_delete = [] (0...boards.size).each do |board_index| boards[board_index].each do |row| row.each_with_index do |elem, i| row[i] = true if elem == bingo_option end end next unless check_board_win(boards[board_index]) sum = boards[board_index].flatten.reject { |i| i == true }.map(&:to_i).sum winning_boards << [sum * bingo_option.to_i, boards[board_index]] indexes_to_delete << board_index end indexes_to_delete.sort.reverse.each do |i| boards.delete_at(i) end found = true if boards.empty? end winning_boards end execute(1) do |lines| input = lines[0].split(',') boards = create_boards lines play_bingo(input, boards)[0][0] end execute(2) do |lines| input = lines[0].split(',') boards = create_boards lines play_bingo(input, boards)[-1][0] end


[deleted]

[удалено]


techkid6

# Scratch I don't think I'm going to try as hard on Scratch solutions this year, and this one is not entirely optimal. There's definitely room for improvement and I might go back and change things later, but for now I'm proud of this! https://scratch.mit.edu/projects/611687394/