Advent of Code 2018 - 25x2 coding puzzles for December

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

Here’s @gadgetgirl’s description from last year, which I think covers it with more brevity than I likely would:

It’s almost time for 2018’s Advent of Code, so I thought I’d preemptively create a thread for interested parties to organize, collaboratize, and agonize.

I wasn’t aware of private leaderboards last year, but I might not have been paying attention. This year, I went ahead and created one for anyone who wants to compare their progress with a smaller list of people. Given my performance last year, I will only remain at the top of this list for another day.

If you want to join the private leaderboard, please use the code 256706-bb2717ff

Here’s the list of people that were participating last year, in case they somehow miss this thread:

Please tag anyone else you think might be interested. I’ll try to do better this year and share my solutions, and I’d really like to see other approaches too.

5 Likes

I didn’t have a chance to get involved but these look pretty fun. I’ll see if I can give it a go this time around.

3 Likes

I’m pretty much guaranteed to not get any good scores this time around since work’s been running me ragged and the whole middle-of-the-night starting time is just not going to be possible, but it was pretty fun last time so I certainly hope to get the time to play along.

5 Likes

The nice thing about the private leaderboard is that you can see your scores relative to a smaller group, which may be either more or less stressful, depending upon your perspective.

6 Likes

Well, since I was still working when the first puzzle came out, I went ahead and hit it. Actually, it was an hour later when I suddenly realized what the time was…

I’m glad these start easy, since I definitely needed to knock some rust off the gears.

2 Likes

Day 1 Problem 1 was no challenge at all.
Day 1 Problem 2, I wrote a program to solve it, but it kept timing out. Like, the scripting engine I was running it on said that it hit a maximum execution time. So, instead of brute-forcing it, I figured out why that sum would show up again, and then skipped to the instance of the loop where I knew that would end up happening, and found the solution there.

Annoying, but it worked.

I’m going to have to find something better to code on, though.

4 Likes

I was tempted to do that, but haven’t been able to focus enough for it yet.

I ran quick-and-dirty with perl:

my $test = "INPUT HERE";

my @input = split("\n", $test);

my $result = 0;
my %freqs;
my $current = 0;

while (1) {
        if($input[$current] =~ /^[+-]\d+$/) { $result+= eval($input[$current]) };
        $current++;
        if($current > $#input) { $current = 0 };
        if(exists $freqs{$result}) {
                print $result;
                exit;
    }
    else {
        $freqs{$result} = 1;
    }
}

since I just had to remind myself how to do it, the method I’m using for the spoiler here is
[spoiler]
<pre><code>
code goes here
</code></pre>
[/spoiler]

2 Likes

Here’s my function (in Google Sheets, so basically Javascript):


function Dec01B() {
  var sum=0;
  var count=0;
  var spreadsheet = SpreadsheetApp.getActive();
  var rowCount=0;
  rowCount = spreadsheet.getLastRow();
  var currValue = 0;
  var inputArray = spreadsheet.getRange('A1:A'+parseInt(rowCount)).getValues();
  var outputArray = [];
  
 do {
    for (var i=0;i<rowCount;i++){
      sum+=parseInt(inputArray[i],10);
      outputArray[count]=sum;
      for (var j=0;j<count;j++) {
        currValue=outputArray[j];
        if (currValue==sum) break;
      }  
      if (currValue==sum) break;
      count++;
    }
  } while (currValue!=sum);
  spreadsheet.getRange('B1').setValue(sum);
}

As far as I can tell, it would have worked, but I guess it couldn’t be bothered to hit the outermost loop 144 times.

1 Like

I had a serious reading comprehension problem with Day 1 Problem 2. I kept insanely overcomplicating the solution until I realized exactly what it was asking for and got it solved pretty fast.

I’ve been using PowerShell to write my solutions since that’s the scripting language I work with the most these days.

Here’s my solution:

Set-StrictMode -Version Latest # Save me from myself
$rawValues = '...' # Unique puzzle values

# Convert the raw values into integers to speed up calculations
$cookedValues = @() # Array to store the integer representations
$sr = [System.IO.StringReader]::new($rawValues)
while($null -ne ($v = $sr.ReadLine())) {
    $cookedValues += ([int]::Parse($v))
}

# Now let's make it happen
$max = $cookedValues.Length
$freq = @{} # hash of frequency + count
$rt = 0 # running total
$it = 0 # iteration
while($it -lt $max) {
    for($i = 0; $i -lt $max; $i++) {
        $rt += $cookedValues[$i]
        $freq[$rt]++

        if($freq[$rt] -gt 1) {
            Write-Output $rt
            exit
        }
    }
    $it++
}

Write-Host "Game over!" # If we get here something went horribly wrong
4 Likes

I should try writing my answer in powershell. Mostly I’ve been working in COBOL lately, but I don’t have access to that outside of work. Google Scripts has that run-time limit, which will probably only get more annoying as the month goes on, and I haven’t programmed in Java or C or VB in years.

4 Likes

I do most of my coding these days in C# and in the .NET Framework so PowerShell is something I’m quite comfortable with. That solution took about 3 seconds to find a result on my fairly underpowered laptop. I’m sure I could have optimized it further (if I cared enough to do so).

But, damn, Google Sheets? You deserve a gold star for thinking out of the box there.

4 Likes

I’ve been maintaining a macro-enabled spreadsheet for a competition I help with in another community, so it wasn’t as outside-the-box as it sounds.

But yeah, in the end, I ended up using the spreadsheet functionality more than I did the scripting.

4 Likes

To try to teach myself PowerShell, I did a couple of last year’s puzzles, and then came back to this one. This was my final solution:


Set-StrictMode -Version Latest

$input = "[snip]"
$sum=0;

$inputArray = $input.split([Environment]::NewLine);

$rowCount=$inputArray.Count;

$currValue = 0;

$outputArray = New-Object System.Collections.ArrayList;

  
do {
  for ($i=0;$i -lt $rowCount;$i++){
    if($inputArray.getValue($i) -ne ''){
      $sum+=([int]::Parse($inputArray.getValue($i)));
        if ( $outputArray.IndexOf($sum) -gt -1) {
          $currValue=$sum;
          break;
        }
        else {$outputArray.Add($sum);}
    }
  }
} while ($currValue -ne $sum);
Write-Output $sum;

It annoys me that I have to explicitly mark my variables with a ‘$’, and that it lets me define variables on-the-fly rather than having to declare them beforehand.

(Yes, I know the semicolons aren’t needed, but they make me feel better).

4 Likes

Although I don’t think I’d normally recommend more COBOL in the world…

But beware of COBOL Fingers.

3 Likes

Bah. You don’t type more in COBOL than you would in properly-commented code in any other language; COBOL is just largely self-commenting.

Although I suppose properly commented code is pretty rare to see in the wild.

4 Likes

Properly commented code limits the commentary to portions that need comment. :wink:

And once you start doing lots of nested loops, arrays, and more complex stuff in COBOL, you end up needing extra comments anyways just to avoid needing to read all that verbosity. :stuck_out_tongue:

4 Likes

When you use Strict Mode that at least ensures you’re not accidentally using undefined variables (which it will happily let you do otherwise, with predictably broken results).

3 Likes

I’ve tried using strict mode; it still didn’t stop me from typing $currentValue=$sum when I meant to type $currValue=$sum, even when the former hadn’t been defined previously.

3 Likes

Yeah, that’s considered legal. It will stop you from doing something like:

$i = 1
if($j -eq 1) {
}

… which is far more insidious and is allowed without strict mode ($j will just be null) and that makes it worth the price of admission IMO.

3 Likes

Day 2.

Part 1 I solved pretty quickly.

$input = '...' # my values
$counts = @{ 2 = 0; 3 = 0} # Hashtable of our counts across all inputs

$sr = [System.IO.StringReader]::new($input)
while($null -ne ($v = $sr.ReadLine())) {
    $charCounts = @{}
    $v.ToCharArray() | foreach {
        $charCounts[$_]++
    }

    $hasTwo = $false
    $hasThree = $false
    $charCounts.GetEnumerator() | foreach {
        if($_.Value -eq 2 -and $hasTwo -eq $false) {
            $counts[2]++
            $hasTwo = $true
        } elseif($_.Value -eq 3 -and $hasThree -eq $false) {
            $counts[3]++
            $hasThree = $true
        }
    }
}

Write-Output ($counts[2] * $counts[3])

But I had a hell of a time wrapping my head around part 2 – yet again I was severely overcomplicating the solution (I am seeing a trend here), but I finally got it figured out.

Set-StrictMode -Version Latest

$input = '...' # my values
# Get all the lines
$inputs = @()
$sr = [System.IO.StringReader]::new($input)
while($null -ne ($v = $sr.ReadLine())) {
    $inputs += $v
}

# Let's make it happen
$sb = [System.Text.StringBuilder]::new() # Our buffer
for($i = 0; $i -lt $inputs.Length; $i++) {
    $src = $inputs[$i]

    # Compare with our other stored values (starting from the next one)
    for($j = $i + 1; $j -lt $inputs.Length; $j++) {
        $sb.Clear() | Out-Null        
        $cmp = $inputs[$j]
        $diff = 0
        for($k = 0; $k -lt $cmp.Length; $k++) {
            if($src[$k] -eq $cmp[$k]) {
                $sb.Append($src[$k]) | Out-Null
            } else {
                ++$diff
            }

            # If we have more than 1 different char, bail.
            if($diff -gt 1) {
                break
            }
        }

        # If we only have one different char, then we've found our match
        if($diff -eq 1) {
            $sb.ToString()
            exit # Got it!
        }
    }
}

Write-Host "Surprise, motherfucker!" # We should never get here
1 Like