Last active
January 3, 2016 07:19
-
-
Save yamadapc/8428269 to your computer and use it in GitHub Desktop.
roman2decimal
This file contains 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
'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]; |
This file contains 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
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 |
This file contains 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
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 |
This file contains 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
'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(); | |
}); | |
}); |
This file contains 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
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 }; |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.