So, since I'm done with work for the year (I'm either taking PTO or it's a holiday for the rest of the year) I made the 300 IQ play to stay up to attempt to complete today's Advent of Code puzzle when it was released. I knew this was a bad idea because I have done it a few other times and regretted it almost immediately, but I figured there may be something different here since I really am done working for the year and wanted to set up the next morning (today) to take care of starting the process to switch out my monitors on my desktop and really begin the process of re-doing cable management for my desk (putting a "work laptop" station onto my desk so that I can really finally have a better workflow for day-to-day activities. Also, one benefit of doing this at night is that Sudo was pretty sleepy, so he decided to snooze next to me in the office yesterday. (picture below)
Anyway, in today's puzzle, you're reading up a file that contains two hands of cards and in part one, you're playing war (all of the cards have a different value, so there's no potential to tie) and the resulting return is the reverse position in the hand times the card value at that position, so the hand
[3, 5, 10] would return the value
9 + 10 + 10 or
29. This was a pretty straightforward part one, but the problem that I faced was that I wanted to use queues to store the cards, because then you can
poll to get the first item in the Queue and
add adds to the end of the queue, but when you have to continually copy those queues (because of the default reference pass) it causes some problems. I ended up using a List and doing some of my own work to "pop" off the top of the list as the default is to add to the end of the list which is very much appreciated.
Since part two required recursion, I decided to simply make a single method for dealing with the recursive actions, I pass the initial data to the recursive method without copying it, so that the resulting array could be used to calculate the sum. The method returns the winning player (
2) which helps the recursive pattern decide how to move forward with the CURRENT iteration it is on. The rules are as follows:
Recursive Combat still starts by splitting the cards into two decks (you offer to play with the same starting decks as before - it's only fair). Then, the game consists of a series of rounds with a few changes:
- Before either player deals a card, if there was a previous round in this game that had exactly the same cards in the same order in the same players' decks, the game instantly ends in a win for player 1. Previous rounds from other games are not considered. (This prevents infinite games of Recursive Combat, which everyone agrees is a bad idea.)
- Otherwise, this round's cards must be in a new configuration; the players begin the round by each drawing the top card of their deck as normal.
- If both players have at least as many cards remaining in their deck as the value of the card they just drew, the winner of the round is determined by playing a new game of Recursive Combat (see below).
- Otherwise, at least one player must not have enough cards left in their deck to recurse; the winner of the round is the player with the higher-value card.
As in regular Combat, the winner of the round (even if they won the round by winning a sub-game) takes the two cards dealt at the beginning of the round and places them on the bottom of their own deck (again so that the winner's card is above the other card). Note that the winner's card might be the lower-valued of the two cards if they won the round due to winning a sub-game. If collecting cards by winning the round causes a player to have all of the cards, they win, and the game ends.
The reason my part two solution took so long was that I misread the first rule. I misread the first rule as only having to check the first card for each hand, this caused my solution to see an infinite loop initially and cause me to start investigating further options. I also ran into a problem of the way that Java deals with lists where those lists are not considered copies when they enter the method and because initially, I was using Queues, this seemed to be a more difficult to deal with item. I eventually changed out my method to take in two
Lists and the internal recursion sent in a
list.stream().collect(Collectors.toList() of the value, and the
part2 method sent in the actual non-copy lists so that the changes in "Game 1" will apply to the lists that were passed in. Once I had all of that work completed, I was able to finally get two things, 1) AN answer to come out and 2) the answer to complete in a somewhat more reasonable timeframe. If you want to join my Advent of Code leaderboard, feel free to join with the code: