Single digit Roman numeral
Given a single character, which is a valid Roman numeral, output its value.
Values
There are 7 valid single character Roman numerals, with the following values:
Character | Value |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
Input
- A single character, which will always be one of
IVXLCDM
.
Output
- The corresponding value.
- The output value must not be a Roman numeral.
Test cases
As there are only 7 valid inputs, the list of test cases is exhaustive.
Test cases are in the format "input" : output
.
"I" : 1
"V" : 5
"X" : 10
"L" : 50
"C" : 100
"D" : 500
"M" : 1000
Scoring
This is a code golf challenge. Your score is the number of bytes in your code.
Explanations are optional, but I'm more likely to upvote answers that have one.
Python 3.8+, 51 byte ```pyt …
1y ago
[AWK], 80 bytes {split( …
6mo ago
[Swift], 114 bytes …
1y ago
C, 59 byte ```c h(n){retur …
1y ago
Haskell, 62 bytes ``` (\n- …
1y ago
Vyxal, 12 bitsv2, 1.5 or 2 byt …
1y ago
6 answers
Haskell, 62 bytes
(\n->(scanl(*)1$cycle[5,2])!!(length$takeWhile(/=n)"IVXLCDM"))
No import needed. It just uses standard Prelude functions.
scanl(*)1$cycle[5,2]
will give you the infinite list of [1,5,10,50...]. With
length$takeWhile(/=n)"IVXLCDM"
you will get the index of the element you would like to look up.
If you set
n='V'
the length part will be 1, and the index 1 means the 2nd element, so you'll get 5.
Python 3.8+, 51 byte
lambda n:((i:="IVXLCDM".index(n))%2*4+1)*10**(i//2)
Testing the code:
f=lambda n:((i:="IVXLCDM".index(n))%2*4+1)*10**(i//2)
for s in "IVXLCDM":
print(s, f(s))
The walrus operator stores the index in the variable i
, that is used in the exponent.
A much more readable version with the same logic:
def f(n):
i = "IVXLCDM".index(n)
return (i%2*4+1) * 10 ** (i // 2)
Thanks for [Object object] for getting rid of 5 bytes.
3 comment threads
C, 59 byte
h(n){return n&4?n&2?5:n&1?1e3:n&8?50:500:n&2?100:n&1?1:10;}
Old version, 60 byte:
h(n){return n&4?n&2?5:n&1?1000:n&8?50:500:n&2?100:n&1?1:10;}
Not very creative, there is probably a smaller version. Takes a ASCII character as argument and returns the value.
n&4
separates 'V'
/5
, 'L'
/50
, 'D'
/500
and 'M'
/1000
, which have bit 2 set and end up in this part: n&2?5:n&1?1000:n&8?50:500
, and 'I'
/1
, 'X'
/10
, 'C'
/100
, which have bit 2 cleared and end up in this part: n&2?100:n&1?1:10
.
A similar thing is done after that, of 'V', 'L', 'D', 'M'
, only 'V'
has bit 1 set, so if n&2
is true, the value is 5. If not, we check bit 0 with n&1
for 'M'
or 1000, bit 3 for 'L'
or 50
and if it is none of them it must be 'D'
or 500
. A similar thing is done for the numbers 100
, 1
and 10
. This has the nice side effect that it works work lower and upper case letters, since it ignores all bits >3.
Tried a version for EBCDIC-Encoding but that is longer (because some characters only differ at bit 4, which requires a n&16
, which is 1 byte longer).
0 comment threads
AWK, 80 bytes
{split("I V X L C D M 1 5 10 50 100 500 1000",d);for(;d[++i]!=$1;);print d[i+7]}
A quick map function. 'split' breaks the string into array elements. Find the string, and we know the Arabic numbers are always seven spots -> down the array from its Latin variant.
0 comment threads
Swift, 114 bytes
func y(x:String)->Int?{return ["I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000].filter{$0.key==x}.first?.value}
Explanation + Non-Golfed Version
The non-golfed version of this function would go one of two ways; the argument could be iterated over using a switch
statement, or (as seen above) could be mapped to a Dictionary
. Here are both non-golfed forms:
1. Switch
func romanNumeralAsInt(numeral: String) -> Int {
switch numeral{
case "I":
return 0
case "V":
return 5
case "X":
return 10
case "L":
return 50
case "C":
return 100
case "D":
return 500
case "M":
return 1000
default:
return 0
}
Example usage:
romanNumeralAsInt(numeral: "V") // 5
This has some advantages. To walk through the code above:
- The function takes in a
String
(though it is only one Character, and Swift also has a Character type) and returns anInt
. - The function iterates over all permutations of the input
- If the input did not match any of the specific cases, the function returns the
default
of0
.
2. Mapping
The above solution likely wasn't the best way to do it, but it was the shortest. Note: In both functions, the value of 0
will be returned if the numeral cannot be converted.
func romanNumeralAsInt(numeral: String) -> Int {
let mappings: [String: Int] = [
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000
]
if let firstResult = mappings.first(where: { item in
item.key == numeral
} {
return firstResult.value
}
return 0
}
- The above function has the same inputs and outputs as the first example (
String
input andInt
outptut). - The function declares a
Dictionary
(a Swift key-value pair type). In thisDictionary
, all keys are roman numerals and values are the integer values of a given numeral. - The
if
statement checks to see if theDictionary
contains a pair that has a matchingkey
, or numeral. - If so, it returns the
value
of that pair. - If not, the function returns
0
.
The Given Solution
The following is the given solution, but split across lines for readability:
func y(x: String) -> Int? {
return ["I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000]
.filter{$0.key==x}
.first?
.value
}
What this does:
- This function takes in a
String
, but outputs anInt?
- anOptional
type. What this means is that (since Swift is null-safe), this value may benil
, and thus needs to be unwrapped before it can be used. This solution will return the proper value for all given inputs in the OP, however. - The function declares the same
Dictionary
. - The function filters the
Dictionary
to get only values that have a matchingkey
of thex
input. - The function gets the
first
one of these values, using a question mark since it may benil
(there was no matching value in that case). - The function returns the integer value for that pair.
If we wanted to use this function, we would need nil coalescing, such as an ??
operator like the following:
let value = y(x: "V") ?? 0 // Value will be 5
0 comment threads
Vyxal, 12 bitsv2, 1.5 or 2 bytes
øṘ
Try it Online! or Try the entire test suite
Bitstring:
000101111100
Very simply a built-in
2 comment threads