diff --git a/2023/04/benchmark.js b/2023/04/benchmark.js new file mode 100644 index 0000000..69b227e --- /dev/null +++ b/2023/04/benchmark.js @@ -0,0 +1,38 @@ +import fs from "fs-extra"; +import { parse } from "yaml"; +import { Bench } from "tinybench"; +import assert from "assert"; + +import { solution_1 } from "./part1.js"; +import { solution_2 } from "./part2.js"; + +const input = fs.readFileSync("./input", { encoding: "utf8" }); +const solutions = parse( + fs.readFileSync("./solutions.yml", { encoding: "utf8" }) +); + +const bench = new Bench({ time: 10000 }); + +bench + .add("1", () => { + assert.equal(solution_1(input), solutions[1]); + }) + .add("2", () => { + assert.equal(solution_2(input), solutions[2]); + }); + +await bench.run(); + +bench.tasks.forEach(({ result, name }) => { + console.log( + JSON.stringify({ + day: 1, + year: 2023, + language: "javascript", + part: name, + timestamp: new Date().toISOString(), + time: result.mean / 1000, + persec: 1000 / result.mean, + }) + ); +}); diff --git a/2023/04/benchmark.test.js b/2023/04/benchmark.test.js new file mode 100644 index 0000000..5fb0b6a --- /dev/null +++ b/2023/04/benchmark.test.js @@ -0,0 +1,12 @@ +import { bench, expect } from "vitest"; +import { readFileSync } from "fs-extra"; +import { parse } from "yaml"; + +import { solution_1 } from "./part1.js"; + +const input = readFileSync("./input", { encoding: "utf8" }); +const solutions = parse(readFileSync("./solutions.yml", { encoding: "utf8" })); + +bench("part 1", () => { + expect(solution_1(input)).toBe(solutions[1]); +}); diff --git a/2023/04/example b/2023/04/example new file mode 100644 index 0000000..9bdb874 --- /dev/null +++ b/2023/04/example @@ -0,0 +1,6 @@ +Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 diff --git a/2023/04/part1.js b/2023/04/part1.js new file mode 100644 index 0000000..5439f5b --- /dev/null +++ b/2023/04/part1.js @@ -0,0 +1,28 @@ +import * as R from "remeda"; + +export const slice_and_dice = R.createPipe( + (l) => + l + .replace(/Card \d+:/, "") + .split("|") + .map((segment) => segment.split(" ").filter(R.identity)), + ([winning, mine]) => { + let seen = {}; + winning.forEach((n) => (seen[n] = true)); + let got = mine.filter((n) => seen[n]).length; + return got; + }, + (n) => (n == 0 ? 0 : Math.pow(2, n - 1)) +); + +export const get_lines = R.createPipe( (i) => i.split("\n"), +R.compact); + +export function solution_1(input) { + return R.pipe( + input, + get_lines, + R.map(slice_and_dice), + R.sumBy(R.identity) + ); +} diff --git a/2023/04/part2.js b/2023/04/part2.js new file mode 100644 index 0000000..914fc35 --- /dev/null +++ b/2023/04/part2.js @@ -0,0 +1,31 @@ +import * as R from "remeda"; + +import { get_lines } from "./part1.js"; + +export function solution_2(input) { + const cards = get_lines(input); + + const cards_won = cards.map(()=>1); + let total_won = 0; + + while( cards.length ) { + // console.log(cards_won); + let card = cards.shift(); + const [ winning, mine ] = card + .replace(/Card \d+:/, "") + .split("|") + .map((segment) => segment.split(" ").filter(R.identity)); + + let seen = {}; + winning.forEach((n) => (seen[n] = true)); + let got = mine.filter((n) => seen[n]).length; + + R.range(1,got+1).forEach( i => { + cards_won[i] = (cards_won[i] ?? 0 ) +cards_won[0]; + }); + + total_won += cards_won.shift()??0; + } + + return total_won; +} diff --git a/2023/04/solutions.yml b/2023/04/solutions.yml new file mode 100644 index 0000000..23a78b7 --- /dev/null +++ b/2023/04/solutions.yml @@ -0,0 +1,2 @@ +1: 23678 +2: 15455663 diff --git a/2023/04/test.js b/2023/04/test.js new file mode 100644 index 0000000..27df077 --- /dev/null +++ b/2023/04/test.js @@ -0,0 +1,23 @@ +import { test, expect } from "vitest"; +import { readFileSync } from "fs-extra"; +import { parse } from "yaml"; + +import { solution_1, slice_and_dice } from "./part1.js"; +import { solution_2 } from "./part2.js"; + +const input = readFileSync("./input", { encoding: "utf8" }); +const example = readFileSync("./example", { encoding: "utf8" }); +const solutions = parse(readFileSync("./solutions.yml", { encoding: "utf8" })); + +test("part 1", () => { + expect( + slice_and_dice("Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53") + ).toBe(8); + + expect(solution_1(example)).toBe(13); + expect(solution_1(input)).toBe(solutions["1"]); +}); +test("part 2", () => { + expect(solution_2(example)).toBe(30); + expect(solution_2(input)).toBe(solutions["2"]); +}); diff --git a/2023/benchmark.json b/2023/benchmark.json index 4d326db..59a284c 100644 --- a/2023/benchmark.json +++ b/2023/benchmark.json @@ -6,5 +6,7 @@ {"language":"perl","timestamp":"2023-12-02T16:40:55","part":2,"day":"2","time":0.00338658146964856,"year":"2023","persec":295.283018867925} {"timestamp":"2023-12-02T18:29:20","day":"2","part":1,"variant":"v2","year":"2023","time":0.00388473053892216,"language":"perl","persec":257.418111753372} {"day":"2","timestamp":"2023-12-02T18:29:32","part":2,"year":"2023","variant":"v2","persec":258.117195004803,"language":"perl","time":0.00387420915519166} -{"time":0.00837944664031621,"timestamp":"2023-12-03T20:10:46","parsec":119.339622641509,"day":"3","year":"2023","part":1,"language":"perl"} -{"year":"2023","day":"3","parsec":4.03940886699507,"language":"perl","part":2,"time":0.247560975609756,"timestamp":"2023-12-03T20:10:59"} +{"time":0.00837944664031621,"timestamp":"2023-12-03T20:10:46","persec":119.339622641509,"day":"3","year":"2023","part":1,"language":"perl"} +{"year":"2023","day":"3","persec":4.03940886699507,"language":"perl","part":2,"time":0.247560975609756,"timestamp":"2023-12-03T20:10:59"} +{"day":4,"year":2023,"language":"javascript","part":"1","timestamp":"2023-12-04T15:22:09.048Z","time":0.0021685645699029317,"persec":461.13452828603647} +{"day":4,"year":2023,"language":"javascript","part":"2","timestamp":"2023-12-04T15:22:09.052Z","time":0.002291685911610818,"persec":436.3599719025647} diff --git a/2023/preset/day/preset.ts b/2023/preset/day/preset.ts index 163677f..abdd037 100644 --- a/2023/preset/day/preset.ts +++ b/2023/preset/day/preset.ts @@ -1,13 +1,19 @@ export default definePreset({ name: 'day', options: { - perl: true, + perl: false, + js: false, }, handler: async(context) => { if( context.options.perl ) { await extractTemplates({ from: 'perl', whenConflict: 'skip' }) + } + if( context.options.js ) { + await extractTemplates({ + from: 'js', whenConflict: 'skip' + }) } // ... }, diff --git a/2023/preset/day/templates/js/benchmark.js b/2023/preset/day/templates/js/benchmark.js new file mode 100644 index 0000000..5d7fe0c --- /dev/null +++ b/2023/preset/day/templates/js/benchmark.js @@ -0,0 +1,33 @@ +import fs from 'fs-extra'; +import { parse } from 'yaml'; +import { Bench } from 'tinybench'; +import assert from 'assert'; + +import { solution_1 } from './part1.js'; +import { solution_2 } from './part2.js'; + +const input = fs.readFileSync('./input',{ encoding: 'utf8'}); +const solutions = parse( fs.readFileSync('./solutions.yml',{encoding:'utf8'})); + +const bench = new Bench({time: 10000}); + +bench.add( '1', () => { + assert.equal(solution_1(input),solutions[1]) +}) +.add( '2', () => { + assert.equal(solution_2(input),solutions[2]) +}); + +await bench.run(); + +bench.tasks.forEach( ({result,name}) => { + console.log(JSON.stringify({ + day : 1, + year : 2023, + language: 'javascript', + part: name, + timestamp: new Date().toISOString(), + time: result.mean / 1000, + persec: 1000 / result.mean, + })); +}) diff --git a/2023/preset/day/templates/js/benchmark.test.js b/2023/preset/day/templates/js/benchmark.test.js new file mode 100644 index 0000000..4ec0bda --- /dev/null +++ b/2023/preset/day/templates/js/benchmark.test.js @@ -0,0 +1,13 @@ +import { bench, expect } from 'vitest'; +import { readFileSync } from 'fs-extra'; +import { parse } from 'yaml'; + +import { solution_1 } from './part1.js'; + +const input = readFileSync('./input',{ encoding: 'utf8'}); +const solutions = parse( readFileSync('./solutions.yml',{encoding:'utf8'})); + +bench( 'part 1', () => { + expect(solution_1(input)).toBe(solutions[1]) +}); + diff --git a/2023/preset/day/templates/js/part1.js b/2023/preset/day/templates/js/part1.js new file mode 100644 index 0000000..2520ce0 --- /dev/null +++ b/2023/preset/day/templates/js/part1.js @@ -0,0 +1,6 @@ +import * as R from 'remeda'; + + +export function solution_1(input) { + +} diff --git a/2023/preset/day/templates/js/part2.js b/2023/preset/day/templates/js/part2.js new file mode 100644 index 0000000..0eb2b95 --- /dev/null +++ b/2023/preset/day/templates/js/part2.js @@ -0,0 +1,5 @@ +import * as R from 'remeda'; + +import { } from './part1.js'; + +export function solution_2(input){} diff --git a/2023/preset/day/templates/js/test.js b/2023/preset/day/templates/js/test.js new file mode 100644 index 0000000..5649d82 --- /dev/null +++ b/2023/preset/day/templates/js/test.js @@ -0,0 +1,16 @@ +import { test, expect } from 'vitest'; +import { readFileSync } from 'fs-extra'; +import { parse } from 'yaml'; + +import { solution_1 } from './part1.js'; +import { solution_2 } from './part2.js'; + +const input = readFileSync('./input',{ encoding: 'utf8'}); +const solutions = parse( readFileSync('./solutions.yml',{encoding:'utf8'})); + +test( 'part 1', () => { + expect( solution_1(input)).toBe(solutions['1']); +}) +test( 'part 2', () => { + expect( solution_2(input)).toBe(solutions['2']); +})