双方向探索でビットパターンを使っていますが、重いですね。
window.onload = function() { /* * Fly Me to the Moon * */ var K = 1, R = 2, B = 4, W = 8, M = 16, F = 32; var mem = [ K, R, B, W ], pil = [ M, F ]; var spd = [ 1, 2, 4, 8 ]; /* 全員 */ var all = K|R|B|W|M|F; /* 最初と最後の状態 */ var start = { bank:all, roc:0, prev:null, back:false }; var end = { bank:all<<6, roc:0, prev:null, back:true }; /* ロケットの飛行パターン */ var pt = [ K|M, R|M, B|M, W|M, K|F, R|F, B|F, W|F, K|M|F, R|M|F, B|M|F, W|M|F, K|M|R|F, K|M|B|F, K|M|W|F, R|M|B|F, R|M|W|F, B|M|W|F, 0 ]; /* 値の取得と設定 */ var getv = function(p, n) { return (p.bank>>6*n)&0x3f; }; var putv = function(p, n, val) { p.bank &= ~(0x3f<<6*n); p.bank |= val<<6*n; }; var getroc = function(p, n) { return (p.roc>>4*n)&0xf; }; var putroc = function(p, n, val) { p.roc &= ~(0xf<<4*n); p.roc |= val<<4*n; }; /* 結果の表示 */ var output = function(n) { var s = ''; if (n&K) s += '黒'; if (n&R) s += '赤'; if (n&B) s += '青'; if (n&W) s += '白'; if (n&M) s += '<span>飛</span>'; if (n&F) s += '<span>飛</span>'; return s; }; var printroc = function(p) { var r = []; for (var i in mem) { r.push(getroc(p, i)); } return r.toString(); }; var print = function(a, b) { var r = [], p = a; while (p) { r.unshift(p); p = p.prev; } p = b.prev; while (p) { r.push(p); p = p.prev; } if (r.length > 15) return false; s += '<div>'; for (var i in r) { s += '(' + i + ') '; s += output(getv(r[i], 0)); s += '[' + output(getv(r[i], 2)) + '→]'; s += '[←' + output(getv(r[i], 3)) + ']'; s += output(getv(r[i], 1)); s += ' [' + printroc(r[i]) + ']'; s += '<br />'; } s += '</div>'; return true; }; /* 履歴のパターンと照合 */ var regist = function() { for (var i = 0; i < arguments.length; i++) { var t = arguments[i]; hash[t.bank+','+t.roc] = t; } }; var search = function(t) { return !!hash[t.bank+','+t.roc]; }; var goal = function(t) { var p = hash[t.bank+','+t.roc]; if (p && p.back != t.back) return p; return null; }; /* ロケットの操作関数 */ var count = function(n) { var c = [ 0, 0 ]; for (var i in mem) { if (n&mem[i]) c[0]++; } for (var i in pil) { if (n&pil[i]) c[1]++; } return c; }; var indexOf = function(arr, val) { for (var i in arr) { if (arr[i] == val) return i; } return -1; }; var _step = function(t, n) { var id = indexOf(mem, n); for (var i = 2; i <= 3; i++) { var v1 = getv(t, i); var v2 = getv(t, t.back ? i-2 : 3-i); if (!(v1&n^n)) { var d = t.back ? getroc(t, id)+1 : getroc(t, id)-1; putroc(t, id, d); if (getroc(t, id) != (t.back ? spd[id] : 0)) continue; putroc(t, id, 0); var c = count(v1); if (c[0] == 1 && c[1] == 2) { putv(t, i, v1^(n|M|F)); putv(t, t.back ? i-2 : 3-i, v2|n|M|F); } else if (v1&M) { putv(t, i, v1^(n|M)); putv(t, t.back ? i-2 : 3-i, v2|n|M); } else { putv(t, i, v1^(n|F)); putv(t, t.back ? i-2 : 3-i, v2|n|F); } } } }; var step = function(t) { for (var i in mem) { _step(t, mem[i]); } }; var select = function(no, now, next, pt) { var v1 = getv(now, no); var v2 = getv(now, next.back ? 3-no : no+2); if (!(v1&pt^pt)) { putv(next, no, v1^pt); putv(next, next.back ? 3-no : no+2, v2|pt); for (var i in mem) { if (pt&mem[i]) { var d = next.back ? 0 : spd[i]; putroc(next, i, d); } } return true; } return false; }; /* キューとハッシュ表を用意 */ var queue = [ start, end ], hash = {}; /* ロケット発射(双方向探索) */ var trip = function() { var found, res; regist(start, end); while (queue.length > 0) { var now = queue.shift(); for (var i in pt) { for (var j in pt) { var next = {}; next.bank = now.bank; next.roc = now.roc; next.prev = now; next.back = now.back; if (select(0, now, next, pt[i]) && select(1, now, next, pt[j])) { step(next); if (found = goal(next)) { res = found.back ? print(next, found) : print(found, next); if (res) return; } else if (!search(next)) { regist(next); queue.push(next); } } } } } }; /* 実行と解答表示 */ var s = ''; trip(); document.getElementById('answer').innerHTML = s; /* ソース表示用 */ var jsparser_obj = new JSParser(); var ro = document.getElementById('ro_script'); var src = ro.text || ro.innerHTML; document.getElementById('viewsrc').innerHTML = jsparser_obj.parse(src); };