マージャンのやつ JavaScript
あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002_2.html
※トータルで1週間以上かかっているorz
var assert = require('assert'); var test = function(results, answers) { if (results == null && answers == null) return; assert.equal(results.length, answers.length); answers.forEach(function(answer) { assert(~results.indexOf(answer)); }); }; var machi = (function() { var format = function(answer) { var s = ''; answer.grouped.sort().forEach(function(g) { s += '(' + g + ')'; }); return s + (answer.rest ? '[' + answer.rest + ']' : ''); }; var collectFlattens = function(input, enough) { var regexp = new RegExp('(.)\\1{' + (enough - 1) +'}', 'g'); return input.match(regexp); }; test(collectFlattens('112224588899', 2), ['11', '22', '88', '99']); test(collectFlattens('12345', 2), null); test(collectFlattens('1112224588899', 3), ['111', '222', '888']); test(collectFlattens('124589', 3), null); var collectAscendings = function(input, enough) { var results = []; var collected; var curr; var foundIndex; var isEnough = function() { return collected && collected.length >= enough; }; while (input.length >= 2) { collected = ''; curr = 0; foundIndex = -1; while (~(foundIndex = input.indexOf(+input[curr] + 1, curr + 1))) { if (!collected) collected = input[curr]; collected += input[foundIndex]; if (isEnough()) break; curr = foundIndex; } if (isEnough()) results.push(collected); input = input.slice(1); } return results.length >= 1 ? results : null; }; test(collectAscendings('1122335556799', 3), ['123', '123', '567', '567', '567']); test(collectAscendings('112255578', 3), null); var getRest = function(collected, original) { collected.split('').forEach(function(letter) { original = original.replace(letter, ''); }); return original; }; assert.equal(getRest('123', '1122335556799'), '1235556799'); assert.equal(getRest('567', '11225556799'), '11225599'); assert.equal(getRest('789', '1122555789'), '1122555'); var hasHead = function(grouped) { return grouped.some(function(group) { return group.length == 2; }); }; assert.equal(hasHead(['234', '555', '888']), false); assert.equal(hasHead(['234', '555', '88']), true); return function(original) { var answers = []; (function collect(grouped, input) { var finalizer = function(candidates) { if (!candidates) return; candidates.forEach(function(newGroup) { var newGrouped = grouped.slice(0); newGrouped.push(newGroup); var rest = getRest(newGroup, input); if (rest && ( collectFlattens(rest, 3) || collectAscendings(rest, 3))) { collect(newGrouped.slice(0), rest); } else if (rest.length <= 3) { var heads = collectFlattens(rest, 2); if (rest.length == 1 || (heads && heads.length >= 1) || collectAscendings(rest, 2)) { var a = format({ grouped: newGrouped, rest: rest }); if (!~answers.indexOf(a)) answers.push(a); } } }); }; if (!hasHead(grouped)) { finalizer(collectFlattens(input, 2)); } finalizer(collectFlattens(input, 3)); finalizer(collectAscendings(input, 3)); })([], original); return answers; }; })(); test(machi('1112224588899'), [ '(111)(222)(888)(99)[45]' ]); test(machi('1122335556799'), [ '(123)(123)(55)(567)[99]', '(123)(123)(555)(99)[67]', '(123)(123)(567)(99)[55]' ]); test(machi('1112223335559'), [ '(123)(123)(123)(555)[9]', '(111)(222)(333)(555)[9]' ]); test(machi('1223344888999'), [ '(123)(44)(888)(999)[23]', '(123)(234)(888)(999)[4]', '(234)(234)(888)(999)[1]' ]); test(machi('1112345678999'), [ '(11)(123)(456)(999)[78]', '(11)(123)(678)(999)[45]', '(11)(345)(678)(999)[12]', '(11)(123)(456)(789)[99]', '(111)(234)(567)(99)[89]', '(111)(234)(789)(99)[56]', '(111)(456)(789)(99)[23]', '(123)(456)(789)(99)[11]', '(111)(234)(567)(999)[8]', '(111)(234)(678)(999)[5]', '(111)(345)(678)(999)[2]' ]);