this post was submitted on 01 Dec 2023
18 points (100.0% liked)

NotAwfulTech

386 readers
7 users here now

a community for posting cool tech news you don’t want to sneer at

non-awfulness of tech is not required or else we wouldn’t have any posts

founded 1 year ago
MODERATORS
 

Rules: no spoilers.

The other rules are made up as we go along.

Share code by link to a forge, home page, pastebin (Eric Wastl has one here) or code section in a comment.

you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 7 points 1 year ago* (last edited 1 year ago) (2 children)

day 1

part 1

perl

#!/usr/bin/env perl

use strict;
use warnings;
use 5.010;

my $total = 0;

for my $line (<>) {
    my @nums = ($line =~ /\d/g);
    $total += $nums[0] * 10 + $nums[-1];
}

say $total;

part 2

perl

#!/usr/bin/env perl

use strict;
use warnings;
use v5.010;

my %nums = (one => 1, two => 2, three => 3, four => 4, five => 5, six => 6, seven => 7, eight => 8, nine => 9);
$nums{$_} = $_ for 1..9;

my $regex = join "|", keys %nums;

my $total = 0;

for my $line (<>) {
    $line =~ /($regex)/;
    my $first_num = $nums{$1};

    my $window = 1;
    my $sub = substr $line, -1;
    while ($sub !~ /($regex)/) {
        $window ++;
        $sub = substr $line, -$window;
    }

    $sub =~ /($regex)/;
    my $second_num = $nums{$1};

    $total += $first_num * 10 + $second_num;
}

say $total;

Part 2 gave me a surprising amount of trouble. I resolved it by looking at longer and longer substrings from the end of the line in order to find the very last word even if it overlapped, which you can't do with normal regex split. I doubt this is the most efficient possible solution.

Also Lemmy is eating my < characters inside code blocks, which seems wrong. Pretend the "&lt;>" part says "<>", lol

[–] [email protected] 4 points 1 year ago

lemme is an incredibly hungry little shit, it eats so much

[–] [email protected] 4 points 1 year ago

day 2

perl

#!/usr/bin/env perl

use strict;
use warnings;
use v5.010;
use List::Util qw/ max /;

# Parse the input

my %games = ();

for my $line (&lt;>) {
    $line =~ /Game (\d+): (.+)/;
    my $game_id = $1;
    my $game_str = $2;

    my @segments = split '; ', $game_str;
    my @game = ();
    for my $segment (@segments) {
        my @counts = split ', ', $segment;

        my %colors = (red => 0, blue => 0, green => 0);
        for my $count (@counts) {
            $count =~ /(\d+) (\w+)/;
            $colors{$2} = $1;
        }

        push @game, { %colors };
    }

    $games{$game_id} = [ @game ];
}

# Part 1

my $part1 = 0;

game: for my $game_id (keys %games) {
    for my $segment (@{$games{$game_id}}) {
        next game if $segment->{red} > 12 || $segment->{green} > 13 || $segment->{blue} > 14;
    }

    $part1 += $game_id;
}

say "Part 1: $part1";

# Part 2

my $part2 = 0;

for my $game (values %games) {
    my ($red, $green, $blue) = (0, 0, 0);

    for my $segment (@$game) {
        $red = max $segment->{red}, $red;
        $green = max $segment->{green}, $green;
        $blue = max $segment->{blue}, $blue;
    }

    $part2 += $red * $green * $blue;
}

say "Part 2: $part2";

Found this much easier than day 1 honestly...