-
-
Save yamadapc/8428269 to your computer and use it in GitHub Desktop.
'use strict'; | |
module.exports = function(roman) { | |
var roman_array = roman.split(''); | |
var dec_array = roman_array.map(function(roman_alg) { | |
return ROMAN_MAP[roman_alg]; | |
}); | |
var same = 1; | |
return dec_array.reduce(function(memo, n, index, list) { | |
var next = list[index + 1], prev = list[index - 1]; | |
var n_prec = PRECEDENCE_MAP.indexOf(n), next_prec = PRECEDENCE_MAP.indexOf(next); | |
// Validate repetition | |
if(n === next) { | |
same += 1; | |
if(same > 3) throw new Error('Only 3 equal algorisms may be consecutive'); | |
} | |
else same = 1; | |
// Validate 'precedence' | |
if(next_prec > n_prec + 2 || (n === prev && next_prec > n_prec)) | |
throw new Error('Input must obey to the precendence map'); | |
// Subtractive case | |
if(next && n < next) { | |
// Validate subtractive redundancy | |
if(next - n === n) | |
throw new Error('Input may not be redundant'); | |
return memo - n; | |
} | |
// Aditive case | |
else { | |
if(next + n === PRECEDENCE_MAP[PRECEDENCE_MAP.indexOf(n) + 1]) | |
throw new Error('Input may not be redundant'); | |
return memo + n; | |
} | |
}, 0); | |
}; | |
/** | |
* Constants and mappings | |
* --------------------------------------------------------------------------*/ | |
var ROMAN_MAP = { | |
'I': 1, | |
'V': 5, | |
'X': 10, | |
'L': 50, | |
'C': 100, | |
'D': 500, | |
'M': 1000 | |
}; | |
var PRECEDENCE_MAP = [1, 5, 10, 50, 100, 500, 1000]; |
ROMAN_MAP = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000} | |
result = 0 | |
roman = [ROMAN_MAP[c] for c in raw_input()] | |
for i, n in enumerate(roman): | |
nxt = 0 if len(roman) == i + 1 else roman[i + 1] | |
result = result - n if nxt > n else result + n | |
print result |
ROMAN_MAP = {'I'=>1,'V'=>5,'X'=>10,'L'=>50,'C'=>100,'D'=>500,'M'=>1000} | |
roman = gets.chomp.split '' | |
result = 0 | |
roman.each_with_index do |roman_alg, i| | |
nxt = ROMAN_MAP[roman[i + 1]] | |
n = ROMAN_MAP[roman_alg] | |
result = (nxt and nxt > n) ? result - n : result + n | |
end | |
puts result |
'use strict'; /* global describe, it */ | |
/** | |
* Dependencies | |
* --------------------------------------------------------------------------*/ | |
require('should'); | |
var roman_to_dec = require('..'); | |
describe('roman2decimal', function() { | |
it('works purely additive input', function() { | |
roman_to_dec('CCC').should.equal(300); | |
roman_to_dec('CCCXX').should.equal(320); | |
}); | |
it('works with subtractive input', function() { | |
roman_to_dec('XC').should.equal(90); | |
roman_to_dec('IV').should.equal(4); | |
roman_to_dec('CD').should.equal(400); | |
roman_to_dec('IX').should.equal(9); | |
}); | |
it('should work on mixed input', function() { | |
roman_to_dec('MMMCCXC').should.equal(3290); | |
roman_to_dec('MCMVII').should.equal(1907); | |
roman_to_dec('MMCDXLVII').should.equal(2447); | |
roman_to_dec('MMCMLXXXIV').should.equal(2984); | |
roman_to_dec('MXCVI').should.equal(1096); | |
roman_to_dec('MCMIV').should.equal(1904); | |
roman_to_dec('MMDII').should.equal(2502); | |
roman_to_dec('M').should.equal(1000); | |
roman_to_dec('MMDLXXIX').should.equal(2579); | |
roman_to_dec('MMMLXXXVIII').should.equal(3088); | |
roman_to_dec('MMDCCXCIX').should.equal(2799); | |
roman_to_dec('CXCVII').should.equal(197); | |
}); | |
it('throws errors on invalid input', function() { | |
// Precedence errors | |
roman_to_dec.bind(null, 'CCM').should.throw(); | |
roman_to_dec.bind(null, 'IC').should.throw(); | |
roman_to_dec.bind(null, 'IVX').should.throw(); | |
roman_to_dec.bind(null, 'MMID').should.throw(); | |
roman_to_dec.bind(null, 'IIIC').should.throw(); | |
roman_to_dec.bind(null, 'IVX').should.throw(); | |
// Over-consecutiveness errors | |
roman_to_dec.bind(null, 'XIIII').should.throw(); | |
roman_to_dec.bind(null, 'XXXX').should.throw(); | |
// Redundancy errors | |
roman_to_dec.bind(null, 'XXXVVI').should.throw(); | |
roman_to_dec.bind(null, 'LC').should.throw(); | |
roman_to_dec.bind(null, 'VX').should.throw(); | |
roman_to_dec.bind(null, 'VXX').should.throw(); | |
}); | |
}); |
module.exports = function(roman) { | |
return roman.split('').reduce(function(memo, roman_alg, index, list) { | |
var n = ROMAN_MAP[roman_alg], next = ROMAN_MAP[list[index + 1]]; | |
return (next && next > n) ? memo - n : memo + n; | |
}, 0); | |
}; | |
var ROMAN_MAP = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 }; |
Revision 3 adds my test suite
Revision 4 cleans up the test suite and adds some comments to it
though I'm probably wrong, I can't see more cases than these
Revision 5 cleans-up the code
The fact I'm using a same
captured variable inside the reduction function is really shitty and breaks the point of using a reduce in the first place.
The fact that I have to use a prev
variable means my algorithm performs one of the validations twice for each element - which is also pretty shitty.
Revisions 6 and 7 add a version without any validations.
(this is only to demonstrate how trivial the initial problem seems to be; these 8 lines pass the whole suite but the invalid input cases)
Revision 8 adds a tiny python solution without validation
Revision 9 adds another tiny ingenious implementation in ruby without validation
Revisions 10 and 11 use ternary operators (though not quite in python) to remove a line from the "mini" javascript version and a couple from the python version.
Revision 2 fixes spelling and formatting.