From 62aa6e6a9378ad52619ea2c2301e9ccdc4e41648 Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Tue, 12 Aug 2025 17:16:00 -0400 Subject: [PATCH 1/9] initial passing tests --- .gitignore | 1 + .prettierrc | 10 + .vscode/settings.json | 5 + main.mjs | 26 ++ main.test.mjs | 22 + package.json | 19 + pnpm-lock.yaml | 955 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1038 insertions(+) create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 .vscode/settings.json create mode 100644 main.mjs create mode 100644 main.test.mjs create mode 100644 package.json create mode 100644 pnpm-lock.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..87669c6 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "arrowParens": "avoid", + "printWidth": 1000, + "bracketSameLine": true, + "bracketSpacing": false, + "objectWrap": "collapse", + "semi": false, + "singleAttributePerLine": false, + "trailingComma": "none" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ddcd4d8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "github.copilot.enable": { + "*": false + } +} diff --git a/main.mjs b/main.mjs new file mode 100644 index 0000000..8b7bade --- /dev/null +++ b/main.mjs @@ -0,0 +1,26 @@ +import * as fs from "fs" + +let p = [ + [1000, "M"], + [500, "D"], + [400, "CD"], + [100, "C"], + [50, "L"], + [40, "XL"], + [10, "X"], + [5, "V"], + [4, "IV"] +] + +let c = fs.readFileSync(process.argv[2]) +c.split("\n").forEach(l => { + let v = "I".repeat(parseInt(l)) + let o = "" + p.forEach(([x, r]) => { + while (v.length >= x) { + o += r + v = v.slice(x) + } + }) + console.log(o + v) +}) diff --git a/main.test.mjs b/main.test.mjs new file mode 100644 index 0000000..5308c3a --- /dev/null +++ b/main.test.mjs @@ -0,0 +1,22 @@ +import {expect} from "vitest" +import {it, mock, vi, beforeEach} from "vitest" + +vi.mock("fs", () => ({ + readFileSync: () => `43 +104 +243 +401 +3277 +` +})) + +let log = vi.spyOn(console, "log") + +it("produces the right output", async () => { + await import("./main.mjs") + expect(log).toHaveBeenNthCalledWith(1, "XLIII") + expect(log).toHaveBeenNthCalledWith(2, "CIV") + expect(log).toHaveBeenNthCalledWith(3, "CCXLIII") + expect(log).toHaveBeenNthCalledWith(4, "CDI") + expect(log).toHaveBeenNthCalledWith(5, "MMMCCLXXVII") +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..ef15e47 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "code_golf", + "dependencies": { + "@types/node": "24.2.1" + }, + "engines": { + "node": "24.5.0" + }, + "volta": { + "node": "24.5.0" + }, + "scripts": { + "test": "vitest", + "start": "node ./main.mjs" + }, + "devDependencies": { + "vitest": "^3.2.4" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9ccc125 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,955 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@types/node': + specifier: 24.2.1 + version: 24.2.1 + devDependencies: + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/node@24.2.1) + +packages: + + '@esbuild/aix-ppc64@0.25.8': + resolution: {integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.8': + resolution: {integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.8': + resolution: {integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.8': + resolution: {integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.8': + resolution: {integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.8': + resolution: {integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.8': + resolution: {integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.8': + resolution: {integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.8': + resolution: {integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.8': + resolution: {integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.8': + resolution: {integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.8': + resolution: {integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.8': + resolution: {integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.8': + resolution: {integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.8': + resolution: {integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.8': + resolution: {integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.8': + resolution: {integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.8': + resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.8': + resolution: {integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.8': + resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.8': + resolution: {integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.8': + resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.8': + resolution: {integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.8': + resolution: {integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.8': + resolution: {integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.8': + resolution: {integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@rollup/rollup-android-arm-eabi@4.46.2': + resolution: {integrity: sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.46.2': + resolution: {integrity: sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.46.2': + resolution: {integrity: sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.46.2': + resolution: {integrity: sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.46.2': + resolution: {integrity: sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.46.2': + resolution: {integrity: sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.46.2': + resolution: {integrity: sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.46.2': + resolution: {integrity: sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.46.2': + resolution: {integrity: sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.46.2': + resolution: {integrity: sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.46.2': + resolution: {integrity: sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.46.2': + resolution: {integrity: sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.46.2': + resolution: {integrity: sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.46.2': + resolution: {integrity: sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.46.2': + resolution: {integrity: sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.46.2': + resolution: {integrity: sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.46.2': + resolution: {integrity: sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.46.2': + resolution: {integrity: sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.46.2': + resolution: {integrity: sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.46.2': + resolution: {integrity: sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==} + cpu: [x64] + os: [win32] + + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@24.2.1': + resolution: {integrity: sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==} + + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + chai@5.2.1: + resolution: {integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==} + engines: {node: '>=18'} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + esbuild@0.25.8: + resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==} + engines: {node: '>=18'} + hasBin: true + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} + engines: {node: '>=12.0.0'} + + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + loupe@3.2.0: + resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + rollup@4.46.2: + resolution: {integrity: sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + + strip-literal@3.0.0: + resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + engines: {node: '>=14.0.0'} + + undici-types@7.10.0: + resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} + + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@7.1.2: + resolution: {integrity: sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + +snapshots: + + '@esbuild/aix-ppc64@0.25.8': + optional: true + + '@esbuild/android-arm64@0.25.8': + optional: true + + '@esbuild/android-arm@0.25.8': + optional: true + + '@esbuild/android-x64@0.25.8': + optional: true + + '@esbuild/darwin-arm64@0.25.8': + optional: true + + '@esbuild/darwin-x64@0.25.8': + optional: true + + '@esbuild/freebsd-arm64@0.25.8': + optional: true + + '@esbuild/freebsd-x64@0.25.8': + optional: true + + '@esbuild/linux-arm64@0.25.8': + optional: true + + '@esbuild/linux-arm@0.25.8': + optional: true + + '@esbuild/linux-ia32@0.25.8': + optional: true + + '@esbuild/linux-loong64@0.25.8': + optional: true + + '@esbuild/linux-mips64el@0.25.8': + optional: true + + '@esbuild/linux-ppc64@0.25.8': + optional: true + + '@esbuild/linux-riscv64@0.25.8': + optional: true + + '@esbuild/linux-s390x@0.25.8': + optional: true + + '@esbuild/linux-x64@0.25.8': + optional: true + + '@esbuild/netbsd-arm64@0.25.8': + optional: true + + '@esbuild/netbsd-x64@0.25.8': + optional: true + + '@esbuild/openbsd-arm64@0.25.8': + optional: true + + '@esbuild/openbsd-x64@0.25.8': + optional: true + + '@esbuild/openharmony-arm64@0.25.8': + optional: true + + '@esbuild/sunos-x64@0.25.8': + optional: true + + '@esbuild/win32-arm64@0.25.8': + optional: true + + '@esbuild/win32-ia32@0.25.8': + optional: true + + '@esbuild/win32-x64@0.25.8': + optional: true + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@rollup/rollup-android-arm-eabi@4.46.2': + optional: true + + '@rollup/rollup-android-arm64@4.46.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.46.2': + optional: true + + '@rollup/rollup-darwin-x64@4.46.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.46.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.46.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.46.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.46.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.46.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.46.2': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.46.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.46.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.46.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.46.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.46.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.46.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.46.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.46.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.46.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.46.2': + optional: true + + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/node@24.2.1': + dependencies: + undici-types: 7.10.0 + + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.1 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@7.1.2(@types/node@24.2.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 7.1.2(@types/node@24.2.1) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.0.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.3 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.0 + tinyrainbow: 2.0.0 + + assertion-error@2.0.1: {} + + cac@6.7.14: {} + + chai@5.2.1: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.2.0 + pathval: 2.0.1 + + check-error@2.1.1: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + deep-eql@5.0.2: {} + + es-module-lexer@1.7.0: {} + + esbuild@0.25.8: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.8 + '@esbuild/android-arm': 0.25.8 + '@esbuild/android-arm64': 0.25.8 + '@esbuild/android-x64': 0.25.8 + '@esbuild/darwin-arm64': 0.25.8 + '@esbuild/darwin-x64': 0.25.8 + '@esbuild/freebsd-arm64': 0.25.8 + '@esbuild/freebsd-x64': 0.25.8 + '@esbuild/linux-arm': 0.25.8 + '@esbuild/linux-arm64': 0.25.8 + '@esbuild/linux-ia32': 0.25.8 + '@esbuild/linux-loong64': 0.25.8 + '@esbuild/linux-mips64el': 0.25.8 + '@esbuild/linux-ppc64': 0.25.8 + '@esbuild/linux-riscv64': 0.25.8 + '@esbuild/linux-s390x': 0.25.8 + '@esbuild/linux-x64': 0.25.8 + '@esbuild/netbsd-arm64': 0.25.8 + '@esbuild/netbsd-x64': 0.25.8 + '@esbuild/openbsd-arm64': 0.25.8 + '@esbuild/openbsd-x64': 0.25.8 + '@esbuild/openharmony-arm64': 0.25.8 + '@esbuild/sunos-x64': 0.25.8 + '@esbuild/win32-arm64': 0.25.8 + '@esbuild/win32-ia32': 0.25.8 + '@esbuild/win32-x64': 0.25.8 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + expect-type@1.2.2: {} + + fdir@6.4.6(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fsevents@2.3.3: + optional: true + + js-tokens@9.0.1: {} + + loupe@3.2.0: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + rollup@4.46.2: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.46.2 + '@rollup/rollup-android-arm64': 4.46.2 + '@rollup/rollup-darwin-arm64': 4.46.2 + '@rollup/rollup-darwin-x64': 4.46.2 + '@rollup/rollup-freebsd-arm64': 4.46.2 + '@rollup/rollup-freebsd-x64': 4.46.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.46.2 + '@rollup/rollup-linux-arm-musleabihf': 4.46.2 + '@rollup/rollup-linux-arm64-gnu': 4.46.2 + '@rollup/rollup-linux-arm64-musl': 4.46.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.46.2 + '@rollup/rollup-linux-ppc64-gnu': 4.46.2 + '@rollup/rollup-linux-riscv64-gnu': 4.46.2 + '@rollup/rollup-linux-riscv64-musl': 4.46.2 + '@rollup/rollup-linux-s390x-gnu': 4.46.2 + '@rollup/rollup-linux-x64-gnu': 4.46.2 + '@rollup/rollup-linux-x64-musl': 4.46.2 + '@rollup/rollup-win32-arm64-msvc': 4.46.2 + '@rollup/rollup-win32-ia32-msvc': 4.46.2 + '@rollup/rollup-win32-x64-msvc': 4.46.2 + fsevents: 2.3.3 + + siginfo@2.0.0: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@3.9.0: {} + + strip-literal@3.0.0: + dependencies: + js-tokens: 9.0.1 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.3: {} + + undici-types@7.10.0: {} + + vite-node@3.2.4(@types/node@24.2.1): + dependencies: + cac: 6.7.14 + debug: 4.4.1 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.1.2(@types/node@24.2.1) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@7.1.2(@types/node@24.2.1): + dependencies: + esbuild: 0.25.8 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.46.2 + tinyglobby: 0.2.14 + optionalDependencies: + '@types/node': 24.2.1 + fsevents: 2.3.3 + + vitest@3.2.4(@types/node@24.2.1): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.1.2(@types/node@24.2.1)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.1 + debug: 4.4.1 + expect-type: 1.2.2 + magic-string: 0.30.17 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.1.2(@types/node@24.2.1) + vite-node: 3.2.4(@types/node@24.2.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.2.1 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 From e85eaf913e8ecf4844c48bc28663a4b6ad2088a6 Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Tue, 12 Aug 2025 17:41:08 -0400 Subject: [PATCH 2/9] smaller --- .prettierrc | 10 ---------- .vscode/settings.json | 4 +++- main.mjs | 27 +-------------------------- main.test.mjs | 8 +++++++- min.mjs | 3 +++ package.json | 3 ++- src.mjs | 11 +++++++++++ 7 files changed, 27 insertions(+), 39 deletions(-) delete mode 100644 .prettierrc create mode 100644 min.mjs create mode 100644 src.mjs diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 87669c6..0000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "arrowParens": "avoid", - "printWidth": 1000, - "bracketSameLine": true, - "bracketSpacing": false, - "objectWrap": "collapse", - "semi": false, - "singleAttributePerLine": false, - "trailingComma": "none" -} diff --git a/.vscode/settings.json b/.vscode/settings.json index ddcd4d8..303ddc4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { "github.copilot.enable": { "*": false - } + }, + "prettier.enable": false, + "prettier.requireConfig": true } diff --git a/main.mjs b/main.mjs index 8b7bade..409547a 100644 --- a/main.mjs +++ b/main.mjs @@ -1,26 +1 @@ -import * as fs from "fs" - -let p = [ - [1000, "M"], - [500, "D"], - [400, "CD"], - [100, "C"], - [50, "L"], - [40, "XL"], - [10, "X"], - [5, "V"], - [4, "IV"] -] - -let c = fs.readFileSync(process.argv[2]) -c.split("\n").forEach(l => { - let v = "I".repeat(parseInt(l)) - let o = "" - p.forEach(([x, r]) => { - while (v.length >= x) { - o += r - v = v.slice(x) - } - }) - console.log(o + v) -}) +import * as fs from "fs";let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2]).split("\n")) { v = "I".repeat(0+l); o = ""; for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); console.log(o + v)} \ No newline at end of file diff --git a/main.test.mjs b/main.test.mjs index 5308c3a..9a1b88d 100644 --- a/main.test.mjs +++ b/main.test.mjs @@ -1,5 +1,6 @@ import {expect} from "vitest" import {it, mock, vi, beforeEach} from "vitest" +import * as fs from "fs/promises" vi.mock("fs", () => ({ readFileSync: () => `43 @@ -13,10 +14,15 @@ vi.mock("fs", () => ({ let log = vi.spyOn(console, "log") it("produces the right output", async () => { - await import("./main.mjs") + await import("./src.mjs") expect(log).toHaveBeenNthCalledWith(1, "XLIII") expect(log).toHaveBeenNthCalledWith(2, "CIV") expect(log).toHaveBeenNthCalledWith(3, "CCXLIII") expect(log).toHaveBeenNthCalledWith(4, "CDI") expect(log).toHaveBeenNthCalledWith(5, "MMMCCLXXVII") }) + +it("golfs", async () => { + const content = await fs.readFile("./main.mjs", "utf-8") + expect(content.length).toMatchInlineSnapshot(`320`) +}) diff --git a/min.mjs b/min.mjs new file mode 100644 index 0000000..518eed9 --- /dev/null +++ b/min.mjs @@ -0,0 +1,3 @@ +import * as fs from 'fs'; +const content = fs.readFileSync('./src.mjs', 'utf-8'); +fs.writeFileSync('./main.mjs', content.replace(/\n+/g, '')); \ No newline at end of file diff --git a/package.json b/package.json index ef15e47..30e8ad4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "scripts": { "test": "vitest", - "start": "node ./main.mjs" + "start": "node ./main.mjs", + "min": "node ./min.mjs" }, "devDependencies": { "vitest": "^3.2.4" diff --git a/src.mjs b/src.mjs new file mode 100644 index 0000000..6c2d4d3 --- /dev/null +++ b/src.mjs @@ -0,0 +1,11 @@ +import * as fs from "fs"; + +let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]], +v,o,x,r,l; + +for (l of fs.readFileSync(process.argv[2]).split("\n")) { + v = "I".repeat(0+l); + o = ""; + for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); + console.log(o + v) +} From 5cc66ec851a7ad4bf368c5fd30f9787737ca0abe Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Tue, 12 Aug 2025 17:43:15 -0400 Subject: [PATCH 3/9] fix fs error --- main.mjs | 2 +- main.test.mjs | 2 +- package.json | 2 +- src.mjs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main.mjs b/main.mjs index 409547a..af86ff8 100644 --- a/main.mjs +++ b/main.mjs @@ -1 +1 @@ -import * as fs from "fs";let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2]).split("\n")) { v = "I".repeat(0+l); o = ""; for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); console.log(o + v)} \ No newline at end of file +import * as fs from "fs";let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")) { v = "I".repeat(0+l); o = ""; for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); console.log(o + v)} \ No newline at end of file diff --git a/main.test.mjs b/main.test.mjs index 9a1b88d..eacc86e 100644 --- a/main.test.mjs +++ b/main.test.mjs @@ -24,5 +24,5 @@ it("produces the right output", async () => { it("golfs", async () => { const content = await fs.readFile("./main.mjs", "utf-8") - expect(content.length).toMatchInlineSnapshot(`320`) + expect(content.length).toMatchInlineSnapshot(`328`) }) diff --git a/package.json b/package.json index 30e8ad4..b53dd25 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "scripts": { "test": "vitest", - "start": "node ./main.mjs", + "start": "pnpm min && node ./main.mjs", "min": "node ./min.mjs" }, "devDependencies": { diff --git a/src.mjs b/src.mjs index 6c2d4d3..1f8be04 100644 --- a/src.mjs +++ b/src.mjs @@ -3,7 +3,7 @@ import * as fs from "fs"; let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]], v,o,x,r,l; -for (l of fs.readFileSync(process.argv[2]).split("\n")) { +for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")) { v = "I".repeat(0+l); o = ""; for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); From ea8cc137c0bf1297d5b97518ff2919873b422ddf Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Tue, 12 Aug 2025 17:44:46 -0400 Subject: [PATCH 4/9] instructions --- README.md | 7 +++++-- package.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f7fdde3..4a9d1bc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +# Instructions for my repo + +Install Node/NPM +`npm start` + # What is Code Golf? > Code golf is a type of recreational computer programming competition in which participants strive to achieve the shortest possible source code that solves a certain problem. Code golf challenges and tournaments may also be named with the programming language used. --- [Wikipedia](https://en.wikipedia.org/wiki/Code_golf) @@ -9,7 +14,6 @@ 3. Don't Google/Bing/DDG/Kagi for answers. 4. All pull requests must be opened before Aug 14 2025 11:30 AM EDT. - The shortest _correct_ program wins. In the event no submissions fully pass the test suite winners will be selected by number of passing test cases and code brevity. ## Supported Languages @@ -81,4 +85,3 @@ if __name__ == "__main__": ``` This repo contains a [sample file](https://github.com/kevsmith/code_golf/blob/main/input.txt) you can use for development. - diff --git a/package.json b/package.json index b53dd25..908800a 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "scripts": { "test": "vitest", - "start": "pnpm min && node ./main.mjs", + "start": "pnpm min && node ./main.mjs ./input.txt", "min": "node ./min.mjs" }, "devDependencies": { From 27187633ce52b907a615ab408db10be78ba6f8fe Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Wed, 13 Aug 2025 08:39:43 -0400 Subject: [PATCH 5/9] break 300 chars --- main.mjs | 2 +- main.test.mjs | 2 +- min.mjs | 3 ++- src.mjs | 15 ++++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/main.mjs b/main.mjs index af86ff8..6c76f7a 100644 --- a/main.mjs +++ b/main.mjs @@ -1 +1 @@ -import * as fs from "fs";let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")) { v = "I".repeat(0+l); o = ""; for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); console.log(o + v)} \ No newline at end of file +import * as fs from "fs";let p=[[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p) while(v[x-1]) {o+=r; v=v.slice(x)}console.log(o+v)} \ No newline at end of file diff --git a/main.test.mjs b/main.test.mjs index eacc86e..8df41c6 100644 --- a/main.test.mjs +++ b/main.test.mjs @@ -24,5 +24,5 @@ it("produces the right output", async () => { it("golfs", async () => { const content = await fs.readFile("./main.mjs", "utf-8") - expect(content.length).toMatchInlineSnapshot(`328`) + expect(content.length).toMatchInlineSnapshot(`292`) }) diff --git a/min.mjs b/min.mjs index 518eed9..591a086 100644 --- a/min.mjs +++ b/min.mjs @@ -1,3 +1,4 @@ import * as fs from 'fs'; + const content = fs.readFileSync('./src.mjs', 'utf-8'); -fs.writeFileSync('./main.mjs', content.replace(/\n+/g, '')); \ No newline at end of file +fs.writeFileSync('./main.mjs', content.replace(/\n+/g, '').replace(/\t+/g,'')); \ No newline at end of file diff --git a/src.mjs b/src.mjs index 1f8be04..f073227 100644 --- a/src.mjs +++ b/src.mjs @@ -1,11 +1,12 @@ import * as fs from "fs"; - -let p = [[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]], +let p=[[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]], v,o,x,r,l; -for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")) { - v = "I".repeat(0+l); - o = ""; - for ([x,r] of p) while (v.length >= x) (o += r) && (v = v.slice(x)); - console.log(o + v) +for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){ + v="I".repeat(0+l); + o=""; + for([x,r]of p) + while(v[x-1]) + {o+=r; v=v.slice(x)} + console.log(o+v) } From 8d8299a91223a4108b16b57d6afe942bd9fa18f8 Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Wed, 13 Aug 2025 08:42:45 -0400 Subject: [PATCH 6/9] more numerals support --- main.mjs | 2 +- main.test.mjs | 6 +++++- src.mjs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/main.mjs b/main.mjs index 6c76f7a..f1f5a94 100644 --- a/main.mjs +++ b/main.mjs @@ -1 +1 @@ -import * as fs from "fs";let p=[[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p) while(v[x-1]) {o+=r; v=v.slice(x)}console.log(o+v)} \ No newline at end of file +import * as fs from "fs";let p=[[1000,"M"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p) while(v[x-1]) {o+=r; v=v.slice(x)}console.log(o+v)} \ No newline at end of file diff --git a/main.test.mjs b/main.test.mjs index 8df41c6..b147fb2 100644 --- a/main.test.mjs +++ b/main.test.mjs @@ -8,6 +8,8 @@ vi.mock("fs", () => ({ 243 401 3277 +90 +449 ` })) @@ -20,9 +22,11 @@ it("produces the right output", async () => { expect(log).toHaveBeenNthCalledWith(3, "CCXLIII") expect(log).toHaveBeenNthCalledWith(4, "CDI") expect(log).toHaveBeenNthCalledWith(5, "MMMCCLXXVII") + expect(log).toHaveBeenNthCalledWith(6, "XC"); + expect(log).toHaveBeenNthCalledWith(7, "CDXLIX") }) it("golfs", async () => { const content = await fs.readFile("./main.mjs", "utf-8") - expect(content.length).toMatchInlineSnapshot(`292`) + expect(content.length).toMatchInlineSnapshot(`302`) }) diff --git a/src.mjs b/src.mjs index f073227..63b6732 100644 --- a/src.mjs +++ b/src.mjs @@ -1,5 +1,5 @@ import * as fs from "fs"; -let p=[[1000, "M"],[500, "D"],[400, "CD"],[100, "C"],[50, "L"],[40, "XL"],[10, "X"],[5, "V"],[4, "IV"]], +let p=[[1000,"M"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]], v,o,x,r,l; for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){ From 7aa160af86e314ace34faab3bf2c0af9c297aa61 Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Wed, 13 Aug 2025 08:49:55 -0400 Subject: [PATCH 7/9] add more numeral support --- main.mjs | 2 +- main.test.mjs | 26 ++++++++++++++++++-------- src.mjs | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/main.mjs b/main.mjs index f1f5a94..f9c380c 100644 --- a/main.mjs +++ b/main.mjs @@ -1 +1 @@ -import * as fs from "fs";let p=[[1000,"M"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p) while(v[x-1]) {o+=r; v=v.slice(x)}console.log(o+v)} \ No newline at end of file +import * as fs from "fs";let p=[[1000,"M"],[900,'CM'],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p) while(v[x-1]) {o+=r; v=v.slice(x)}console.log(o+v)} \ No newline at end of file diff --git a/main.test.mjs b/main.test.mjs index b147fb2..c33c48f 100644 --- a/main.test.mjs +++ b/main.test.mjs @@ -10,23 +10,33 @@ vi.mock("fs", () => ({ 3277 90 449 +1199 +905 ` })) +const outputs = [ + 'XLIII', + 'CIV', + 'CCXLIII', + 'CDI', + 'MMMCCLXXVII', + 'XC', + 'CDXLIX', + 'MCXCIX', + 'CMV' +] + let log = vi.spyOn(console, "log") it("produces the right output", async () => { await import("./src.mjs") - expect(log).toHaveBeenNthCalledWith(1, "XLIII") - expect(log).toHaveBeenNthCalledWith(2, "CIV") - expect(log).toHaveBeenNthCalledWith(3, "CCXLIII") - expect(log).toHaveBeenNthCalledWith(4, "CDI") - expect(log).toHaveBeenNthCalledWith(5, "MMMCCLXXVII") - expect(log).toHaveBeenNthCalledWith(6, "XC"); - expect(log).toHaveBeenNthCalledWith(7, "CDXLIX") + for (let i = 0; i < outputs.length; i++) { + expect(log).toHaveBeenNthCalledWith(i + 1, outputs[i]); + } }) it("golfs", async () => { const content = await fs.readFile("./main.mjs", "utf-8") - expect(content.length).toMatchInlineSnapshot(`302`) + expect(content.length).toMatchInlineSnapshot(`313`) }) diff --git a/src.mjs b/src.mjs index 63b6732..fd1b5d1 100644 --- a/src.mjs +++ b/src.mjs @@ -1,5 +1,5 @@ import * as fs from "fs"; -let p=[[1000,"M"],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]], +let p=[[1000,"M"],[900,'CM'],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]], v,o,x,r,l; for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){ From b7bb29d67c4ff462fcc96844cac4e8119351f6ba Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Wed, 13 Aug 2025 09:06:31 -0400 Subject: [PATCH 8/9] shave off a few more chars --- main.mjs | 2 +- main.test.mjs | 7 +++++++ min.mjs | 7 +++++-- src.mjs | 8 ++++---- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/main.mjs b/main.mjs index f9c380c..81fde2a 100644 --- a/main.mjs +++ b/main.mjs @@ -1 +1 @@ -import * as fs from "fs";let p=[[1000,"M"],[900,'CM'],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]],v,o,x,r,l;for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p) while(v[x-1]) {o+=r; v=v.slice(x)}console.log(o+v)} \ No newline at end of file +import * as fs from "fs";let p=[[1000,"M"],[900,'CM'],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]],v,o,x,r,l='';for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){v="I".repeat(0+l);o="";for([x,r]of p)while(v[x-1]){o+=r;v=v.slice(x)}console.log(o+v)} \ No newline at end of file diff --git a/main.test.mjs b/main.test.mjs index c33c48f..9927849 100644 --- a/main.test.mjs +++ b/main.test.mjs @@ -36,6 +36,13 @@ it("produces the right output", async () => { } }) +it("produces the right output minified", async () => { + await import("./main.mjs") + for (let i = 0; i < outputs.length; i++) { + expect(log).toHaveBeenNthCalledWith(i + 1, outputs[i]); + } +}) + it("golfs", async () => { const content = await fs.readFile("./main.mjs", "utf-8") expect(content.length).toMatchInlineSnapshot(`313`) diff --git a/min.mjs b/min.mjs index 591a086..73217da 100644 --- a/min.mjs +++ b/min.mjs @@ -1,4 +1,7 @@ import * as fs from 'fs'; -const content = fs.readFileSync('./src.mjs', 'utf-8'); -fs.writeFileSync('./main.mjs', content.replace(/\n+/g, '').replace(/\t+/g,'')); \ No newline at end of file + +fs.watchFile('./src.mjs', { }, (cur) => { + const content = fs.readFileSync('./src.mjs', 'utf-8'); + fs.writeFileSync('./main.mjs', content.replace(/\/\/.*$/gm,'').replace(/\n+/g, '').replace(/\t+/g,'')); +}) \ No newline at end of file diff --git a/src.mjs b/src.mjs index fd1b5d1..12c6f43 100644 --- a/src.mjs +++ b/src.mjs @@ -1,12 +1,12 @@ import * as fs from "fs"; let p=[[1000,"M"],[900,'CM'],[500,"D"],[400,"CD"],[100,"C"],[90,"XC"],[50,"L"],[40,"XL"],[10,"X"],[9,"IX"],[5,"V"],[4,"IV"]], -v,o,x,r,l; +v,o,x,r,l=''; for (l of fs.readFileSync(process.argv[2],'utf-8').split("\n")){ v="I".repeat(0+l); o=""; - for([x,r]of p) - while(v[x-1]) - {o+=r; v=v.slice(x)} + for([x,r]of p) + while(v[x-1]) + {o+=r;v=v.slice(x)} console.log(o+v) } From 571d3a296d1181529241898fe3367b99517521bd Mon Sep 17 00:00:00 2001 From: Grant Forrest Date: Wed, 13 Aug 2025 09:36:45 -0400 Subject: [PATCH 9/9] fix start command --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 908800a..f7f5426 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "scripts": { "test": "vitest", - "start": "pnpm min && node ./main.mjs ./input.txt", + "dev": "pnpm min && node ./main.mjs ./input.txt", + "start": "node ./main.mjs", "min": "node ./min.mjs" }, "devDependencies": {