Aloha people,
It's already Day 6, and we are still working on day 4. My weekend was great. I ate so much yummy food. Now I feel prepared for all the Christmas lunch and diner rounds. The submarine has averted its last crisis with the power of Java and JavaScript. Now there is a new threat to the crew: A huge squid that wants to play some bingo, to my surprise the submarine has a “bingo subsystem”. 🤣 I really love the storytelling of advent of code. I hope it stays this awesome. I am doing the puzzle for today again in JavaScript as Rust is still too much. Not only that, but I am too scared to use the language currently. My issue is the required mental model for Rust. I just don't have it yet, and these puzzles are hard. Writing and coding takes some time. Anyway, let's play some BINGO!
The puzzle input are blocks of matrices of the size 5 and the first line are the numbers which are being drawn. Is someone here who hasn't played bingo? Let me explain: you have this 5x5 matrix and each round a number is drawn “randomly” from a pile of numbers. You as the player have to mark each number that was drawn and when there is a full line somewhere you yell "BINGO". It's pretty fun to play, you should try it.
7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7
BTW, I am pairing again with good pal Gabriel on this. The first obstacle was the parsing, but with a little regex magic every problem can be solved. Luckily for us, we averted the xkcd reference. The blocks will be parsed and stored in an array of arrays. We could have used a two-dimensional array and brute force our way through this puzzle, but there is a better solution: a bag of words. I felt so clever when I came up with the idea to use it. Good that I did that two day intensive machine learning course for beginners two years ago. Man, I was so tired these two days. This machine learning python code is still hunting me in my dreams. If I remember correclty you give every word a index or rather its position in a dictonary and we give gonna store the position for each number in a list on the position of the number. That means everytime the code needs all position of for example 7
then we do not need to search for the values. They will be there at 7th position in the array. Hurray 😎
Let's get back to the code. This function below will iterate over all numbers in the tables and will save the position of each number to a list within an array. For this moment I can proudly say that the lambda function foreach()
is such a great tool. It gives you the element in the array but also the index of the current iteration. That's just some awesome stuff. Why do other language don't have something like that? Through this we were able to set the index of the block, which otherwise would have been much more complicated.
const generateIndexTable = (tables) => {
let indexTable = []
tables.forEach((singleTable, index) => {
for (let x = 0; x < MATRIX_SIZE; x++) {
for (let y = 0; y < MATRIX_SIZE; y++) {
if(indexTable[singleTable[x][y].value]==null){
indexTable[singleTable[x][y].value] = [];
}
indexTable[singleTable[x][y].value].push({block: index, x : x, y: y})
}
}
})
return indexTable
}
Now we have all positions of the numbers in their respected block on the respected index. The array on the position [7]
will return a list of three elements. These objects contain the position of all three seven's in the whole test input. Through this we do not need to run over the tables to find the number and flagging them as marked is so much faster. Direct access baby!
The last part of the puzzle is to figure out whether there is a bingo in a block. Part One asks us to find the first bingo and then sum some numbers and multiply with the last drawn number. The search for this can also be made fast. The idea is to only check the first line and column. If there is a marked number, then and only then the code checks whether the whole line is marked.
const checkIfBingo = (xCoordinateOfFoundNumber, yCoordinateOfFoundNumber, table) => {
return checkLineOfTableForBingo(xCoordinateOfFoundNumber, table) || checkColumnOfTableForBingo(yCoordinateOfFoundNumber, table)
}
const checkLineOfTableForBingo = (indexOfLine, table) => {
let isBingo = true;
for (let i = 0; i < MATRIX_SIZE; i++) {
isBingo = isBingo && table[indexOfLine][i].isMarked;
}
return isBingo
}
}
I will show only one of the methods. If you want, you can read the whole code here. This will solve you the first part of the puzzle. The thing is the squid is a sore loser and Santa recognizes that letting the squid win would be a wiser strategy. Therefore we need to ignore all wins and wait for the last win and then save the index of the block. The thing I didn't understood is that there can be only one bingo per block. If all blocks have a bingo, the last one is the one we needed. Fortunately for me, Gabriel got my back.
Earlier I was applauding JavaScript for its awesome forEach()
function, but then the language just surprised me. We needed to store the table in an object, but it would only make a shallow copy of the table and therefore would change over time. We searched for some minutes and found out that it is a legitimate way to use JSON.stringify()
to produce a JSON string and then parse it back to a object with JSON.parse()
. Stay classy JavaScript, stay classy.