Gena Playing Hanoi

  • + 0 comments

    JavaScript based on solution from @chuntao_liu_0118

    function hanoi(posts) {
        // Write your code here
        const n = posts.length;
        const rods = [0, 0, 0, 0];
        for (let i = 0; i < n; i++) {
            rods[posts[i] - 1] += 2 ** i;
        }
        const base = 2 ** n;
        const win_state = (base - 1) * (base ** 3);
        const start_state =
            rods[0] * (base ** 3) + rods[1] * (base ** 2) + rods[2] * base + rods[3];
        const visited = new Set();
        let current = [start_state];
        let moves = 0;
    
        while (current.length > 0) {
            const next = [];
    
            for (const state of current) {
                if (state === win_state) {
                    return moves;
                }
                if (visited.has(state)) {
                    continue;
                }
                visited.add(state);
                const rods = [
                    Math.floor((state / (base ** 3)) % base),
                    Math.floor((state / (base ** 2)) % base),
                    Math.floor((state / base) % base),
                    state % base
                ];
                const top_discs = rods.map(n =>
                    n === 0 ? Infinity : n ^ (n & (n - 1))
                );
    
                for (let i = 0; i < 4; i++) {
                    for (let j = i + 1; j < 4; j++) {
                        if (top_discs[i] === Infinity && top_discs[j] === Infinity) {
                            continue;
                        }
                        let new_state;
                        if (top_discs[i] < top_discs[j]) {
                            new_state =
                                state -
                                top_discs[i] * (base ** (3 - i)) +
                                top_discs[i] * (base ** (3 - j));
                        } else {
                            new_state =
                                state +
                                top_discs[j] * (base ** (3 - i)) -
                                top_discs[j] * (base ** (3 - j));
                        }
                        if (!visited.has(new_state)) {
                            next.push(new_state);
                        }
                    }
                }
            }
            moves += 1;
            current = next;
        }
    }