Advent of Code 2019 - 25x2 coding puzzles for December

Continuing the discussion from Advent of Code 2018 - 25x2 coding puzzles for December:

It has begun again…

From Day 1:

Santa has become stranded at the edge of the Solar System while delivering presents to other planets! To accurately calculate his position in space, safely align his warp drive, and return to Earth in time to save Christmas, he needs you to bring him measurements from fifty stars .

Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star . Good luck!

The leaderboard from last year appears to still be intact, but feel free to join if you aren’t already, the code is still 256706-bb2717ff

Tagging those who participated last year:

Please tag anyone else you think might want to participate.

I haven’t started yet, so I’m technically two days behind now… That’s what I get for it starting on a weekend.

Feel free to post questions and solutions in this thread, but please be kind and blur out any spoilers.

5 Likes

Thanks for tagging me. I just saw a reminder on HN that this was back. I’ll start working on it once I am more motivated. Probably later this week.

3 Likes

Hmm, I wish I’d realized this started over the weekend. I’m likely to end up with no time for this during the week.

4 Likes

Sadly, I doubt I will even touch this before my vacation starts… and then I’m not sure I’ll get to it then either. I’m trying to finish my React course I started last February and sputtered out on.

3 Likes

Had some time this morning that I probably shouldn’t have spent on this, but… I caught up to day 3. The first two were pretty simple, though I initially chose a much too difficult way to attack day 2’s second part (brute force definitely wins this one ).

My code for day 3 is an absolute mess of repetitive code that makes me cringe just looking at it, and I since I was feeling lazy I didn’t do it the way I originally thought I should. As it turns out, the way I did it is probably better, but still feels messy to me… (not much of a spoiler, just nattering about variable type choice) I used a perl hash as an array, which saved me from writing code to expand an array in multiple directions. With the sparseness of the data, it was probably better in resource usage, and let me store extra data for each cell. Always feels like an ugly hack to use numeric indexes in a hash, though….

I’ve got a lot of work schedule f*ckery coming up that’s really going to mess with any attempt to get some sleep, let alone do much with this, but I’ll see how things go.


I was able to get day 3’s code to 70 lines, down from the 177 it was when I wrote that earlier. Could go down another 20+ lines if I ripped out the pretty-print code that’s useless on anything but the testing examples. At least now it doesn’t make me cringe :slight_smile:

3 Likes

Due to said schedule stuff, I ended up being awake the last two mornings, so I’ve done days 4 & 5. Day 4 was fairly simple, though part 2 requires some care in reading the instructions… I’m pretty sure it’s almost identical to puzzles that were used in earlier years.

Day 5 isn’t difficult, but requires some drudge work. Part 1 also tripped me up a bit since the instructions telling you which of multiple results to enter really aren’t entirely straightforward. It refers to both an output “indicating how far the result of the test was from the expected value”, and a “diagnostic code” as though they are two different things, with one coming after the other… in actuality, the terms are referring to the same thing.

3 Likes

I feel bad that I was complaining about not having the time for these, but I seem to be the only one finding that time. I guess having my sleep schedule thrown all out of whack was good for something. :slight_smile:

Day 6 was fairly straightforward, although I’m very rusty with recursion. There used to be a time I’d have been able to throw the solution I ended up with together without thinking.

Day 7 is a doozy, and I don’t think I can say anything else about it outside a spoiler tag.
Part 1 involves running a previous day’s program multiple times, feeding outputs into the inputs of the next run… ok, annoying, but I pulled together a controlling process to handle that. Then part 2 wants multiple runs of that previous program to be happening simultaneously.

I could have re-written my previous program to accommodate having multiple storage areas and worked up a pseudo multitasking setup to handle it, and now that I write that out in that way I realize that would probably have been easier and is most likely what the puzzle’s writer had in mind. Instead, I ended up converting the earlier program into a full-fledged multithreaded TCP server, and wrote a client program that sets up multiple connections to that server and juggles the inputs/outputs as the problem wanted.

Everything was actually going along pretty quick until I ran into some weird socket issues - first the server would completely die as soon as a client socket disconnected, and then once I fixed that I ran into an issue of the client not realizing when the server had closed down a connection. I got it solved this morning, but it ended up being way more work than I bargained for.

1 Like

I finally had a few minutes to work on the first challenges. I’m going to try to do them in Swift which is a brand new language for me. But, after reading some of the chatter for this year’s challenges I’m not sure how much I want to invest but we’ll see.

2 Likes

I got up to day 10, but got stuck there… I have an idea of how to do it, but haven’t had the time or focus to actually work on it. Possibly the next few days will be a bit slower and I’ll have a chance to look at things again…

2 Likes

Finally got through day 10 today. Once I refreshed my memory of high-school geometry it wasn’t difficult, but coming up with an approach took me a good while and then I kept getting bogged down by simple cases I forgot to account for. If I’d found some graph paper to draw out some simple tests, it probably would have also helped me keep my code straight.

3 Likes

So I had some time over the past couple of days to mess around with this. Day 2 part 1 was easy enough. I had a few bugs but nothing a few unit tests couldn’t work the kinks out of and it was actually kind of fun to write my own virtual machine. But part 2 is just killing me.

I’ve read the instructions numerous times but they are so poorly done I feel like I’m missing something obvious. I’m just not getting any numbers anything like what it’s expecting. Is this just me being dumb? I feel like it would be simple enough to solve this exercise if I better understood what it’s actually asking me to do.

What I’m doing is for a a series of 0-99 and 0-99 (the noun and verbs) I’m going through each instruction set, getting the opcode, performing the operation against the value at the noun and verb address, and setting the result at position 0. I’m resetting the memory back to the original data after each iteration. It’s just not working at all though.

1 Like

It’s difficult to tell what’s going on without seeing the code (or the instructions, since I think both the input and some of the information in the instructions varies from person to person). Assuming you got the same instructions as I did, it’s just saying to try numbers between 0 - 99 in positions 1 and 2 of the program until one combination of them leaves the result it’s asking for in position 0 when the program halts.

If that doesn’t help, then elaborating a little on the detail-free spoiler I had in my earlier post for day 2…

When I started working on the second part, I started out with trying to decipher the program code… and got bogged down there. Simply trying every possible combination of two numbers was a possibility, but my code wasn’t really written for repeated running. My code was written to let me manually choose the numbers for those two locations easily on each run, so I backed up and started looking at how the result changed when I incremented just one or the other.

There ended up being a definite pattern there, and with probably fewer than 20 trial and error runs I was able to narrow down the range of possibilities until I hit the target asked for. Now that I think about it, I suppose that doesn’t exactly fit my description of “brute force” in the earlier spoiler… my only explanation is that I meant it in a “I tried random things until a pattern emerged” way.

2 Likes

Yeah, sorry. I was being vague; nothing’s worse than a code question without examples. I’ll take another stab at it when I have some time and I’ll post my code if I’m still stuck. I feel like I know exactly what I need to do at this point - things just aren’t working like I expect. My virtual machine seems to be functioning properly so I’m probably just doing something dumb in my iterations.

2 Likes

Oh, trust me, there’s much worse. :wink: To be clear, I wasn’t meaning that as criticism or anything.

Since the first part worked for you, your interpreter is probably functioning correctly. So probably one of those annoying issues where the process just isn’t quite right.

Another possibility for troubleshooting, if things refuse to work: I’d be happy to send you my input and results so you could test your code on them, or run your input on my code to check that we get similar results for the same inputs. Just as a spoiler-free sanity check of whether the problem is code or process.

2 Likes

After doing day 10 I finally took a few hours of free time to completely rewrite/refactor some of my earlier code, so I didn’t make any further progress until today. I did refresh my memory on how to write code for perl’s old-school pseudo-object-oriented module style, and built a self-contained perl module for the interpreter that has been used and built on through the previous days. I still need to remember how to properly do inheritance in order to really clean up my results, but once I do that I should have some code that would be very easy to re-use for similar projects. I’m pretty certain I’m re-inventing the wheel on it, but it’s nice to know it’s my own work, and that I’m getting something useful (to me) out of the exercise. :wink:

Day 11 was pretty straightforward thanks to that refactor.

Day 12’s part 1 was pretty easy. Part 2… this took me so long to work out a solution for it. I admit, I ended up going out to look for spoilers on this one, and even then it was a pain in the rear. After I finally got something that worked, it made sense, but even as I was building my final version I wasn’t entirely sure I had my brain wrapped around the problem.

Day 13 was fun, and part 1 was easy again, partly because of turning that interpreter into a module… part 2 was easy to code, but took me a while to figure out a good way to get the correct answer. I think there’s probably at least three or four entirely different ways to do that one, the easiest probably depends a lot on your own code. With the method I chose, I ended up needing to do some extra bits without entirely being sure why I needed them… but made things work, so I was happy. :smiley:

Day 14 looks like another pain in the rear…

1 Like

So, I figured it out. It was a reading comprehension fail. Even more annoyingly I had about 99% of the code right, it was just one aspect of my approach that was wrong because I just didn’t “get” what it was asking me to do.

Here’s the problem I was running into.

In day 2 part 1 it was very clear to set instructions[1] to a value (for me it was 12) and instructions[2] to (for me it was 2) before proceeding. After running through the entire set of instructions, instructions[0] should be set to a specific value which is the solution.

For day 2 part 2, I was reading it as I needed to set the noun/verb for each instruction pointer operation. In other words, instead of setting instructions[1] to noun and instructions[2] to verb and running through the entire set as before, I was setting instructions[ip+1] to noun and instructions[ip+2] to verb through each instruction step. This meant I was never coming close to the expected values (or I would overflow maxint depending on how I tried it).

After basically making my run loop identical for step 1 and step 2 with the only change is that for step 2 I’m passing in a looped value rather than a hard coded value it worked as expected.

Phew. I was just way over-complicating things.

1 Like

As an aside, I actually kind of like Swift. It has some rather annoying quirks (like why the bloody hell must I specify the parameter names rather than the compiler being smart enough to be positionally aware) and it’s infuriating that each new version of Swift has a ton of breaking changes from the previous version which means that since I’m using Swift 5.0 a lot of sample code from earlier versions doesn’t work anymore. And why in the world they decided in their infinite wisdom to remove the ability to do C-style ‘for’ loops is beyond me. Oh, and why a public class doesn’t by default have a public constructor was something that had me facepalming.

But, thus far I’m finding it to be rather intuitive. A little weird, but intuitive still.

ETA maybe I’m just spoiled after decades of Visual Studio but XCode is definitely not intuitive. Changing my Intcode interpreter into a library so it can be easily reused in the future was a massive PITA.

3 Likes

14 ended up not being as much of a pain as I expected on first look, although it is one of those where part 2 expands the problem to silly lengths.

15 was another one that was kinda fun… the code was really easy, but using that code to get the answers took some time.

Day 16 is slowly driving me insane. Part 1 was relatively easy, but part 2 goes into “if you haven’t worked out how to optimize the heck out of the problem, this’ll take until the heat death of the universe to run” territory. It doesn’t help that it’s a very math-heavy problem and the description is a little tough to follow.
[Edit] Ok, I made it through day 16, but it was rather unsatisfying since my “solution” rather depends on a quirk of the input.

Day 17 was fairly quick to get through. They’re getting rather impressive in what functionality they’re able to squeeze into provided input, though.

1 Like

Day 4 Part 2. This is another WTF for me.

Based on what I think it’s asking for, I must have groupings of digits in multiples of two. In the example it says the following is valid: 112233, and 111122 but not 123444. I am trying to brute force it and I think I’m misunderstanding the problem. In all the groupings I’m getting, any number that has groupings is always in a multiple of two. Maybe I’m just experiencing another reading comprehension fail?

Here’s my current code:

var p1IsValid = 0; // part 1 result count
var p2IsValid = 0; // part 2 result count

for v in 273025...767253 {
    var n: [Int] = [];
    var nn = v;

    // Get each digit and add it to an array
    repeat {
        n.append(nn % 10);
        nn /= 10;
    } while(nn > 0)
    n.reverse();

    var isSeqValid = true;
    for i in 0...4 {
        if(n[i+1] < n[i]) {
            isSeqValid = false;
            break;
        }
    }

    if(isSeqValid == false) {
        continue;
    }

    var doubles:[Int:Int] = [:]
    for i in 0...4 {
        if(n[i] == n[i+1]) {
            let ev = (doubles[n[i]] ?? 0) + 1;
            doubles.updateValue(ev, forKey: n[i]);
        }
    }

    if(doubles.count == 0) {
        continue;
    }

    p1IsValid += 1;

    for v in doubles.values {
        if(v % 2 == 0) {
            isSeqValid = false;
            break;
        }
    }

    if(isSeqValid == true) {
        print(v); // these are supposedly valid values but some aren't
        p2IsValid += 1;
    }
}

print("Part 1: \(p1IsValid)"); // this is right
print("Part 2: \(p2IsValid)"); // this is wrong
1 Like

I think I tried to do the same thing the first time around on that one. If I remember correctly, what it’s saying is that there has to be at least one pair of a digit, but that pair can’t be part of a group of more than two of that digit (and following the rest of the rules from part 1).

So, for instance, 111122 is valid not because the 1’s are in multiples of two, but because there’s the one pair of 22. 111233 would also be a possibility, for example - the digits only increment or stay the same from left to right, and there’s one pair of digits (the 3s) that aren’t part of a larger group of that digit.

1 Like