From 9721f9c59f25629840be32ba67248e5a5d2c27c5 Mon Sep 17 00:00:00 2001 From: Kolade Chris <65571316+Ksound22@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:24:12 +0100 Subject: [PATCH] feat(curriculum): add shortest path algo to js v9 cert (#66681) Co-authored-by: jdwilkin4 --- client/i18n/locales/english/intro.json | 7 + .../0095d0567b6817114989a1dd.md | 38 +++++ .../69c918841987bf16c1d1baba.md | 59 +++++++ .../69c918841987bf16c1d1babb.md | 52 ++++++ .../69c918841987bf16c1d1babc.md | 54 +++++++ .../69c918841987bf16c1d1babd.md | 57 +++++++ .../69c918841987bf16c1d1babe.md | 47 ++++++ .../69c918841987bf16c1d1babf.md | 83 ++++++++++ .../69c918841987bf16c1d1bac0.md | 58 +++++++ .../69c918841987bf16c1d1bac1.md | 70 ++++++++ .../69c918841987bf16c1d1bac2.md | 57 +++++++ .../69c918841987bf16c1d1bac3.md | 59 +++++++ .../69c918841987bf16c1d1bac4.md | 68 ++++++++ .../69c918841987bf16c1d1bac5.md | 70 ++++++++ .../69c918841987bf16c1d1bac6.md | 65 ++++++++ .../69c918841987bf16c1d1bac7.md | 85 ++++++++++ .../69c918841987bf16c1d1bac8.md | 80 ++++++++++ .../69c918841987bf16c1d1bac9.md | 81 ++++++++++ .../69c918841987bf16c1d1baca.md | 90 +++++++++++ .../69c918841987bf16c1d1bacb.md | 98 ++++++++++++ .../69c918841987bf16c1d1bacc.md | 77 +++++++++ .../69c918841987bf16c1d1bacd.md | 89 +++++++++++ .../69c918841987bf16c1d1bace.md | 94 +++++++++++ .../69c918841987bf16c1d1bacf.md | 113 +++++++++++++ .../69c918841987bf16c1d1bad0.md | 86 ++++++++++ .../69c918841987bf16c1d1bad1.md | 151 ++++++++++++++++++ .../69c937c73f23b1140bcd297a.md | 45 ++++++ .../workshop-shortest-path-algorithm-js.json | 37 +++++ .../structure/superblocks/javascript-v9.json | 1 + 29 files changed, 1971 insertions(+) create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/0095d0567b6817114989a1dd.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baba.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babb.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babc.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babd.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babe.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babf.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac0.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac1.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac2.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac3.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac4.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac5.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac6.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac7.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac8.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac9.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baca.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacb.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacc.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacd.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bace.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacf.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad0.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad1.md create mode 100644 curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c937c73f23b1140bcd297a.md create mode 100644 curriculum/structure/blocks/workshop-shortest-path-algorithm-js.json diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index a97ab0dc73f..9850457281e 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -5701,6 +5701,13 @@ "In this lesson, you will learn about fundamental data structures like graphs, trees, and their practical applications in computer science." ] }, + "workshop-shortest-path-algorithm-js": { + "title": "Implement the Shortest Path Algorithm", + "intro": [ + "The shortest path algorithm finds the minimum distance between nodes in a weighted graph.", + "In this workshop, you'll implement the shortest path algorithm in JavaScript and return both the shortest distances and the paths taken." + ] + }, "lab-adjacency-list-to-matrix-converter-js": { "title": "Build an Adjacency List to Matrix Converter", "intro": [ diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/0095d0567b6817114989a1dd.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/0095d0567b6817114989a1dd.md new file mode 100644 index 00000000000..64daaf37d04 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/0095d0567b6817114989a1dd.md @@ -0,0 +1,38 @@ +--- +id: 0095d0567b6817114989a1dd +title: Step 1 +challengeType: 1 +dashedName: step-1 +--- + +# --description-- + +In this workshop, you will implement the shortest path algorithm in JavaScript. You will write a function that computes the shortest path between nodes in a weighted graph and returns both the distances and the paths taken. + +For example, given a graph where cities are connected by roads with different distances, the algorithm will find the shortest route from one city to another. If you want to travel from City A to City D, the algorithm might find that going A ⇨ B ⇨ C ⇨ D (total: 15km) is shorter than going directly A ⇨ D (20km). + +To get started, define a variable named `INF` and assign it the value `Infinity`. Later, you'll use it to indicate that there is no direct connection between two nodes. + +# --hints-- + +You should define a variable named `INF`. + +```js +assert.isDefined(INF); +``` + +Your `INF` variable should have the value `Infinity`. + +```js +assert.strictEqual(INF, Infinity); +``` + +# --seed-- + +## --seed-contents-- + +```js +--fcc-editable-region-- + +--fcc-editable-region-- +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baba.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baba.md new file mode 100644 index 00000000000..028f92e3f24 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baba.md @@ -0,0 +1,59 @@ +--- +id: 69c918841987bf16c1d1baba +title: Step 2 +challengeType: 1 +dashedName: step-2 +--- + +# --description-- + +You will need a 2D array to represent the adjacency matrix of the graph. Each value represents the weight (distance) of the edge between two nodes. A value of `INF` means there is no direct edge. + +Create another variable named `adjMatrix` and assign it a 2D array with the following values: + +```js +[0, 5, 3, INF, 11, INF], +[5, 0, 1, INF, INF, 2], +[3, 1, 0, 1, 5, INF], +[INF, INF, 1, 0, 9, 3], +[11, INF, 5, 9, 0, INF], +[INF, 2, INF, 3, INF, 0] +``` + +# --hints-- + +You should create a variable named `adjMatrix`. + +```js +assert.isDefined(adjMatrix); +``` + +`adjMatrix` should be a 2D array with 6 rows and 6 columns. + +```js +assert.isArray(adjMatrix); +assert.lengthOf(adjMatrix, 6); +adjMatrix.forEach(row => assert.lengthOf(row, 6)); +``` + +`adjMatrix` should contain the correct values. + +```js +assert.deepEqual(adjMatrix[0], [0, 5, 3, INF, 11, INF]); +assert.deepEqual(adjMatrix[1], [5, 0, 1, INF, INF, 2]); +assert.deepEqual(adjMatrix[2], [3, 1, 0, 1, 5, INF]); +assert.deepEqual(adjMatrix[3], [INF, INF, 1, 0, 9, 3]); +assert.deepEqual(adjMatrix[4], [11, INF, 5, 9, 0, INF]); +assert.deepEqual(adjMatrix[5], [INF, 2, INF, 3, INF, 0]); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +--fcc-editable-region-- + +--fcc-editable-region-- +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babb.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babb.md new file mode 100644 index 00000000000..29a4f7dd626 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babb.md @@ -0,0 +1,52 @@ +--- +id: 69c918841987bf16c1d1babb +title: Step 3 +challengeType: 1 +dashedName: step-3 +--- + +# --description-- + +Now you will create the main function that does all the work. + +Create a function named `shortestPath` that takes three parameters: `matrix`, `startNode`, and `targetNode`. + +Over the next few steps, you will build out the logic for this function. + +# --hints-- + +You should create a function named `shortestPath`. + +```js +assert.isFunction(shortestPath); +``` + +Your `shortestPath` function should have the parameters `matrix`, `startNode`, and `targetNode`. + +```js +const params = __helpers.getFunctionParams(shortestPath.toString()); +const names = params.map(p => p.name); +assert.include(names, 'matrix'); +assert.include(names, 'startNode'); +assert.include(names, 'targetNode'); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +--fcc-editable-region-- + +--fcc-editable-region-- +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babc.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babc.md new file mode 100644 index 00000000000..56a3fe25dee --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babc.md @@ -0,0 +1,54 @@ +--- +id: 69c918841987bf16c1d1babc +title: Step 5 +challengeType: 1 +dashedName: step-5 +--- + +# --description-- + +You need to store the number of nodes in the graph. + +Inside the `shortestPath` function, create a variable named `n` and assign it `matrix.length`. + +# --hints-- + +You should create a variable `n` inside the `shortestPath` function. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+n\s*=/ +); +``` + +Your `n` variable should have the value `matrix.length`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+n\s*=\s*matrix\.length/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +--fcc-editable-region-- +function shortestPath(matrix, startNode, targetNode = null) { + +} +--fcc-editable-region-- +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babd.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babd.md new file mode 100644 index 00000000000..bc4cdb99499 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babd.md @@ -0,0 +1,57 @@ +--- +id: 69c918841987bf16c1d1babd +title: Step 6 +challengeType: 1 +dashedName: step-6 +--- + +# --description-- + +You need to keep track of the shortest known distance from the start node to every other node. To begin, you'll assume every node is infinitely far away. + +In JavaScript, you can create an array pre-filled with a value using `new Array(n).fill(value)`. For example, `new Array(3).fill(0)` creates `[0, 0, 0]`. + +Inside the `shortestPath` function, create a variable named `distances` and assign it `new Array(n).fill(INF)`. + +# --hints-- + +You should create a variable named `distances` inside `shortestPath`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+distances\s*=/ +); +``` + +Your `distances` variable should be set to `new Array(n).fill(INF)`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /new\s+Array\s*\(\s*n\s*\)\s*\.fill\s*\(\s*INF\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +--fcc-editable-region-- +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + +} +--fcc-editable-region-- +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babe.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babe.md new file mode 100644 index 00000000000..abd85eab2e1 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babe.md @@ -0,0 +1,47 @@ +--- +id: 69c918841987bf16c1d1babe +title: Step 7 +challengeType: 1 +dashedName: step-7 +--- + +# --description-- + +The distance from the starting node to itself is always `0`. You have to update the `distances` array to reflect this. + +After the `distances` array, set `distances[startNode]` to `0`. + +# --hints-- + +You should set `distances[startNode]` to `0`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /distances\s*\[\s*startNode\s*\]\s*=\s*0/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +--fcc-editable-region-- +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + +} +--fcc-editable-region-- +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babf.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babf.md new file mode 100644 index 00000000000..fd27d3df34e --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1babf.md @@ -0,0 +1,83 @@ +--- +id: 69c918841987bf16c1d1babf +title: Step 8 +challengeType: 1 +dashedName: step-8 +--- + +# --description-- + +You also need to track the actual path taken to reach each node. You will store a list of paths where each entry is an array of node indices representing the route taken. + +Initially, each node's path will just contain itself. You can create this structure using `Array.from()`: + +```js +Array.from({ length: n }, (_, i) => [i]); +``` + +This creates an array of `n` elements, where the element at index `i` is `[i]`. + +Still within the `shortestPath` function, create a variable named `paths` and assign it `Array.from({ length: n }, (_, i) => [i])`. + +# --hints-- + +You should create a variable `paths` inside the `shortestPath` function. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+paths\s*=/ +); +``` + +Your `paths` variable should be initialized using `Array.from`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /paths\s*=\s*Array\.from/ +); +``` + +Your `paths` variable should use `{ length: n }` as the first argument to `Array.from`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /Array\.from\s*\(\s*\{\s*length\s*:\s*n\s*\}/ +); +``` + +The second argument to `Array.from` should be a callback `(_, i) => [i]`, where `_` is a placeholder for the unused element and `i` is the index. It should return `[i]`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /Array\.from\s*\([\s\S]*?,\s*function\s*\(\s*\w+\s*,\s*(\w+)\s*\)\s*\{[\s\S]*?return\s*\[\s*\1\s*\]|Array\.from\s*\([\s\S]*?,\s*\(\s*\w+\s*,\s*\w+\s*\)\s*=>\s*\[\s*\w+\s*\]/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + --fcc-editable-region-- + + --fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac0.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac0.md new file mode 100644 index 00000000000..d443fdea165 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac0.md @@ -0,0 +1,58 @@ +--- +id: 69c918841987bf16c1d1bac0 +title: Step 9 +challengeType: 1 +dashedName: step-9 +--- + +# --description-- + +As the algorithm runs, you need to track which nodes have already been processed so you don't revisit them. + +Create a variable named `visited` and assign it `new Array(n).fill(false)`. + +# --hints-- + +You should create a variable named `visited`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+visited\s*=/ +); +``` + +Your `visited` variable should be set to `new Array(n).fill(false)`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /new\s+Array\s*\(\s*n\s*\)\s*\.fill\s*\(\s*false\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); +--fcc-editable-region-- + +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac1.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac1.md new file mode 100644 index 00000000000..3a1f773aa29 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac1.md @@ -0,0 +1,70 @@ +--- +id: 69c918841987bf16c1d1bac1 +title: Step 10 +challengeType: 1 +dashedName: step-10 +--- + +# --description-- + +Now you'll add the main loop that drives the algorithm. It runs once for each node in the graph, selecting the closest unvisited node each time. + +Inside the `shortestPath` function, add a `for` loop that runs `n` times using `i` as the loop variable. + +At the start of the loop body, using `let`, declare two variables `minDistance` and `current` set to `INF`, and `-1` respectively. These will track the closest unvisited node found in each iteration. + +# --hints-- + +You should have a `for` loop inside `shortestPath` that runs `n` times. Don't forget to set `i` with `let` inside it. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*n\s*;\s*i\+\+\s*\)/ +); +``` + +You should have a `minDistance` variable set to `INF` inside the loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(let|var)\s+minDistance\s*=\s*INF/ +); +``` + +You should have a `current` variable set to `-1` inside the loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(let|var)\s+current\s*=\s*-1/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); +--fcc-editable-region-- + +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac2.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac2.md new file mode 100644 index 00000000000..918b87ad51b --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac2.md @@ -0,0 +1,57 @@ +--- +id: 69c918841987bf16c1d1bac2 +title: Step 11 +challengeType: 1 +dashedName: step-11 +--- + +# --description-- + +Inside the loop, you need to scan every node to find the one with the smallest known distance that hasn't been visited yet. + +Add a `for` loop inside the main loop that iterates through each node. Use `nodeNo` as the loop variable going from `0` to `n`. + +Leave the body empty for now. + +# --hints-- + +You should have a second (inner) `for` loop inside the main loop with `nodeNo` as its loop variable. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /for\s*\(\s*(let|var)\s+nodeNo\s*=\s*0\s*;\s*nodeNo\s*<\s*n\s*;\s*nodeNo\+\+\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + +--fcc-editable-region-- + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + + } +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac3.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac3.md new file mode 100644 index 00000000000..7dce4793c2a --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac3.md @@ -0,0 +1,59 @@ +--- +id: 69c918841987bf16c1d1bac3 +title: Step 12 +challengeType: 1 +dashedName: step-12 +--- + +# --description-- + +Inside the inner `for` loop, you need to check whether the current node is unvisited and closer than the best you've found so far. + +Add an `if` statement that checks if `nodeNo` has not been visited and `distances[nodeNo]` is less than `minDistance`. + +Leave the body empty for now. + +# --hints-- + +You should have an `if` statement with the condition `!visited[nodeNo] && distances[nodeNo] < minDistance` inside the inner `for` loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*!visited\s*\[\s*nodeNo\s*\]\s*&&\s*distances\s*\[\s*nodeNo\s*\]\s*<\s*minDistance\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + --fcc-editable-region-- + + --fcc-editable-region-- + } + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac4.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac4.md new file mode 100644 index 00000000000..f35051f2f45 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac4.md @@ -0,0 +1,68 @@ +--- +id: 69c918841987bf16c1d1bac4 +title: Step 13 +challengeType: 1 +dashedName: step-13 +--- + +# --description-- + +If the condition is true, the current node is the best unvisited candidate found so far. You need to update your tracking variables to reflect that. + +Inside the `if` statement, update `minDistance` to `distances[nodeNo]` and `current` to `nodeNo`. + +# --hints-- + +You should set `minDistance` to `distances[nodeNo]` inside the `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /minDistance\s*=\s*distances\s*\[\s*nodeNo\s*\]/ +); +``` + +You should set `current` to `nodeNo` inside the `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /current\s*=\s*nodeNo/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + --fcc-editable-region-- + + --fcc-editable-region-- + } + } + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac5.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac5.md new file mode 100644 index 00000000000..c0f2c5c0b6a --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac5.md @@ -0,0 +1,70 @@ +--- +id: 69c918841987bf16c1d1bac5 +title: Step 14 +challengeType: 1 +dashedName: step-14 +--- + +# --description-- + +After scanning all nodes to find the closest unvisited one, you need to handle the case where no valid node is found. This happens when all remaining nodes are unreachable. + +After the inner `for` loop, but still inside the outer loop, add an `if` statement that checks if `current` is strictly equal to `-1`. If that is true, use `break` inside the `if` block to stop the outer loop early. + +# --hints-- + +You should add an `if` statement that checks if `current === -1`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*current\s*===\s*-1\s*\)/ +); +``` + +You should use `break` inside the `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*current\s*===\s*-1\s*\)[\s\S]*?break/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } +--fcc-editable-region-- + +--fcc-editable-region-- + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac6.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac6.md new file mode 100644 index 00000000000..f4ba402d318 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac6.md @@ -0,0 +1,65 @@ +--- +id: 69c918841987bf16c1d1bac6 +title: Step 15 +challengeType: 1 +dashedName: step-15 +--- + +# --description-- + +Once you've confirmed a valid node was found, mark it as visited so the algorithm won't process it again. + +After the `if` statement with the condition `current === -1`, set `visited[current]` to `true`. + +# --hints-- + +You should set `visited[current]` to `true`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /visited\s*\[\s*current\s*\]\s*=\s*true/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + + if (current === -1) { + break; + } + --fcc-editable-region-- + + --fcc-editable-region-- + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac7.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac7.md new file mode 100644 index 00000000000..d898bc3db31 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac7.md @@ -0,0 +1,85 @@ +--- +id: 69c918841987bf16c1d1bac7 +title: Step 16 +challengeType: 1 +dashedName: step-16 +--- + +# --description-- + +Now that the current node is marked as visited, you need to look at all its neighbors to see if you can reach them more efficiently through the current node. + +After `visited[current] = true`, add a neighbor `for` loop that iterates through each `nodeNo` from `0` to `n`. Note that this is another inner loop on the same level as the first. + +Inside the loop, declare a variable named `distance` and assign it `matrix[current][nodeNo]`. This gives you the edge weight between the current node and its neighbor. + +# --hints-- + +You should add a neighbor `for` loop after marking the current node as visited. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /visited\s*\[\s*current\s*\]\s*=\s*true[\s\S]*?for\s*\(/ +); +``` + +The neighbor `for` loop should iterate from `0` to `n`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /visited\s*\[\s*current\s*\]\s*=\s*true[\s\S]*?for\s*\(\s*(var|let)\s+\w+\s*=\s*0\s*;\s*\w+\s*<\s*n\s*;\s*\w+\+\+\s*\)/ +); +``` + +You should have a `distance` variable assigned to `matrix[current][nodeNo]` inside the neighbor loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+distance\s*=\s*matrix\s*\[\s*current\s*\]\s*\[\s*\w+\s*\]/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; +--fcc-editable-region-- + +--fcc-editable-region-- + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac8.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac8.md new file mode 100644 index 00000000000..b85ceb87c5c --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac8.md @@ -0,0 +1,80 @@ +--- +id: 69c918841987bf16c1d1bac8 +title: Step 17 +challengeType: 1 +dashedName: step-17 +--- + +# --description-- + +Before updating distances, you need to verify the neighbor is worth considering. There must be an actual edge to it (`distance !== INF`) and it must not have been visited yet. + +Inside the neighbor `for` loop, add an `if` statement that checks if `distance` is not strictly equal to `INF` **and** if `nodeNo` is not visited. + +Inside the `if` block, declare a variable `newDistance` assigned to `distances[current] + distance`. This is the total cost of reaching the neighbor through the current node. + +# --hints-- + +You should add an `if` statement with the condition `distance !== INF && !visited[nodeNo]`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*distance\s*!==\s*INF\s*&&\s*!\s*visited\s*\[\s*\w+\s*\]\s*\)/ +); +``` + +You should declare a `newDistance` with the value `distances[current] + distance` inside the `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+newDistance\s*=\s*distances\s*\[\s*current\s*\]\s*\+\s*distance/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + --fcc-editable-region-- + + --fcc-editable-region-- + } + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac9.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac9.md new file mode 100644 index 00000000000..daf8e577fd8 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bac9.md @@ -0,0 +1,81 @@ +--- +id: 69c918841987bf16c1d1bac9 +title: Step 18 +challengeType: 1 +dashedName: step-18 +--- + +# --description-- + +Now you should check whether going through the current node gives a shorter route to the neighbor. If `newDistance` is better than what's already stored, then you should update it. + +Inside the existing `if` block, add a nested `if` statement that checks if `newDistance` is less than `distances[nodeNo]`. Inside that nested `if` block, update `distances[nodeNo]` to `newDistance`. + +# --hints-- + +You should add a nested `if` statement with the condition `newDistance < distances[nodeNo]`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*newDistance\s*<\s*distances\s*\[\s*\w+\s*\]\s*\)/ +); +``` + +You should update `distances[nodeNo]` to `newDistance` inside the nested `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /distances\s*\[\s*\w+\s*\]\s*=\s*newDistance/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + --fcc-editable-region-- + + --fcc-editable-region-- + } + } + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baca.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baca.md new file mode 100644 index 00000000000..b0596c51db3 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1baca.md @@ -0,0 +1,90 @@ +--- +id: 69c918841987bf16c1d1baca +title: Step 19 +challengeType: 1 +dashedName: step-19 +--- + +# --description-- + +When you find a shorter path to a neighbor, you also need to update the recorded path to reach it. + +In JavaScript, you can create a new array combining an existing array and a new element using the spread operator: + +```js +const newPath = [...existingArray, newElement]; +``` + +Inside the nested `if` block, update `paths[nodeNo]` to be the path to the current node with `nodeNo` appended at the end using spread syntax like so: `[...paths[current], nodeNo]`. + +# --hints-- + +You should update `paths[nodeNo]` inside the nested `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /paths\s*\[\s*\w+\s*\]\s*=/ +); +``` + +`paths[nodeNo]` should be set to `[...paths[current], nodeNo]`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /paths\s*\[\s*\w+\s*\]\s*=\s*\[\s*\.\.\.\s*paths\s*\[\s*current\s*\]\s*,\s*\w+\s*\]/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + --fcc-editable-region-- + + --fcc-editable-region-- + } + } + } + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacb.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacb.md new file mode 100644 index 00000000000..76b8e4373d2 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacb.md @@ -0,0 +1,98 @@ +--- +id: 69c918841987bf16c1d1bacb +title: Step 20 +challengeType: 1 +dashedName: step-20 +--- + +# --description-- + +Once the main loop finishes, you need to decide which node(s) to display results for. + +If a specific `targetNode` was provided, only show results for that node. Otherwise, show results for all nodes. + +In JavaScript, you can get all indices of an array as an iterable using `[...Array(n).keys()]`. + +After the outer `for` loop, create a variable named `targets`. Using a ternary expression, if `targetNode` is strictly not `null`, assign `[targetNode]`, otherwise assign `[...Array(n).keys()]`. + +# --hints-- + +You should create a variable `targets` after the main loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /(const|let|var)\s+targets\s*=/ +); +``` + +Your `targets` variable should use a ternary checking `targetNode !== null`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /targets\s*=\s*targetNode\s*!==\s*null\s*\?/ +); +``` + +When a target is provided, `targets` should be `[targetNode]`, otherwise it should be `[...Array(n).keys()]`. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /\?\s*\[\s*targetNode\s*\]\s*:\s*\[\s*\.\.\.\s*Array\s*\(\s*n\s*\)\s*\.keys\s*\(\s*\)\s*\]/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } +--fcc-editable-region-- + +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacc.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacc.md new file mode 100644 index 00000000000..4df6bd50680 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacc.md @@ -0,0 +1,77 @@ +--- +id: 69c918841987bf16c1d1bacc +title: Step 21 +challengeType: 1 +dashedName: step-21 +--- + +# --description-- + +Now loop through the target nodes to display results for each one. + +Add a `for...of` loop that iterates over `targets` using `nodeNo` as the loop variable. Leave the body empty for now. + +# --hints-- + +You should create a `for...of` loop with the variable `nodeNo` iterating over `targets`. + +```js +assert.match( + __helpers.removeJSComments(code), + /for\s*\(\s*(const|let)\s+nodeNo\s+of\s+targets\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; +--fcc-editable-region-- + +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacd.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacd.md new file mode 100644 index 00000000000..a653ee9d129 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacd.md @@ -0,0 +1,89 @@ +--- +id: 69c918841987bf16c1d1bacd +title: Step 22 +challengeType: 1 +dashedName: step-22 +--- + +# --description-- + +You only want to display results for nodes that are reachable and different from the start node. + +Inside the `for...of` loop, add an `if` statement that checks if `nodeNo` is strictly equal to `startNode` **or** `distances[nodeNo]` is strictly equal to `INF`. If either is true, use `continue` inside the `if` block to skip to the next iteration. + +# --hints-- + +You should have an `if` statement with the condition `nodeNo === startNode || distances[nodeNo] === INF` inside your `for...of` loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*\w+\s*===\s*startNode\s*\|\|\s*distances\s*\[\s*\w+\s*\]\s*===\s*INF\s*\)/ +); +``` + +You should use `continue` in the `if` block. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /if\s*\(\s*\w+\s*===\s*startNode\s*\|\|\s*distances\s*\[\s*\w+\s*\]\s*===\s*INF\s*\)[\s\S]*?continue/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; +--fcc-editable-region-- + for (const nodeNo of targets) { + + } +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bace.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bace.md new file mode 100644 index 00000000000..75edad93d73 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bace.md @@ -0,0 +1,94 @@ +--- +id: 69c918841987bf16c1d1bace +title: Step 23 +challengeType: 1 +dashedName: step-23 +--- + +# --description-- + +Now that you know the node is reachable and not the start, format its path into a readable string. + +The `paths[nodeNo]` array holds the sequence of node indices visited to reach `nodeNo`. You can turn that into a human-readable string like `0 -> 2 -> 3` using the `.join()` method. + +Inside the `for...of` loop, after the `if` statement with `continue`, declare a variable named `path` and assign it the value `paths[nodeNo].join(' -> ')`. + +# --hints-- + +You should have a variable named `path` inside the `for...of` loop. + +```js +assert.match( + __helpers.removeJSComments(code), + /for\s*\(\s*(const|let)\s+nodeNo\s+of\s+targets\s*\)[\s\S]*?(const|let)\s+path\s*=/ +); +``` + +Your `path` variable should have the value `paths[nodeNo].join(' -> ')`. + +```js +assert.match( + __helpers.removeJSComments(code), + /path\s*=\s*paths\s*\[\s*\w+\s*\]\s*\.\s*join\s*\(\s*['"]\s*->\s*['"]\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; + for (const nodeNo of targets) { + if (nodeNo === startNode || distances[nodeNo] === INF) { + continue; + } + --fcc-editable-region-- + + --fcc-editable-region-- + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacf.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacf.md new file mode 100644 index 00000000000..0249fc8f0be --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bacf.md @@ -0,0 +1,113 @@ +--- +id: 69c918841987bf16c1d1bacf +title: Step 24 +challengeType: 1 +dashedName: step-24 +--- + +# --description-- + +Now, you should print the result for each reachable node. + +After the `path` variable, add a `console.log()` call with a template literal that outputs: + +```md +\n{startNode}-{nodeNo} distance: {distances[nodeNo]}\nPath: {path} +``` + +For example, if `startNode` is `0` and `nodeNo` is `3`, the output should look like this: + +```md +0-3 distance: 4 +Path: 0 -> 2 -> 3 +``` + +# --hints-- + +You should have a `console.log()` inside the `for...of` loop. + +```js +assert.match( + __helpers.removeJSComments(code), + /for\s*\(\s*(const|let)\s+nodeNo\s+of\s+targets\s*\)[\s\S]*?console\s*\.\s*log\s*\(/ +); +``` + +The `console.log()` should use a template literal containing `${startNode}-${nodeNo} distance: ${distances[nodeNo]}`. + +```js +assert.match( + __helpers.removeJSComments(code), + /console\s*\.\s*log\s*\(\s*`[\s\S]*?\$\{\s*startNode\s*\}[\s\S]*?\$\{\s*nodeNo\s*\}[\s\S]*?\$\{\s*distances\s*\[\s*nodeNo\s*\]\s*\}[\s\S]*?`\s*\)/ +); +``` + +The template literal should also include `${path}`. + +```js +assert.match( + __helpers.removeJSComments(code), + /console\s*\.\s*log\s*\(\s*`[\s\S]*?\$\{\s*path\s*\}[\s\S]*?`\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; + for (const nodeNo of targets) { + if (nodeNo === startNode || distances[nodeNo] === INF) { + continue; + } + const path = paths[nodeNo].join(' -> '); + --fcc-editable-region-- + + --fcc-editable-region-- + } +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad0.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad0.md new file mode 100644 index 00000000000..ee95527f180 --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad0.md @@ -0,0 +1,86 @@ +--- +id: 69c918841987bf16c1d1bad0 +title: Step 25 +challengeType: 1 +dashedName: step-25 +--- + + +# --description-- + +The function should return the computed data so callers can use it programmatically. + +After the `for...of` loop, add a `return` statement that returns an array containing `distances` and `paths`, in that order. + +# --hints-- + +You should return `[distances, paths]` after the `for...of` loop. + +```js +assert.match( + __helpers.removeJSComments(shortestPath.toString()), + /return\s*\[\s*distances\,\s*paths\]/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; + for (const nodeNo of targets) { + if (nodeNo === startNode || distances[nodeNo] === INF) { + continue; + } + const path = paths[nodeNo].join(' -> '); + console.log(`\n${startNode}-${nodeNo} distance: ${distances[nodeNo]}\nPath: ${path}`); + } +--fcc-editable-region-- + +--fcc-editable-region-- +} +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad1.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad1.md new file mode 100644 index 00000000000..101af91c87f --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c918841987bf16c1d1bad1.md @@ -0,0 +1,151 @@ +--- +id: 69c918841987bf16c1d1bad1 +title: Step 26 +challengeType: 1 +dashedName: step-26 +--- + +# --description-- + +The function is complete. Now call it to see the results. + +At the bottom of the file (outside the function), call `shortestPath` with `adjMatrix` as the matrix, `0` as the start node, and `5` as the target node. + +This will print the shortest path from node `0` to node `5` in the adjacency matrix. + +With that, your shortest path algorithm workshop is complete! + +# --hints-- + +You should call the `shortestPath` function with `adjMatrix, 0, 5`. + +```js +assert.match( + __helpers.removeJSComments(code), + /shortestPath\s*\(\s*adjMatrix\s*,\s*0\s*,\s*5\s*\)/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; + for (const nodeNo of targets) { + if (nodeNo === startNode || distances[nodeNo] === INF) { + continue; + } + const path = paths[nodeNo].join(' -> '); + console.log(`\n${startNode}-${nodeNo} distance: ${distances[nodeNo]}\nPath: ${path}`); + } + return [distances, paths]; +} + +--fcc-editable-region-- + +--fcc-editable-region-- +``` + +# --solutions-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +function shortestPath(matrix, startNode, targetNode = null) { + const n = matrix.length; + const distances = new Array(n).fill(INF); + distances[startNode] = 0; + const paths = Array.from({ length: n }, (_, i) => [i]); + const visited = new Array(n).fill(false); + + for (let i = 0; i < n; i++) { + let minDistance = INF; + let current = -1; + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + if (!visited[nodeNo] && distances[nodeNo] < minDistance) { + minDistance = distances[nodeNo]; + current = nodeNo; + } + } + if (current === -1) { + break; + } + visited[current] = true; + + for (let nodeNo = 0; nodeNo < n; nodeNo++) { + const distance = matrix[current][nodeNo]; + if (distance !== INF && !visited[nodeNo]) { + const newDistance = distances[current] + distance; + if (newDistance < distances[nodeNo]) { + distances[nodeNo] = newDistance; + paths[nodeNo] = [...paths[current], nodeNo]; + } + } + } + } + + const targets = targetNode !== null ? [targetNode] : [...Array(n).keys()]; + for (const nodeNo of targets) { + if (nodeNo === startNode || distances[nodeNo] === INF) { + continue; + } + const path = paths[nodeNo].join(' -> '); + console.log(`\n${startNode}-${nodeNo} distance: ${distances[nodeNo]}\nPath: ${path}`); + } + return [distances, paths]; +} + +shortestPath(adjMatrix, 0, 5); +``` diff --git a/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c937c73f23b1140bcd297a.md b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c937c73f23b1140bcd297a.md new file mode 100644 index 00000000000..fc65629043a --- /dev/null +++ b/curriculum/challenges/english/blocks/workshop-shortest-path-algorithm-js/69c937c73f23b1140bcd297a.md @@ -0,0 +1,45 @@ +--- +id: 69c937c73f23b1140bcd297a +title: Step 4 +challengeType: 1 +dashedName: step-4 +--- + +# --description-- + +The `targetNode` parameter is optional. When not provided, the function will compute shortest paths from `startNode` to all other nodes in the graph. + +Give the `targetNode` parameter a default value of `null`. + +# --hints-- + +The `targetNode` parameter of your `shortestPath` function should default to `null`. + +```js +assert.match( + __helpers.removeJSComments(code), + /targetNode\s*=\s*null/ +); +``` + +# --seed-- + +## --seed-contents-- + +```js +const INF = Infinity; +const adjMatrix = [ + [0, 5, 3, INF, 11, INF], + [5, 0, 1, INF, INF, 2], + [3, 1, 0, 1, 5, INF], + [INF, INF, 1, 0, 9, 3], + [11, INF, 5, 9, 0, INF], + [INF, 2, INF, 3, INF, 0], +]; + +--fcc-editable-region-- +function shortestPath(matrix, startNode, targetNode) { + +} +--fcc-editable-region-- +``` diff --git a/curriculum/structure/blocks/workshop-shortest-path-algorithm-js.json b/curriculum/structure/blocks/workshop-shortest-path-algorithm-js.json new file mode 100644 index 00000000000..c6b4afd56cd --- /dev/null +++ b/curriculum/structure/blocks/workshop-shortest-path-algorithm-js.json @@ -0,0 +1,37 @@ +{ + "isUpcomingChange": true, + "dashedName": "workshop-shortest-path-algorithm-js", + "helpCategory": "JavaScript", + "blockLayout": "challenge-grid", + "blockLabel": "workshop", + "usesMultifileEditor": true, + "hasEditableBoundaries": true, + "challengeOrder": [ + { "id": "0095d0567b6817114989a1dd", "title": "Step 1" }, + { "id": "69c918841987bf16c1d1baba", "title": "Step 2" }, + { "id": "69c918841987bf16c1d1babb", "title": "Step 3" }, + { "id": "69c937c73f23b1140bcd297a", "title": "Step 4" }, + { "id": "69c918841987bf16c1d1babc", "title": "Step 5" }, + { "id": "69c918841987bf16c1d1babd", "title": "Step 6" }, + { "id": "69c918841987bf16c1d1babe", "title": "Step 7" }, + { "id": "69c918841987bf16c1d1babf", "title": "Step 8" }, + { "id": "69c918841987bf16c1d1bac0", "title": "Step 9" }, + { "id": "69c918841987bf16c1d1bac1", "title": "Step 10" }, + { "id": "69c918841987bf16c1d1bac2", "title": "Step 11" }, + { "id": "69c918841987bf16c1d1bac3", "title": "Step 12" }, + { "id": "69c918841987bf16c1d1bac4", "title": "Step 13" }, + { "id": "69c918841987bf16c1d1bac5", "title": "Step 14" }, + { "id": "69c918841987bf16c1d1bac6", "title": "Step 15" }, + { "id": "69c918841987bf16c1d1bac7", "title": "Step 16" }, + { "id": "69c918841987bf16c1d1bac8", "title": "Step 17" }, + { "id": "69c918841987bf16c1d1bac9", "title": "Step 18" }, + { "id": "69c918841987bf16c1d1baca", "title": "Step 19" }, + { "id": "69c918841987bf16c1d1bacb", "title": "Step 20" }, + { "id": "69c918841987bf16c1d1bacc", "title": "Step 21" }, + { "id": "69c918841987bf16c1d1bacd", "title": "Step 22" }, + { "id": "69c918841987bf16c1d1bace", "title": "Step 23" }, + { "id": "69c918841987bf16c1d1bacf", "title": "Step 24" }, + { "id": "69c918841987bf16c1d1bad0", "title": "Step 25" }, + { "id": "69c918841987bf16c1d1bad1", "title": "Step 26" } + ] +} diff --git a/curriculum/structure/superblocks/javascript-v9.json b/curriculum/structure/superblocks/javascript-v9.json index 5f79a90eede..0f819e949f5 100644 --- a/curriculum/structure/superblocks/javascript-v9.json +++ b/curriculum/structure/superblocks/javascript-v9.json @@ -329,6 +329,7 @@ "comingSoon": true, "blocks": [ "lecture-understanding-graphs-and-trees-js", + "workshop-shortest-path-algorithm-js", "lab-adjacency-list-to-matrix-converter-js", "workshop-breadth-first-search-js", "lab-depth-first-search-js",