diff --git a/.github/workflows/deno.yaml b/.github/workflows/deno.yaml index c4c5831..1ae0943 100644 --- a/.github/workflows/deno.yaml +++ b/.github/workflows/deno.yaml @@ -16,13 +16,12 @@ jobs: - uses: denoland/setup-deno@v2 with: deno-version: v2.x - - run: | - deno test --allow-read --coverage=cov_profile - deno coverage --lcov --output=cov.lcov cov_profile + - run: deno task test + - run: deno task lcov - uses: hrishikesh-kadam/setup-lcov@v1 - uses: zgosalvez/github-actions-report-lcov@v3 with: - coverage-files: cov.lcov + coverage-files: cov_profile/cov.lcov minimum-coverage: 60 github-token: ${{ secrets.GITHUB_TOKEN }} update-comment: true diff --git a/.gitignore b/.gitignore index 5d4ba38..a44d15c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ deno.lock **/input.txt .vscode +cov_profile diff --git a/day1/mod.ts b/day1/mod.ts index de489f4..5b30d65 100644 --- a/day1/mod.ts +++ b/day1/mod.ts @@ -1,31 +1,31 @@ export function parse(data: string): number[][] { const parsed = data.trim().split("\n").map((x) => - x.split(" ").map((x) => parseInt(x)) + // 3 spaces between the numbers + x.split(" ").map((x) => parseInt(x)) ); return parsed - // Three spaces are used to separate the numbers - .map((x) => [x[0], x[3]]); + .map((x) => [x[0], x[1]]); } export function solve1(data: number[][]): number { - const left_nums = data.map((x) => x[0]); - const right_nums = data.map((x) => x[1]); + const leftNums = data.map((x) => x[0]); + const rightNums = data.map((x) => x[1]); - const sorted_left_nums = left_nums.sort((a, b) => a - b); - const sorted_right_nums = right_nums.sort((a, b) => a - b); + const sortedLeftNums = leftNums.sort((a, b) => a - b); + const sortedRightNums = rightNums.sort((a, b) => a - b); return Array.from({ length: data.length }, (_, i) => i) .reduce( - (acc, i) => acc + Math.abs(sorted_left_nums[i] - sorted_right_nums[i]), + (acc, i) => acc + Math.abs(sortedLeftNums[i] - sortedRightNums[i]), 0, ); } export function solve2(data: number[][]): number { - const left_nums = data.map((x) => x[0]); - const right_nums = data.map((x) => x[1]); + const leftNums = data.map((x) => x[0]); + const rightNums = data.map((x) => x[1]); - const right_count = right_nums.reduce>( + const rightCount = rightNums.reduce>( (acc, x) => { acc[x] = (acc[x] || 0) + 1; return acc; @@ -33,17 +33,15 @@ export function solve2(data: number[][]): number { {}, ); - return left_nums.reduce( - (acc, x) => { - return acc + (x * (right_count[x] || 0)); - }, + return leftNums.reduce( + (acc, x) => acc + (x * (rightCount[x] || 0)), 0, ); } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = parse(await Deno.readTextFile(data_path)); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day1/test.ts b/day1/test.ts index fe6f505..6fb684e 100644 --- a/day1/test.ts +++ b/day1/test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "@std/assert"; import { parse, solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path = new URL("example.txt", import.meta.url).pathname; - const example_data = parse(await Deno.readTextFile(example_data_path)); - assertEquals(solve1(example_data), 11); - assertEquals(solve2(example_data), 31); + const dataPath = new URL("example.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); + assertEquals(solve1(data), 11); + assertEquals(solve2(data), 31); }); diff --git a/day2/mod.ts b/day2/mod.ts index acb1adb..05eec36 100644 --- a/day2/mod.ts +++ b/day2/mod.ts @@ -5,9 +5,10 @@ export function parse(data: string): number[][] { } function is_safe(report: number[]): boolean { - const diffs = Array.from({ length: report.length - 1 }, (_, i) => { - return (report[i + 1] - report[i]); - }); + const diffs = Array.from( + { length: report.length - 1 }, + (_, i) => report[i + 1] - report[i], + ); if (diffs[0] === 0) { return false; @@ -15,9 +16,7 @@ function is_safe(report: number[]): boolean { const direction = diffs[0] / Math.abs(diffs[0]); - return diffs.every((x) => { - return 1 <= x / direction && x / direction <= 3; - }); + return diffs.every((x) => 1 <= x / direction && x / direction <= 3); } export function solve1(data: number[][]): number { @@ -26,16 +25,17 @@ export function solve1(data: number[][]): number { } export function solve2(data: number[][]): number { - return data.filter((report) => { - return Array.from({ length: report.length }, (_, i) => { - return report.slice(0, i).concat(report.slice(i + 1)); - }).some(is_safe); - }).length; + return data.filter((report) => + Array.from( + { length: report.length }, + (_, i) => report.slice(0, i).concat(report.slice(i + 1)), + ).some(is_safe) + ).length; } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = parse(await Deno.readTextFile(data_path)); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day2/test.ts b/day2/test.ts index 405dc7b..1aa648f 100644 --- a/day2/test.ts +++ b/day2/test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "@std/assert"; import { parse, solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path = new URL("example.txt", import.meta.url).pathname; - const example_data = parse(await Deno.readTextFile(example_data_path)); - assertEquals(solve1(example_data), 2); - assertEquals(solve2(example_data), 4); + const dataPath = new URL("example.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); + assertEquals(solve1(data), 2); + assertEquals(solve2(data), 4); }); diff --git a/day3/mod.ts b/day3/mod.ts index 08d9a76..0190492 100644 --- a/day3/mod.ts +++ b/day3/mod.ts @@ -2,25 +2,23 @@ export const regex1 = /mul\(([0-9]{1,3}),([0-9]{1,3})\)/g; export const regex2 = /do(?:n't)?\(\)|mul\(([0-9]{1,3}),([0-9]{1,3})\)/g; export function solve1(data: string): number { - return data.matchAll(regex1).map((match) => { - const [_, a, b] = match; - return Number(a) * Number(b); - }).reduce((acc, val) => acc + val, 0); + return data.matchAll(regex1).map(([_, a, b]) => Number(a) * Number(b)).reduce( + (acc, val) => acc + val, + 0, + ); } export function solve2(data: string): number { - let is_enabled = true; - return data.matchAll(regex2).map((match) => { - const [m, a, b] = match; - + let isEnabled = true; + return data.matchAll(regex2).map(([m, a, b]) => { if (m === "do()") { - is_enabled = true; + isEnabled = true; return 0; } else if (m === "don't()") { - is_enabled = false; + isEnabled = false; return 0; } else { - if (is_enabled) { + if (isEnabled) { return Number(a) * Number(b); } else return 0; } @@ -28,8 +26,8 @@ export function solve2(data: string): number { } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = await Deno.readTextFile(data_path); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = await Deno.readTextFile(dataPath); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day3/test.ts b/day3/test.ts index 1929f28..f600cf9 100644 --- a/day3/test.ts +++ b/day3/test.ts @@ -2,11 +2,11 @@ import { assertEquals } from "@std/assert"; import { solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path_1 = new URL("example1.txt", import.meta.url).pathname; - const example_data_1 = await Deno.readTextFile(example_data_path_1); - assertEquals(solve1(example_data_1), 161); + const dataPath1 = new URL("example1.txt", import.meta.url).pathname; + const data1 = await Deno.readTextFile(dataPath1); + assertEquals(solve1(data1), 161); - const example_data_path_2 = new URL("example2.txt", import.meta.url).pathname; - const example_data_2 = await Deno.readTextFile(example_data_path_2); - assertEquals(solve2(example_data_2), 48); + const dataPath2 = new URL("example2.txt", import.meta.url).pathname; + const data2 = await Deno.readTextFile(dataPath2); + assertEquals(solve2(data2), 48); }); diff --git a/day4/mod.ts b/day4/mod.ts index 2236a2c..b77fa52 100644 --- a/day4/mod.ts +++ b/day4/mod.ts @@ -11,11 +11,11 @@ class Grid { this.grid = grid; } - x_len(): number { + width(): number { return this.grid[0].length; } - y_len(): number { + height(): number { return this.grid.length; } @@ -23,7 +23,7 @@ class Grid { return this.grid[y]?.[x] ?? ""; } - find_xmas_at(x: number, y: number): number { + findXMasAt(x: number, y: number): number { let count = 0; for (const dx of [-1, 0, 1]) { @@ -46,32 +46,32 @@ class Grid { return count; } - is_x_mas_at(x: number, y: number): boolean { - return [-1, 1].some((d) => { - return this.get(x - d, y - d) + this.get(x, y) + - this.get(x + d, y + d) == MAS; - }) && - [-1, 1].some((d) => { - return this.get(x - d, y + d) + this.get(x, y) + - this.get(x + d, y - d) == MAS; - }); + isXAndMasAt(x: number, y: number): boolean { + return [-1, 1].some((d) => + this.get(x - d, y - d) + this.get(x, y) + + this.get(x + d, y + d) == MAS + ) && + [-1, 1].some((d) => + this.get(x - d, y + d) + this.get(x, y) + + this.get(x + d, y - d) == MAS + ); } - find_all_xmas(): number { + findAllXmas(): number { let count = 0; - for (let x = 0; x < this.x_len(); x++) { - for (let y = 0; y < this.y_len(); y++) { - count += this.find_xmas_at(x, y); + for (let x = 0; x < this.width(); x++) { + for (let y = 0; y < this.height(); y++) { + count += this.findXMasAt(x, y); } } return count; } - find_all_x_mas(): number { + findAllXAndMas(): number { let count = 0; - for (let y = 0; y < this.y_len(); y++) { - for (let x = 0; x < this.x_len(); x++) { - if (this.is_x_mas_at(x, y)) { + for (let y = 0; y < this.height(); y++) { + for (let x = 0; x < this.width(); x++) { + if (this.isXAndMasAt(x, y)) { count++; } } @@ -82,17 +82,17 @@ class Grid { export function solve1(data: string[]): number { const grid = new Grid(data); - return grid.find_all_xmas(); + return grid.findAllXmas(); } export function solve2(data: string[]): number { const grid = new Grid(data); - return grid.find_all_x_mas(); + return grid.findAllXAndMas(); } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = parse(await Deno.readTextFile(data_path)); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day4/test.ts b/day4/test.ts index a3d60ad..f272b7d 100644 --- a/day4/test.ts +++ b/day4/test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "@std/assert"; import { parse, solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path = new URL("example.txt", import.meta.url).pathname; - const example_data = parse(await Deno.readTextFile(example_data_path)); - assertEquals(solve1(example_data), 18); - assertEquals(solve2(example_data), 9); + const dataPath = new URL("example.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); + assertEquals(solve1(data), 18); + assertEquals(solve2(data), 9); }); diff --git a/day5/mod.ts b/day5/mod.ts index f01e69a..866bbd7 100644 --- a/day5/mod.ts +++ b/day5/mod.ts @@ -91,7 +91,7 @@ class DirectedGraph { return false; } - topological_sort(): number[] { + topologicalSort(): number[] { const nodes: Set = new Set(); for (const [from, tos] of this.edges) { @@ -129,14 +129,14 @@ class DirectedGraph { const result = []; while (parents.size > 0) { - const next_nodes = [...parents.entries()].find(([node, parent]) => { - return parent.size === 0; - }); - if (next_nodes === undefined) { + const nextNodes = [...parents.entries()].find(([_, parent]) => + parent.size === 0 + ); + if (nextNodes === undefined) { return []; } - const node = next_nodes[0]; + const node = nextNodes[0]; result.push(node); parents.delete(node); @@ -155,12 +155,12 @@ class DirectedGraph { } export function parse(data: string): [number[][], number[][]] { - const [rules_s, pages_s, _] = data.trim().split("\n\n"); - const rules = rules_s.split("\n").map((rule) => + const [rulesStr, pagesStr] = data.trim().split("\n\n"); + const rules = rulesStr.split("\n").map((rule) => rule.split("|").map((r) => Number(r)) ); - const pages = pages_s.split("\n").map((page) => page.split(",").map(Number)); + const pages = pagesStr.split("\n").map((page) => page.split(",").map(Number)); return [rules, pages]; } @@ -170,9 +170,7 @@ export function solve1(data: [number[][], number[][]]): number { const dirGraph = new DirectedGraph(); - rules.forEach(([from, to]) => { - dirGraph.addEdge(from, to); - }); + rules.forEach(([from, to]) => dirGraph.addEdge(from, to)); return pages.map((page) => { const pageGraph = dirGraph.restrict(new Set(page)); @@ -180,8 +178,8 @@ export function solve1(data: [number[][], number[][]]): number { for (let i = 0; i < page.length - 1; i++) { pageGraph.addEdge(page[i], page[i + 1]); } - const top_sort = pageGraph.topological_sort(); - if (top_sort.length === 0) { + const topSort = pageGraph.topologicalSort(); + if (topSort.length === 0) { return 0; } else { return page[(page.length - 1) / 2]; @@ -194,27 +192,23 @@ export function solve2(data: [number[][], number[][]]): number { const dirGraph = new DirectedGraph(); - rules.forEach(([from, to]) => { - dirGraph.addEdge(from, to); - }); + rules.forEach(([from, to]) => dirGraph.addEdge(from, to)); - const topological_sort = dirGraph.topological_sort(); + const topologicalSort = dirGraph.topologicalSort(); - const topological_index = new Map(); - topological_sort.forEach((node, index) => { - topological_index.set(node, index); - }); + const topologicalIndex = new Map(); + topologicalSort.forEach((node, index) => topologicalIndex.set(node, index)); return pages.map((page) => { const pageGraph = dirGraph.restrict(new Set(page)); - const fixed = pageGraph.topological_sort(); + const fixed = pageGraph.topologicalSort(); for (let i = 0; i < page.length - 1; i++) { pageGraph.addEdge(page[i], page[i + 1]); } - const top_sort = pageGraph.topological_sort(); - if (top_sort.length === 0) { + const topSort = pageGraph.topologicalSort(); + if (topSort.length === 0) { return fixed[(fixed.length - 1) / 2]; } else { return 0; @@ -223,8 +217,8 @@ export function solve2(data: [number[][], number[][]]): number { } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = parse(await Deno.readTextFile(data_path)); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day5/test.ts b/day5/test.ts index 17cbc26..342851c 100644 --- a/day5/test.ts +++ b/day5/test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "@std/assert"; import { parse, solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path = new URL("example.txt", import.meta.url).pathname; - const example_data = parse(await Deno.readTextFile(example_data_path)); - assertEquals(solve1(example_data), 143); - assertEquals(solve2(example_data), 123); + const dataPath = new URL("example.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); + assertEquals(solve1(data), 143); + assertEquals(solve2(data), 123); }); diff --git a/day6/mod.ts b/day6/mod.ts index 4578cf0..d997813 100644 --- a/day6/mod.ts +++ b/day6/mod.ts @@ -69,16 +69,16 @@ class Grid { const [x, y] = this.guard; const [dx, dy] = this.guardDirection; - const [x_, y_] = [x + dx, y + dy]; + const [xNext, yNext] = [x + dx, y + dy]; - if (this.isWall(x_, y_)) { + if (this.isWall(xNext, yNext)) { this.changeDirection(); this.guardWalk(); } else { - this.guard = [x_, y_]; + this.guard = [xNext, yNext]; { this.set(x, y, "X"); - this.set(x_, y_, "^"); + this.set(xNext, yNext, "^"); } } } @@ -87,7 +87,7 @@ class Grid { this.set(x, y, "#"); } - x_locations(): number[][] { + xLocations(): number[][] { const locations = []; for (let y = 0; y < this.height; y++) { for (let x = 0; x < this.width; x++) { @@ -101,16 +101,11 @@ class Grid { } function clone(data: string[][]): string[][] { - return data.map((row) => { - return row.slice(); - }); + return data.map((row) => row.slice()); } -export function parse(data_r: string): string[][] { - const data = data_r.trim(); - return data.split("\n").map((line) => { - return line.split(""); - }); +export function parse(data: string): string[][] { + return data.trim().split("\n").map((line) => line.split("")); } export function solve1(data: string[][]): number { @@ -123,7 +118,7 @@ export function solve1(data: string[][]): number { } } - return grid.x_locations().length; + return grid.xLocations().length; } export function solve2(data: string[][]): number { @@ -136,7 +131,7 @@ export function solve2(data: string[][]): number { } } - const locations = grid.x_locations(); + const locations = grid.xLocations(); return locations.filter(([x, y]) => { const grid = new Grid(clone(data)); @@ -148,6 +143,8 @@ export function solve2(data: string[][]): number { break; } stepCount++; + // this is a hack - if guard has walked too many steps, he may be in a loop. + // we should rather check guard's location is visited with same direction if (stepCount > 2 * locations.length) { return true; } @@ -157,8 +154,8 @@ export function solve2(data: string[][]): number { } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = parse(await Deno.readTextFile(data_path)); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day6/test.ts b/day6/test.ts index 3356421..81e52c6 100644 --- a/day6/test.ts +++ b/day6/test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "@std/assert"; import { parse, solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path = new URL("example.txt", import.meta.url).pathname; - const example_data = parse(await Deno.readTextFile(example_data_path)); - assertEquals(solve1(example_data), 41); - assertEquals(solve2(example_data), 6); + const dataPath = new URL("example.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); + assertEquals(solve1(data), 41); + assertEquals(solve2(data), 6); }); diff --git a/day7/mod.ts b/day7/mod.ts index 6f18764..36ee0bd 100644 --- a/day7/mod.ts +++ b/day7/mod.ts @@ -1,12 +1,11 @@ -export function parse(data_r: string): [number, number[]][] { - const data = data_r.trim(); - return data.split("\n").map((line) => { +export function parse(data: string): [number, number[]][] { + return data.trim().split("\n").map((line) => { const [a, b] = line.split(":"); return [Number(a.trim()), b.trim().split(" ").map(Number)]; }); } -function solve1_util(value: number, remaining: number[]): boolean { +function solve1Rec(value: number, remaining: number[]): boolean { if (remaining.length === 1) { return remaining[0] === value; } @@ -14,11 +13,22 @@ function solve1_util(value: number, remaining: number[]): boolean { // input is reversed // tail + head = value // tail * head = value - return (head <= value && solve1_util(value - head, tail)) || - (value % head == 0 && solve1_util(value / head, tail)); + return (head <= value && solve1Rec(value - head, tail)) || + (value % head == 0 && solve1Rec(value / head, tail)); } -function solve2_util(value: number, remaining: number[]): boolean { +function trimSuffix(big: number, small: number): number | undefined { + const bigLen = Math.floor(Math.log10(big)) + 1; + const smallLen = Math.floor(Math.log10(small)) + 1; + if (smallLen < bigLen) { + const suffix = big % Math.pow(10, smallLen); + if (suffix === small) { + return Math.floor(big / Math.pow(10, smallLen)); + } + } +} + +function solve2Rec(value: number, remaining: number[]): boolean { if (remaining.length === 1) { return remaining[0] === value; } @@ -27,39 +37,29 @@ function solve2_util(value: number, remaining: number[]): boolean { // tail + head = value // tail * head = value // tail | head = value - const value_str = value.toString(); - const head_str = head.toString(); - if (value_str.length > head_str.length && value_str.endsWith(head_str)) { - const new_value_str = value_str.slice( - 0, - value_str.length - head_str.length, - ); - const new_value = Number(new_value_str); - if (solve2_util(new_value, tail)) { - return true; - } - } - return (head <= value && solve2_util(value - head, tail)) || - (value % head == 0 && solve2_util(value / head, tail)); + const newValue = trimSuffix(value, head); + return (newValue !== undefined && solve1Rec(newValue!, tail)) || + (head <= value && solve2Rec(value - head, tail)) || + (value % head == 0 && solve2Rec(value / head, tail)); } export function solve1(data: [number, number[]][]): number { - return data.filter((ecase) => { + return data.filter((ecase) => // reverse will reverse the array in place too - return solve1_util(ecase[0], ecase[1].slice().reverse()); - }).reduce((acc, [value, _]) => acc + value, 0); + solve1Rec(ecase[0], ecase[1].slice().reverse()) + ).reduce((acc, [value, _]) => acc + value, 0); } export function solve2(data: [number, number[]][]): number { - return data.filter((ecase) => { + return data.filter((ecase) => // reverse will reverse the array in place too - return solve2_util(ecase[0], ecase[1].slice().reverse()); - }).reduce((acc, [value, _]) => acc + value, 0); + solve2Rec(ecase[0], ecase[1].slice().reverse()) + ).reduce((acc, [value, _]) => acc + value, 0); } if (import.meta.main) { - const data_path = new URL("input.txt", import.meta.url).pathname; - const data = parse(await Deno.readTextFile(data_path)); + const dataPath = new URL("input.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); console.log(solve1(data)); console.log(solve2(data)); } diff --git a/day7/test.ts b/day7/test.ts index 04b21a5..6f396b4 100644 --- a/day7/test.ts +++ b/day7/test.ts @@ -2,8 +2,8 @@ import { assertEquals } from "@std/assert"; import { parse, solve1, solve2 } from "./mod.ts"; Deno.test(async function testExample() { - const example_data_path = new URL("example.txt", import.meta.url).pathname; - const example_data = parse(await Deno.readTextFile(example_data_path)); - assertEquals(solve1(example_data), 3749); - assertEquals(solve2(example_data), 11387); + const dataPath = new URL("example.txt", import.meta.url).pathname; + const data = parse(await Deno.readTextFile(dataPath)); + assertEquals(solve1(data), 3749); + assertEquals(solve2(data), 11387); }); diff --git a/deno.json b/deno.json index bcb6abc..35e6415 100644 --- a/deno.json +++ b/deno.json @@ -1,5 +1,15 @@ { "workspace": ["./day*"], + "tasks": { + "test": { + "description": "Run tests", + "command": "deno test --allow-read" + }, + "lcov": { + "description": "Generate LCOV report", + "command": "rm -rf cov_profile && deno test --allow-read --coverage=cov_profile && deno coverage --lcov --output=cov_profile/cov.lcov cov_profile" + } + }, "imports": { "@std/assert": "jsr:@std/assert@1" }