From e7173b60ca6d4f1ea8555788b23fd17dec66834f Mon Sep 17 00:00:00 2001 From: skdthread Date: Sun, 22 Feb 2026 22:19:04 +0100 Subject: [PATCH 1/4] Add goodie for pre-order of an n-ary tree Closes #396. --- .../traversePreOrderNAry/index.test.ts | 51 +++++++++++++++++++ .../typescript/traversePreOrderNAry/index.ts | 17 +++++++ 2 files changed, 68 insertions(+) create mode 100644 workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts create mode 100644 workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts diff --git a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts new file mode 100644 index 00000000..f17f8440 --- /dev/null +++ b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from "@jest/globals"; + +import { traversePreOrderNAry } from "./index.ts"; + +type Node = { val: number; children: Node[] }; + +describe("traversePreOrderNAry", () => { + it("returns empty for null root", () => { + expect([...traversePreOrderNAry(null)]).toStrictEqual([]); + }); + + it("returns empty for undefined root", () => { + expect([...traversePreOrderNAry(undefined)]).toStrictEqual([]); + }); + + it("yields root only for single node", () => { + const root: Node = { val: 1, children: [] }; + expect([...traversePreOrderNAry(root)].map((n) => n.val)).toStrictEqual([ + 1, + ]); + }); + + it("visits parent before children", () => { + const root: Node = { + val: 1, + children: [{ val: 2, children: [] }, { val: 3, children: [] }], + }; + expect([...traversePreOrderNAry(root)].map((n) => n.val)).toStrictEqual([ + 1, 2, 3, + ]); + }); + + it("traverses deeper trees in pre-order", () => { + const root: Node = { + val: 1, + children: [ + { + val: 2, + children: [ + { val: 4, children: [] }, + { val: 5, children: [] }, + ], + }, + { val: 3, children: [] }, + ], + }; + expect([...traversePreOrderNAry(root)].map((n) => n.val)).toStrictEqual([ + 1, 2, 4, 5, 3, + ]); + }); +}); diff --git a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts new file mode 100644 index 00000000..1c2c42ee --- /dev/null +++ b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts @@ -0,0 +1,17 @@ +export function* traversePreOrderNAry( + root: T | null | undefined, +): Generator { + if (root == null) { + return; + } + + const stack: T[] = [root]; + + do { + const node = stack.pop()!; + yield node; + for (let i = node.children.length - 1; i >= 0; --i) { + stack.push(node.children[i]); + } + } while (stack.length > 0); +} From da3d56038b73b22e71b2b61fb8520078afef21c1 Mon Sep 17 00:00:00 2001 From: skdthread Date: Sun, 22 Feb 2026 22:31:36 +0100 Subject: [PATCH 2/4] Fix formatting and regenerate snapshots --- .../traversePreOrderNAry/index.test.ts | 5 +- .../__snapshots__/equip-test.ts.snap | 50 +++++++++++++++++++ .../__snapshots__/render-test.ts.snap | 38 ++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts index f17f8440..fa84643e 100644 --- a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts +++ b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts @@ -23,7 +23,10 @@ describe("traversePreOrderNAry", () => { it("visits parent before children", () => { const root: Node = { val: 1, - children: [{ val: 2, children: [] }, { val: 3, children: [] }], + children: [ + { val: 2, children: [] }, + { val: 3, children: [] }, + ], }; expect([...traversePreOrderNAry(root)].map((n) => n.val)).toStrictEqual([ 1, 2, 3, diff --git a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap index f7a3641e..ff4906c8 100644 --- a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap +++ b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap @@ -2724,6 +2724,30 @@ function* traversePreOrder(root) { /////////////////////////// END ADVENTURE PACK CODE ////////////////////////////" `; +exports[`App can equip single goody: JavaScript traversePreOrderNAry 1`] = ` +"////////////////////////// BEGIN ADVENTURE PACK CODE /////////////////////////// +// Adventure Pack commit fake-commit-hash +// Running at: https://example.com/ + +function* traversePreOrderNAry(root) { + if (root == null) { + return; + } + + const stack = [root]; + + do { + const node = stack.pop(); + yield node; + for (let i = node.children.length - 1; i >= 0; --i) { + stack.push(node.children[i]); + } + } while (stack.length > 0); +} + +/////////////////////////// END ADVENTURE PACK CODE ////////////////////////////" +`; + exports[`App can equip single goody: Kotlin gcd(Int,Int) 1`] = ` "////////////////////////// BEGIN ADVENTURE PACK CODE /////////////////////////// // Adventure Pack commit fake-commit-hash @@ -5509,3 +5533,29 @@ function* traversePreOrder< /////////////////////////// END ADVENTURE PACK CODE ////////////////////////////" `; + +exports[`App can equip single goody: TypeScript traversePreOrderNAry 1`] = ` +"////////////////////////// BEGIN ADVENTURE PACK CODE /////////////////////////// +// Adventure Pack commit fake-commit-hash +// Running at: https://example.com/ + +function* traversePreOrderNAry( + root: T | null | undefined, +): Generator { + if (root == null) { + return; + } + + const stack: T[] = [root]; + + do { + const node = stack.pop()!; + yield node; + for (let i = node.children.length - 1; i >= 0; --i) { + stack.push(node.children[i]); + } + } while (stack.length > 0); +} + +/////////////////////////// END ADVENTURE PACK CODE ////////////////////////////" +`; diff --git a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap index f0a6e8f0..5921b2cc 100644 --- a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap +++ b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap @@ -1499,6 +1499,24 @@ exports[`App can render goody: JavaScript traversePreOrder 1`] = ` }" `; +exports[`App can render goody: JavaScript traversePreOrderNAry 1`] = ` +"export function* traversePreOrderNAry(root) { + if (root == null) { + return; + } + + const stack = [root]; + + do { + const node = stack.pop(); + yield node; + for (let i = node.children.length - 1; i >= 0; --i) { + stack.push(node.children[i]); + } + } while (stack.length > 0); +}" +`; + exports[`App can render goody: Kotlin gcd(Int,Int) 1`] = ` "package gcd_int_int @@ -3159,3 +3177,23 @@ exports[`App can render goody: TypeScript traversePreOrder 1`] = ` } while (stack.length > 0); }" `; + +exports[`App can render goody: TypeScript traversePreOrderNAry 1`] = ` +"export function* traversePreOrderNAry( + root: T | null | undefined, +): Generator { + if (root == null) { + return; + } + + const stack: T[] = [root]; + + do { + const node = stack.pop()!; + yield node; + for (let i = node.children.length - 1; i >= 0; --i) { + stack.push(node.children[i]); + } + } while (stack.length > 0); +}" +`; From d6a2af60bb47f3dca9019d86dadb4a13c402f901 Mon Sep 17 00:00:00 2001 From: skdthread Date: Mon, 23 Feb 2026 16:52:18 +0100 Subject: [PATCH 3/4] update test cases --- .../typescript/traversePreOrderNAry/index.test.ts | 14 ++++++++++++-- .../typescript/traversePreOrderNAry/index.ts | 1 + .../app/__tests__/__snapshots__/equip-test.ts.snap | 2 ++ .../__tests__/__snapshots__/render-test.ts.snap | 2 ++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts index fa84643e..e657604f 100644 --- a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts +++ b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts @@ -24,12 +24,22 @@ describe("traversePreOrderNAry", () => { const root: Node = { val: 1, children: [ - { val: 2, children: [] }, + { + val: 2, + children: [ + { val: 5, children: [] }, + { val: 6, children: [] }, + ], + }, { val: 3, children: [] }, + { + val: 4, + children: [{ val: 7, children: [] }], + }, ], }; expect([...traversePreOrderNAry(root)].map((n) => n.val)).toStrictEqual([ - 1, 2, 3, + 1, 2, 5, 6, 3, 4, 7, ]); }); diff --git a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts index 1c2c42ee..9091473f 100644 --- a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts +++ b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.ts @@ -10,6 +10,7 @@ export function* traversePreOrderNAry( do { const node = stack.pop()!; yield node; + // TODO: add an Array.prototype.valuesReversed() goody and use it here for (let i = node.children.length - 1; i >= 0; --i) { stack.push(node.children[i]); } diff --git a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap index ff4906c8..9790af51 100644 --- a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap +++ b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/equip-test.ts.snap @@ -2739,6 +2739,7 @@ function* traversePreOrderNAry(root) { do { const node = stack.pop(); yield node; + // TODO: add an Array.prototype.valuesReversed() goody and use it here for (let i = node.children.length - 1; i >= 0; --i) { stack.push(node.children[i]); } @@ -5551,6 +5552,7 @@ function* traversePreOrderNAry( do { const node = stack.pop()!; yield node; + // TODO: add an Array.prototype.valuesReversed() goody and use it here for (let i = node.children.length - 1; i >= 0; --i) { stack.push(node.children[i]); } diff --git a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap index 5921b2cc..e5a54523 100644 --- a/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap +++ b/workspaces/adventure-pack/src/app/__tests__/__snapshots__/render-test.ts.snap @@ -1510,6 +1510,7 @@ exports[`App can render goody: JavaScript traversePreOrderNAry 1`] = ` do { const node = stack.pop(); yield node; + // TODO: add an Array.prototype.valuesReversed() goody and use it here for (let i = node.children.length - 1; i >= 0; --i) { stack.push(node.children[i]); } @@ -3191,6 +3192,7 @@ exports[`App can render goody: TypeScript traversePreOrderNAry 1`] = ` do { const node = stack.pop()!; yield node; + // TODO: add an Array.prototype.valuesReversed() goody and use it here for (let i = node.children.length - 1; i >= 0; --i) { stack.push(node.children[i]); } From 1ea29487ca1e4d4dce035958d6b2107e3787460d Mon Sep 17 00:00:00 2001 From: skdthread Date: Mon, 23 Feb 2026 17:44:32 +0100 Subject: [PATCH 4/4] merge 2 test cases --- .../goodies/typescript/traversePreOrderNAry/index.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts index e657604f..21e30acb 100644 --- a/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts +++ b/workspaces/adventure-pack/goodies/typescript/traversePreOrderNAry/index.test.ts @@ -5,11 +5,8 @@ import { traversePreOrderNAry } from "./index.ts"; type Node = { val: number; children: Node[] }; describe("traversePreOrderNAry", () => { - it("returns empty for null root", () => { + it("yields nothing for null/undefined root", () => { expect([...traversePreOrderNAry(null)]).toStrictEqual([]); - }); - - it("returns empty for undefined root", () => { expect([...traversePreOrderNAry(undefined)]).toStrictEqual([]); });