From 999e63ec2253e9ebc55d71c388eecf0f0d1efdf2 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 7 Dec 2022 18:40:16 -0500 Subject: [PATCH 1/2] day 6 --- .gitignore | 4 ++++ 2022/06/part1.js | 22 ++++++++++++++++++++++ 2022/06/part2.js | 19 +++++++++++++++++++ 2022/06/test.js | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 2022/06/part1.js create mode 100644 2022/06/part2.js create mode 100644 2022/06/test.js diff --git a/.gitignore b/.gitignore index 2b0c653..b1383ce 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ node_modules .pls_cache/ .perl-version pnpm-lock.yaml +*_BACKUP_* +*_BASE_* +*_LOCAL_* +*_REMOTE_* diff --git a/2022/06/part1.js b/2022/06/part1.js new file mode 100644 index 0000000..2ba5f23 --- /dev/null +++ b/2022/06/part1.js @@ -0,0 +1,22 @@ +import * as R from "remeda"; +import { readFile } from "../05/part1.js"; + +export const puzzleInput = readFile(import.meta.url, "input"); + +export default function (code) { + const size = 4; + let index = size; + + while (true) { + if ( + R.pipe( + code, + (c) => c.substr(index - size, size).split(""), + R.uniq, + (c) => c.length + ) === size + ) + return index; + index++; + } +} diff --git a/2022/06/part2.js b/2022/06/part2.js new file mode 100644 index 0000000..d3e5dfd --- /dev/null +++ b/2022/06/part2.js @@ -0,0 +1,19 @@ +import * as R from "remeda"; + +export default function (code) { + const size = 14; + let index = size; + + while (true) { + if ( + R.pipe( + code, + (c) => c.substr(index - size, size).split(""), + R.uniq, + (c) => c.length + ) === size + ) + return index; + index++; + } +} diff --git a/2022/06/test.js b/2022/06/test.js new file mode 100644 index 0000000..8c6502f --- /dev/null +++ b/2022/06/test.js @@ -0,0 +1,37 @@ +import { test, expect, describe } from "vitest"; + +import { expectSolution } from "../01/main.js"; +import part1, { puzzleInput } from "./part1.js"; +import part2 from "./part2.js"; + +describe("part 1", () => { + test("samples", () => { + expect(part1("mjqjpqmgbljsphdztnvjfqwrcgsmlb")).toEqual(7); + + Object.entries({ + bvwbjplbgvbhsrlpgdmjqwftvncz: 5, + nppdvjthqldpwncqszvftbrmjlhg: 6, + nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg: 10, + zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw: 11, + }).forEach(([code, index]) => expect(part1(code)).toEqual(index)); + }); + test("solution", () => { + expectSolution(part1(puzzleInput)).toEqual(1640); + }); +}); + +describe("part 2", () => { + test("samples", () => { + expect(part2("mjqjpqmgbljsphdztnvjfqwrcgsmlb")).toEqual(19); + + Object.entries({ + bvwbjplbgvbhsrlpgdmjqwftvncz: 23, + nppdvjthqldpwncqszvftbrmjlhg: 23, + nznrnfrfntjfmvfwmzdfjlvtqnbhcprsg: 29, + zcfzfwzzqfrljwzlrfnpqdbhtmscgvjw: 26, + }).forEach(([code, index]) => expect(part2(code)).toEqual(index)); + }); + test("solution", () => { + expectSolution(part2(puzzleInput)).toEqual(3613); + }); +}); From 09f79cb253205d5a394798c30bd4f32922e40d12 Mon Sep 17 00:00:00 2001 From: Yanick Champoux Date: Wed, 7 Dec 2022 18:42:05 -0500 Subject: [PATCH 2/2] tweaks --- 2022/01/test.js | 10 +++-- 2022/05/Part1.pm | 56 ++++++++++++++++++++++++++ 2022/05/part1.js | 21 +++++++--- 2022/05/part1.js.orig | 91 ++++++++++++++++++++++++++++++++++++++++++ 2022/05/part2.js | 23 +++++++++++ 2022/05/test.js | 8 ++-- 2022/05/test.t | 8 ++++ 2022/template/part2.js | 1 - 2022/template/test.js | 9 ++--- Taskfile.yaml | 7 ++++ 10 files changed, 213 insertions(+), 21 deletions(-) create mode 100644 2022/05/Part1.pm create mode 100644 2022/05/part1.js.orig create mode 100644 2022/05/test.t diff --git a/2022/01/test.js b/2022/01/test.js index 7da2d97..da1e615 100644 --- a/2022/01/test.js +++ b/2022/01/test.js @@ -1,14 +1,17 @@ import * as R from "remeda"; import { test, expect } from "vitest"; import fs from "fs-extra"; -import path from 'path'; -import { expectSolution } from './main.js'; +import path from "path"; +import { expectSolution } from "./main.js"; const split = (splitter) => (text) => text.split(splitter); const sum = R.sumBy(R.identity); const input = R.pipe( - fs.readFileSync( path.join( path.dirname(import.meta.url), "input").replace('file:',''), "utf8"), + fs.readFileSync( + path.join(path.dirname(import.meta.url), "input").replace("file:", ""), + "utf8" + ), split("\n\n"), R.map((x) => split("\n")(x) @@ -18,7 +21,6 @@ const input = R.pipe( R.map(sum) ); - test("part 1", () => { const maxCalories = R.pipe(input, (calories) => Math.max(...calories)); diff --git a/2022/05/Part1.pm b/2022/05/Part1.pm new file mode 100644 index 0000000..2724832 --- /dev/null +++ b/2022/05/Part1.pm @@ -0,0 +1,56 @@ +package Part1; + +use 5.36.0; + +our @ISA = 'Exporter'; +our @EXPORT_OK = qw/ part1 $sample /; + +use Path::Tiny; + +our $sample = path('./sample')->slurp; + +sub parse_heaps($heaps) { + my( $header, @crates ) = reverse split "\n", $heaps; + + my @stacks; + + while( $header !~ /^\s*$/ ) { + $header =~ s/^(\s+)\d//; + my $n = length $1; + @crates = map { no warnings; substr $_, $n } @crates; + + my @stack = grep { /\w/ } map { no warnings; s/(.)//; $1 } @crates; + push @stacks, \@stack; + } + + return @stacks; +} + +sub parse_commands($text) { + return map { [/\d+/g] } split "\n", $text +} + +sub move_stacks($stacks, $commands) { + for my $command ( @$commands ) { + for( 1..$command->[0] ) { + push $stacks->[$command->[2] - 1]->@*, + pop $stacks->[$command->[1]- 1]->@*; + + } + } + + return @$stacks; +} + +sub part1($text) { + my( $heaps, $commands ) = split "\n\n", $text; + + my @heaps = parse_heaps($heaps); + my @commands = parse_commands($commands); + + my @stacks = move_stacks( \@heaps, \@commands ); + + return join '', map { pop @$_ } @stacks; +} + +1; diff --git a/2022/05/part1.js b/2022/05/part1.js index 37c24fc..a620123 100644 --- a/2022/05/part1.js +++ b/2022/05/part1.js @@ -1,9 +1,14 @@ import * as R from "remeda"; -import { readFile } from "../03/part1.js"; +import fs from "fs-extra"; +import path from "path"; +import { fileURLToPath } from "url"; -export const sample = readFile("2022", "05", "sample"); -export const puzzleInput = readFile("2022", "05", "input"); +export const readFile = (url, file) => + fs.readFileSync(path.join(fileURLToPath(new URL(".", url)), file), "utf8"); + +export const sample = readFile(import.meta.url, "sample"); +export const puzzleInput = readFile(import.meta.url, "input"); function parseHeaps(text) { const lines = text.split("\n").filter(R.identity); @@ -54,16 +59,20 @@ function moveStacks([stacks, commands]) { return stacks; } -const spy = (x) => { +export const spy = (x) => { console.log(x); return x; }; +export const parseLines = ([heaps, commands]) => [ + parseHeaps(heaps), + parseCommands(commands), +]; + export const solutionPart1 = R.createPipe( (text) => text.split("\n\n"), - ([heaps, commands]) => [parseHeaps(heaps), parseCommands(commands)], + parseLines, moveStacks, - spy, R.map((x) => x.pop()), (x) => x.join("") ); diff --git a/2022/05/part1.js.orig b/2022/05/part1.js.orig new file mode 100644 index 0000000..0ccf64f --- /dev/null +++ b/2022/05/part1.js.orig @@ -0,0 +1,91 @@ +import * as R from "remeda"; + +import fs from "fs-extra"; +import path from "path"; +import { fileURLToPath } from "url"; + +export const readFile = (url, file) => + fs.readFileSync(path.join(fileURLToPath(new URL(".", url)), file), "utf8"); + +export const sample = readFile(import.meta.url, "sample"); +export const puzzleInput = readFile(import.meta.url, "input"); + +function parseHeaps(text) { + const lines = text.split("\n").filter(R.identity); + lines.reverse(); + + let [header, ...crates] = lines; + + const stacks = []; + + while (header.trimEnd()) { + header = header.replace(/^(\s+)\d/, (...args) => { + crates = crates.map((c) => c.slice(args[1].length)); + + const stack = []; + + crates = crates.map((l) => + l.replace(/./, (c) => { + if (c !== " ") stack.push(c); + return ""; + }) + ); + + stacks.push(stack); + + return ""; + }); + } + + return stacks; +} + +function parseCommands(text) { + return text + .split("\n") + .filter(R.identity) + .map((line) => line.match(/\d+/g).map((x) => parseInt(x))); +} + +function moveStacks([stacks, commands]) { + for (let [move, from, to] of commands) { + console.log({ move, from, to }); + + while (move-- > 0) { + stacks[to - 1].push(stacks[from - 1].pop()); + } + } + + return stacks; +} + +<<<<<<< HEAD +const spy = (x) => { + console.log(x); + return x; +}; + +export const solutionPart1 = R.createPipe( + (text) => text.split("\n\n"), + ([heaps, commands]) => [parseHeaps(heaps), parseCommands(commands)], + moveStacks, + spy, +======= +export const spy = (x) => { + console.log(x); + return x; +}; + +export const parseLines = ([heaps, commands]) => [ + parseHeaps(heaps), + parseCommands(commands), +]; + +export const solutionPart1 = R.createPipe( + (text) => text.split("\n\n"), + parseLines, + moveStacks, +>>>>>>> 2a1e7da (part 1) + R.map((x) => x.pop()), + (x) => x.join("") +); diff --git a/2022/05/part2.js b/2022/05/part2.js index b509eb0..590d6b8 100644 --- a/2022/05/part2.js +++ b/2022/05/part2.js @@ -1 +1,24 @@ import * as R from "remeda"; + +import { parseLines, spy } from "./part1.js"; + +function moveStacks([stacks, commands]) { + for (let [move, from, to] of commands) { + console.log({ move, from, to }); + + stacks[to - 1].push( + ...stacks[from - 1].splice(stacks[from - 1].length - move) + ); + } + + return stacks; +} + +export default R.createPipe( + (text) => text.split("\n\n"), + parseLines, + moveStacks, + spy, + R.map((x) => x.pop()), + (x) => x.join("") +); diff --git a/2022/05/test.js b/2022/05/test.js index 31df8ed..efc5dcc 100644 --- a/2022/05/test.js +++ b/2022/05/test.js @@ -2,19 +2,19 @@ import { test, expect, describe } from "vitest"; import { expectSolution } from "../01/main.js"; import { solutionPart1, puzzleInput, sample } from "./part1.js"; -import { solutionPart2 } from "./part2.js"; +import part2 from "./part2.js"; describe("part 1", () => { test("sample", () => { expect(solutionPart1(sample)).toEqual("CMZ"); }); - test.only("solution", () => { + test("solution", () => { expectSolution(solutionPart1(puzzleInput)).toEqual("VPCDMSLWJ"); }); }); describe("part 2", () => { - test.todo("solution", () => { - expectSolution(solutionPart2(puzzleInput)).toEqual("TODO"); + test("solution", () => { + expectSolution(part2(puzzleInput)).toEqual("TPWCGNCCG"); }); }); diff --git a/2022/05/test.t b/2022/05/test.t new file mode 100644 index 0000000..91a5822 --- /dev/null +++ b/2022/05/test.t @@ -0,0 +1,8 @@ +use 5.36.0; + +use Test2::V0; + +use Part1 qw/ part1 $sample /; + +is part1($sample) => 'CMZ'; + diff --git a/2022/template/part2.js b/2022/template/part2.js index 31477e8..b509eb0 100644 --- a/2022/template/part2.js +++ b/2022/template/part2.js @@ -1,2 +1 @@ import * as R from "remeda"; - diff --git a/2022/template/test.js b/2022/template/test.js index 9859a0e..07ae1e1 100644 --- a/2022/template/test.js +++ b/2022/template/test.js @@ -1,20 +1,17 @@ import { test, expect, describe } from "vitest"; import { expectSolution } from "../01/main.js"; -import { - solutionPart1, - puzzleInput, -} from "./part1.js"; +import { solutionPart1, puzzleInput } from "./part1.js"; import { solutionPart2 } from "./part2.js"; describe("part 1", () => { test.todo("solution", () => { - expectSolution(solutionPart1(puzzleInput)).toEqual('TODO'); + expectSolution(solutionPart1(puzzleInput)).toEqual("TODO"); }); }); describe("part 2", () => { test.todo("solution", () => { - expectSolution(solutionPart2(puzzleInput)).toEqual('TODO'); + expectSolution(solutionPart2(puzzleInput)).toEqual("TODO"); }); }); diff --git a/Taskfile.yaml b/Taskfile.yaml index ba044cb..af75c42 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -3,6 +3,9 @@ version: "3" vars: + YEAR: 2022 + DAY: + sh: date '+%d' | perl -pe's/^0//' GREETING: Hello, World! tasks: @@ -18,6 +21,10 @@ tasks: cmds: - npx prettier --write {{.CLI_ARGS | default "." }} + page: + cmds: + - firefox https://adventofcode.com/{{.YEAR}}/day/{{.DAY}} + default: cmds: - echo "{{.GREETING}}"