4
3

paiza×Qiita記事投稿キャンペーン「プログラミング問題をやってみて書いたコードを投稿しよう!」に参加してみた。

問題はハノイの塔

残念ながら、問題通りのアウトプットが作れませんでした。配列の状態を書き換えるのができないので、書き換えずに常に3本の杭の状態を返す関数を作ればよいのだと思うのですが、難しい。。。
=>何とか解くことができましたので、完成版はこちら。

使い方はこんな感じ。
円盤3枚を初期値として、4回まで動かすとしたら、=HANOI(3,4)とするイメージ。

image.png

Excel LAMBDA関数版「ハノイの塔」のコード

コード
HANOI = LAMBDA(_n, _t,
    LET(
        // Zコンビネータ。無名関数で再帰を実現するヘルパー関数
        Z, LAMBDA(_functionTemplate,
            LET(
                _applyFunction, LAMBDA(_recursiveFunction,
                    _functionTemplate(LAMBDA(_a1,_a2,_a3,_a4,_a5, _recursiveFunction(_recursiveFunction)(_a1,_a2,_a3,_a4,_a5)))
                ),
                _applyFunction(_applyFunction)
            )
        ),
        // ハノイの塔を解く関数。再帰呼び出しで実現
        _fncHanoi,Z(LAMBDA(_fnc, LAMBDA(_moves, _n, _from, _to, _work,
            IF(_n = 0,
                // voidをreturnできないので、空を表すレコードをスタックに積む
                VSTACK(_moves, HSTACK(_n, 0, 0)),
                LET(
                    _moveFromToOther, _fnc(_moves, _n-1,_from, _work, _to),
                    _pusedhMoveLog, VSTACK(_moveFromToOther, HSTACK("円盤:"&_n&"", _from & "から", _to & "へ。")),
                    _return, _fnc(_pusedhMoveLog, _n-1, _work, _to, _from),
                    _return
                )
            )))),
        // ハノイの塔を解く
        _solvedHanoi, _fncHanoi(VSTACK(0),_n,"杭A","杭C","杭B"),
        // 空のレコードを取り除く
        _removedEmptyDisc, LAMBDA(_table, FILTER(_table, INDEX(_table, 0, 1) <> 0))(_solvedHanoi),
        _toSeq, IF(ROWS(_removedEmptyDisc)<_t, SEQUENCE(ROWS(_removedEmptyDisc)), SEQUENCE(_t)),
        _return, MAP(_toSeq, LAMBDA(_i, TEXTJOIN("",TRUE, INDEX(_removedEmptyDisc,_i)))),
        _return
    )
);

JavaScript版「ハノイの塔」のコード

こんな感じ。

image.png

コード
const  hanoi=(n, t)=>{
    // 初期状態の杭
    let pegs = [
        Array.from({ length: n }, (_, i) => n - i),
        [],
        []
    ];

    // 移動の記録
    let moves = [];

    // ハノイの塔の再帰関数
    const _hanoi=(n, from, to, work)=>{
        if (n === 0) return;
        _hanoi(n - 1, from, work, to);
        moves.push([from, to]);
        _hanoi(n - 1, work, to, from);
    };

    // ハノイの塔を解く
    _hanoi(n, 0, 2, 1);

    // 指定された回数 t まで移動を実行
    for (let i = 0; i < t; i++) {
        let [from, to] = moves[i];
        pegs[to].push(pegs[from].pop());
    }

    // 各杭の状態を出力
    pegs.forEach(peg => {
        if (peg.length === 0) {
            console.log("-");
        } else {
            console.log(peg.join(" "));
        }
    });
};

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3