質問するログイン新規登録
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1780閲覧

javascriptでハノイの塔を出力する。

str753

総合スコア1

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2023/02/11 09:51

0

1

実現したいこと

  • javascriptでハノイの塔を途中経過(どの円盤がどこからどこまで移動したか、移動した後の各棒に重なっている円盤の状態)をコンソール上に出力したい。

前提

初学者です。
javascriptでハノイの塔を動作させ、詳細をconsole.logで出力させています。
円盤が移動した際に、各棒に重なっている円盤の状態を出力させたいのですが、
方法がわからず、行き詰ってしまいました。
どのようなコードを追加すれば出力できるのか教えていただきたいです。

発生している問題・エラーメッセージ

該当のソースコード

javascript

1function hanoi(n, a, b, c) { 2 if (n>1) { 3 hanoi(n-1,a,c,b); 4 tower('1本目','2本目','3本目'); 5 console.log(`${n}番目の円盤: ${a} -> ${c}`); 6 tower('1本目','2本目','3本目'); 7 hanoi(n-1,b,a,c); 8 } else { 9 console.log(`${n}番目の円盤: ${a} -> ${c}`); 10 } 11 12 function tower(x,y,z) { 13 console.log(`${x}: `); 14 console.log(`${y}: `); 15 console.log(`${z}: `); 16 } 17} 18 19hanoi(3,'1本目','2本目','3本目');

試したこと

for文を使うなど、さまざまな方法を考えましたが知識が足りず実装できておりません。

補足情報(FW/ツールのバージョンなど)

AWSのcloud9で開発しております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

汎用的ではないですし冗長な部分も多いですが、質問者さんのコードになるべく沿う形で実装すると
下記のようになります。
(あくまで一例にすぎず、もっとシンプルで美しい方法もあると思います)

js

1 let tower = {}; 2 tower['1本目'] = [3,2,1]; 3 tower['2本目'] = []; 4 tower['3本目'] = []; 5 6 function hanoi(n, a, b, c) { 7 if (n > 1) { 8 hanoi(n - 1, a, c, b); 9 console.log(`${n}番目の円盤: ${a} -> ${c}`); 10 tower[c].push(tower[a].pop()) 11 printStatus('1本目', '2本目', '3本目'); 12 hanoi(n - 1, b, a, c); 13 } else { 14 console.log(`${n}番目の円盤: ${a} -> ${c}`); 15 tower[c].push(tower[a].pop()); 16 printStatus('1本目', '2本目', '3本目'); 17 } 18 19 function printStatus(x, y, z) { 20 console.log(`${x}: ${tower[x]}`); 21 console.log(`${y}: ${tower[y]}`); 22 console.log(`${z}: ${tower[z]}`); 23 } 24 } 25 26 hanoi(3, '1本目', '2本目', '3本目');

考え方

各塔を tower で表し、円盤の保持状態を配列で表します。
初期状態は、1本目に、下から大きい順(上から小さい順)に3つの円盤が入っており、
2本目、3本目は何も入っていないので、下記のようになります。

js

1 let tower = {}; 2 tower['1本目'] = [3,2,1]; // 数字が小さいほど、小さい円盤(常に大=>小の順番) 3 tower['2本目'] = []; // 空っぽ 4 tower['3本目'] = []; // 空っぽ

この状態で、たとえば 1本目の塔 から 3本目の塔に円盤を移すときは、
tower['1本目'] の配列の、最後尾にある「円盤1」を取り出して、
tower['3本目'] の配列の、最後尾に加える、
という考え方になります。
これをプログラムにすると下記になります。

js

1 // 1本目の塔の一番上にある円盤を取り出す(=配列の一番最後尾の要素を取り出す) 2const takenDisk = tower['1本目'].pop(); 3 4 // 取り出した円盤を、3本目の塔の一番上に重ねる。(=配列の最後尾にpush) 5tower['3本目'].push(takenDisk);

これをまとめると

js

1tower['3本目'].push(tower['1本目'].pop());

となり、この1回目の操作が終わった後の状態は

js

1 tower['1本目'] = [3,2]; 2 tower['2本目'] = []; // 空っぽ 3 tower['3本目'] = [1];

となります。

投稿2023/02/11 12:04

編集2023/02/11 12:18
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

str753

2023/02/11 14:14

コードのみならず解説までしていただきありがとうございます。 このコードでは2行目の tower['1本目'] = [円盤の数]; と26行目の hanoi(円盤の数,'1本目', '2本目', '3本目'); に円盤の数を逐一入力しなければいけない手間があるので、 自分自身でそちらを解決しようと思います。 本当にありがとうございました。
guest

0

この回答のソースコードは、ChatGPT が出力したものを一部修正したものとなっています。
※ "A","B","C" → "1本目","2本目","3本目" と表示するよう修正しました。

javascriptでハノイの塔を途中経過(どの円盤がどこからどこまで移動したか、
移動した後の各棒に重なっている円盤の状態)をコンソール上に出力したい

コンソールは基本文字しか扱えないのでグラフィカルな表現には向いていません。
テキスト表現でよければ以下のような出力は可能です。絵文字を使用しています。
※ このコードは円盤3枚までしか対応していません。あしからず。。

javascript

1function hanoi(n, from, to, using, result) { 2 if (n === 0) { 3 return; 4 } 5 hanoi(n - 1, from, using, to, result); 6 result[to].push(result[from].pop()); 7 console.log(`円盤 ${n}${towers[from]} から ${towers[to]} に移動`); 8 showTower(result); 9 hanoi(n - 1, using, to, from, result); 10} 11 12function showTower(result) { 13 console.log(`1本目: ${makeTower(result.A)}`); 14 console.log(`2本目: ${makeTower(result.B)}`); 15 console.log(`3本目: ${makeTower(result.C)}`); 16 console.log(""); 17} 18 19function makeTower(diskArray) { 20 let towerString = ""; 21 for (let i = 0; i < 3; i++) { 22 if (i < diskArray.length) { 23 towerString += disks[diskArray[i]]; 24 } else { 25 towerString += "━━"; 26 } 27 } 28 return towerString; 29} 30 31let towers = { A: "1本目", B: "2本目", C: "3本目" }; 32let disks = { 1: "▪", 2: "◾", 3: "⬛" }; 33let result = { A: [3, 2, 1], B: [], C: [] }; 34showTower(result); 35hanoi(3, "A", "C", "B", result);
1本目: ⬛◾▪ 2本目: ━━━━━━ 3本目: ━━━━━━ 円盤 1 を 1本目 から 3本目 に移動 1本目: ⬛◾━━ 2本目: ━━━━━━ 3本目: ▪━━━━ 円盤 2 を 1本目 から 2本目 に移動 1本目: ⬛━━━━ 2本目: ◾━━━━ 3本目: ▪━━━━ 円盤 1 を 3本目 から 2本目 に移動 1本目: ⬛━━━━ 2本目: ◾▪━━ 3本目: ━━━━━━ 円盤 3 を 1本目 から 3本目 に移動 1本目: ━━━━━━ 2本目: ◾▪━━ 3本目: ⬛━━━━ 円盤 1 を 2本目 から 1本目 に移動 1本目: ▪━━━━ 2本目: ◾━━━━ 3本目: ⬛━━━━ 円盤 2 を 2本目 から 3本目 に移動 1本目: ▪━━━━ 2本目: ━━━━━━ 3本目: ⬛◾━━ 円盤 1 を 1本目 から 3本目 に移動 1本目: ━━━━━━ 2本目: ━━━━━━ 3本目: ⬛◾▪

投稿2023/02/11 11:56

編集2023/02/11 12:11
cx20

総合スコア4700

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

str753

2023/02/11 14:21

回答ありがとうございます! ChatGPTでのコード出力は私には考えつかなかったのでとても助かります。 私も最初参考にした別言語のコードではグラフィカルな出力が多く、コンソール上にうまく表示できなかったので、文字だけの出力を目標にすれば円盤の数を増やして実行できる余地が生まれると考えています。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問