Advent of Code -- 25x2 coding puzzles for December

I found out about this at work, but it’s on the open web. The idea is to solve two coding puzzles a day in the language of your choice. The first of each pair of puzzles is made available at the beginning of the day; the second one is unveiled only when you prove you’ve solved the first.

I’m using Python, since I keep taking tutorials in it but never actually do anything with it. I’m not a dev, which means not only is this going to take forever, but the code will be very, ah, inelegant. But hey. I like solving puzzles.

http://adventofcode.com

7 Likes

Looks neat.

1 Like

I was doing ok (slow, but ok… haven’t done nearly enough coding for a long while) until I hit the second part of day three. I was able to come up with a math shortcut to get the first part, but the second one seems like it would be easier to just work it out on paper than to write code for it.

I’m stuck on the first part of day 3. I have an ugly, inefficient way to do it, but I haven’t written it out yet. Day 4 is string manipulation, which makes me happy 'cos it’s my favourite :slight_smile:. I need to catch up later this week.

2 Likes

If I’d done the first part the long way rather than the math/geometry way I could probably have saved time on the second part. I did come up with three different ways to handle the memory structure for the second part, but in the end I just worked it out with a quick spreadsheet. I used the sum() function, so it’s still programming, right?

2 Likes

Here’s my day 1 solutions, in Python:

input = '3294199471327195994824832197564859876682638188889768298894243832665654681412886862234525991553276578641265589959178414218389329361496673991614673626344552179413995562266818138372393213966143124914469397692587251112663217862879233226763533911128893354536353213847122251463857894159819828724827969576432191847787772732881266875469721189331882228146576832921314638221317393256471998598117289632684663355273845983933845721713497811766995367795857965222183668765517454263354111134841334631345111596131682726196574763165187889337599583345634413436165539744188866156771585647718555182529936669683581662398618765391487164715724849894563314426959348119286955144439452731762666568741612153254469131724137699832984728937865956711925592628456617133695259554548719328229938621332325125972547181236812263887375866231118312954369432937359357266467383318326239572877314765121844831126178173988799765218913178825966268816476559792947359956859989228917136267178571776316345292573489873792149646548747995389669692188457724414468727192819919448275922166321158141365237545222633688372891451842434458527698774342111482498999383831492577615154591278719656798277377363284379468757998373193231795767644654155432692988651312845433511879457921638934877557575241394363721667237778962455961493559848522582413748218971212486373232795878362964873855994697149692824917183375545192119453587398199912564474614219929345185468661129966379693813498542474732198176496694746111576925715493967296487258237854152382365579876894391815759815373319159213475555251488754279888245492373595471189191353244684697662848376529881512529221627313527441221459672786923145165989611223372241149929436247374818467481641931872972582295425936998535194423916544367799522276914445231582272368388831834437562752119325286474352863554693373718848649568451797751926315617575295381964426843625282819524747119726872193569785611959896776143539915299968276374712996485367853494734376257511273443736433464496287219615697341973131715166768916149828396454638596713572963686159214116763'
sum = 0
sum2 = 0
l = len(input)
for i, c in enumerate(input):
    e = i+1 if i < l-1 else 0
    x = int(i+(l/2))
    if x >= l: x -= l
    if c == input[e]: sum += int(c)
    if c == input[x]: sum2 += int(c)
print(sum)
print(sum2)

It’s not fancy, but it gets the job done.

3 Likes

Looks cleaner than mine (perl for me)…

my $test = "29917128875332952564321392569634257121244516819997569284938677239676779378822158323549832814412597817651244117851771257438674567254146559419528411463781241159837576747416543451994579655175322397355255587935456185669334559882554936642122347526466965746273596321419312386992922582836979771421518356285534285825212798113159911272923448284681544657616654285632235958355867722479252256292311384799669645293812691169936746744856227797779513997329663235176153745581296191298956836998758194274865327383988992499115472925731787228592624911829221985925935268785757854569131538763133427434848767475989173579655375125972435359317237712667658828722623837448758528395981635746922144957695238318954845799697142491972626942976788997427135797297649149849739186827185775786254552866371729489943881272817466129271912247236569141713377483469323737384967871876982476485658337183881519295728697121462266226452265259877781881868585356333494916519693683238733823362353424927852348119426673294798416314637799636344448941782774113142925315947664869341363354235389597893211532745789957591898692253157726576488811769461354938575527273474399545366389515353657644736458182565245181653996192644851687269744491856672563885457872883368415631469696994757636288575816146927747179133188841148212825453859269643736199836818121559198563122442483528316837885842696283932779475955796132242682934853291737434482287486978566652161245555856779844813283979453489221189332412315117573259531352875384444264457373153263878999332444178577127433891164266387721116357278222665798584824336957648454426665495982221179382794158366894875864761266695773155813823291684611617853255857774422185987921219618596814446229556938354417164971795294741898631698578989231245376826359179266783767935932788845143542293569863998773276365886375624694329228686284863341465994571635379257258559894197638117333711626435669415976255967412994139131385751822134927578932521461677534945328228131973291962134523589491173343648964449149716696761218423314765168285342711137126239639867897341514131244859826663281981251614843274762372382114258543828157464392";

$output = 0;
my @captcha = split(undef, $test);
my $current = 0;
my $captchalen = $#captcha +1;
my $half = $captchalen / 2;

foreach $i (@captcha) {
        if($i == @captcha[($current + $half)%$captchalen]) {
                $output += $i;
        }
        $current++;
}

print $output;

I keep thinking of ways to optimize these things, and then reminding myself that it’s just a quick game and I should just get the answer… :slight_smile:

3 Likes

It would be interesting if they created a histogram like in Zachtronics games so that you could see how you stack up against other solutions on metrics like cycles, execution time, line count, etc. That would require them to use a platform setup similar to CodeWars, which would necessarily reduce the number of languages available, unfortunately.

3 Likes

This reminds me I should do project euler at some point as well.
https://projecteuler.net

2 Likes

They’d have to re-write the puzzles to be more specific as well. For instance, for the first one I used up a few lines making a user input prompt instead of just assigning the value to a variable in the code like people have above, just 'cos I liked it better that way.

2 Likes

The way that CodeWars does it is by declaring the method signature, and giving one or more unit tests that execute that method. That keeps the API consistent, but also means that each exercise must be language-specific.

2 Likes

Well, day 6 was definitely less straightforward than 4 or 5 were, but I did at least manage a better rank than I had on any of the previous puzzles.

I’m apparently really rusty on perl’s array handling. Between that and forgetting that I changed part of my strategy part-way through writing my code, I can’t believe how many completely wrong runs I had before getting a proper answer.

1 Like

Day 2 solutions, still in Python:

import itertools
input2 = [
    [1136, 1129, 184, 452, 788, 1215, 355, 1109, 224, 1358, 1278, 176, 1302, 186, 128, 1148],
    [242, 53, 252, 62, 40, 55, 265, 283, 38, 157, 259, 226, 322, 48, 324, 299],
    [2330, 448, 268, 2703, 1695, 2010, 3930, 3923, 179, 3607, 217, 3632, 1252, 231, 286, 3689],
    [89, 92, 903, 156, 924, 364, 80, 992, 599, 998, 751, 827, 110, 969, 979, 734],
    [100, 304, 797, 81, 249, 1050, 90, 127, 675, 1038, 154, 715, 79, 1116, 723, 990],
    [1377, 353, 3635, 99, 118, 1030, 3186, 3385, 1921, 2821, 492, 3082, 2295, 139, 125, 2819],
    [3102, 213, 2462, 116, 701, 2985, 265, 165, 248, 680, 3147, 1362, 1026, 1447, 106, 2769],
    [5294, 295, 6266, 3966, 2549, 701, 2581, 6418, 5617, 292, 5835, 209, 2109, 3211, 241, 5753],
    [158, 955, 995, 51, 89, 875, 38, 793, 969, 63, 440, 202, 245, 58, 965, 74],
    [62, 47, 1268, 553, 45, 60, 650, 1247, 1140, 776, 1286, 200, 604, 399, 42, 572],
    [267, 395, 171, 261, 79, 66, 428, 371, 257, 284, 65, 25, 374, 70, 389, 51],
    [3162, 3236, 1598, 4680, 2258, 563, 1389, 3313, 501, 230, 195, 4107, 224, 225, 4242, 4581],
    [807, 918, 51, 1055, 732, 518, 826, 806, 58, 394, 632, 36, 53, 119, 667, 60],
    [839, 253, 1680, 108, 349, 1603, 1724, 172, 140, 167, 181, 38, 1758, 1577, 748, 1011],
    [1165, 1251, 702, 282, 1178, 834, 211, 1298, 382, 1339, 67, 914, 1273, 76, 81, 71],
    [6151, 5857, 4865, 437, 6210, 237, 37, 410, 544, 214, 233, 6532, 2114, 207, 5643, 6852]
]
checksum = 0
evensum = 0
for r in input2:
    checksum += max(r) - min(r)
    for c in itertools.combinations(r, 2):
        evensum += int(max(c) / min(c)) if max(c) % min(c) == 0 else 0
print(checksum)
print(evensum)

itertools might have made the second half a bit too easy. I did learn something new, though.

I’m still catching up, which is going to be difficult if I don’t get more than one of these done a day.

1 Like

Darn it, you made me end up rewriting my own day 2, just from the realization that I coulda done it easier.

Your mention of things making it easier made me realize that I could just have sort()ed the values to save myself work.

End result still isn’t as compact as yours, but not too bad. I could shave some loops off the second part’s run with a single line added, but, eh, it works. :wink:

@input = split(/\n/, "Input string here");

$output = 0;
$output2 = 0;
foreach $line (@input) {
    @values = sort { $a <=> $b } (split(/\t/, $line));
    $output += @values[$#values] - @values[0];
    for(my $divisor = 0; $divisor < $#values; $divisor++) {
        for(my $i = ($divisor + 1); $i <= $#values; $i++) {
            if((@values[$i] % @values[$divisor]) == 0){
                $output2 += (@values[$i] / @values[$divisor]);
                last;
            }
        }
    }
}
print "first part: $output, second part: $output2\n";
1 Like

This would probably work in Python:

import AdventOfCode2017

day1part1()
day1Part2()
day2Part1()
...

:slight_smile:

4 Likes

I would try that but I imported antigravity and now my computer floated away.

3 Likes

Just make sure that you don’t import a soul.

3 Likes

That one’s rough. I finally solved it yesterday. I’ll post my solution later. I still haven’t solved part 2 yet. It’s different enough that I don’t think my part 1 solution will adapt easily. :frowning_face:

2 Likes

Exactly the problem I ran into, though it’s entirely possible your solution’s closer to an adaptable one.

Just for giggles, here’s my (embarrassing) solution for day 3 part 1. I wouldn’t recommend anyone rely on it, since it’s absolutely worthless for part 2.

I’ve got an idea on how I could un-spiral the array into a 1-dimensional array, but haven’t taken the time to try to make it work…

This is actually a minor rework of my solution…my original version was only 13 lines long but I had to do a little manual subtraction afterwards to get the answer, this one does it all on its own, albeit very messily.

$input = 289326;
$layer = 1;
while($input > ((($layer*2)-1) * (($layer*2)-1))) { $layer++; }
$sidelen = (($layer*2)-1);
$layerstart = (((($layer-1)*2)-1) * ((($layer-1)*2)-1) + 1);
$layerend = ((($layer*2)-1) * (($layer*2)-1));
print "$input is on layer $layer: side length $sidelen, starts at $layerstart, ends at $layerend\n";
print "center is at (" . (($sidelen + 1)/2) . "," . (($sidelen +1 )/2) . ")\n";
if($input < ($layerstart + ($sidelen - 1))) {
    $x = $sidelen;
    $y = ($layerstart + ($sidelen - 1) - $input);
}
elsif($input < ($layerstart + (($sidelen - 1)*2)))
{
    $x = ($layerstart + ($sidelen - 1) + ($sidelen - 1) - $input);
    $y = 1;
}
elsif($input < ($layerstart + (($sidelen - 1)*3)))
{
    $x = 1;
    $y = ($input - ($layerstart+($sidelen-1)+($sidelen-3)));
}
elsif($input < ($layerstart + (($sidelen - 1)*4)))
{
    $x = $input - ($layerstart + (($sidelen - 1)*3) -2);
    $y = $sidelen;
}

print "$input is at ($x,$y), manhattan distance is " . (abs($x-(($sidelen + 1)/2)) + abs($y-(($sidelen + 1)/2))) . "\n";
1 Like

I knuckled down and built a “proper” solution for part 2 of day 3, not having really solved that with code was annoying me. Perl complains that I’m using “experimental” features, but it works. I still feel like there’s a more math-based solution, but I haven’t quite worked it out yet.

The last several days’ challenges have been interesting. It feels like the difficulty level can swing wildly from day to day, though.

Dynamically expanding arrays sorta feels like cheating to me, being able to do that back when I first learned to code would have been amazing.

use strict; use warnings;

my($input) = 289326;
my($level) = 0;
my($found) = 0;
my(@array);
my($sidemax);

$array[0][0] = 1;

while(!$found) {
    $level++;
    $sidemax = $level * 2;

    # Enlarge array by one cell on all sides
    for(my $pushy = 0; $pushy <= $#array; $pushy++) {
        push($array[$pushy], 0);
        unshift($array[$pushy], 0);
    }
    push(@array, [(0) x (($level * 2)+1)]);
    unshift(@array, [(0) x (($level * 2)+1)]);

    # Walk around the outside
    my($y) = ($level + ($level-1));
    my($x) = $sidemax;
    for(;$y >=0; $y--) { addcell($x, $y); }
    for($y=0,$x--; $x >=0; $x--) { addcell($x, $y); }
    for($y=1,$x=0; $y <= $sidemax; $y++) { addcell($x, $y); }
    for($y=$sidemax,$x=1; $x <= $sidemax; $x++) { addcell($x, $y); }
}

# Unnecessary output, but since I've spent the time to build the array...
for(my $printy = 0; $printy <= $#array; $printy++) {
    for(my $printx = 0; $printx <= $#{$array[$printy]}; $printx++) {
        print $array[$printy][$printx] . "\t";
    }
    print "\n";
}


# Add together all surrounding cells
sub addcell {
    my($x, $y) = @_;
    for(my $addy = -1; $addy <=1; $addy++) {
        for(my $addx  = -1; $addx <=1; $addx++) {
            if(($addy != 0 || $addx != 0) && ($y+$addy) >= 0 && ($x+$addx) >= 0 && (($y+$addy) <= $sidemax && ($x+$addx) <= $sidemax)) {
                $array[$y][$x] += $array[$y+$addy][$x+$addx];
            }
        }
    }
    if(!$found && $array[$y][$x] > $input) { print "Found " . $array[$y][$x] . ", larger than $input\n"; $found++;}
}

1 Like