Advent of Code 2019

Every year I try to solve the problems in the Advent of Code… I usually don’t get very far.

Trying once again, using Racket. Day 1 is complete. Let’s see how far I can go this year. Want to do it with me? (no cheating!)

5 Likes

This looks fun! However I have finals in two weeks and I have to take my stupid security+ exam on the 19th. I can’t afford to get sucked into this!!

I hope you find some challengers!

1 Like

Late to this party but heard you mention this during the tech guy last week and I decided to give it a try. Probably really far behind but starting Day 5 now. Writing my code with PowerShell since it’s something I wanted to learn.

3 Likes

Well I did day 1 in a few minutes… no problem. But I strongly dislike the scoring… it’s based on rushing to complete from the very beginning. It would make more sense for it to time how long it took you to complete a solution, or the number of guesses, or almost any other bogus metric rather than “I have not life so I was awake the very second day n became available and I got the answer first.” Scoring 0 because I am 20 days late doesn’t inspire me, coming in late to the challenges, to want to bother doing any more.

1 Like

Jeepers… Day 1 was pretty easy, Day 2 wasn’t too bad, Day 3 was nearly off the chart relative to the first two… way to scale the difficulty there folks!

1 Like

For me the Advent of Code 2019 has been a blast so far. (I’ve been on Day 5 for the last three days - working sloooooow.)

(By the way, if you haven’t started yet this looks like an awesome way to do it, from Twilio: https://www.twilio.com/quest)

I’ve found it’s not that the puzzles are conceptually all that difficult - it’s just putting it in code. I’m making it harder by doing it in a functional language (Racket) that I’m not yet proficient in. I think it would be a lot easier in Python! But as I go I’m learning a lot of Racket.

I’m not rushing it. I can’t devote all that much time to it anyway. And there’s no way I’d ever get on the leaderboard. Those cats are solving the puzzles in minutes. I’m not going for speed, just clean, elegant code. I’m doing it HtDP style which includes unit tests and (extensive) type comments. (There’s a typed version of Racket which I should start using - another thing to learn.)

I figure it will take me all year to get through the entire 2019 AoC. Right now working on an intcode parser for Day 5 which should make the whole thing faster since I understand the intcode interpreter is much used in later days.

Just to give you an idea of how I’m working, here’s my Day 1 solution (SPOILER).

The whole thing could be written in four lines of code but I’m treating this as an exercise in proper coding style.

#lang racket
(require rackunit)
(require racket/string)   

;  --- Day 1: The Tyranny of the Rocket Equation ---
; 
; 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 Elves quickly load you into a spacecraft and prepare to launch.
; 
; At the first Go / No Go poll, every Elf is Go until the Fuel Counter-Upper. They
; haven't determined the amount of fuel required yet.
; 
; Fuel required to launch a given module is based on its mass. Specifically, to
; find the fuel required for a module, take its mass, divide by three, round down,
; and subtract 2.
; 
; For example:
; 
;     For a mass of 12, divide by 3 and round down to get 4, then subtract 2 to get 2.
;     For a mass of 14, dividing by 3 and rounding down still yields 4, so the fuel
; required is also 2.
;     For a mass of 1969, the fuel required is 654.
;     For a mass of 100756, the fuel required is 33583.
; 
; The Fuel Counter-Upper needs to know the total fuel requirement. To find it,
; individually calculate the fuel needed for the mass of each module (your puzzle input),
; then add together all the fuel values.
; 
; What is the sum of the fuel requirements for all of the modules on your spacecraft?
; 


;; provided by AOC:

(define module-masses (file->list "input1.txt"))

;; Integer -> Integer
;; Given the mass of a module return the amount of fuel required

(define (fuel mass)
  (- (quotient mass 3) 2))

(check-eq? (fuel 12) 2)
(check-eq? (fuel 14) 2)
(check-eq? (fuel 1969) 654)
(check-eq? (fuel 100756) 33583)

;; use (map total-fuel modules) to apply total-fuel to every module in the list,
;; producing a list of results
;; then use foldr to add the results together thus:

(printf "AOC Problem 1.1 = ~a\n"
    (foldr + 0 (map fuel module-masses)))
    

;  --- Part Two ---
; 
; During the second Go / No Go poll, the Elf in charge of the Rocket Equation Double-Checker stops the
; launch sequence. Apparently, you forgot to include additional fuel for the fuel you just added.
; 
; Fuel itself requires fuel just like a module - take its mass, divide by three, round down, and subtract 2.
; However, that fuel also requires fuel, and that fuel requires fuel, and so on. Any mass that would require
; negative fuel should instead be treated as if it requires zero fuel; the remaining mass, if any, is instead
; handled by wishing really hard, which has no mass and is outside the scope of this calculation.
; 
; So, for each module mass, calculate its fuel and add it to the total. Then, treat the fuel amount you
; just calculated as the input mass and repeat the process, continuing until a fuel requirement is zero
; or negative. For example:
; 
;     A module of mass 14 requires 2 fuel. This fuel requires no further fuel (2 divided by 3 and rounded    
;     down is 0, which would call for a negative fuel), so the total fuel required is still just 2.
; 
;    At first, a module of mass 1969 requires 654 fuel. Then, this fuel requires 216 more fuel (654 / 3 - 2).
;    216 then requires 70 more fuel, which requires 21 fuel, which requires 5 fuel, which requires no further fuel.
;    So, the total fuel required for a module of mass 1969 is 654 + 216 + 70 + 21 + 5 = 966
; 
;    The fuel required by a module of mass 100756 and its fuel is:
;           33583 + 11192 + 3728 + 1240 + 411 + 135 + 43 + 12 + 2 = 50346.
; 
; What is the sum of the fuel requirements for all of the modules on your spacecraft when also taking into
; account the mass of the added fuel? (Calculate the fuel requirements for each module separately, then add
; them all up at the end.)
; 


;; Integer -> Integer
;; Given the mass of a module, produces the total fuel required
;; taking into account the amount of fuel the fuel will require
;; if any mass requires negative fuel amount, discard it

(define (total-fuel mass)
  (local [(define f (fuel mass))]
  (cond [(<= f 0) 0]
    [else (+ (total-fuel f) f)])))

(check-eq? (total-fuel 14) 2)
(check-eq? (total-fuel 1969) 966)
(check-eq? (total-fuel 100756) 50346)

(printf "AOC Problem 1.2 = ~a\n"
    (foldr + 0 (map total-fuel module-masses)))

I am working in OO Java, and doing unit tests of important classes. My goal is to know it works before submitting my guess. I have needed two guesses max on a couple of my submissions so far, but that means 8 were right on the first try (I have 10 stars, having done the first 5 questions.)

Here’s my solution to day 1 Q1 (which is strictly procedural and has none of my objects because it’s so simple):

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

final class Advent2019Day01Q01
{
  public static void calculateFuel() throws FileNotFoundException
  {
    final Scanner scanner = new Scanner(new File("codechallenge/advent2019/day01/Q01_Input.txt"));
    int numberOfModules = 0;
    int totalFuel = 0;
    while (scanner.hasNext())
    {
      final int moduleSize = scanner.nextInt();
      // System.out.println("moduleSize: " + moduleSize);
      final int fuelNeededForModule = (moduleSize / 3)-2;
      System.out.format("Needed fuel for module size %d is %d%n", moduleSize, fuelNeededForModule);
      numberOfModules++;
      totalFuel += fuelNeededForModule;
    }
    System.out.println("Number of modules: " + numberOfModules);
    System.out.println("Total fuel needed: " + totalFuel);
  }
}

and here’s some unit tests from day 1 Q2:

  @Test
   public void testCalculateExtraFuel()
   {
     assertEquals(0, Advent2019Day01Q02.calculateExtraFuel(14));
     assertEquals(966-654, Advent2019Day01Q02.calculateExtraFuel(1969));
     assertEquals(50346-33583, Advent2019Day01Q02.calculateExtraFuel(100756));
   }

And there’s day 6 done. It’s an interesting graph problem. These aren’t trivial amounts of code, but it is a bit eye opening how much you can achieve with very minor changes from part one to part two.

Day 7 was interesting. Lots of refactoring between part 1 and part 2. I make a mistake that had me scratching my head for a good half an hour or more. When I refactored to support the feedback I had accidentally left IntCode program executor restarting the program counter at 0 for each input step, which leads to an infinite loop.

You’re trucking @PHolder! I’m still working on my INTCODE interpreter from Day 5!!

1 Like

Day 10 is really beating me up! It’s all about 2D topology and this is not really an area I have spent much time coding in in the past. Not that the geometry is impossible, but coming up with the right approach to make it match their expected answers is more of a struggle than I ever would have expected. I’m about to throw away a few hours of work and start over with a new approach.

Edit: (3 hours later)

Finally found a working approach! Took me two guesses though because I didn’t keep enough digits of precision the first time

2nd Edit: (3 more hours later)

Wow, the second part was a good bit of mental gymnastics for me. I made two wrong guesses because I was lazy and didn’t properly compare my code against their given test cases (hangs head in shame.) Interestingly it told me that my second wrong guess was the correct answer for someone else, and to make sure I was using my own data. (LOL, it thought I was cheating by getting the answers from someone else.)

This tells me that the questions are customized to each user, which doesn’t surprise me, but does mean they’re a clever bunch of programmers that put the whole site together so that it could generate custom data for each user.

1 Like

Oh that’s interesting. I never thought of that. No wonder the input data seems so random. It is!

Still stuck on 5. My intcode interpreter passes all the tests except the one that matters! I wish they’d provided more test data on this one.

The first part of Day 12 is done… I made a stupid mistake for my first guess and once again I was too smug to do the testing until after I got that wrong. I forgot to apply gravity in both directions between each pair of moons.

I finished Day 14, it was a lot of code IMHO. The optimization portion for part 2 was hard to figure out at first, until I realized my code ran fast enough to use binary search to find the answer much more quickly than brute force.

Also, I came across this from Twitter

So Day 15 is an interesting challenge. I can see two ways to solve it. One would be to make a user interface (a game UI in essence )and just explore on your own. The other would be to program a bot to “play” for you. I chose the second approach, and so far my bot doesn’t know how to do backtracking (because I saved implementing that for after I saw some results from this proof of concept.) This is a picture of what my bot with no backtracking has so far revealed:

octothorpe = wall
period = unknown
S = where it started
blank space is empty space it progressed through

Edit: 6 hours later I finally solved part one after adding backtracking and chasing a bug. And part 2 looks like more of the same but even more intense. :crazy_face:

1 Like

I think I will give this a shot next year so I can start at day 1. I’ll try it with Nim as my language since that’s what I have been learning lately.

1 Like

You can start at day 1 today. You don’t need to try and be first and make the leaderboard, because to do that, you need to be awake around midnight, and be able to solve the problems in 30min or less to even have a hope. Not that you may not be a genius or something, but why bother with all that. The only competition is with yourself, and whether you can handle it. And if you do want to seriously try for the leaderboards, then you will need practice with the system and how to use it. Watch the video I linked above where the author explains it, and he’ll talk about people competing for the leaderboards…

2 Likes

There are five years total - it’s worth doing them all, although this year’s has been the best yet.

I’m working very slowly - still at Day 6 – but I’m learning a lot and having a blast. It does get a little harder every day but then I’m getting better every day!

1 Like

I completed part 1 of day 15 and day 16 and then part 2 of either has kicked my ass so far. I know how to do day 15 part 2, but I have a bug and I’ve left it to percolate with my subconscious while I moved on. Day 16 part 1 is dirt easy, really, but part 2 is the exponential version, so you need to find a trick for a solution (because brute force will take forever) and I haven’t figured the trick out quite yet.

Edit: For part 2 of Day 16, this hint really helped me figure out how to optimize it https://old.reddit.com/r/adventofcode/comments/ebf5cy/2019_day_16_part_2_understanding_how_to_come_up/fb5p0hy/

Completed both parts of Day 17. It’s another INT_CODE program. It was fairly straightforward, except that I did part 2 partially by hand to save writing what would have been a lot of code (for me.) I wrote a program to get the long form answer, but you need to divide it up into smaller chunks, and I did that part by hand in a text editor using a heuristic and some search and replace. This was the first time the INT_CODE program simulates user IO with text prompts and text inputs.