Quick actions

cmd+k|ctrl+k

Navigation

Languages

AoC 2023, day 14

Snippet info

Language

Raku

Visibility

public

Author

seaker

Created

2023-12-14T09:22:50.624109Z

Updated

2023-12-14T09:58:19.015206Z

sub solve-p1(@dish, \rows, \cols) {
    for ^cols -> $col {
        my ($start-row, $row) = 0, 0;
        while $row < rows {
            given @dish[$row;$col] {
                when 'O' {
                    @dish[$start-row,$row;$col] = 'O', '.' if $start-row != $row;
                    ++$start-row;
                }
                when '#' { $start-row = $row + 1; }
            }
            ++$row;
        }
    }
}

sub tilt-line-front(@line, @ranges) {
    for @ranges -> (\begin, \end) {
        my $circles = +@line[begin..end].grep('O');
        @line[begin..(begin+$circles-1)] X= 'O' if $circles;
        @line[(begin+$circles)..end]     X= '.';
        @line.eager;
    }
}

sub tilt-line-back(@line, @ranges) {
    for @ranges -> (\begin, \end) {
        my $circles = +@line[begin..end].grep('O');
        @line[(end-$circles+1)..end] X= 'O' if $circles;
        @line[begin..(end-$circles)] X= '.';
        @line.eager;
    }
}

my @recs;

sub solve-p2(@dish, \rows, \cols, \rounds) {
    my %rocks is Set = @dish[*;*].grep('#', :k).map({ [$_ div cols, $_ mod cols] });
    my (@row-ranges, @col-ranges);

    for ^rows -> \row {
        my $start = 0;
        @row-ranges[row] = (gather {
            for %rocks.keys.grep(*[0] == row).sort -> ($, \col) {
                take [$start,col-1] if col - $start > 1;
                $start = col + 1;
            }
            take [$start,cols-1] if cols - $start > 1;
        }).Array;
    }

    for ^cols -> \col {
        my $start = 0;
        @col-ranges[col] = (gather {
            for %rocks.keys.grep(*[1] == col).sort -> (\row, $) {
                take [$start,row-1] if row - $start > 1;
                $start = row + 1;
            }
            take [$start,rows-1] if rows - $start > 1;
        }).Array;
    }

    for ^rounds -> \round {
        tilt-line-front(@dish[*;$_], @col-ranges[$_]) for ^cols;    # north
        tilt-line-front(@dish[$_],   @row-ranges[$_]) for ^rows;    # west
        tilt-line-back(@dish[*;$_], @col-ranges[$_]) for ^cols;     # south
        tilt-line-back(@dish[$_],   @row-ranges[$_]) for ^rows;     # east

        my $rec = @dish[*;*].grep('O', :k).sort.Array;
        return [$_, round] with @recs.first($rec, :k);
        @recs.push($rec);
    }
}

my @dish = $*IN.lines.map(*.comb.Array);
my (\rows, \cols) = +@dish, +@dish[0];

solve-p1(@dish, rows, cols);
put 'part 1: ', @dish[*;*].grep('O', :k).map({ rows - $_ div cols }).sum;

with solve-p2(@dish, rows, cols, 1_000_000_000) {
    put 'part 2: ', @recs[.[0] + (1_000_000_000 - .[0] - 1) % (.[1] - .[0])].map({ rows - $_ div cols }).sum;
}
INFO