first 4 days of 2024

This commit is contained in:
Yanick Champoux 2024-12-04 15:46:05 -05:00
parent be223b6cef
commit 0ebf67a5cc
22 changed files with 420 additions and 0 deletions

22
2024/01/Part1.pm Normal file
View File

@ -0,0 +1,22 @@
package Day1::Part1;
use 5.36.0;
use List::Util qw/ sum pairmap /;
use List::MoreUtils qw/ part zip /;
sub read_file(@lines) {
my $i = 0;
my @lists = part { $i++ % 2} map { split } @lines;
return @lists;
}
sub solve(@lists) {
for my $x (1,0) {
$lists[$x] = [ sort { $a <=> $b } $lists[$x]->@* ];
}
return sum pairmap { abs $a - $b } zip $lists[0]->@*, $lists[1]->@*;
}
1;

17
2024/01/Part2.pm Normal file
View File

@ -0,0 +1,17 @@
package Day1::Part2;
use 5.36.0;
use List::Util qw/ sum pairmap /;
use List::MoreUtils qw/ part zip /;
sub solve($l1,$l2) {
my %occur;
$occur{$_}++ for @$l2;
no warnings qw/ uninitialized /;
sum map { $occur{$_}*$_ } @$l1;
}
1;

8
2024/01/main.ts Normal file
View File

@ -0,0 +1,8 @@
export function add(a: number, b: number): number {
return a + b;
}
// Learn more at https://docs.deno.com/runtime/manual/examples/module_metadata#concepts
if (import.meta.main) {
console.log("Add 2 + 3 =", add(2, 3));
}

34
2024/01/part1.ts Normal file
View File

@ -0,0 +1,34 @@
import * as fs from "node:fs/promises";
export async function readFile(filename: string): Promise<number[][]> {
const lines = await fs
.readFile(filename, { encoding: "utf8" })
.then((lines: string) => lines.split(/\n/))
.then((lines: string[]) =>
lines.filter((x) => x).map((x) =>
x.split(/ +/).map((x) => Number(x))
)
);
const l1: number[] = [];
const l2: number[] = [];
lines.forEach(([a, b]) => {
l1.push(a);
l2.push(b);
});
return [l1, l2];
}
export function solve(...lists: number[][]) {
lists.forEach((l) => l.sort());
let sum = 0;
for (const i in lists[0]) {
sum += Math.abs(lists[0][i] - lists[1][i]);
}
return sum;
}

15
2024/01/test.t Normal file
View File

@ -0,0 +1,15 @@
use lib qw/ . /;
use Part1;
use Part2;
use Test2::V0;
use Path::Tiny;
my @lists = Day1::Part1::read_file( path('input')->lines );
is Day1::Part1::solve(@lists) => 1889772;
is Day1::Part2::solve(@lists) => 23228917;
done_testing();

9
2024/01/test.ts Normal file
View File

@ -0,0 +1,9 @@
import { expect } from 'jsr:@std/expect';
import { readFile, solve as d1Solve } from './part1.ts';
const input = readFile( import.meta.dirname + '/input');
Deno.test( 'part 1', async () => {
expect(d1Solve(...((await input) as any))).toEqual(1889772);
});

32
2024/02/Part1.pm Normal file
View File

@ -0,0 +1,32 @@
package Day2::Part1;
use 5.36.0;
use List::Util qw/ sum pairmap /;
use List::MoreUtils qw/ part zip /;
sub read_file(@lines) {
return map { [split] } @lines;
}
sub is_safe(@report) {
my $asc = $report[1] - $report[0];
my $level = shift @report;
while(@report) {
my $next = shift @report;
my $delta = $next - $level;
return 0 unless $delta*$asc >= 0;
return 0 unless 1 <= abs($delta) <= 3;
$level = $next;
}
return 1;
}
sub solve(@reports) {
return sum map { is_safe(@$_) } @reports;
}
1;

25
2024/02/Part2.pm Normal file
View File

@ -0,0 +1,25 @@
use lib qw/ . /;
use Part1;
package Day2::Part2;
use 5.36.0;
use List::Util qw/ sum pairmap /;
use List::MoreUtils qw/ part zip /;
sub is_safe_dampened(@report) {
for my $i ( 0..$#report) {
my @copy = @report;
splice @copy, $i, 1;
return 1 if Day2::Part1::is_safe(@copy);
}
return 0;
}
sub solve(@reports) {
return sum map { is_safe_dampened(@$_) } @reports;
}
1;

34
2024/02/part1.ts Normal file
View File

@ -0,0 +1,34 @@
import * as fs from "node:fs/promises";
export function readInput(filename: string): Promise<number[][]> {
return fs
.readFile(filename, { encoding: "utf8" })
.then((lines: string) => lines.split(/\n/))
.then((lines: string[]) =>
lines.filter((x) => x).map((x) =>
x.split(/ +/).map((x) => Number(x))
)
);
}
export function isSafe(report: readonly number[]): boolean {
const r = [ ...report ];
const asc = r[1] - r[0];
let level = r.shift();
while (r.length) {
const next = r.shift();
const delta = next! - level!;
if (delta * asc < 0) return false;
if (Math.abs(delta) < 1 || Math.abs(delta) > 3) return false;
level = next;
}
return true;
}
export function solve(reports: number[][]): number {
return reports.filter(isSafe).length;
}

13
2024/02/part2.ts Normal file
View File

@ -0,0 +1,13 @@
import { isSafe } from './part1.ts';
function isSafeDampened(report: number[]) {
for( let i =0; i < report.length; i++) {
const copy = [...report];
copy.splice( i, 1);
if( isSafe(copy) ) return true;
}
return false;
}
export function solve(reports: number[][]) {
return reports.filter(isSafeDampened).length;
}

6
2024/02/sample Normal file
View File

@ -0,0 +1,6 @@
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9

22
2024/02/test.t Normal file
View File

@ -0,0 +1,22 @@
use lib qw~ . ~;
use Part1;
use Part2;
use Test2::V0;
use Path::Tiny;
my @sample_reports = Day2::Part1::read_file( path('sample')->lines );
my @reports = Day2::Part1::read_file( path('input')->lines );
subtest 'part 1' => sub {
is Day2::Part1::is_safe(qw/ 7 6 4 2 1 /) => 1;
is Day2::Part1::solve(@sample_reports) => 2;
is Day2::Part1::solve(@reports) => 598;
};
subtest 'part 2' => sub {
is Day2::Part2::solve(@reports) => 634;
};
done_testing();

14
2024/02/test.ts Normal file
View File

@ -0,0 +1,14 @@
import { expect } from 'jsr:@std/expect';
import { readInput, solve as p1Solve } from './part1.ts';
import { solve as p2Solve } from './part2.ts';
const reports = await readInput( import.meta.dirname + '/input');
Deno.test( 'part 1', () => {
expect( p1Solve(reports)).toEqual(598);
});
Deno.test( 'part 2', () => {
expect( p2Solve(reports)).toEqual(634);
});

11
2024/03/Part1.pm Normal file
View File

@ -0,0 +1,11 @@
use 5.36.0;
package Day3::Part1;
sub solve($program) {
my $total = 0;
$total += $1 * $2 while $program =~ /mul \( (\d+) , (\d+) \)/xg;
return $total;
}
1;

15
2024/03/Part2.pm Normal file
View File

@ -0,0 +1,15 @@
use lib qw/ . /;
use Part1;
package Day3::Part2;
use 5.36.0;
sub solve($program) {
my $p = $program;
$p =~ s/ don't\(\) .*? (do\(\)|\Z) //smgx;
return Day3::Part1::solve($p);
}
1;

20
2024/03/test.t Normal file
View File

@ -0,0 +1,20 @@
use lib qw~ . ~;
use Part1;
use Part2;
use Test2::V0;
use Path::Tiny;
# my @sample_reports = Day2::Part1::read_file( path('sample')->slurp );
my $program = path('input')->slurp ;
subtest 'part 1' => sub {
is Day3::Part1::solve($program) => 184576302;
};
subtest 'part 2' => sub {
is Day3::Part2::solve($program) => 118173507;
};
done_testing();

47
2024/04/Part1.pm Normal file
View File

@ -0,0 +1,47 @@
package Part1;
use 5.36.0;
no warnings qw/ uninitialized /;
use Math::VectorXYZ::2D;
use List::Util qw/ sum pairmap /;
use List::MoreUtils qw/ part zip /;
sub read_file (@lines) {
return [ map { [ split '' ] } @lines ];
}
my @directions;
for my $x ( -1 .. 1 ) {
for my $y ( -1 .. 1 ) {
push @directions, Vec( $x, $y ) if $x or $y;
}
}
sub find_word ( $grid, $letters, $loc, $dir ) {
return 1 unless @$letters;
$loc += $dir;
return 0 if $loc->[0] < 0 or $loc->[1] < 0;
return 0 if $grid->[ $loc->[0] ][ $loc->[1] ] ne shift @$letters;
return find_word( $grid, $letters, $loc, $dir );
}
sub solve ($grid) {
my $total = 0;
for my $x ( 0 .. $grid->$#* ) {
for my $y ( 0 .. $grid->[0]->$#* ) {
if ( $grid->[$x][$y] eq 'X' ) {
$total += find_word( $grid, [qw/M A S/], Vec( $x, $y ), $_ )
for @directions;
}
}
}
return $total;
}
1;

42
2024/04/Part2.pm Normal file
View File

@ -0,0 +1,42 @@
package Part2;
use 5.36.0;
no warnings qw/ uninitialized /;
use Math::VectorXYZ::2D;
use List::Util qw/ sum pairmap /;
use List::MoreUtils qw/ part zip /;
sub find_word ( $grid, @locs ) {
for (@locs) {
return 0 if $_->[0] < 0 or $_->[1] < 0;
}
my $letters = join '', sort map { $grid->[ $_->[0] ][ $_->[1] ] } @locs;
return $letters eq 'MS';
}
sub solve ($grid) {
my $total = 0;
for my $x ( 0 .. $grid->$#* ) {
for my $y ( 0 .. $grid->[0]->$#* ) {
if ( $grid->[$x][$y] eq 'A' ) {
$total++ if 2 == grep {
find_word(
$grid,
Vec( $x, $y ) - Vec(@$_),
Vec( $x, $y ) + Vec(@$_)
)
} [ 1, 1 ], [ -1, 1 ];
}
}
}
return $total;
}
1;

10
2024/04/sample Normal file
View File

@ -0,0 +1,10 @@
MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX

22
2024/04/test.t Normal file
View File

@ -0,0 +1,22 @@
use lib qw~ . ~;
use Part1;
use Part2;
use Test2::V0;
use Path::Tiny;
my $sample = Part1::read_file( path('sample')->lines );
my $input= Part1::read_file( path('input')->lines );
subtest 'part 1' => sub {
is Part1::solve($sample) => 18;
is Part1::solve($input) => 2336;
};
subtest 'part 2' => sub {
is Part2::solve($sample) => 9;
is Part2::solve($input) => 1831;
};
done_testing();

1
2024/cpanfile Normal file
View File

@ -0,0 +1 @@
requires 'Math::VectorXYZ';

1
2024/settings.json Normal file
View File

@ -0,0 +1 @@
{ "deno.enable": true}