Created
January 24, 2014 11:23
-
-
Save Kuniwak/8595658 to your computer and use it in GitHub Desktop.
CodeIQ「数列の四則演算」問題の回答。 https://codeiq.jp/magazine/2014/01/4799/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var StopIteration = Error('STOP_ITERATION'); | |
| var util = { | |
| array: { | |
| clone: function(arr) { | |
| var clone = []; | |
| Array.prototype.push.apply(clone, arr); | |
| return clone; | |
| } | |
| }, | |
| object: { | |
| getValues: function(obj) { | |
| var values = []; | |
| var idx = 0; | |
| for (var key in obj) { | |
| values[idx++] = obj[key]; | |
| } | |
| return values; | |
| }, | |
| getCount: function(obj) { | |
| var count = 0; | |
| for (var key in obj) { | |
| ++count; | |
| } | |
| return count; | |
| } | |
| }, | |
| math: { | |
| randomInt: function(a) { | |
| return Math.floor(Math.random() * a); | |
| } | |
| } | |
| }; | |
| /** | |
| * @constructor | |
| */ | |
| var IncrementalNumSeq = function(opt_len) { | |
| this.assertLength_(opt_len); | |
| var len = opt_len || 0; | |
| this.nums_ = new Array(len); | |
| }; | |
| IncrementalNumSeq.MAX_LENGTH = 1023; | |
| /** | |
| * @enum {string} | |
| */ | |
| IncrementalNumSeq.Operator = { | |
| ADDITION: '+', | |
| SUBTRACTION: '-', | |
| MULTIPLICATION: '*', | |
| DEVISION: '/', | |
| JOIN: '' | |
| }; | |
| IncrementalNumSeq.getOperatorByIndex = (function() { | |
| var operators = util.object.getValues(IncrementalNumSeq.Operator); | |
| return function(idx) { | |
| return operators[idx]; | |
| }; | |
| })(); | |
| IncrementalNumSeq.prototype.assertLength_ = function(len) { | |
| if (!isFinite(len) && len !== undefined && len !== null) { | |
| throw Error('Sequence length must be finite but come: ' + len); | |
| } | |
| else if (len < 0) { | |
| throw Error('Sequence length must be positive or zero but come: ' + len); | |
| } | |
| }; | |
| IncrementalNumSeq.prototype.equals = function(incNumSeq) { | |
| var aLen = this.nums_.length; | |
| var bLen = incNumSeqGen_.nums_.length; | |
| if (aLen !== bLen) { | |
| return false; | |
| } | |
| for (var idx = 0; idx < aLen; idx++) { | |
| if (this.nums_[idx] !== incNumSeq.nums_[idx]) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }; | |
| IncrementalNumSeq.prototype.fill = function(val) { | |
| this.set(function() { | |
| return val; | |
| }); | |
| return this; | |
| }; | |
| IncrementalNumSeq.prototype.set = function(func, opt_this) { | |
| for (var idx = 0, len = this.nums_.length; idx < len; idx++) { | |
| this.nums_[idx] = func.call(opt_this, this.nums_[idx], idx); | |
| } | |
| return this; | |
| }; | |
| IncrementalNumSeq.prototype.reverse = function() { | |
| this.nums_.reverse(); | |
| return this; | |
| }; | |
| IncrementalNumSeq.prototype.reduce = function(func, start, opt_this) { | |
| return this.nums_.reduce(func, start, opt_this); | |
| }; | |
| IncrementalNumSeq.prototype.map = function(func, opt_this) { | |
| return this.nums_.map(func, opt_this); | |
| }; | |
| IncrementalNumSeq.prototype.evaluate = function(opSeq) { | |
| var expr = this.toExprString(opSeq); | |
| return eval(expr); | |
| }; | |
| IncrementalNumSeq.prototype.clone = function() { | |
| var clone = new this.constructor(); | |
| clone.nums_ = util.array.clone(this.nums_); | |
| return clone; | |
| }; | |
| IncrementalNumSeq.prototype.toExprString = function(opSeq) { | |
| return this.reduce(function(prev, curr, idx) { | |
| return (opSeq[idx] || '') + curr + prev; | |
| }, ''); | |
| }; | |
| IncrementalNumSeq.prototype.toString = function() { | |
| return '<' + this.nums_.join(', ') + '>'; | |
| }; | |
| /** | |
| * @constructor | |
| */ | |
| var IncrementalNumSeqGenerator = function(len, opt_lower, opt_upper) { | |
| this.len = len; | |
| this.lower = opt_lower || 0; | |
| this.upper = opt_upper || IncrementalNumSeqGenerator.MAX_LENGTH; | |
| }; | |
| IncrementalNumSeqGenerator.MAX_LENGTH = 1023; | |
| IncrementalNumSeqGenerator.prototype.next = function() { | |
| var finish = false; | |
| var finisher = Error(); | |
| if (!this.numSeq_) { | |
| this.numSeq_ = new IncrementalNumSeq(this.len); | |
| this.numSeq_.fill(this.lower); | |
| return this.numSeq_; | |
| } | |
| try { | |
| this.numSeq_ = this.numSeq_.clone(); | |
| this.numSeq_.set(function(num) { | |
| if (finish) { | |
| throw finisher; | |
| } | |
| if (num < this.upper) { | |
| finish = true; | |
| return num + 1; | |
| } | |
| else { | |
| return this.lower; | |
| } | |
| }, this); | |
| } | |
| catch (e) { | |
| if (e !== finisher) { | |
| throw e; | |
| } | |
| } | |
| if (finish) { | |
| return this.numSeq_; | |
| } | |
| else { | |
| throw StopIteration; | |
| } | |
| }; | |
| /** | |
| * @constructor | |
| */ | |
| var OperatorSeqGenerator = function(len) { | |
| var maxOperatorsIdx = util.object.getCount(IncrementalNumSeq.Operator) - 1; | |
| this.incNumSeqGen_ = new IncrementalNumSeqGenerator(len, 0, maxOperatorsIdx); | |
| }; | |
| OperatorSeqGenerator.prototype.next = function() { | |
| return this.incNumSeqGen_.next().map(function(opIdx) { | |
| return IncrementalNumSeq.getOperatorByIndex(opIdx); | |
| }); | |
| }; | |
| var SEQ_LEN = 4; | |
| var incNumSeqGen = new IncrementalNumSeqGenerator(SEQ_LEN, 0, 9); | |
| var opGen = new OperatorSeqGenerator(SEQ_LEN - 1); | |
| var incrementalNumSeqToNumberString = function(incNumSeq) { | |
| return incNumSeq.reduce(function(prev, curr) { | |
| return curr + prev; | |
| }, ''); | |
| }; | |
| for (var start = 1000; start >= 0; start--) { | |
| incNumSeqGen.next(); | |
| } | |
| while (true) { | |
| try { | |
| var incNumSeq = incNumSeqGen.next(); | |
| } | |
| catch (e) { | |
| if (e === StopIteration) { | |
| console.log('Complete.'); | |
| break; | |
| } | |
| else { | |
| throw e; | |
| } | |
| } | |
| while (true) { | |
| try { | |
| var opSeq = opGen.next(); | |
| } | |
| catch (e) { | |
| if (e === StopIteration) { | |
| break; | |
| } | |
| else { | |
| throw e; | |
| } | |
| } | |
| // Expression must contained an four arithmetic operations. | |
| if (!opSeq.join('')) { | |
| continue; | |
| } | |
| var expected = incrementalNumSeqToNumberString(incNumSeq.clone().reverse()); | |
| if (String(incNumSeq.evaluate(opSeq)) === expected) { | |
| console.log('HIT: ' + incNumSeq.toExprString(opSeq) + ' = ' + expected); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment