From 2caf310b4276dcc3b47d77074e716e944927d54d Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 24 Mar 2024 16:24:03 +0000 Subject: [PATCH 01/21] feat/ generate exercise --- 20_hanoi/README.md | 3 +++ 20_hanoi/hanoi.js | 6 ++++++ 20_hanoi/hanoi.spec.js | 15 +++++++++++++++ 20_hanoi/solution/hanoi-solution.js | 6 ++++++ 20_hanoi/solution/hanoi-solution.spec.js | 15 +++++++++++++++ 5 files changed, 45 insertions(+) create mode 100644 20_hanoi/README.md create mode 100644 20_hanoi/hanoi.js create mode 100644 20_hanoi/hanoi.spec.js create mode 100644 20_hanoi/solution/hanoi-solution.js create mode 100644 20_hanoi/solution/hanoi-solution.spec.js diff --git a/20_hanoi/README.md b/20_hanoi/README.md new file mode 100644 index 00000000000..decdd70fe7c --- /dev/null +++ b/20_hanoi/README.md @@ -0,0 +1,3 @@ +# Exercise 20 - hanoi + +Description of the exercise goes here. diff --git a/20_hanoi/hanoi.js b/20_hanoi/hanoi.js new file mode 100644 index 00000000000..1f84ae7b454 --- /dev/null +++ b/20_hanoi/hanoi.js @@ -0,0 +1,6 @@ +const hanoi = function() { + +}; + +// Do not edit below this line +module.exports = hanoi; diff --git a/20_hanoi/hanoi.spec.js b/20_hanoi/hanoi.spec.js new file mode 100644 index 00000000000..f29dc5dcc57 --- /dev/null +++ b/20_hanoi/hanoi.spec.js @@ -0,0 +1,15 @@ +const hanoi = require('./hanoi'); + +describe('hanoi', () => { + test('First test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(hanoi()).toBe(''); + }); + + test.skip('Second test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(hanoi()).toBe(''); + }); +}); diff --git a/20_hanoi/solution/hanoi-solution.js b/20_hanoi/solution/hanoi-solution.js new file mode 100644 index 00000000000..43a19463956 --- /dev/null +++ b/20_hanoi/solution/hanoi-solution.js @@ -0,0 +1,6 @@ +const hanoi = function() { + // Replace this comment with the solution code +}; + +// Do not edit below this line +module.exports = hanoi; diff --git a/20_hanoi/solution/hanoi-solution.spec.js b/20_hanoi/solution/hanoi-solution.spec.js new file mode 100644 index 00000000000..897e9086f55 --- /dev/null +++ b/20_hanoi/solution/hanoi-solution.spec.js @@ -0,0 +1,15 @@ +const hanoi = require('./hanoi-solution'); + +describe('hanoi', () => { + test('First test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(hanoi()).toBe(''); + }); + + test('Second test description', () => { + // Replace this comment with any other necessary code, and update the expect line as necessary + + expect(hanoi()).toBe(''); + }); +}); From d5d8bc8c8062fc215cf9cd8c0911ba251bb75cf2 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:52:48 +0100 Subject: [PATCH 02/21] feat(hanoi): create solution --- 20_hanoi/solution/hanoi-solution.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/20_hanoi/solution/hanoi-solution.js b/20_hanoi/solution/hanoi-solution.js index 43a19463956..3f465abb0fb 100644 --- a/20_hanoi/solution/hanoi-solution.js +++ b/20_hanoi/solution/hanoi-solution.js @@ -1,6 +1,29 @@ -const hanoi = function() { - // Replace this comment with the solution code +const hanoi = function ( + n, + fromTowerIndex = 0, + storageTowerIndex = 1, + toTowerIndex = 2, + towers = [ + Array(n) + .fill() // Array function creates an array with "empty" slots which map does not iterate over + .map((_, i) => n - i), + [], + [], + ], + steps = [towers.map((tower) => [...tower])], +) { + if (n === 0) return steps; + + hanoi(n - 1, fromTowerIndex, toTowerIndex, storageTowerIndex, towers, steps); + + towers[toTowerIndex].push(towers[fromTowerIndex].pop()); + + steps.push(towers.map((tower) => [...tower])); + + hanoi(n - 1, storageTowerIndex, fromTowerIndex, toTowerIndex, towers, steps); + + return steps; }; - + // Do not edit below this line module.exports = hanoi; From 9577544e1e54206245cd8231aaa760341e7554a0 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:53:00 +0100 Subject: [PATCH 03/21] feat(hanoi): create explanation readme --- 20_hanoi/README.md | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index decdd70fe7c..1ff8e36ee86 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -1,3 +1,39 @@ # Exercise 20 - hanoi -Description of the exercise goes here. +Good job, you have come a very long way. You should be proud of yourself for making it this far. At this point, you hopefully feel comfortable +with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the _next_ level. + +Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. +Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are exactly the in the same order. For instance: + +```javascript +[[3, 2, 1], [], []] + +// ... + +[[], [], [3, 2, 1]] +``` + +The rules are as follows: +- Each disk has a length. For abstraction purposes, we will imagine each disk as an integer with that disks' length. +- We can only move 1 disk at a time between any of the towers +- The towers are modelled as stacks. We can move disks from the top and add them to the top with the `Array.prototype.pop` and `Array.prototype.push` methods. +- **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the following tower: `[3, 4]`. It would violate the rules + +Your task is to create a function, `hanoi`, that when given an integer `n` will perform the required operations to transport all the numbers from the `first tower` +onto the `third tower`. + +For example, lets say we had given this function `3`, it will then output the Tower of Hanoi solution as a series of steps: + +``` +[ +[[3, 2, 1], [], []], +[[3, 2], [], [1]], +[[3], [2], [1]], +[[3], [2, 1], []], +[[], [2, 1], [3]], +[[1], [2], [3]], +[[1], [], [3, 2]], +[[], [], [3, 2, 1]], +] +``` From 509c18d3b97474c4f17296ff9884ba4a45f2b02a Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Fri, 3 May 2024 01:18:37 +0100 Subject: [PATCH 04/21] feat(hanoi): create tests for exercise --- 20_hanoi/solution/hanoi-solution.spec.js | 64 ++++++++++++++++++++---- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/20_hanoi/solution/hanoi-solution.spec.js b/20_hanoi/solution/hanoi-solution.spec.js index 897e9086f55..198b4245162 100644 --- a/20_hanoi/solution/hanoi-solution.spec.js +++ b/20_hanoi/solution/hanoi-solution.spec.js @@ -1,15 +1,61 @@ -const hanoi = require('./hanoi-solution'); +const hanoi = require("./hanoi-solution"); -describe('hanoi', () => { - test('First test description', () => { - // Replace this comment with any other necessary code, and update the expect line as necessary +describe("hanoi", () => { + test("hanoi(1) should solve the puzzle in 1 move", () => { + const result = hanoi(1); + expect(result).toEqual([ + [[1], [], []], + [[], [], [1]], + ]); + expect(result.length).toBe(2); + }); + + test("hanoi(2) should solve the puzzle in 3 moves", () => { + const result = hanoi(2); + expect(result).toEqual([ + [[2, 1], [], []], + [[2], [1], []], + [[], [1], [2]], + [[], [], [2, 1]], + ]); + expect(result.length).toBe(4); + }); - expect(hanoi()).toBe(''); + test("hanoi(3) should solve the puzzle in 7 moves", () => { + const result = hanoi(3); + expect(result).toEqual([ + [[3, 2, 1], [], []], + [[3, 2], [], [1]], + [[3], [2], [1]], + [[3], [2, 1], []], + [[], [2, 1], [3]], + [[1], [2], [3]], + [[1], [], [3, 2]], + [[], [], [3, 2, 1]], + ]); + expect(result.length).toBe(8); }); - - test('Second test description', () => { - // Replace this comment with any other necessary code, and update the expect line as necessary - expect(hanoi()).toBe(''); + test("hanoi(4) should solve the puzzle in 15 moves", () => { + const result = hanoi(4); + const expected = [ + [[4, 3, 2, 1], [], []], + [[4, 3, 2], [1], []], + [[4, 3], [1], [2]], + [[4, 3], [], [2, 1]], + [[4], [3], [2, 1]], + [[4, 1], [3], [2]], + [[4, 1], [3, 2], []], + [[4], [3, 2, 1], []], + [[], [3, 2, 1], [4]], + [[], [3, 2], [4, 1]], + [[2], [3], [4, 1]], + [[2, 1], [3], [4]], + [[2, 1], [], [4, 3]], + [[2], [1], [4, 3]], + [[], [1], [4, 3, 2]], + [[], [], [4, 3, 2, 1]], + ]; + expect(result).toEqual(expected); }); }); From 507b137292515257b4cc1c75fc6643e2cc26199e Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:15:17 +0100 Subject: [PATCH 05/21] refactor: wording Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 1ff8e36ee86..cbf80e92533 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -18,7 +18,7 @@ The rules are as follows: - Each disk has a length. For abstraction purposes, we will imagine each disk as an integer with that disks' length. - We can only move 1 disk at a time between any of the towers - The towers are modelled as stacks. We can move disks from the top and add them to the top with the `Array.prototype.pop` and `Array.prototype.push` methods. -- **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the following tower: `[3, 4]`. It would violate the rules +- **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the tower `[3, 4]` but `[4, 3]` is fine. Your task is to create a function, `hanoi`, that when given an integer `n` will perform the required operations to transport all the numbers from the `first tower` onto the `third tower`. From 2d6cdc310e6bdfacaf62a5dc4ed65be4004e97e2 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:15:36 +0100 Subject: [PATCH 06/21] chore: use `_` instead of `*` Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index cbf80e92533..3b51255742a 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -1,7 +1,7 @@ # Exercise 20 - hanoi Good job, you have come a very long way. You should be proud of yourself for making it this far. At this point, you hopefully feel comfortable -with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the _next_ level. +with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are exactly the in the same order. For instance: From c9f385f4b17bb9042917a97442cfbcdf7cd90f44 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:15:47 +0100 Subject: [PATCH 07/21] refactor: wording Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 3b51255742a..2082d711362 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -4,7 +4,7 @@ Good job, you have come a very long way. You should be proud of yourself for mak with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. -Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are exactly the in the same order. For instance: +Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are in the exact same order. For instance: ```javascript [[3, 2, 1], [], []] From 85570c60ee99769eeb81079f557017d7b00cad50 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Wed, 3 Jul 2024 17:16:04 +0100 Subject: [PATCH 08/21] fix: spelling Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 2082d711362..263e17145e7 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -15,7 +15,7 @@ Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so ``` The rules are as follows: -- Each disk has a length. For abstraction purposes, we will imagine each disk as an integer with that disks' length. +- Each disk has a length. For abstraction purposes, we will imagine each disk as an integer with that disk's length. - We can only move 1 disk at a time between any of the towers - The towers are modelled as stacks. We can move disks from the top and add them to the top with the `Array.prototype.pop` and `Array.prototype.push` methods. - **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the tower `[3, 4]` but `[4, 3]` is fine. From 842e1b7fb2fb42e0da0fe8e19ead1b4362a2e562 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:49:16 +0100 Subject: [PATCH 09/21] refactor: remove redundant `length` tests --- 20_hanoi/solution/hanoi-solution.spec.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/20_hanoi/solution/hanoi-solution.spec.js b/20_hanoi/solution/hanoi-solution.spec.js index 198b4245162..79c8970f7b1 100644 --- a/20_hanoi/solution/hanoi-solution.spec.js +++ b/20_hanoi/solution/hanoi-solution.spec.js @@ -3,27 +3,27 @@ const hanoi = require("./hanoi-solution"); describe("hanoi", () => { test("hanoi(1) should solve the puzzle in 1 move", () => { const result = hanoi(1); - expect(result).toEqual([ + const expected = [ [[1], [], []], [[], [], [1]], - ]); - expect(result.length).toBe(2); + ]; + expect(result).toEqual(expected); }); test("hanoi(2) should solve the puzzle in 3 moves", () => { const result = hanoi(2); - expect(result).toEqual([ + const expected = [ [[2, 1], [], []], [[2], [1], []], [[], [1], [2]], [[], [], [2, 1]], - ]); - expect(result.length).toBe(4); + ]; + expect(result).toEqual(expected); }); test("hanoi(3) should solve the puzzle in 7 moves", () => { const result = hanoi(3); - expect(result).toEqual([ + const expected = [ [[3, 2, 1], [], []], [[3, 2], [], [1]], [[3], [2], [1]], @@ -32,15 +32,15 @@ describe("hanoi", () => { [[1], [2], [3]], [[1], [], [3, 2]], [[], [], [3, 2, 1]], - ]); - expect(result.length).toBe(8); + ]; + expect(result).toEqual(expected); }); test("hanoi(4) should solve the puzzle in 15 moves", () => { const result = hanoi(4); const expected = [ [[4, 3, 2, 1], [], []], - [[4, 3, 2], [1], []], + [[4, 3, 2], [1], []], [[4, 3], [1], [2]], [[4, 3], [], [2, 1]], [[4], [3], [2, 1]], From 6163c8dd4413f1d40bd7ca6c309468bf163b59d6 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:56:54 +0100 Subject: [PATCH 10/21] feat: clarify requirements --- 20_hanoi/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 263e17145e7..5edbb2eedb7 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -17,11 +17,11 @@ Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so The rules are as follows: - Each disk has a length. For abstraction purposes, we will imagine each disk as an integer with that disk's length. - We can only move 1 disk at a time between any of the towers -- The towers are modelled as stacks. We can move disks from the top and add them to the top with the `Array.prototype.pop` and `Array.prototype.push` methods. +- The towers are modelled as stacks. We can move disks from the top of one stack to the top of another stack with the `Array.prototype.pop` and `Array.prototype.push` methods. - **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the tower `[3, 4]` but `[4, 3]` is fine. -Your task is to create a function, `hanoi`, that when given an integer `n` will perform the required operations to transport all the numbers from the `first tower` -onto the `third tower`. +Your task is to create a function, `hanoi(n)`, that when given the number of disks in the starting tower (`n`), will return an array. The first element of this array will be the towers' initial state. The last element will be the towers' final state. Every intermediary element will represent a step to get from the initial position to the final position. +The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the array returned. For example, lets say we had given this function `3`, it will then output the Tower of Hanoi solution as a series of steps: From e010cdcdcd62c021f271d0bedfcb5f6b8950427d Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:29:30 +0100 Subject: [PATCH 11/21] feat(hanoi): add line breaks Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 5edbb2eedb7..13ba5820ed5 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -1,7 +1,6 @@ # Exercise 20 - hanoi -Good job, you have come a very long way. You should be proud of yourself for making it this far. At this point, you hopefully feel comfortable -with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. +Good job, you have come a very long way. You should be proud of yourself for making it this far. At this point, you hopefully feel comfortable with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are in the exact same order. For instance: From 1fc7d090413144dc34aa6229af40231a8bd09296 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:29:42 +0100 Subject: [PATCH 12/21] feat(hanoi): add line breaks Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 13ba5820ed5..c6109271225 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -2,8 +2,7 @@ Good job, you have come a very long way. You should be proud of yourself for making it this far. At this point, you hopefully feel comfortable with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. -Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. -Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are in the exact same order. For instance: +Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are in the exact same order. For instance: ```javascript [[3, 2, 1], [], []] From 3f983878f81386a04edf486108f88fe0a0ae354b Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:29:59 +0100 Subject: [PATCH 13/21] feat(hanoi): add line breaks Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index c6109271225..c0d532f5024 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -19,6 +19,7 @@ The rules are as follows: - **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the tower `[3, 4]` but `[4, 3]` is fine. Your task is to create a function, `hanoi(n)`, that when given the number of disks in the starting tower (`n`), will return an array. The first element of this array will be the towers' initial state. The last element will be the towers' final state. Every intermediary element will represent a step to get from the initial position to the final position. + The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the array returned. For example, lets say we had given this function `3`, it will then output the Tower of Hanoi solution as a series of steps: From 58a7f67450493c7a6c936fb1f085115913ff91bb Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 15:30:16 +0100 Subject: [PATCH 14/21] feat(hanoi): more concise representation of function in readme Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index c0d532f5024..3454349818e 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -22,7 +22,7 @@ Your task is to create a function, `hanoi(n)`, that when given the number of dis The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the array returned. -For example, lets say we had given this function `3`, it will then output the Tower of Hanoi solution as a series of steps: +For example, `hanoi(3)` will output the Tower of Hanoi solution as a series of steps: ``` [ From 12cd75c8699ca586f45074afd6ae8be25d0885ef Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 18 Aug 2024 16:34:32 +0100 Subject: [PATCH 15/21] feat(hanoi): change the way the function is tested to use strings instead of arrays --- 20_hanoi/solution/hanoi-solution.js | 29 ++++------ 20_hanoi/solution/hanoi-solution.spec.js | 74 ++++++++++-------------- 2 files changed, 44 insertions(+), 59 deletions(-) diff --git a/20_hanoi/solution/hanoi-solution.js b/20_hanoi/solution/hanoi-solution.js index 3f465abb0fb..7c65cdf9107 100644 --- a/20_hanoi/solution/hanoi-solution.js +++ b/20_hanoi/solution/hanoi-solution.js @@ -1,26 +1,21 @@ const hanoi = function ( n, - fromTowerIndex = 0, - storageTowerIndex = 1, - toTowerIndex = 2, - towers = [ - Array(n) - .fill() // Array function creates an array with "empty" slots which map does not iterate over - .map((_, i) => n - i), - [], - [], - ], - steps = [towers.map((tower) => [...tower])], + fromTower = 0, + storageTower = 1, + toTower = 2, + steps = [], ) { - if (n === 0) return steps; + if (n <= 0) { + return steps; + } - hanoi(n - 1, fromTowerIndex, toTowerIndex, storageTowerIndex, towers, steps); + hanoi(n - 1, fromTower, toTower, storageTower, steps); - towers[toTowerIndex].push(towers[fromTowerIndex].pop()); + steps.push( + `Move disc ${n} from tower ${fromTower + 1} to tower ${toTower + 1}`, + ); - steps.push(towers.map((tower) => [...tower])); - - hanoi(n - 1, storageTowerIndex, fromTowerIndex, toTowerIndex, towers, steps); + hanoi(n - 1, storageTower, fromTower, toTower, steps); return steps; }; diff --git a/20_hanoi/solution/hanoi-solution.spec.js b/20_hanoi/solution/hanoi-solution.spec.js index 79c8970f7b1..2c7501324e2 100644 --- a/20_hanoi/solution/hanoi-solution.spec.js +++ b/20_hanoi/solution/hanoi-solution.spec.js @@ -3,59 +3,49 @@ const hanoi = require("./hanoi-solution"); describe("hanoi", () => { test("hanoi(1) should solve the puzzle in 1 move", () => { const result = hanoi(1); - const expected = [ - [[1], [], []], - [[], [], [1]], - ]; - expect(result).toEqual(expected); + expect(result).toEqual(["Move disc 1 from tower 1 to tower 3"]); }); test("hanoi(2) should solve the puzzle in 3 moves", () => { const result = hanoi(2); - const expected = [ - [[2, 1], [], []], - [[2], [1], []], - [[], [1], [2]], - [[], [], [2, 1]], - ]; - expect(result).toEqual(expected); + expect(result).toEqual([ + "Move disc 1 from tower 1 to tower 2", + "Move disc 2 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + ]); }); test("hanoi(3) should solve the puzzle in 7 moves", () => { const result = hanoi(3); - const expected = [ - [[3, 2, 1], [], []], - [[3, 2], [], [1]], - [[3], [2], [1]], - [[3], [2, 1], []], - [[], [2, 1], [3]], - [[1], [2], [3]], - [[1], [], [3, 2]], - [[], [], [3, 2, 1]], - ]; - expect(result).toEqual(expected); + expect(result).toEqual([ + "Move disc 1 from tower 1 to tower 3", + "Move disc 2 from tower 1 to tower 2", + "Move disc 1 from tower 3 to tower 2", + "Move disc 3 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 1", + "Move disc 2 from tower 2 to tower 3", + "Move disc 1 from tower 1 to tower 3", + ]); }); test("hanoi(4) should solve the puzzle in 15 moves", () => { const result = hanoi(4); - const expected = [ - [[4, 3, 2, 1], [], []], - [[4, 3, 2], [1], []], - [[4, 3], [1], [2]], - [[4, 3], [], [2, 1]], - [[4], [3], [2, 1]], - [[4, 1], [3], [2]], - [[4, 1], [3, 2], []], - [[4], [3, 2, 1], []], - [[], [3, 2, 1], [4]], - [[], [3, 2], [4, 1]], - [[2], [3], [4, 1]], - [[2, 1], [3], [4]], - [[2, 1], [], [4, 3]], - [[2], [1], [4, 3]], - [[], [1], [4, 3, 2]], - [[], [], [4, 3, 2, 1]], - ]; - expect(result).toEqual(expected); + expect(result).toEqual([ + "Move disc 1 from tower 1 to tower 2", + "Move disc 2 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + "Move disc 3 from tower 1 to tower 2", + "Move disc 1 from tower 3 to tower 1", + "Move disc 2 from tower 3 to tower 2", + "Move disc 1 from tower 1 to tower 2", + "Move disc 4 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + "Move disc 2 from tower 2 to tower 1", + "Move disc 1 from tower 3 to tower 1", + "Move disc 3 from tower 2 to tower 3", + "Move disc 1 from tower 1 to tower 2", + "Move disc 2 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + ]); }); }); From 98242fb05b776bcc38a30603d874444dd2840878 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:41:23 +0100 Subject: [PATCH 16/21] feat(hanoi): copy over tests from solution --- 20_hanoi/hanoi.spec.js | 64 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/20_hanoi/hanoi.spec.js b/20_hanoi/hanoi.spec.js index f29dc5dcc57..2a905997b07 100644 --- a/20_hanoi/hanoi.spec.js +++ b/20_hanoi/hanoi.spec.js @@ -1,15 +1,65 @@ -const hanoi = require('./hanoi'); +const hanoi = require("./hanoi"); -describe('hanoi', () => { - test('First test description', () => { +describe("hanoi", () => { + test("hanoi(1) should solve the puzzle in 1 move", () => { + const result = hanoi(1); + expect(result).toEqual(["Move disc 1 from tower 1 to tower 3"]); + }); + + test.skip("hanoi(2) should solve the puzzle in 3 moves", () => { + const result = hanoi(2); + expect(result).toEqual([ + "Move disc 1 from tower 1 to tower 2", + "Move disc 2 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + ]); + }); + + test.skip("hanoi(3) should solve the puzzle in 7 moves", () => { + const result = hanoi(3); + expect(result).toEqual([ + "Move disc 1 from tower 1 to tower 3", + "Move disc 2 from tower 1 to tower 2", + "Move disc 1 from tower 3 to tower 2", + "Move disc 3 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 1", + "Move disc 2 from tower 2 to tower 3", + "Move disc 1 from tower 1 to tower 3", + ]); + }); + + test.skip("hanoi(4) should solve the puzzle in 15 moves", () => { + const result = hanoi(4); + expect(result).toEqual([ + "Move disc 1 from tower 1 to tower 2", + "Move disc 2 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + "Move disc 3 from tower 1 to tower 2", + "Move disc 1 from tower 3 to tower 1", + "Move disc 2 from tower 3 to tower 2", + "Move disc 1 from tower 1 to tower 2", + "Move disc 4 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + "Move disc 2 from tower 2 to tower 1", + "Move disc 1 from tower 3 to tower 1", + "Move disc 3 from tower 2 to tower 3", + "Move disc 1 from tower 1 to tower 2", + "Move disc 2 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 3", + ]); + }); +}); + +describe("hanoi", () => { + test("First test description", () => { // Replace this comment with any other necessary code, and update the expect line as necessary - expect(hanoi()).toBe(''); + expect(hanoi()).toBe(""); }); - - test.skip('Second test description', () => { + + test.skip("Second test description", () => { // Replace this comment with any other necessary code, and update the expect line as necessary - expect(hanoi()).toBe(''); + expect(hanoi()).toBe(""); }); }); From 7b343a1eec005efeb1a19175e08781c6cffcaaf2 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:56:26 +0100 Subject: [PATCH 17/21] feat: remove redundant test Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/hanoi.spec.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/20_hanoi/hanoi.spec.js b/20_hanoi/hanoi.spec.js index 2a905997b07..da85314d734 100644 --- a/20_hanoi/hanoi.spec.js +++ b/20_hanoi/hanoi.spec.js @@ -50,16 +50,3 @@ describe("hanoi", () => { }); }); -describe("hanoi", () => { - test("First test description", () => { - // Replace this comment with any other necessary code, and update the expect line as necessary - - expect(hanoi()).toBe(""); - }); - - test.skip("Second test description", () => { - // Replace this comment with any other necessary code, and update the expect line as necessary - - expect(hanoi()).toBe(""); - }); -}); From dbd8ee149e59757a75816c65e972c22827479f62 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:06:02 +0100 Subject: [PATCH 18/21] doc(hanoi): update instructions to use the new expected method --- 20_hanoi/README.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 3454349818e..305ffea6785 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -18,21 +18,20 @@ The rules are as follows: - The towers are modelled as stacks. We can move disks from the top of one stack to the top of another stack with the `Array.prototype.pop` and `Array.prototype.push` methods. - **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the tower `[3, 4]` but `[4, 3]` is fine. -Your task is to create a function, `hanoi(n)`, that when given the number of disks in the starting tower (`n`), will return an array. The first element of this array will be the towers' initial state. The last element will be the towers' final state. Every intermediary element will represent a step to get from the initial position to the final position. +Your task is to create a function, `hanoi(n)`, that when given the number of disks in the starting tower (`n`), will return an array containing the steps that have to be taken in order to get from the initial state to the final state. -The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the array returned. +The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the solution array returned. -For example, `hanoi(3)` will output the Tower of Hanoi solution as a series of steps: +For example, here is tho expected output of `hanoi(3)`: -``` +```javascript [ -[[3, 2, 1], [], []], -[[3, 2], [], [1]], -[[3], [2], [1]], -[[3], [2, 1], []], -[[], [2, 1], [3]], -[[1], [2], [3]], -[[1], [], [3, 2]], -[[], [], [3, 2, 1]], + "Move disc 1 from tower 1 to tower 3", + "Move disc 2 from tower 1 to tower 2", + "Move disc 1 from tower 3 to tower 2", + "Move disc 3 from tower 1 to tower 3", + "Move disc 1 from tower 2 to tower 1", + "Move disc 2 from tower 2 to tower 3", + "Move disc 1 from tower 1 to tower 3", ] ``` From 86a7cfae5eb936a4f0a1cae43540338ada188d7a Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:07:09 +0100 Subject: [PATCH 19/21] fix(hanoi): spelling error --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 305ffea6785..01948265aa9 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -22,7 +22,7 @@ Your task is to create a function, `hanoi(n)`, that when given the number of dis The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the solution array returned. -For example, here is tho expected output of `hanoi(3)`: +For example, here is the expected output of `hanoi(3)`: ```javascript [ From e6d50347899a46aa43626da54a3b692ca74e4fac Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:07:51 +0100 Subject: [PATCH 20/21] feat: use exclamation mark instead of period --- 20_hanoi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index 01948265aa9..f88cedb31e9 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -1,6 +1,6 @@ # Exercise 20 - hanoi -Good job, you have come a very long way. You should be proud of yourself for making it this far. At this point, you hopefully feel comfortable with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. +Good job, you have come a very long way. You should be proud of yourself for making it this far! At this point, you hopefully feel comfortable with recursion, and so, this **final recursive exercise** should give you a proper challenge and take your abilities to the *next* level. Tower of Hanoi is a classic challenge in which we have 3 towers. Tower 2 and tower 3 are empty. Tower 1 has `n` disks. The goal is to move all disks from tower 1 to tower 3 so that they are in the exact same order. For instance: From 70e61a45714d41ff87e722b62878fd35600535e2 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+nikitarevenco@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:22:01 +0100 Subject: [PATCH 21/21] feat: provide a more explicit example of what form the string should be in Co-authored-by: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> --- 20_hanoi/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/20_hanoi/README.md b/20_hanoi/README.md index f88cedb31e9..4892fb40106 100644 --- a/20_hanoi/README.md +++ b/20_hanoi/README.md @@ -18,7 +18,11 @@ The rules are as follows: - The towers are modelled as stacks. We can move disks from the top of one stack to the top of another stack with the `Array.prototype.pop` and `Array.prototype.push` methods. - **Disks can only be placed on top of disks that are smaller**. For instance, we cannot have the tower `[3, 4]` but `[4, 3]` is fine. -Your task is to create a function, `hanoi(n)`, that when given the number of disks in the starting tower (`n`), will return an array containing the steps that have to be taken in order to get from the initial state to the final state. +Your task is to create a function, `hanoi(n)`, that when given the number of disks in the starting tower (`n`), will return an array containing the steps that have to be taken in order to get from the initial state to the final state. Each step will be a string in the form: + +```javascript +`Move disc ${discNumber} from tower ${fromTower} to tower ${toTower}` +``` The function **must** return a solution in the minimum number of moves. i.e. there will be no duplicates in the solution array returned.