0
0

【JavaScript】マリオRPGのトライアスロン問題を解くプログラム

Last updated at Posted at 2023-12-30

問題

A,B,C,Dがトライアスロン(※)をしました。
それぞれの証言から順位を推理し、1位から順にA,B,C,Dを並べ替えてください。

※:水泳→自転車→マラソンの順で争う競技。マラソンの順位が最終的な順位

【証言】
A「水泳も自転車も順位は同じだったけど、マラソンで二人に抜かれちゃった。」
B「自転車でDを抜いて、そのあとはゴールまで Dには抜かれてないよ。」
C「水泳で3位だったけど、ゴールするまで3位より上になったことはなかったよ。ちぇ。」
D「自転車で調子が悪くて 4位に落ちちゃったけど、結局水泳と同じ順位でゴールできた。」

プログラム

const 順位 = {
    A: { 水泳: 0, 自転車: 0, マラソン: 0 },
    B: { 水泳: 0, 自転車: 0, マラソン: 0 },
    C: { 水泳: 0, 自転車: 0, マラソン: 0 },
    D: { 水泳: 0, 自転車: 0, マラソン: 0 },
};

const 満たすべき条件たち = [
    // A「水泳も自転車も順位は同じだったけど、マラソンで二人に抜かれちゃった。」
    () => 順位.A.水泳 === 順位.A.自転車,
    () => 順位.A.マラソン === 順位.A.自転車 + 2,
    // B「自転車でDを抜いて、そのあとはゴールまで Dには抜かれてないよ。」
    () => 順位.B.自転車 < 順位.D.自転車,
    () => 順位.B.マラソン < 順位.D.マラソン,
    // C「水泳で3位だったけど、ゴールするまで3位より上になったことはなかったよ。ちぇ。」
    () => 順位.C.水泳 === 3,
    () => 順位.C.自転車 >= 3 && 順位.C.マラソン >= 3,
    // D「自転車で調子が悪くて 4位に落ちちゃったけど、結局水泳と同じ順位でゴールできた。」
    () => 順位.D.自転車 === 4,
    () => 順位.D.水泳 === 順位.D.マラソン,
];

function permute(nums) {
    const result = [];
    function backtrack(current, remaining) {
        if (remaining.length === 0) {
            result.push(current);
            return;
        }
        for (let i = 0; i < remaining.length; i++) {
            const newCurrent = current.concat([remaining[i]]);
            const newRemaining = remaining.slice(0, i).concat(remaining.slice(i + 1));
            backtrack(newCurrent, newRemaining);
        }
    }
    backtrack([], nums);
    return result;
}

const 順位組み合わせ一覧 = permute([1, 2, 3, 4]);

loop:
for (const 水泳順位 of 順位組み合わせ一覧) {
    順位.A.水泳 = 水泳順位[0];
    順位.B.水泳 = 水泳順位[1];
    順位.C.水泳 = 水泳順位[2];
    順位.D.水泳 = 水泳順位[3];
    for (const 自転車順位 of 順位組み合わせ一覧) {
        順位.A.自転車 = 自転車順位[0];
        順位.B.自転車 = 自転車順位[1];
        順位.C.自転車 = 自転車順位[2];
        順位.D.自転車 = 自転車順位[3];
        for (const マラソン順位 of 順位組み合わせ一覧) {
            順位.A.マラソン = マラソン順位[0];
            順位.B.マラソン = マラソン順位[1];
            順位.C.マラソン = マラソン順位[2];
            順位.D.マラソン = マラソン順位[3];
            let 条件が満たされているか = true;
            for (const 満たすべき条件 of 満たすべき条件たち) {
                if (!満たすべき条件()) {
                    条件が満たされているか = false;
                    break;
                }
            }
            if (条件が満たされているか) {
                break loop;
            }
        }
    }
}

console.log(
    [
        { 名前: "A", 順位: 順位.A.マラソン },
        { 名前: "B", 順位: 順位.B.マラソン },
        { 名前: "C", 順位: 順位.C.マラソン },
        { 名前: "D", 順位: 順位.D.マラソン },
    ]
    .sort((a, b) => a.順位 - b.順位)
    .map(e => e.名前)
    .join("")
);

結果

BDAC

その他

論理的な解き方が知りたい方は以下のサイトを見てください。

Prolog版

0
0
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
0
0