Roman Enumeration

« Return to Article
  • yoda 2012-04-02 09:03
    Ist, yeah!!!
  • P. Almonius 2012-04-02 09:09
    That should be "prmium"
  • RandomGuy42 2012-04-02 09:10
    if(r=="III") return "tertium";
  • qbolec 2012-04-02 09:14
    Obviously, he should have used switch.
  • Nagesh 2012-04-02 09:14
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.
  • meme 2012-04-02 09:15
    Nice implementation of Y2k12.
  • anon 2012-04-02 09:19
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Cool, I'll thank Gray Eagle next time I see him.
  • Peyote `Simon` Joints 2012-04-02 09:44
    One line in Haskell.
  • LimitedMemory 2012-04-02 09:52
    Well, on embedded systems with limited processing power, a lookup table is still the best way ... Memory in GB's is cheap offcourse. And, the error return is TRWTF, it should be FILE_NOT_FOUND
  • PoPSiCLe 2012-04-02 09:55
    Why would you call it a Roman Numerals to decimal numbers converter? A Roman Numeral can, by definition, not be a decimal (the Romans didn't have "0"), and neither did they use decimals (only whole numbers).

    A better title for the "project" would be Roman Numerals to Integers (although this would also be wrong, as "integers" both incorporates negative numbers and zero), so the absolute correct naming would be Roman Numerals to Natural numbers (the numbers we learn when we learn to count, which are normally 1,2,3,4,5,6,7,8,9,10 etc)
  • Anon 2012-04-02 09:56
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    (Fake) Nagesh makes a valid point?!? Must be a late April Fools day joke.
  • Anon 2012-04-02 10:01
    TRWTF is this assignment, since there is no single standard for Roman numerals.
  • Coyne 2012-04-02 10:13
    ...and the best part of the routine is carefully hidden deep in the list: If you input 'MCMLXXXIX', it returns 'FILE NOT FOUND'.
  • NSCoder 2012-04-02 10:17
    PoPSiCLe:
    Why would you call it a Roman Numerals to decimal numbers converter?
    Because it returns the decimal (base 10) representation of the number. Strictly-speaking, with this name, it's correct to return it as a string (or a decimal datatype, if there is one in whichever language is being used), since returning it as an integer would make it a roman numerals to integer-without-any-particular-representation-or-base (or roman numerals to binary, depending on how you look at it) convertor, rather than specifically roman numerals to decimal.

    So you're asking the right question, but for the wrong reasons. Roman Numerals to Natural Numbers doesn't make much sense, really, because all Roman numerals already do represent natural numbers; no conversion necessary. The function just changes the notation, in this case to Hindu-Arabic numerals (which are decimal, although it might not be what Kendall wanted.) If Kendall didn't want the result as a string, he should have either called it a roman numerals to integer convertor, or told the programmer whether he wanted the decimal number as a string, binary-coded decimal, or other decimal data type.
  • ubersoldat 2012-04-02 10:20
    Hmmm... this is a pretty interesting example... and complex too:



    public String toNormal(final String roman){
    List<Integer> ints = new ArrayList<Integer>();
    char[] cArray = roman.toCharArray();
    for(int i = 0; i < cArray.length; i++){
    switch(cArray[i]){
    case 'I': ints.add(1); break;
    case 'V': ints.add(5); break;
    case 'X': ints.add(10); break;
    case 'L': ints.add(50); break;
    case 'C': ints.add(100); break;
    case 'D': ints.add(500); break;
    case 'M': ints.add(1000); break;
    default: throw new IllegalArgumentException();
    }
    }
    Integer total = ints.get(ints.size()-1);
    for(int i = ints.size()-1; i > 0; i--){
    if(ints.get(i) > ints.get(i-1))
    total = total - ints.get(i-1);
    else
    total = total + ints.get(i-1);
    }
    return String.valueOf(total);
    }
  • Toodle 2012-04-02 10:26
    Code fail on
    IIX
  • Black Bart 2012-04-02 10:29
    The new hire was obviously an Aztec, since he knew from hist calendar that there was no need for years beyond 2012.
  • TheJonB 2012-04-02 10:37
    Toodle:
    Code fail on
    IIX


    IIX is invalid, 8 is written VIII as any fule no.


    [ As an aside, I'm a bit thick, but I just realised that the real WTF is that the captcha answer
    is encoded in the viewstate on this site.. ]
  • frits 2012-04-02 10:41
    qbolec:
    Obviously, he should have used switch.
    A series of "cleverly" nested switches would be even better.
  • PiisAWheeL 2012-04-02 10:48
    Toodle:
    Code fail on
    IIX
    8 being written as VIII aside, wouldn't it also fail on IV first?

    Black Bart:
    The new hire was obviously an Aztec, since he knew from hist calendar that there was no need for years beyond 2012.
    Wrong. That is a reason not to include 2013. You still need to include the last year that will exist. December 20th is most of the year.
  • PedanticCurmudgeon 2012-04-02 10:52
    Peyote `Simon` Joints:
    One line in Haskell.
    I think you're bluffing. Code or it didn't happen.
  • Zolo 2012-04-02 10:59
    r = { "I" : 1, "V" : 5, "X" : 10, "L" : 50, "C" : 100, "D" : 500, "M" : 1000 }
    def r2d(m, p="I"):
    return 0 if m=="" else r2d(m[:-1],m[-1])+r[m[-1]]*(1 if r[m[-1]]>=r[p] else -1)

    print r2d("") # 0
    print r2d("IX") # 9
    print r2d("XI") # 11
    print r2d("MDCCCCX") # 1910
    print r2d("MCMLIV") # 1954
    print r2d("MCMXC") # 1990
    print r2d("MCMXCIX") # 1999
  • Daniel 2012-04-02 10:59
    PiisAWheeL:
    8 being written as VIII aside, wouldn't it also fail on IV first?

    Yes, doubly so: it should both remove twice the ints.get(i-1) number (since an instance of it was added in its own loop, and an extra should be removed) AND add ints.get(i).

    So "IV" (and IX/XL/XC/LC/CD/CM/DM wherever they occur in a number) would return 0 in the current state.

    CAPTCHA: "validus": indeed
  • the beholder 2012-04-02 11:14
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity
  • Loren Pechtel 2012-04-02 11:21
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity


    It wouldn't be that hard with a bit of cut & paste.
  • the beholder 2012-04-02 11:22
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity

    There is such a function indeed. He just lost that hard-earned +1
  • iToad 2012-04-02 11:24
    Zolo:
    r = { "I" : 1, "V" : 5, "X" : 10, "L" : 50, "C" : 100, "D" : 500, "M" : 1000 }
    def r2d(m, p="I"):
    return 0 if m=="" else r2d(m[:-1],m[-1])+r[m[-1]]*(1 if r[m[-1]]>=r[p] else -1)

    print r2d("") # 0
    print r2d("IX") # 9
    print r2d("XI") # 11
    print r2d("MDCCCCX") # 1910
    print r2d("MCMLIV") # 1954
    print r2d("MCMXC") # 1990
    print r2d("MCMXCIX") # 1999


    ...and this is why we will never see a Haskell WTF here. Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
  • KattMan 2012-04-02 11:26
    The better way in my mind is to use the interpreter pattern and let it build any decimal representation of any given roman numeral representation you give it.

    Bonus points for the fact there this is an example found with an easy google search on the interpreter pattern that does this exact same thing.
  • Kivi 2012-04-02 11:34
    the beholder:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity

    There is such a function indeed. He just lost that hard-earned +1

    And, to be fair, the -100 as well.

    The function, if anyone's interested, is here: http://office.microsoft.com/en-us/excel-help/convert-arabic-to-roman-numerals-HA010007443.aspx

    Using Excel to auto-generate code is delightfully perverse. That's one of those innovations that is just crazy enough to be crazy.
  • D-Coder 2012-04-02 11:35
    PoPSiCLe:
    Why would you call it a Roman Numerals to decimal numbers converter? A Roman Numeral can, by definition, not be a decimal (the Romans didn't have "0"), and neither did they use decimals (only whole numbers).

    A better title for the "project" would be Roman Numerals to Integers (although this would also be wrong, as "integers" both incorporates negative numbers and zero), so the absolute correct naming would be Roman Numerals to Natural numbers (the numbers we learn when we learn to count, which are normally 1,2,3,4,5,6,7,8,9,10 etc)
    I can always count on TDWTF for my daily dose of pedantic dickweedery.
  • JAHH (Just Another Haskell Hobo) 2012-04-02 11:43
    Here's my single line (assuming correctly formed romans):


    let roman = "MDIX"; nums = map (\r -> lookup r (zip "IVXLCDM" [1,5,10,50,100,500,1000])) roman in sum $ zipWith (\xx yy -> case xx of Just x -> case yy of Just y -> if (x<y) then -x else x) nums ((tail nums)++[Just 0])
  • PaulaBean 2012-04-02 11:44
    easy peasy.

    private int toInt(string roman) {
    int lastnum = 0;
    int total = 0;
    for (int c = roman.Length - 1; c >= 0; c--) {
    string number = roman.Substring(c, 1);
    int value = singleRomanToInt(number);
    if (value < lastnum) total -= value;
    else {
    lastnum = value;
    total += value;
    }
    }
    return total;
    }

    private int singleRomanToInt(string romanchar) {
    switch (romanchar.ToUpper()) {
    case "I": return 1;
    case "V": return 5;
    case "X": return 10;
    case "L": return 50;
    case "C": return 100;
    case "M": return 1000;
    default:
    return Convert.ToInt32("PaulaBean!");
    }
    }
  • PedanticCurmudgeon 2012-04-02 12:09
    iToad:
    Zolo:
    r = { "I" : 1, "V" : 5, "X" : 10, "L" : 50, "C" : 100, "D" : 500, "M" : 1000 }
    
    def r2d(m, p="I"):
    return 0 if m=="" else r2d(m[:-1],m[-1])+r[m[-1]]*(1 if r[m[-1]]>=r[p] else -1)

    print r2d("") # 0
    print r2d("IX") # 9
    print r2d("XI") # 11
    print r2d("MDCCCCX") # 1910
    print r2d("MCMLIV") # 1954
    print r2d("MCMXC") # 1990
    print r2d("MCMXCIX") # 1999


    ...and this is why we will never see a Haskell WTF here. Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Python.
    FTFY
  • mwchase 2012-04-02 12:09
    That's not Haskell, that's Python. It's using a language feature that I was previously unaware of, oops. ([value] if [condition] else [alternative])
  • Nagesh 2012-04-02 12:12
    Nagesh (fake):
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Fake nagesh has stole words from my key-board. It is "modern numbers", you idiot.

    Also Alegbra invented here.
  • PedanticCurmudgeon 2012-04-02 12:13
    iToad:
    Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
    Some would say that there is no difference.
  • foo 2012-04-02 12:17
    ubersoldat:
    Hmmm... this is a pretty interesting example... and complex too:



    public String toNormal(final String roman){
    List<Integer> ints = new ArrayList<Integer>();
    char[] cArray = roman.toCharArray();
    for(int i = 0; i < cArray.length; i++){
    switch(cArray[i]){
    case 'I': ints.add(1); break;
    case 'V': ints.add(5); break;
    case 'X': ints.add(10); break;
    case 'L': ints.add(50); break;
    case 'C': ints.add(100); break;
    case 'D': ints.add(500); break;
    case 'M': ints.add(1000); break;
    default: throw new IllegalArgumentException();
    }
    }
    Integer total = ints.get(ints.size()-1);
    for(int i = ints.size()-1; i > 0; i--){
    if(ints.get(i) > ints.get(i-1))
    total = total - ints.get(i-1);
    else
    total = total + ints.get(i-1);
    }
    return String.valueOf(total);
    }
    A list of integers. Really? I mean ... where's the XML?
  • fjf 2012-04-02 12:20
    foo:
    ubersoldat:
    Hmmm... this is a pretty interesting example... and complex too:



    public String toNormal(final String roman){
    List<Integer> ints = new ArrayList<Integer>();
    char[] cArray = roman.toCharArray();
    for(int i = 0; i < cArray.length; i++){
    switch(cArray[i]){
    case 'I': ints.add(1); break;
    case 'V': ints.add(5); break;
    case 'X': ints.add(10); break;
    case 'L': ints.add(50); break;
    case 'C': ints.add(100); break;
    case 'D': ints.add(500); break;
    case 'M': ints.add(1000); break;
    default: throw new IllegalArgumentException();
    }
    }
    Integer total = ints.get(ints.size()-1);
    for(int i = ints.size()-1; i > 0; i--){
    if(ints.get(i) > ints.get(i-1))
    total = total - ints.get(i-1);
    else
    total = total + ints.get(i-1);
    }
    return String.valueOf(total);
    }
    A list of integers. Really? I mean ... where's the XML?
    XML == 1040, according to this function
  • briverymouse 2012-04-02 12:31
    PedanticCurmudgeon:
    iToad:
    Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
    Some would say that there is no difference.


    The average Haskell WTF is something about a guy who, during an interview, forgot to make his Monad an Applicative. Can you imagine such foolishness? Also, missing a perfectly good opportunity to use a zipWith or a liftM is cause for certain derision.
  • TheJonB 2012-04-02 12:33
    Nagesh:

    Also Alegbra invented here.


    Etymology suggests it's from them Ay-rabs.
  • Meep 2012-04-02 12:38
    PedanticCurmudgeon:
    Peyote `Simon` Joints:
    One line in Haskell.
    I think you're bluffing. Code or it didn't happen.


    rom 'I' = 1
    rom 'V' = 5
    rom 'X' = 10
    ...

    All of which can be translated into a single case statement, rom x = case x of { 'I' -> 1; 'V' -> 5; 'X' -> 10 ... }

    Since a string is simply a list of characters:

    raw_decode nums = map rom nums

    Or as a comprehension: raw_decode nums = [ rom num | num <- nums ]

    So raw_decode "IXX" yields [1, 10, 10]

    Next we want to group up all the IX type cases. Our numerals should always be in descending order, except for those cases, so we can simply group using the < operator.

    rollup_prefixes raw = groupBy (<) raw

    That gives us a list of lists that may be one or two elements long, by our invariants.

    sub_prefix [ num ] = num
    sub_prefix [ pre num ] = num - pre

    Or as a case statement:

    sub_prefix roll = case roll of { [ num ] -> num; [ pre num ] -> num - pre; }

    And we then map that out:

    sub_prefixes rolled_up = map sub_prefix rolled_up

    Then we simply sum the result:

    final subbed = sum subbed

    Put it all together:

    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case num of { 'I' -> 1; 'V' -> 2; ... } | letter <- roman ] ]
  • Sir Twist 2012-04-02 12:39
    If I were more efficient at commenting, this would be first. Perhaps they will assign commenting duties to the marketing department.
  • Anketam 2012-04-02 12:42
    Kivi:
    the beholder:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity

    There is such a function indeed. He just lost that hard-earned +1

    And, to be fair, the -100 as well.

    The function, if anyone's interested, is here: http://office.microsoft.com/en-us/excel-help/convert-arabic-to-roman-numerals-HA010007443.aspx

    Using Excel to auto-generate code is delightfully perverse. That's one of those innovations that is just crazy enough to be crazy.
    So the best solution to this is to create an excel macro to do it. That is Brillant! Then again I have been known to use excel to create 100+ statements (that contain things like counters) for random things like database inserts and xml input files.
  • iToad 2012-04-02 12:42
    mwchase:
    That's not Haskell, that's Python. It's using a language feature that I was previously unaware of, oops. ([value] if [condition] else [alternative])


    Crap, you're right. To add insult to injury, I use Python. This is what happens when you post on a Monday morning.
  • tundog 2012-04-02 12:43
    Clearly this problem is screaming for a Perl REGEX!
  • Ol' Bob 2012-04-02 12:48
    Nagesh:
    Nagesh (fake):
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Fake nagesh has stole words from my key-board. It is "modern numbers", you idiot.

    Also Alegbra invented here.


    Who's this Aleg chick? And what're you doin' inventin' underwear for her?
  • PiisAWheeL 2012-04-02 12:49
    briverymouse:
    PedanticCurmudgeon:
    iToad:
    Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
    Some would say that there is no difference.


    The average Haskell WTF is something about a guy who, during an interview, forgot to make his Monad an Applicative. Can you imagine such foolishness? Also, missing a perfectly good opportunity to use a zipWith or a liftM is cause for certain derision.
    Haskell people are wierd... and they talk funny.
  • LANMind 2012-04-02 12:50
    JAHH (Just Another Haskell Hobo):
    Here's my single line (assuming correctly formed romans):


    let roman = "MDIX"; nums = map (\r -> lookup r (zip "IVXLCDM" [1,5,10,50,100,500,1000])) roman in sum $ zipWith (\xx yy -> case xx of Just x -> case yy of Just y -> if (x<y) then -x else x) nums ((tail nums)++[Just 0])


    Two comments.

    First, any time I see code that might perhaps be more easily understood if represented in cyrilic, or maybe a right to left language, I figure "wtf?" Then again, I'm not building device drivers or something else that requires the most succinct code - I'm solving business problems - and you'd better believe that maintainability is a so-close-it's-immaterial second to whether or not it produces the right result. As sure as God made little green apples, today's correct solution will be incorrect tomorrow. All of that leads to...

    Second, the technical debt in our instance would be prohibitively high.
  • Jay 2012-04-02 12:53
    PoPSiCLe:
    Why would you call it a Roman Numerals to decimal numbers converter? A Roman Numeral can, by definition, not be a decimal (the Romans didn't have "0"), and neither did they use decimals (only whole numbers).

    A better title for the "project" would be Roman Numerals to Integers (although this would also be wrong, as "integers" both incorporates negative numbers and zero), so the absolute correct naming would be Roman Numerals to Natural numbers (the numbers we learn when we learn to count, which are normally 1,2,3,4,5,6,7,8,9,10 etc)


    The word "decimal" means "base 10". He is converting from Roman numberals to Hindu-Arabic numerals in base 10. The name is perfectly appropriate.

    He is not converting Roman Numerals to natural numbers. Roman Numerals already are natural numbers. Natural numbers exist independent of the notation used to represent them.

    Even if we understood "integer" to mean "Hindu-Arabic represenstation of integers" and "natural numbers" to mean "Hindu-Arabic representation of natural numbers", your comment makes no sense. Even if the function can never produce zero or negative numbers, so what? If someone says that he has written a "French to English translation dictionary", would it be fair to say he was lying because you found an English word for which there is no corresponding word in French, and which the dictionary did not therefore have an entry for? Or for a closer analogy, would it really be fair to say that there cannot possibly be any such thing as a function to convert short integers to long integers, because many long integers exist which could never be output by this function? So the range of possible outputs is a subset of the domain. So what?
  • visualbasucks 2012-04-02 12:54
    Why doesnt it return a "end of source file not found" error?
    If it has a prefixed "e" it can be tested for being an error string too or maybe garbled floating point numbers.
  • Katy Gaga 2012-04-02 12:54
    Nagesh:
    Nagesh (fake):
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Fake nagesh has stole words from my key-board. It is "modern numbers", you idiot.

    Also Alegbra invented here.
    Also, keyboard isn't hyphenated.
  • vereor 2012-04-02 12:55
    the beholder:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity

    There is such a function indeed. He just lost that hard-earned +1


    Give him +1 for figuring out how to do that in Excel (unless it's automatic, where you type "I" in the first box and all other values increment by dragging).
  • CarnivorousHippie 2012-04-02 12:56
    Tokenize on (IV, IX, I, XL, XC, X, CD, CM, C, M), map to (4, 9, 1, 40, 90, 10, 400, 900, 100, 1000), and sum.

    Actual code is left as an exercise for the reader.
  • DCRoss 2012-04-02 13:00
    tundog:
    Clearly this problem is screaming for a Perl REGEX!

    Why even use a regex? Larry Wall's corollary to Rule 34 states that "If it exists, there is a perl module for it."

    #!/usr/bin/perl
    use Roman;
    $roman = roman($arabic);

    There you go.

    Of course EMACS users would just use M-x roman-numerals-mode, but that's another story.
  • ObiWayneKenobi 2012-04-02 13:01
    What the hell is it with people and having to return "error codes" from everything? THIS ISN'T VB6. There are sophisticated error handling in modern languages, you don't need to return ints or bools all over the place.
  • Jay 2012-04-02 13:01
    Anon:
    TRWTF is this assignment, since there is no single standard for Roman numerals.


    You must be a barrel of laughs in a requirements meeting.

    Customer: We need to display the number of days between any two given dates.

    Anon: That's impossible. Some months have a different number of days from other months. And the number of days in each month can change: What about leap year? And historically, countries switched from the Julian to the Gregorian calendars at different times.

    Surely the obvious reply is: "The problem is not trivially simple" and/or "The problem as stated has some ambiguitites" is not the same as "The problem is impossible". In this case, we would either agree up front on our definition of how Roman numerals are to be parsed, or if we really wanted to be thorough, we could include some setting or parameter to specify which variation we want. This is hardly a ground-breaking idea. We regularly deal with different date and number formats. Why not different Roman numeral formats?
  • Cap'n Spanky 2012-04-02 13:04
    Roman Enumeration:
    PedanticCurmudgeon:
    iToad:
    Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
    Some would say that there is no difference.
    The average Haskell WTF is something about a guy who, during an interview, forgot to make his Monad an Applicative. Can you imagine such foolishness? Also, missing a perfectly good opportunity to use a zipWith or a liftM is cause for certain derision.

    I heard that Hitler was a monad.
  • PedanticCurmudgeon 2012-04-02 13:07
    Meep:
    PedanticCurmudgeon:
    Peyote `Simon` Joints:
    One line in Haskell.
    I think you're bluffing. Code or it didn't happen.


    rom 'I' = 1
    rom 'V' = 5
    rom 'X' = 10
    ...

    All of which can be translated into a single case statement, rom x = case x of { 'I' -> 1; 'V' -> 5; 'X' -> 10 ... }

    Since a string is simply a list of characters:

    raw_decode nums = map rom nums

    Or as a comprehension: raw_decode nums = [ rom num | num <- nums ]

    So raw_decode "IXX" yields [1, 10, 10]

    Next we want to group up all the IX type cases. Our numerals should always be in descending order, except for those cases, so we can simply group using the < operator.

    rollup_prefixes raw = groupBy (<) raw

    That gives us a list of lists that may be one or two elements long, by our invariants.

    sub_prefix [ num ] = num
    sub_prefix [ pre num ] = num - pre

    Or as a case statement:

    sub_prefix roll = case roll of { [ num ] -> num; [ pre num ] -> num - pre; }

    And we then map that out:

    sub_prefixes rolled_up = map sub_prefix rolled_up

    Then we simply sum the result:

    final subbed = sum subbed

    Put it all together:

    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case num of { 'I' -> 1; 'V' -> 2; ... } | letter <- roman ] ]
    Actually, I was hoping for something in point-free style, but this works too.
  • Zylon 2012-04-02 13:10
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    Uh, yeah. Nobody's commented on this because it's implicitly stated right in the article:

    //
    // Snipped LOTS of "code" here
    //

    This is, in fact, the entire focus of the WTFery of his solution.
  • PedanticCurmudgeon 2012-04-02 13:15
    briverymouse:
    PedanticCurmudgeon:
    iToad:
    Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
    Some would say that there is no difference.


    The average Haskell WTF is something about a guy who, during an interview, forgot to make his Monad an Applicative. Can you imagine such foolishness? Also, missing a perfectly good opportunity to use a zipWith or a liftM is cause for certain derision.
    Actually, I'd be more inclined to laugh at someone who did:
    upcaseLine = do
    
    str <- getLine
    return $ map toUpper str
    instead of:
    upcaseLine = fmap (map toUpper) getLine
    
  • link87 2012-04-02 13:24
    Roman Enumeration:

    I heard that Hitler was a monad.

    The important question remains: was Hitler also a burrito?
  • qbolec 2012-04-02 13:27
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +1 for dedication
    -100 for stupidity

    I bet he did not write it by hand. Instead he generated code using already implemented function:

    public string num2rom(string n)
    {
    if (n == "1") return "I";
    if (n == "2") return "II";
    if (n == "3") return "III";
    if (n == "4") return "IV";
    if (n == "5") return "V";
    if (n == "6") return "VI";
    if (n == "7") return "VII";
    if (n == "8") return "VIII";
    if (n == "9") return "IX";
    //
    // Snipped LOTS of "code" here
    //
    if (n == "2008") return "MMVIII";
    if (n == "2009") return "MMIX";
    if (n == "2010") return "MMX";
    if (n == "2011") return "MMXI";
    return "E";
    }


    ...and to those curious: I did not write the above function by hand neither -- I used his rom2num to generate mine.
  • SEMI-HYBRID code 2012-04-02 13:27
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    ...last time i checked the "modern numerals" were called "arabic" ;)
  • qbolec 2012-04-02 13:32
    As the author of the article wisely suggested with the comment about >>lots of "code"<<, the real WTF is not separating code and data apropriately.

    The data as this should be stored in an editable database relation:

    CREATE TABLE num_rom(
    num TEXT PRIMARY KEY,
    rom TEXT UNIQUE KEY
    );

    and then accessed with a simple SQL query:

    SELECT rom
    FROM num_rom
    WHERE num = :num


    Of course in a real life application would add a caching proxy layer, and/or store the database in a ROM (as the name of the function suggests).
  • behold me! 2012-04-02 13:51
    Zylon:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    Uh, yeah. Nobody's commented on this because it's implicitly stated right in the article:

    //
    // Snipped LOTS of "code" here
    //

    This is, in fact, the entire focus of the WTFery of his solution.

    YHBT YHL FOAD
  • RJ 2012-04-02 13:53
    Zolo:
    r = { "I" : 1, "V" : 5, "X" : 10, "L" : 50, "C" : 100, "D" : 500, "M" : 1000 }


    No real magic going on b/c this is "Haskell". It'd be 1 line of perl or any language w/ recursion. The string as a hash key helps ... which supports that it'd be 1 line in perl too.
  • jgibson 2012-04-02 14:11
    <?php

    function roman2dec($strRoman)
    {
    $intSum = 0;
    $arrStrRoman = str_split(strtoupper($strRoman));
    $arrErrors = array();
    $arrRomanValues = array('I' => 1,'V' => 5,'X' => 10,'L' => 50,'C' => 100,'D' => 500,'M' => 1000);

    for($i = 0; $i < strlen($strRoman); $i++)
    {
    if(array_key_exists($arrStrRoman[$i], $arrRomanValues))
    {
    if($i != (strlen($strRoman) - 1) && strlen($strRoman) != 1)
    {
    if($arrRomanValues[$arrStrRoman[$i]] >= $arrRomanValues[$arrStrRoman[$i + 1]])
    {
    $intSum += $arrRomanValues[$arrStrRoman[$i]];
    }else{
    $intSum += ($arrRomanValues[$arrStrRoman[$i + 1]] - $arrRomanValues[$arrStrRoman[$i]]);
    $i++;
    }
    }else{
    $intSum += $arrRomanValues[$arrStrRoman[$i]];
    }
    }else{
    $arrErrors[$i] = $arrStrRoman[$i] . ' is an invalid Roman Numeral';
    }
    }
    if(count($arrErrors) > 0)
    {
    return $arrErrors;
    }
    return $intSum;
    }

    //not outputting errors right now, just values
    echo roman2dec('MDCCCCX'); //1910
    echo '<br />';
    echo roman2dec('MMVI'); //2006
    echo '<br />';
    echo roman2dec('MCMLIV'); //1954
    echo '<br />';
    echo roman2dec('MCMXC'); //1990
    echo '<br />';
    echo roman2dec('IV'); //4
    echo '<br />';
    echo roman2dec('V'); //5
    echo '<br />';
    echo roman2dec('MCMXLIV'); //1944
    echo '<br />';
    echo roman2dec(''); //0
    echo '<br />';
  • briverymouse 2012-04-02 14:13
    RJ:
    Zolo:
    r = { "I" : 1, "V" : 5, "X" : 10, "L" : 50, "C" : 100, "D" : 500, "M" : 1000 }


    No real magic going on b/c this is "Haskell". It'd be 1 line of perl or any language w/ recursion. The string as a hash key helps ... which supports that it'd be 1 line in perl too.


    "Haskell", officially the new name for Python.
  • the beholder 2012-04-02 14:27
    CarnivorousHippie:
    Tokenize on (IV, IX, I, XL, XC, X, CD, CM, C, M), map to (4, 9, 1, 40, 90, 10, 400, 900, 100, 1000), and sum.

    Actual code is left as an exercise for the reader.
    I really like your approach, but what's wrong with V, L and D?
  • da Doctah 2012-04-02 14:38
    Somewhat serious followup: Give me a regex that will match only movie titles that end in Roman numerals. Take into account that sometimes there will be a secondary title, as in "Death Warriors IV: the Deaths Continue".

    I tried to do this a few years ago on IMDb to figure out what the highest numbered "sequel" was. Ran into the problem that "mi", "di", "xi" and others are actual words in some languages.
  • Bob C. Cock 2012-04-02 14:39
    prmivm

    FTFY
  • the beholder 2012-04-02 14:40
    vereor:
    the beholder:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    That's not exactly an easy thing to do unless there's a feature in Excel that I'm not aware of.

    +I for dedication
    -C for stupidity
    (FTFM)

    There is such a function indeed. He just lost that hard-earned +I


    Give him +I for figuring out how to do that in Excel (unless it's automatic, where you type "I" in the first box and all other values increment by dragging).
    It isn't (at least in my version), but all it takes is stumbling on a function named ROMAN after pressing equals. Hardly worth +I
  • Nagesh 2012-04-02 14:46
    SEMI-HYBRID code:
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    ...last time i checked the "modern numerals" were called "arabic" ;)

    It is being irony-like turm "American English."
  • Anon 2012-04-02 14:46
    Jay:

    Anon: That's impossible.


    Nobody said it was impossible. Do you always put words in other people's mouths so you can argue with them?
  • Nagesh 2012-04-02 14:47
    Nagesh:
    SEMI-HYBRID code:
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    ...last time i checked the "modern numerals" were called "arabic" ;)

    It is being irony-like turm "American English."

    Also, Times new Roman font developd by Germans.
  • Not provided. 2012-04-02 14:50
    Nah, first he wrote a decimal to roman converter.
  • Anon 2012-04-02 14:50
    SEMI-HYBRID code:
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    ...last time i checked the "modern numerals" were called "arabic" ;)


    Ouch! You just tried to correct [fake] Nagesh when he is actually correct.

    While they are often called "Arabic" numerals, they are more correctly called "Indo-Arabic" numerals. In the west we call them Arabic numerals because we learnt them from Arabs who, in turn, learnt them from the Indians.
  • Brendan 2012-04-02 15:00
    Meep:
    rom 'I' = 1
    rom 'V' = 5
    rom 'X' = 10
    ...

    All of which can be translated into a single case statement, rom x = case x of { 'I' -> 1; 'V' -> 5; 'X' -> 10 ... }

    Since a string is simply a list of characters:

    raw_decode nums = map rom nums

    Or as a comprehension: raw_decode nums = [ rom num | num <- nums ]

    So raw_decode "IXX" yields [1, 10, 10]

    Next we want to group up all the IX type cases. Our numerals should always be in descending order, except for those cases, so we can simply group using the < operator.

    rollup_prefixes raw = groupBy (<) raw

    That gives us a list of lists that may be one or two elements long, by our invariants.

    sub_prefix [ num ] = num
    sub_prefix [ pre num ] = num - pre

    Or as a case statement:

    sub_prefix roll = case roll of { [ num ] -> num; [ pre num ] -> num - pre; }

    And we then map that out:

    sub_prefixes rolled_up = map sub_prefix rolled_up

    Then we simply sum the result:

    final subbed = sum subbed

    Put it all together:

    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case num of { 'I' -> 1; 'V' -> 2; ... } | letter <- roman ] ]


    That's about 25 lines of code (including the comments that are necessary to make Haskell readable). It would've been less typing in something like COBOL (and probably faster too, as there's no need to depend on the misuse of recursion)!
  • daily 2012-04-02 15:02
    RandomGuy42:
    if(r=="III") return "Pentium";

    FTFY
  • qbolec 2012-04-02 15:15
    replace:
    "IV" => "4",
    "IX" => "9",
    "IL" => "49",
    "IC" => "99",
    "ID" => "499",
    "IM" => "999",
    //"VL","VC","VD","VM" not supported, use XLV instead...
    "XL" => "4",
    "XC" => "9",
    "XD" => "49",
    "XM" => "99",
    //"LD","LM"
    "VI" => "6",
    "VII" => "7",
    "VIII" => "8",
    "I" => "1",
    "II" => "2",
    "III" => "3",
    "V" => "5",
    "X" => "1",
    "L" => "5",
    "C" => "1",
    "D" => "5",
    "M" => "1",
  • Nagesh 2012-04-02 15:26
    Anon:
    SEMI-HYBRID code:
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    ...last time i checked the "modern numerals" were called "arabic" ;)


    Ouch! You just tried to correct [fake] Nagesh when he is actually correct.

    While they are often called "Arabic" numerals, they are more correctly called "Indo-Arabic" numerals. In the west we call them Arabic numerals because we learnt them from Arabs who, in turn, learnt them from the Indians.


    He who corects fool is not rewarded for his truble.
    He who corects wise man receves gift beter than golds.
  • zzo38 2012-04-02 15:38
    Toodle:
    Code fail on
    IIX
    IIX is not a valid roman numeral.

    And, in Haskell, you can return the error indicator just by using the Maybe type (in a new programming language, currently codenamed "Ibtlfmm", the you can use the successor type which is the same as Haskell's Maybe just with a different name)

    The average Haskell WTF is something about a guy who, during an interview, forgot to make his Monad an Applicative.
    I often complain about same things too

    Addendum (2012-04-02 15:45):
    (MMMIM is a non-standard, but valid, roman numeral; IIX, however, is not even valid.)
  • Yoh 2012-04-02 15:45
    That code in question did in fact fail on IX though. As will most of the examples people have shared.
  • KattMan 2012-04-02 15:56
    Yoh:
    That code in question did in fact fail on IX though. As will most of the examples people have shared.

    My interpreter pattern suggestion would not fail.

    example here...
    http://www.dofactory.com/Patterns/PatternInterpreter.aspx

    This pattern also works out well for creating a sounddex generator.
  • Matt Westwood 2012-04-02 16:03
    TRWTF is that Roman numerals are still used in certain contexts. How fucking shit-for-brains stupid is that.
  • PiisAWheeL 2012-04-02 16:12
    link87:
    Roman Enumeration:

    I heard that Hitler was a monad.

    The important question remains: was Hitler also a burrito?
    NO HITLER WAS NOT A BURRITO. Burritos are delicious and awesome. Hitler was not delicious or awesome. Do not ruin burritos for me!
  • iToad 2012-04-02 16:17
    There was actually a serious (maybe) proposal to add Roman numerals to Python, but it got rejected:

    PEP 313

    Too bad. I wanted to see whether I could calculate the square root of pi, using only Roman Numerals.
  • jgibson 2012-04-02 16:35
    mine certainly did not fail on IX
  • lunchTime 2012-04-02 16:37
    Here's my (crummy) stab at it:
    (Now with input validation)


    #!~/bin/perl
    use 5.010;
    while ( <DATA> ) {
    chomp; say 0 and next unless length;

    (/\b
    (M+|(?=[CDXLVI]))
    (C{1,4}|CD|DC{0,4}|CM|(?=[XLVI])|(?<=M))
    (X{1,4}|XL|LX{0,4}|XC|(?=[VI])|(?<=[MCD]))
    (I{1,4}|IV|VI{0,4}|IX|(?<=[MCDLX]))
    \b/x) ? do { my $n; $n+={''=>0,I=>1,IV=>4,V=>5,IX=>9,X=>10,XL=>40,L=>50,XC=>90,C=>100,CD=>400,D=>500,CM=>900,M=>1000}->{uc $_} foreach split /(IV|IX|XL|XC|CD|CM|I|V|X|L|C|D|M)\s*/; say $n;}: say "[$_] does not appear to be a valid Roman numeral";
    }
    __DATA__

    MM
    VIIX
    VIIII
    IV
    IX
    IL
    IC
    ID
    IM
    VL
    VC
    VD
    VM
    XLV
    XL
    XC
    XD
    XM
    LD
    LM
    VI
    VII
    VIII
    I
    II
    III
    V
    X
    L
    C
    D
    M


    PRINTS:

    0
    2000
    [VIIX] does not appear to be a valid Roman numeral
    9
    4
    9
    [IL] does not appear to be a valid Roman numeral
    [IC] does not appear to be a valid Roman numeral
    [ID] does not appear to be a valid Roman numeral
    [IM] does not appear to be a valid Roman numeral
    [VL] does not appear to be a valid Roman numeral
    [VC] does not appear to be a valid Roman numeral
    [VD] does not appear to be a valid Roman numeral
    [VM] does not appear to be a valid Roman numeral
    45
    40
    90
    [XD] does not appear to be a valid Roman numeral
    [XM] does not appear to be a valid Roman numeral
    [LD] does not appear to be a valid Roman numeral
    [LM] does not appear to be a valid Roman numeral
    6
    7
    8
    1
    2
    3
    5
    10
    50
    100
    500
    1000
  • KattMan 2012-04-02 16:42
    iToad:
    There was actually a serious (maybe) proposal to add Roman numerals to Python, but it got rejected:

    PEP 313

    Too bad. I wanted to see whether I could calculate the square root of pi, using only Roman Numerals.


    This will get you started
    CD/CXXVII = PI
  • radarbob 2012-04-02 16:45
    Ol' Bob:
    Nagesh:
    Nagesh (fake):
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Fake nagesh has stole words from my key-board. It is "modern numbers", you idiot.

    Also Alegbra invented here.


    Who's this Aleg chick? And what're you doin' inventin' underwear for her?


    Don't laf. There is such a thing as Feminist Algebra. Yes, it's moronic, but is a real-life kolluge kourse.
  • radarbob 2012-04-02 16:49
    Nagesh:
    Anon:
    SEMI-HYBRID code:
    Nagesh:
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    ...last time i checked the "modern numerals" were called "arabic" ;)


    Ouch! You just tried to correct [fake] Nagesh when he is actually correct.

    While they are often called "Arabic" numerals, they are more correctly called "Indo-Arabic" numerals. In the west we call them Arabic numerals because we learnt them from Arabs who, in turn, learnt them from the Indians.


    He who corects fool is not rewarded for his truble.
    He who corects wise man receves gift beter than golds.


    BFD. The copyright expired centuries ago. And, as we say in non-static, loosely typed societies (a little computer language lingo as societal commentary there), "yeah? so what have you done for me lately?"
  • Romanes eunt domus 2012-04-02 17:18
    I guess his solution to the first exercise was this:

    printf(
    "99 bottles of beer on the wall, 99 bottles of beer.\nTake one down and pass it around, 98 bottles of beer on the wall.\n"
    "98 bottles of beer on the wall, 98 bottles of beer.\nTake one down and pass it around, 97 bottles of beer on the wall.\n"
    "97 bottles of beer on the wall, 97 bottles of beer.\nTake one down and pass it around, 96 bottles of beer on the wall.\n"
    "96 bottles of beer on the wall, 96 bottles of beer.\nTake one down and pass it around, 95 bottles of beer on the wall.\n"
    "95 bottles of beer on the wall, 95 bottles of beer.\nTake one down and pass it around, 94 bottles of beer on the wall.\n"
    "94 bottles of beer on the wall, 94 bottles of beer.\nTake one down and pass it around, 93 bottles of beer on the wall.\n"
    /* SNIP 92 lines */
    "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n"
    "1 bottle of beer on the wall, 1 bottle of beer.\nTake one down and pass it around, no more bottles of beer on the wall.\n"
    "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n");




  • PiisAWheeL 2012-04-02 17:24
    KattMan:
    iToad:
    There was actually a serious (maybe) proposal to add Roman numerals to Python, but it got rejected:

    PEP 313

    Too bad. I wanted to see whether I could calculate the square root of pi, using only Roman Numerals.


    This will get you started
    CD/CXXVII = PI
    I. P is not a roman numeral. II. Roman numerals didn't have decimal points. III. The longer roman numerals get the more digits near the beginning get changed until you just have a bunch of M's to count your thousands with. Thats why it (should have) died with the romans.
  • Coyne 2012-04-02 17:27
    Romanes eunt domus:
    I guess his solution to the first exercise was this:

    printf(
    "99 bottles of beer on the wall, 99 bottles of beer.\nTake one down and pass it around, 98 bottles of beer on the wall.\n"
    "98 bottles of beer on the wall, 98 bottles of beer.\nTake one down and pass it around, 97 bottles of beer


    Really? In this thread?

    Why not:

    Romanes eunt domus:
    I guess his solution to the first exercise was this:

    printf(
    "XCIX bottles of beer on the wall, XCIX bottles of beer.\nTake one down and pass it around, XCVIII bottles of beer on the wall.\n"
    "XCVIII bottles of beer on the wall, XCVIII bottles of beer.\nTake one down and pass it around, XCVII bottles of beer on the wall.\n"
    etc.
  • geoffrey, MCP, PMP 2012-04-02 17:51
    The company's hiring practices alone could be its own article.
  • Matt Westwood 2012-04-02 17:53
    radarbob:
    Ol' Bob:
    Nagesh:
    Nagesh (fake):
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Fake nagesh has stole words from my key-board. It is "modern numbers", you idiot.

    Also Alegbra invented here.


    Who's this Aleg chick? And what're you doin' inventin' underwear for her?


    Don't laf. There is such a thing as Feminist Algebra. Yes, it's moronic, but is a real-life kolluge kourse.


    Bleedinell. You ain't wrong:

    http://www.sydneyline.com/Gross%20and%20Levitt%20review.htm

    "There was actually a paper read at a 1993 meeting of the Mathematical Association of America entitled 'Toward a Feminist Algebra' by Maryanne Campbell (a literary critic) and Randall K. Campbell-Wright (a mathematician).

    Part of the paper was a call for an end to what it claimed were sexist stereotypes in college algebra textbooks. They disapproved of problems which used examples of a girl and her boyfriend running towards each other because this portrayed heterosexual involvement. On the other hand, they recommended approval of problems about Sue and Debbie, 'a couple financing their $70,000 home'. They wanted algebra problems to present female heroes, to analyse sex differences and to affirm women's experiences.

    Taking to heart the absurd shibboleth of contemporary literary theory that all language is metaphor, Campbell and Campbell-Wright set out to prove that metaphor plays a central role in the language of mathematics. They do not demonstrate this through the obviously rather difficult cases of symbolic statements and formulae. Instead they offer verbal examples culled from textbooks -- 'manipulate an algebraic expression', 'attack a problem', 'exploit a theorem' -- as evidence that mathematics is a nest of aggression, violence, domination and sexism.

    From this they derive postmodern literary dogma such as: 'Mathematics is portrayed as a woman whose nature desires to be the conquered Other.' They want the whole field of mathematics reappraised so that its imagined failings can be rectified and it can become a discipline fit for women to enter. Gross and Levitt, however, are more perceptive about their motives.

    'The purpose of the carefully tailored feminist language and imagery is not primarily to build the self-confidence of women students, but rather to convert problems and examples into parables of feminist rectitude. It is, at bottom, not different from an imaginary Christian fundamentalist pedagogy requiring that all mathematics problems illustrate biblical episodes and preach evangelical sermons.'

    ... and then I must point you towards this:

    http://stonetelling.com/issue1-sep2010/johnson-towards-a-feminist-algebra.html

    ... enjoy, you buggers.
  • Fred 2012-04-02 17:58
    Matt Westwood:
    ...(snip 2MiB)...

    a nest of aggression, violence, domination and sexism
    But that's what everybody wants! So what's their point?
  • CarnivorousHippie 2012-04-02 18:12
    the beholder:
    CarnivorousHippie:
    Tokenize on (IV, IX, I, XL, XC, X, CD, CM, C, M), map to (4, 9, 1, 40, 90, 10, 400, 900, 100, 1000), and sum.

    Actual code is left as an exercise for the reader.
    I really like your approach, but what's wrong with V, L and D?


    Ummm, oops.


    Public Function CalcRoman(strRN As String) As Long
    If Len(strRN) = 0 Then
    CalcRoman = 0
    ElseIf InStr(1, "iv,ix,xl,xc,cd,cm", Left(strRN, 2)) > 0 Then
    CalcRoman = Split("4,9,40,90,400,900", ",")((InStr(1, "iv,ix,xl,xc,cd,cm", Left(strRN, 2)) - 1) / 3) _
    + CalcRoman(Mid(strRN, 3))
    Else
    CalcRoman = Split("1,5,10,50,100,500,1000", ",")(InStr(1, "ivxlcdm", Left(strRN, 1)) - 1) _
    + CalcRoman(Mid(strRN, 2))
    End If
    End Function


    No error checking and lots of WTFery, but that's the general idea.
  • Eric 2012-04-02 18:22
    Probably not "the" way to do it in c#, but it works...
    [code]
    private enum RomanNumerals
    {
    I = 1, V = 5, X = 10, L = 50, C = 100, M = 1000
    }

    private int ConvertRomanToNumeric(string RomanNumeral)
    {
    // MCMLXXIIX = 1978

    List<char> Numerals = RomanNumeral.ToList<char>();

    int ConvertedNumber = 0;
    int currentNumber = 0;
    int currentMax = 0;

    Numerals.Reverse();

    foreach (char Numeral in Numerals)
    {
    RomanNumerals num = (RomanNumerals)Enum.Parse(typeof(RomanNumerals), Numeral.ToString());
    currentNumber = (int)num;

    if (currentNumber >= currentMax)
    {
    ConvertedNumber += currentNumber;
    currentMax = currentNumber;
    }
    else
    {
    ConvertedNumber -= currentNumber;
    }
    }
    return ConvertedNumber;
    }
    [/code/
  • CarnivorousHippie 2012-04-02 18:23
    da Doctah:
    Somewhat serious followup: Give me a regex that will match only movie titles that end in Roman numerals. Take into account that sometimes there will be a secondary title, as in "Death Warriors IV: the Deaths Continue".

    I tried to do this a few years ago on IMDb to figure out what the highest numbered "sequel" was. Ran into the problem that "mi", "di", "xi" and others are actual words in some languages.


    Was this before or after In the Mix?
  • Alex 2012-04-02 18:29
    Just my one-liner:


    echo "MCMLXVII" | sed "s/IX/+9/g; s/IV/+4/g; s/I/+1/g; s/V/+5/g; s/XL/+40/g; s/XC/+40/g; s/X/+10/g; s/L/+50/g; s/CD/+400/g; s/CM/+900/g; s/C/+100/g; s/M/+1000/g; s/^/echo $\[ /; s/$/ ] /" | bash


    captcha: saluto. I saluto to this code.
  • CXIIX 2012-04-02 18:57
    http://lmgtfy.com/?q=roman+numeral+converter
  • briverymouse 2012-04-02 19:10
    Brendan:
    Meep:
    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case letter of { 'I' -> 1; 'V' -> 5; ... } | letter <- roman ] ]


    That's about 25 lines of code (including the comments that are necessary to make Haskell readable). It would've been less typing in something like COBOL (and probably faster too, as there's no need to depend on the misuse of recursion)!


    I hope you're trolling. It's one line, not 25. The fact that you would need 24 lines of comments to understand one line of code, says nothing about Haskell, and everything about you. I only read the line of code, not the rest of his post, and I understand perfectly what it does, and how. (It's quite succinct and clever by the way, kudos Meep.) So either I am much smarter than you, or you have never read one book on Haskell, and for some reason find it strange that this implies you don't understand the language. Probably both.

    You clearly don't even understand how a processor works. There is no direct recursion in his code, but some of the library functions he uses are implemented as tail recursive functions. Modern compilers (you know, like the one used to compile Haskell, but also most modern C compilers) will output the exact same processor instructions for a tail-recursive function as a C compiler would for a while loop.
  • havokk 2012-04-02 19:40
    Yoh:
    That code in question did in fact fail on IX though. As will most of the examples people have shared.

    Do they fail on VIIII or MIM?
  • Yoh 2012-04-02 20:02
    They wouldn't fail PROPERLY on VIIII, as that is not a valid roman numeral.

    http://mathworld.wolfram.com/RomanNumerals.html
    http://chart.copyrightdata.com/ch02.html
  • NPSF3000 2012-04-02 23:42
    Meep:
    PedanticCurmudgeon:
    Peyote `Simon` Joints:
    One line in Haskell.
    I think you're bluffing. Code or it didn't happen.


    rom 'I' = 1
    rom 'V' = 5
    rom 'X' = 10
    ...

    All of which can be translated into a single case statement, rom x = case x of { 'I' -> 1; 'V' -> 5; 'X' -> 10 ... }

    Since a string is simply a list of characters:

    raw_decode nums = map rom nums

    Or as a comprehension: raw_decode nums = [ rom num | num <- nums ]

    So raw_decode "IXX" yields [1, 10, 10]

    Next we want to group up all the IX type cases. Our numerals should always be in descending order, except for those cases, so we can simply group using the < operator.

    rollup_prefixes raw = groupBy (<) raw

    That gives us a list of lists that may be one or two elements long, by our invariants.

    sub_prefix [ num ] = num
    sub_prefix [ pre num ] = num - pre

    Or as a case statement:

    sub_prefix roll = case roll of { [ num ] -> num; [ pre num ] -> num - pre; }

    And we then map that out:

    sub_prefixes rolled_up = map sub_prefix rolled_up

    Then we simply sum the result:

    final subbed = sum subbed

    Put it all together:

    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case num of { 'I' -> 1; 'V' -> 2; ... } | letter <- roman ] ]


    You know, I wish I used a language that allowed us to put pointlessly long lines together in the name of stupidity.

    Oh wait... I do:

    (from fluff in " " let n = (from c in Console.ReadLine().ToUpper() where "IVXLCDM".Contains(c) select c == 'I' ? 1 : c == 'V' ? 5 : c == 'X' ? 10 : c == 'L' ? 50 : c == 'C' ? 100 : c == 'D' ? 500 : 1000).ToList() let r = from i in Enumerable.Range(0, n.Count) let l = i > 0 && n[i] > n[i - 1] ? -n[i - 1] * 2 : 0 select n[i] + l select r.Sum()).ToList().ForEach(Console.WriteLine);


    With some spacing, for mere mortals:

    http://pastebin.com/usUTLr42

  • Maurits 2012-04-03 00:07
    Yoh:
    They wouldn't fail PROPERLY on VIIII, as that is not a valid roman numeral.

    http://mathworld.wolfram.com/RomanNumerals.html
    http://chart.copyrightdata.com/ch02.html


    From your first link:

    "the practice of placing smaller digits before large ones to indicate subtraction of value was hardly ever used by Romans and came into popularity in Europe after the invention of the printing press"

    So VIIII is a perfectly valid Roman numeral, though the canonical form is probably IX (VIV is definitely incorrect though.)

    It might be worth pointing out though IL is ambiguously 49, the more usually seen way to write that is XLIX. The general rule is that you would only write subtraction BA if B was a power of ten (I, X, C) and A was either 5 * B or 10 * B.
  • Dave 2012-04-03 00:15
    Peyote `Simon` Joints:
    One line in Haskell.


    Yawn. I can do it in one statement in Intercal:

    READ OUT ,1

    (possibly 2 if you need to add a PLEASE before it, and depending on whether you interpret the PLEASE as a separate statement or not).
  • da Doctah 2012-04-03 02:37
    CarnivorousHippie:
    da Doctah:
    Somewhat serious followup: Give me a regex that will match only movie titles that end in Roman numerals. Take into account that sometimes there will be a secondary title, as in "Death Warriors IV: the Deaths Continue".

    I tried to do this a few years ago on IMDb to figure out what the highest numbered "sequel" was. Ran into the problem that "mi", "di", "xi" and others are actual words in some languages.


    Was this before or after In the Mix?


    Before, but there's probably some old western starring Tom Mix that would produce another false hit.
  • Gurth 2012-04-03 02:39
    PiisAWheeL:
    KattMan:
    CD/CXXVII = PI
    I. P is not a roman numeral.

    Better notation would have been CD ÷ CXXVII = π, yes. However:

    PiisAWheeL:
    II. Roman numerals didn't have decimal points.

    Who says they need to? If you work with traditional fractions, you don't need decimal points (or commas, or whatever). CD ÷ CXXVII is a close enough approximation of the value of π for day to day use.
  • Karl 2012-04-03 02:48
    Sorry, dude. That is Python.
  • TheJonB 2012-04-03 04:18
    Ol' Bob:
    Nagesh:
    Nagesh (fake):
    Roman numeral system is being flawed system. The West can be thanking Indian for invention of modurn numerals.


    Fake nagesh has stole words from my key-board. It is "modern numbers", you idiot.

    Also Alegbra invented here.


    Who's this Aleg chick? And what're you doin' inventin' underwear for her?


    Eee ya plonker. Alegbra is for people with saggy legs.
  • Sarcastic kebab reaper 2012-04-03 05:28
    briverymouse:
    Brendan:
    Meep:
    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case letter of { 'I' -> 1; 'V' -> 5; ... } | letter <- roman ] ]


    That's about 25 lines of code (including the comments that are necessary to make Haskell readable). It would've been less typing in something like COBOL (and probably faster too, as there's no need to depend on the misuse of recursion)!


    I hope you're trolling. It's one line, not 25. The fact that you would need 24 lines of comments to understand one line of code, says nothing about Haskell, and everything about you. I only read the line of code, not the rest of his post, and I understand perfectly what it does, and how. (It's quite succinct and clever by the way, kudos Meep.) So either I am much smarter than you, or you have never read one book on Haskell, and for some reason find it strange that this implies you don't understand the language. Probably both.

    You clearly don't even understand how a processor works. There is no direct recursion in his code, but some of the library functions he uses are implemented as tail recursive functions. Modern compilers (you know, like the one used to compile Haskell, but also most modern C compilers) will output the exact same processor instructions for a tail-recursive function as a C compiler would for a while loop.

    I hope you are trolling. There's nothing like a complicated "one liner" that's mostly unreadable and uncommented.
    You clearly aren't a coder, and if you are, you aren't a good coder. You don't give two thoughts to the fact that the maintainability of code has become so important that there are huge books about how to write a readable code. Oh wait, whole languages have been invented with readability and maintainability in mind.
    And yet you will write your "one liner" (which doesn't count as one, having several consecutive instructions slapped together and pretending to be just one) and no comments.
  • Brendan 2012-04-03 06:27
    [quote user="briverymouse"][quote user="Brendan"]That's about 25 lines of code (including the comments that are necessary to make Haskell readable). It would've been less typing in something like COBOL (and probably faster too, as there's no need to depend on the misuse of recursion)![/quote]

    I hope you're trolling. It's one line, not 25. The fact that you would need 24 lines of comments to understand one line of code, says nothing about Haskell, and everything about you. I only read the line of code, not the rest of his post, and I understand perfectly what it does, and how. (It's quite succinct and clever by the way, kudos Meep.) So either I am much smarter than you, or you have never read one book on Haskell, and for some reason find it strange that this implies you don't understand the language. Probably both.

    To be honest, it was a mixture of trolling and joking. However, they say behind every joke there's an element of truth, and obviously this element of truth has made you react in the way you have.

    I've never learnt Pascal, or COBOL, or Objective C, or MIPS assembly; but have no trouble reading code written in any of these (and many other) languages. Some languages are so good that a person with no programming experience at all can get a good idea of what the code is doing. Some languages are so bad that even after learning the language you can't easily follow source code written in it. Are you suggesting that reading a book on Haskell is a necessary step just to understand Haskell source code? If so, what does that tell you about Haskell?

    [quote user="briverymouse"]You clearly don't even understand how a processor works. There is no direct recursion in his code, but some of the library functions he uses are implemented as tail recursive functions. Modern compilers (you know, like the one used to compile Haskell, but also most modern C compilers) will output the exact same processor instructions for a tail-recursive function as a C compiler would for a while loop.[/quote]

    The best way to tell what the compiler generates is to have a look at what the compiler generates. Either post a disassembly so I can laugh at it, or use silence to admit defeat.
  • scoeri 2012-04-03 08:40
    code obfuscation for the win

    here is a ruby version:

    $h = { "I" => 1, "V" => 5, "X" => 10, "L" => 50, "C" => 100, "D" => 500, "M" => 1000 }

    def r2d(r, p=0);r.empty? ? 0 : r2d(r[0..-2], v=$h[r[-1]]) + (v < p ? -v : v);end
  • KattMan 2012-04-03 09:26
    Matt Westwood:
    From this they derive postmodern literary dogma such as: 'Mathematics is portrayed as a woman whose nature desires to be the conquered Other.'


    And here I thought most natural women desired to be the conquered other.
    Take the terms we use in every day society, "A man takes a wife", "A woman gives herself to her man." On top of that look at the desire for women to be attractive, to display themselves to attract a good mate.
    It seems biologically wired that women should be seen this way, but not as weak, one can conquer and take a strong woman, and trust me if she remain strong even when she is yours it is so much better.
    :)
  • PedanticCurmudgeon 2012-04-03 09:30
    Brendan:
    Some languages are so good that a person with no programming experience at all can get a good idea of what the code is doing. Some languages are so bad that even after learning the language you can't easily follow source code written in it. Are you suggesting that reading a book on Haskell is a necessary step just to understand Haskell source code? If so, what does that tell you about Haskell?
    I was just about to post something to this effect as a joke. The worst part is that so many programmers actually take this position seriously.
  • Anon 2012-04-03 09:53
    Alex:
    Just my one-liner:


    echo "MCMLXVII" | sed "s/IX/+9/g; s/IV/+4/g; s/I/+1/g; s/V/+5/g; s/XL/+40/g; s/XC/+40/g; s/X/+10/g; s/L/+50/g; s/CD/+400/g; s/CM/+900/g; s/C/+100/g; s/M/+1000/g; s/^/echo $\[ /; s/$/ ] /" | bash



    Some people look at a problem and think "I know, I'll use regular expressions." Now they have II problems.
  • frits 2012-04-03 09:53
    PedanticCurmudgeon:
    Brendan:
    Some languages are so good that a person with no programming experience at all can get a good idea of what the code is doing. Some languages are so bad that even after learning the language you can't easily follow source code written in it. Are you suggesting that reading a book on Haskell is a necessary step just to understand Haskell source code? If so, what does that tell you about Haskell?
    I was just about to post something to this effect as a joke. The worst part is that so many programmers actually take this position seriously.
    Hey, the same argument can be applied to French, and everybody knows French is stupide.
  • the beholder 2012-04-03 09:54
    Zylon:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.

    Uh, yeah. Nobody's commented on this because it's implicitly stated right in the article:

    //
    // Snipped LOTS of "code" here
    //

    This is, in fact, the entire focus of the WTFery of his solution.
    You clearly didn't understand what I meant. Yes, it's lenghty, but what I really pointed out is the TYPING of roman numbers. It's by far worse than "ha-ha, this guy have typed two thousand consecutive numbers".

    With roman numbers you don't just copy last line, hit backspace and add a char one position higher than the one you erased. If it were that simple it could be done on an "auto-pilot" mode (albeit it would still be a minor WTF)

    So, how does your foot taste?
  • Zunesize Me! 2012-04-03 10:05
    KattMan:
    Matt Westwood:
    From this they derive postmodern literary dogma such as: 'Mathematics is portrayed as a woman whose nature desires to be the conquered Other.'
    And here I thought most natural women desired to be the conquered other.
    Take the terms we use in every day society, "A man takes a wife", "A woman gives herself to her man." On top of that look at the desire for women to be attractive, to display themselves to attract a good mate.
    It seems biologically wired that women should be seen this way, but not as weak, one can conquer and take a strong woman, and trust me if she remain strong even when she is yours it is so much better.
    :)
    I'm not sure where I stand with respect to female dominance/submissiveness, but what I do know is the kind I like are the kind with penises.
  • Zunesize Me! 2012-04-03 10:07
    the beholder:
    Zylon:
    the beholder:
    Nobody commented yet, but this new-hire MUST have typed Every. Single. Number. In roman numbers.
    This is, in fact, the entire focus of the WTFery of his solution.
    You clearly didn't understand what I meant... ...So, how does your foot taste?
    Joke's on you, pal! I regularly taste my own feet, anyway! So there!
  • Qŭert 2012-04-03 10:32
    radarbob:
    Don't laf.

    That awkward moment when a misspelling makes more sense than the "correct" spelling.

    Captcha: commoveo => Con los ojos.
  • briverymouse 2012-04-03 11:00
    Sarcastic kebab reaper:
    briverymouse:
    Brendan:
    Meep:
    rom2num roman = sum [ case roll of { [ num ] -> num; [ pre num ] -> num - pre; } | roll <-
    groupBy (<) [ case letter of { 'I' -> 1; 'V' -> 5; ... } | letter <- roman ] ]


    That's about 25 lines of code (including the comments that are necessary to make Haskell readable). It would've been less typing in something like COBOL (and probably faster too, as there's no need to depend on the misuse of recursion)!


    I hope you're trolling. It's one line, not 25. ...


    I hope you are trolling. There's nothing like a complicated "one liner" that's mostly unreadable and uncommented.
    You clearly aren't a coder, and if you are, you aren't a good coder. You don't give two thoughts to the fact that the maintainability of code has become so important that there are huge books about how to write a readable code. Oh wait, whole languages have been invented with readability and maintainability in mind.
    And yet you will write your "one liner" (which doesn't count as one, having several consecutive instructions slapped together and pretending to be just one) and no comments.


    I never said it was good production code. It obviously isn't. Nesting two list comprehensions is something I would probably never do. This is roughly what I would write in practice (based on Meep's code): http://pastebin.com/7KK7r8jW (I added error handling, as this is supposed to be production code.) As you can see, only ten lines, of which two are imports that you probably already have in any serious application, one is a blank line, and one is a type annotation that's only added for clarity.

    Still, Meep's code is very readable considering it's a one-liner, and every person that actually knows Haskell needs less than a few seconds to see what it does. And it is a one-liner: adding a line break anywhere in there would feel unnatural. I'm not sure what you mean by instruction, as there's no such thing in Haskell, but you probably mean the semicolons. They are part of the case statement, and could indeed be replaced by newlines, but having a small case statement like that on one line is not always considered bad style.
  • Jay 2012-04-03 11:06
    What the hell, have some old school VB:

    Public Function Rom2Dec(Roman As String) As Long
    

    Dim Letter As String
    Dim Result As Long
    Dim MaxValue As Long
    Dim Position As Long

    Result = 0
    MaxValue = 0

    For Position = Len(Roman) To 1 Step -1
    Letter = Mid$(Roman, Position, 1)
    Value = Switch(Letter = "I", 1, Letter = "V", 5, Letter = "X", 10, Letter = "L", 50, Letter = "C", 100, Letter = "D", 500, Letter = "M", 1000)
    If Value < MaxValue Then
    Result = Result - Value
    Else
    Result = Result + Value
    MaxValue = Value
    End If
    Next Position

    Rom2Dec = Result

    End Function


    Deals with all the weird stuff like IIIIX, CCCCCCCCCCCCCCCCCCCIC etc, who knew 1999 can be written as MCMXCIX, MLMVLIV, MXMIX, MVMIV & MIM.
  • markfiend 2012-04-03 11:19
    iToad:
    There was actually a serious (maybe) proposal to add Roman numerals to Python, but it got rejected:

    PEP 313

    Too bad. I wanted to see whether I could calculate the square root of pi, using only Roman Numerals.

    Check the "Created" date on PEP 313...
  • Maurits 2012-04-03 11:31
    Jay:
    who knew 1999 can be written as MCMXCIX, MLMVLIV, MXMIX, MVMIV & MIM.


    MCMXCIX: yes.
    MLMVLIV: no, VL doesn't work because V is not a power of 10.
    MXMIX: no, XM doesn't work because M > 10 * X
    MVMIV: no, VM doesn't work because V is not a power of 10 and M > 10 * V
    MIM: no, IM doesn't work because M > 10 * I

    You could also write it as MDCCCCLXXXXVIIII which is how the Romans would have written it.
  • Rick 2012-04-03 12:24
    ObiWayneKenobi:
    ... There are sophisticated error handling in modern languages, you don't need to return ints or bools all over the place.
    There doesn't appear to be any exception handling in the most modern of all computer languages, Google's Go1.
    s/modern/good/
  • Jay 2012-04-03 12:26
    Maurits:
    Jay:
    who knew 1999 can be written as MCMXCIX, MLMVLIV, MXMIX, MVMIV & MIM.


    MCMXCIX: yes.
    MLMVLIV: no, VL doesn't work because V is not a power of 10.
    MXMIX: no, XM doesn't work because M > 10 * X
    MVMIV: no, VM doesn't work because V is not a power of 10 and M > 10 * V
    MIM: no, IM doesn't work because M > 10 * I

    You could also write it as MDCCCCLXXXXVIIII which is how the Romans would have written it.


    Since there aren't any rules for Roman numbers (citation needed & all that), all those variations are equally valid.

    Those variations are from Excel; for whatever reason it gives you the option of specifying how long-winded you want to be.
  • briverymouse 2012-04-03 12:29
    Brendan:
    Are you suggesting that reading a book on Haskell is a necessary step just to understand Haskell source code?

    Definitely.

    Brendan:
    If so, what does that tell you about Haskell?

    Let's take two ways to write a sum of a list of ten numbers (disregarding the existence of the sum function):

    Haskell:
    foldl1 (+) [1 .. 10]

    Python:
    sum = 0
    
    for a in range(1, 11):
    sum += a


    Which one would you most easily understand? Obviously the Python one. Which one would you most easily understand once you know what foldl1 does? Obviously the Haskell one: it's all there on one line, it folds 1 to 10 using addition. Choose the right tool for the job: if you want your code to be understood by non-programmers, by all means use a language that's easy to read for non-programmers. If you want your code to be easily understood by programmers, use a language like Haskell.

    Brendan:
    The best way to tell what the compiler generates is to have a look at what the compiler generates. Either post a disassembly so I can laugh at it, or use silence to admit defeat.

    http://pastebin.com/2miyJFji
  • I live in hell 2012-04-03 12:50
    Since we don't have a new WTF (yet?) today, I thought I'd share one.

    I sat down to dial in to my daily conference call this morning. You know, the one where 18 highly paid people waste an hour each listening while three people discuss the project's lack of progress? I don't typically say more than one sentence a week but there's no cost to the meeting organizer to invite everyone who might slightly be needed so they blast the world. And in our organization the culture is that you just can't decline a meeting invite without a pretty good reason, like being dead.

    So we spend five minutes waiting for the moderator, then having everyone connect and introduce themselves, and we're almost ready to get down to real not-work when the call suddenly hangs up on everyone. What to do, what to do? Start over of course.

    So five minutes later everyone is kicked off again.

    This happens a couple more times before we figure out that maybe we can live through the day without this call. You think?

    Later the word comes back: the problem was we exceeded our license for 120 simultaneous conference calls.

    WTF#1: Spending 5 hours a week waiting for that one moment to answer a question that could be done in 30 seconds by email.

    WTF#2: Multiplying WTF#1 by 18 highly paid people.

    WTF#3: Multiplying WtF#2 by 120 simultaneous calls. Even if we average only 3 people per call, that's 360 people in our organization all discussing at the same time why nobody is getting anything done. And that's this hour. Start over next hour?

    WTF#4: Could there possibly be a less graceful way to handle the error condition "you haven't paid us enough money to do that"?

    WTF#5: Me, I guess, for trying to tolerate all this.
  • Jay 2012-04-03 12:58
    Cap'n Spanky:
    Roman Enumeration:
    PedanticCurmudgeon:
    iToad:
    Mere mortals such as us are simply not qualified to tell the difference between god-mode Haskell and WTF Haskell.
    Some would say that there is no difference.
    The average Haskell WTF is something about a guy who, during an interview, forgot to make his Monad an Applicative. Can you imagine such foolishness? Also, missing a perfectly good opportunity to use a zipWith or a liftM is cause for certain derision.

    I heard that Hitler was a monad.


    Really? Hitler wandered around the wilderness tending sheep?
  • Jay 2012-04-03 13:01
    da Doctah:
    Somewhat serious followup: Give me a regex that will match only movie titles that end in Roman numerals. Take into account that sometimes there will be a secondary title, as in "Death Warriors IV: the Deaths Continue".

    I tried to do this a few years ago on IMDb to figure out what the highest numbered "sequel" was. Ran into the problem that "mi", "di", "xi" and others are actual words in some languages.


    Did you hear they made a sequel to "Malcolm X"? It is, of course, called "Malcom XI".
  • Jay 2012-04-03 13:13
    Matt Westwood:
    Instead they offer verbal examples culled from textbooks -- 'manipulate an algebraic expression', 'attack a problem', 'exploit a theorem' -- as evidence that mathematics is a nest of aggression, violence, domination and sexism. ... From this they derive postmodern literary dogma such as: 'Mathematics is portrayed as a woman whose nature desires to be the conquered Other.'


    Can we include this text in the description of Algebra II in our course catalog? I think it could really boost enrollment.
  • frits 2012-04-03 13:23
    Jay:
    Matt Westwood:
    Instead they offer verbal examples culled from textbooks -- 'manipulate an algebraic expression', 'attack a problem', 'exploit a theorem' -- as evidence that mathematics is a nest of aggression, violence, domination and sexism. ... From this they derive postmodern literary dogma such as: 'Mathematics is portrayed as a woman whose nature desires to be the conquered Other.'


    Can we include this text in the description of Algebra II in our course catalog? I think it could really boost enrollment.
    Sure. Let's just get rid of all the women.
  • frits 2012-04-03 13:24
    What this thread really needs is a code competition...
  • Jay 2012-04-03 13:37
    Side note: Roman numerals do have one obvious advantage: Addition is easy. At least, if you use "old style" Roman numerals where you don't do that "if the next symbol is higher subtract" stuff, so you write 4 as "IIII", etc.

    To add two numbers, just ram the two together and replace any counts that now "carry" with the higher digit, like 5 I's with a V. Sort them if you like, but it doesn't really matter.

    For example: LXVII + XXIII. LVXIIXXIII. IIIII=V so LVXVXX. VV = X so LXXXX. Done. It's probably easier for children to learn.

    Multiplication isn't that tough either. The "times table" is shorter as you only have to deal with 7 symbols -- I, V, X, L, C, D, and M -- instead of 10. I * I = I, I * V = V, ... V * V = XXV, V * X = L, ... X * V = L, X * X = C, X * L = D, ...

    Multiply each digit of one number by each digit of the other. Ram them all together. Then do the "carries". E.g. LXVII * XXIII = DCLXX DCLXX LXVII LXVII LXVII. The first two groups are when we multiply each digit by X, which we must do twice because there are two X's. The other three groups are when we multiply each digit by I, which we do 3 times. Then simplify:

    DCLXX DCLXX LXVII LXVII LXVII
    IIIII=V: DCLXX DCLXX LXVV LXV LXVI
    VV=X: DCLXX DCLXX LXX LXX LXI
    XXXXX=L: DCLL DCL LX LXX LXI
    LL=C: DCC DCC X CXX XI
    CCCCC=D: DD D X XX XI
    DD=M: MDXXXXI

    Of course a Roman would have done several roll-ups in each pass, maybe all in one pass if he was "good at arithmetic".

    I suspect that with some practice, it's easier to do addition, subtraction, and multiplication with Roman numerals than with Hindu-Arabic numerals.

    Division was probably tough. Of course writing arbitrarily large numbers, working with decimal places, and many other functions are more difficult. I'm not suggesting we use Roman numerals. But they're not totally dumb.
  • Jay 2012-04-03 13:41
    Anon:
    Jay:

    Anon: That's impossible.


    Nobody said it was impossible. Do you always put words in other people's mouths so you can argue with them?


    You said, "The real WTF is ..." What did that mean other than, "The problem is unsolvable"?

    If you simply meant, "The problem is inadequately defined", well, nobody said that the one sentence given in the article was the complete description or that the employee was not allowed to ask questions.
  • Nagesh 2012-04-03 14:04
    Nobody notice that this code can only go up to 2011. Did program candidate think world going to end after that or did he think nobody is going to remember Roman Number greater than 2011?

    I would like to know his think process.
  • Brendan 2012-04-03 14:28
    briverymouse:
    Let's take two ways to write a sum of a list of ten numbers (disregarding the existence of the sum function):

    Haskell:
    foldl1 (+) [1 .. 10]

    Python:
    sum = 0
    
    for a in range(1, 11):
    sum += a


    Which one would you most easily understand? Obviously the Python one.


    Agreed.

    briverymouse:
    Which one would you most easily understand once you know what foldl1 does? Obviously the Haskell one: it's all there on one line, it folds 1 to 10 using addition.


    Wrong. The most natural solution to the problem is a loop ("foreach"). Ask someone who's never programmed anything before how they would do it and I can guarantee their answer won't involve recursion. Once you know what fold1 does it's "clever".

    Note: I use "clever" in a derogatory way. It's like a man who sets up a system of pulleys and levers to push buttons on his remote control just so he can feel superior to everyone else, without realising everyone else thinks he's a moron for not shifting the remote control closer.

    This is the essential problem with Haskell - often the most natural solution isn't suitable in Haskell. You have to spend ages learning how to think "clever" before your mind is so screwed up that unnatural solutions seem acceptable; and only "clever" people are stupid enough to think that is a good idea.

    briverymouse:
    Choose the right tool for the job: if you want your code to be understood by non-programmers, by all means use a language that's easy to read for non-programmers. If you want your code to be easily understood by programmers, use a language like Haskell.


    The right tool for the job is the tool that allows you to express the most natural solution (and get good performance from that). Haskell is the right tool for doing research into compiler optimisations, and is almost never the right tool for any actual programming.

    briverymouse:
    Brendan:
    The best way to tell what the compiler generates is to have a look at what the compiler generates. Either post a disassembly so I can laugh at it, or use silence to admit defeat.

    http://pastebin.com/2miyJFji


    That isn't the piece of code we're talking about. It isn't even Haskell code. You've attempted to prove that apples are yellow and mushy by squashing a banana.
  • PedanticCurmudgeon 2012-04-03 14:52
    Brendan:
    briverymouse:
    Let's take two ways to write a sum of a list of ten numbers (disregarding the existence of the sum function):

    Haskell:
    foldl1 (+) [1 .. 10]

    Python:
    sum = 0
    
    for a in range(1, 11):
    sum += a


    Which one would you most easily understand? Obviously the Python one.


    Agreed.
    Amateur. Professional-level trolls know that the ideal language for comprehension by non-programmers is COBOL.
  • briverymouse 2012-04-03 16:00
    Brendan:
    Wrong. The most natural solution to the problem is a loop ("foreach"). Ask someone who's never programmed anything before how they would do it and I can guarantee their answer won't involve recursion. Once you know what fold1 does it's "clever".

    What do you think foldl1 does? It loops over a list from the left, combining the results using the provided function. It's a more specific kind of loop. The fact that it's implemented internally using recursion is completely irrelevant. Externally, it just behaves like a loop with all the plumbing code removed. You see foldl1, (+) and a list, and you know what it does, without having to read 3 lines of code to see what exactly this particular for loop is meant to accomplish.

    Ask someone who's never programmed anything before how they would do it and I can guarantee their answer won't involve a foreach loop either. They will probably say something like "add the first two, then add the next to it, and so on until the end", which is literally what foldl1 does, and not "make a temporary variable, set it to zero, then take every value from the list and add it to the temporary variable". That would be foldl by the way, which also exists.

    briverymouse:
    Brendan:
    The best way to tell what the compiler generates is to have a look at what the compiler generates. Either post a disassembly so I can laugh at it, or use silence to admit defeat.

    http://pastebin.com/2miyJFji


    That isn't the piece of code we're talking about. It isn't even Haskell code. You've attempted to prove that apples are yellow and mushy by squashing a banana.

    What I said was:
    Modern compilers (you know, like the one used to compile Haskell, but also most modern C compilers) will output the exact same processor instructions for a tail-recursive function as a C compiler would for a while loop.

    You asked me to prove it, and I did. What else do you want me to show? I can't show you that Haskell produces the same bytecode as C, because it obviously doesn't: Haskell has an entirely different execution model (lazy evaluation). And I will immediately admit that this sometimes slows Haskell programs down a bit. That's not what you were claiming though, according to you, Haskell's use of recursion slows it down. That's just bullshit.
  • KattMan 2012-04-03 16:19
    briverymouse:
    Brendan:
    Wrong. The most natural solution ...blah blah blah

    What do you think foldl1 does? It loops over ... blah blah blah

    That isn't the piece of code we're talking about. It isn't even ...blah blah blah

    You asked me to prove it, and I did. What else ... blah blah blah


    I love you guys and this forum!
  • Maurits 2012-04-03 16:56
    Jay:
    Since there aren't any rules for Roman numbers (citation needed & all that), all those variations are equally valid.

    I agree that there is no universally accepted set of rules, and the Romans themselves seen to have been pretty lax about these kinds of things. (Medieval folk didn't tend to spell works the same way all the time, either.)

    But part of implementing a feature is settling on a spec. I am proposing that the following set of rules from Wikipedia be adopted when converting Arabic to Roman. The advantage of this set of rules is that the resulting output is unique. (A different, more all-encompassing set of rules could be applied to converting Roman to Arabic; or the same strict set of rules could be used, depending on the scenario.)

    http://en.wikipedia.org/wiki/Roman_numerals
    The symbols "I", "X", "C", and "M" can be repeated three times in succession, but no more. (They may appear more than three times if they appear non-sequentially, such as XXXIX.) "D", "L", and "V" can never be repeated.
    "I" can be subtracted from "V" and "X" only. "X" can be subtracted from "L" and "C" only. "C" can be subtracted from "D" and "M" only. "V", "L", and "D" can never be subtracted
    Only one small-value symbol may be subtracted from any large-value symbol.
  • Nagesh 2012-04-03 17:10
    Computer science should being more concurned with conversion of Arabian Numerals (but invention in India) -> to binary.
  • Franz Kafka 2012-04-03 17:14
    CarnivorousHippie:
    da Doctah:
    Somewhat serious followup: Give me a regex that will match only movie titles that end in Roman numerals. Take into account that sometimes there will be a secondary title, as in "Death Warriors IV: the Deaths Continue".

    I tried to do this a few years ago on IMDb to figure out what the highest numbered "sequel" was. Ran into the problem that "mi", "di", "xi" and others are actual words in some languages.


    Was this before or after In the Mix?


    simple solution: use a loose regex to get all the sequels, then eliminate entries where prior sequels aren't present - 'In the MVIII' isn't there so 'In the Mix' isn't a sequel.
  • apoc9 2012-04-03 17:18
    Java implementation, only valid roman numerals, throws stadnard exception, single function. It is not so trivial, because the rules for valid numerals.
    public static int decodeRomanNumeral(String numeral) {
    
    int result = 0;
    if (!numeral.matches("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$")) {
    throw new NumberFormatException("For input string: \"" + numeral + '"');
    }
    char[] chars = numeral.toCharArray();
    int p = 0;
    for (int i = chars.length - 1; i >= 0; i--) {
    int ch = 0;
    switch (chars[i]) {
    case 'I':
    ch = 1;
    break;
    case 'V':
    ch = 5;
    break;
    case 'X':
    ch = 10;
    break;
    case 'L':
    ch = 50;
    break;
    case 'C':
    ch = 100;
    break;
    case 'D':
    ch = 500;
    break;
    case 'M':
    ch = 1000;
    break;
    default:
    throw new NumberFormatException("For input string: \"" + numeral + '"');
    }
    if (ch >= p) {
    p = ch;
    result += ch;
    } else {
    result -= ch;
    }
    }
    return result;
    }
  • Remy Martin 2012-04-03 17:32
    IMPORTANT ANNOUNCEMENT:

    Alex is in the hospital in an alcohol-poisoning-induced coma. He did not leave me with the access codes, so I cannot post a new article. I encourage you to try the "Random Article" link, or to post a few more implementations of the Roman Numeral conversion libraries in whatever esotaric language you would like.
  • Captain WTF 2012-04-03 17:39
    And you call yourselves WTFers ...

    You're all reinventing the wheel. Not only is this wheel square it's made out of balsa wood!


    package com.thedailywtf;

    public class RomanNumbers {
    private String number;

    public RomanNumbers() {
    setNumber(null);
    }

    public RomanNumbers(String number) {
    setNumber(number);
    }

    public int toArabic() {
    StringBuffer urlString = new StringBuffer();
    urlString.append("http://www.google.com/search?q=");
    urlString.append(this.number);
    urlString.append("+in+decimal");

    try {
    java.net.URL url = new java.net.URL(urlString.toString());
    java.net.URLConnection urlConnection = url.openConnection();
    urlConnection.setRequestProperty("User-agent",
    "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0");

    java.io.BufferedInputStream bis = new java.io.BufferedInputStream(urlConnection.getInputStream());

    StringBuffer googleHtml = new StringBuffer();
    byte[] googleBits = new byte[1024];
    int bitsRead = 0;
    while ((bitsRead = bis.read(googleBits)) > -1) {
    googleHtml.append(new String(googleBits, 0, bitsRead));
    }

    String myHtml = googleHtml.toString();

    int pos = myHtml.indexOf("<div id=\"topstuff\">");
    myHtml = myHtml.substring(pos);
    pos = myHtml.indexOf("<b>");
    int pos2 = myHtml.indexOf("</b>", pos);
    myHtml = myHtml.substring(pos, pos2);

    pos = myHtml.lastIndexOf(" = ");
    String answer = myHtml.substring(pos + 3).trim();

    return Integer.parseInt(answer);
    } catch (java.net.MalformedURLException e) {
    e.printStackTrace();
    return 0;
    } catch (java.io.IOException e) {
    e.printStackTrace();
    return 0;
    }
    }

    public String getNumber() {
    return this.number;
    }

    public void setNumber(String number) {
    if (number == null)
    this.number = null;
    else
    this.number = number.toUpperCase();
    }
    }
  • Pooh Bear 2012-04-03 17:42
    Remy Martin:
    IMPORTANT ANNOUNCEMENT:

    Alex is in the hospital in an alcohol-poisoning-induced coma. He did not leave me with the access codes, so I cannot post a new article. I encourage you to try the "Random Article" link, or to post a few more implementations of the Roman Numeral conversion libraries in whatever esotaric language you would like.

    Oh, dear.
  • Jack 2012-04-03 17:45
    Remy Martin (unregistered):
    IMPORTANT ANNOUNCEMENT:

    Alex is in the hospital in an alcohol-poisoning-induced coma. He did not leave me with the access codes, so I cannot post a new article. I encourage you to try the "Random Article" link, or to post a few more implementations of the Roman Numeral conversion libraries in whatever esotaric language you would like.
    Apparently he took your "real Remy Martin" password too. Or did the alcohol have something to do with that?
  • AGray 2012-04-03 17:46
    I shortened things up slightly, and for grins and giggles threw in my Reverse method.

        public class RomanToIndoArabic
    
    {
    private readonly Dictionary<char, int> _Romans = new Dictionary<char, int>
    {
    {'I', 1},
    {'V', 5},
    {'X', 10},
    {'L', 50},
    {'C', 100},
    {'M', 1000}
    };

    /// <summary>
    /// This method gets called right after the recording has been started.
    /// It can be used to execute recording specific initialization code.
    /// </summary>
    private void Init()
    {
    // 1978 indo-arabic...
    const string inNumber = "MCMLXXIIX";
    int number = ToArabic(inNumber);

    if(number == 1978)
    {
    Console.WriteLine("Success! " + inNumber + " converts to " + number);
    }
    else
    {
    Console.WriteLine("The conversion did not work....");
    }

    Console.ReadLine();
    }

    private int ToArabic(string inRoman)
    {
    int currentResult = 0;
    int maximum = 0;

    inRoman = Reverse(inRoman);
    foreach(char thisDigit in inRoman)
    {
    int currentValue = _Romans[thisDigit];
    if(currentValue < maximum)
    {
    currentResult -= currentValue;
    }
    else
    {
    currentResult += currentValue;
    maximum = currentValue;
    }
    }

    return currentResult;
    }

    private string Reverse(string inString)
    {
    StringBuilder result = new StringBuilder(inString.Length);
    for (int i = inString.Length - 1; i >= 0; i--)
    {
    result.Append(inString[i]);
    }

    Console.WriteLine(inString + " reversed is " + result);
    return result.ToString();
    }
    }
  • lipinger 2012-04-03 17:49
    Tokenize on (IV, IX, I, XL, XC, X, CD, CM, C, _D_, M), map to (4, 9, 1, 40, 90, 10, 400, 900, 100, _500_, 1000)... ?!
  • Matt Westwood 2012-04-03 17:57
    lipinger:
    Tokenize on (IV, IX, I, XL, XC, X, CD, CM, C, _D_, M), map to (4, 9, 1, 40, 90, 10, 400, 900, 100, _500_, 1000)... ?!


    Perfect. But what's the underscores for?
  • Silverhill 2012-04-03 17:57
    Gurth:
    CD ÷ CXXVII is a close enough approximation of the value of π for day to day use.
    Nah -- CCCLV ÷ CXIII is much better. :)


    Brendan:
    That isn't the piece of code we're talking about.
    You don't need to see our compile listing. Move along.
  • doodle 2012-04-03 18:14
    uberadmin@subdesk:~/kindergarden> expr $(sed 's/IV/4 + /ig; s/IX/9 + /ig; s/IL/49 + /ig; s/IC/99 + /ig; s/ID/499 + /ig; s/IM/999 + /ig; s/XC/90 + /ig; s/XD/490 + /ig; s/XM/990 + /ig; s/CD/500 + /ig; s/CM/900 + /ig; s/VI/6 + /ig; s/VII/7 + /ig; s/VIII/8 + /ig; s/I/1 + /ig; s/II/2 + /ig; s/III/3 + /ig; s/V/5 + /ig; s/X/10 + /ig; s/L/50 + /ig; s/C/100 + /ig; s/D/500 + /ig; s/M/1000 + /ig; s/$/0/;' <<<mcmlxxxix )
    1989
    uberadmin@subdesk:~/kindergarden> !
  • Kuba 2012-04-03 18:15
    Brendan:
    briverymouse:
    Which one would you most easily understand once you know what foldl1 does? Obviously the Haskell one: it's all there on one line, it folds 1 to 10 using addition.
    Wrong. The most natural solution to the problem is a loop ("foreach"). Ask someone who's never programmed anything before how they would do it and I can guarantee their answer won't involve recursion. Once you know what fold1 does it's "clever".
    This is thoroughly silly. Non-programmers or people with very little understanding of computer science often come up with algorithms and code that is bloated, hard to follow, and full of copypasta precisely because they don't know all the idioms and abstractions available to them. Such code lands on TDWTF, duh.

    If you know Haskell, functional constructs are natural. Just because many programming languages don't offer such constructs doesn't mean they are unnatural. The idea that someone who doesn't have proper training can write decent code is ridiculous on its face, as repeatedly demonstrated on this site. I don't know Haskell, but I know LISP, and I immediately knew what foldl must mean, even though LISP is not really a functional language at heart. But then I know more than a Joe Random Coder, perhaps.

    If you seriously think that lowest-level-of-abstraction code that only uses "natural" constructs from Algol is best for maintenance, you must have not ever seen how complex systems can benefit from high level abstractions available in the programming language used. I've seen both Caml and Erlang source that would grow at times by an order of magnitude if ported to any of the Algol-like languages.
  • diddle 2012-04-03 18:37
    root@box:~/tmp> expr $(sed 's/I\([VXLCDM]\)/-1 + \1/ig; s/V\([LCDM]\)/-5 + \1/ig; s/X\([LCDM]\)/-10 + \1/ig; s/L\([DM]\)/-50 + \1/ig; s/C\([DM]\)/-100 + \1/ig; s/I/1 + /ig; s/V/5 + /ig; s/X/10 + /ig; s/L/50 + /ig; s/C/100 + /ig; s/D/500 + /ig; s/M/1000 + /ig; s/$/0/' <<<mcmlxxxix )
    1989
    root@box:~/tmp>
  • dawdle 2012-04-03 18:52
    root@box:~/tmp> expr $(sed 's/I\([VXLCDM]\)/-1 + \1/ig; s/V\([LCDM]\)/-5 + \1/ig; s/X\([LCDM]\)/-10 + \1/ig; s/L\([DM]\)/-50 + \1/ig; s/C\([DM]\)/-100 + \1/ig; s/M/DD/ig; s/D/CCCCC/ig; s/C/LL/ig; s/L/XXXXX/ig; s/X/VV/ig; s/V/IIIII/ig; s/I/1 + /ig; s/$/0/' <<<mcmlxxxix )
    1989
    root@box:~/tmp>
  • daghdle 2012-04-03 19:11
    root@box:~/tmp> sed 's/M/DD/ig;s/CD/CCCC/ig;s/D/CCCCC/ig;s/LC/L/ig;s/C/LL/ig;s/XL/XXXX/ig;s/L/XXXXX/ig;s/VX/V/ig;s/X/VV/ig;s/IV/IIII/ig;s/V/IIIII/ig;s/I/I /ig' <<<mcmlxxxix | wc -w
    1989
    root@box:~/tmp>
  • dddl 2012-04-03 19:22
    root@box:~/tmp> tr /c-x/ /C-X/<<<mcmlxxxix|sed 's/M/DD/g;s/CD/CCCC/g;s/D/CCCCC/g;s/LC/L/g;s/C/LL/g;s/XL/XXXX/g;s/L/XXXXX/g;s/VX/V/g;s/X/VV/g;s/IV/IIII/g;s/V/IIIII/g;s/I$//g'|wc -m
    1989
    root@box:~/tmp>
  • Brendan 2012-04-03 19:23
    briverymouse:
    Brendan:
    Wrong. The most natural solution to the problem is a loop ("foreach"). Ask someone who's never programmed anything before how they would do it and I can guarantee their answer won't involve recursion. Once you know what fold1 does it's "clever".

    What do you think foldl1 does? It loops over a list from the left, combining the results using the provided function.


    In Haskell, "mapM_" is "foreach". Their "foldl1" is very different concept.

    For the list (1, 2, 3, 4) and the functions f(x) and g(x, y); "f(1); f(2); f(3); f(4);" is very different conceptually from "g(1, g(2, g(3, 4)));".

    Perhaps you need to read a book about Haskell?

    briverymouse:
    Ask someone who's never programmed anything before how they would do it and I can guarantee their answer won't involve a foreach loop either. They will probably say something like "add the first two, then add the next to it, and so on until the end", which is literally what foldl1 does, and not "make a temporary variable, set it to zero, then take every value from the list and add it to the temporary variable". That would be foldl by the way, which also exists.


    So you're saying that for the list (1, 2, 3, 4) a real person wouldn't do "3 + 4 = 5", then "2 + 5 = 7" then "1 + 7 = 8" to get the sum? You're saying that a real person would assume addition is an operator and not a function? You're saying a real person would do something like "temp = list.next(); while(list.hasNext) { temp += list.next(); }"?

    You're saying a real person wouldn't do anything like foldl1, but you thought they might because you don't know how foldl1 works?

    briverymouse:
    What I said was:


    What I said was "Haskell is poo because it forces people to use recursion". You replied with "modern compilers can do tailcall optimisation", completely missing the point that programmers still have to deal with the concept whether it makes sense for their problem or not (regardless of what the compiler generates). I played along and asked for a disassembly of the Haskell code we were talking about, with the intention of either showing that Haskell failed to use tail recursion to remove all of the recursion from it's own library functions or that the generated code is a huge bloated mess anyway, and you missed the point there too and showed C code where the compiler did do tail call optimisation. I restated my request for a disassembly of the Haskell code in question, and you've failed to produce it again.

    I'm not sure if, like me, you don't have Haskell installed on any of your computers and couldn't be bothered installing it (I couldn't blame you if that's the case), or if you're deliberately trying to avoid posting the disassembly because you're ashamed of it, or if you're honestly unable to follow the conversation.
  • Tud 2012-04-03 19:37
    mwchase:
    That's not Haskell, that's Python. It's using a language feature that I was previously unaware of, oops. ([value] if [condition] else [alternative])


    Here's another cool feature: lambda forms.


    r = {"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
    r2d = lambda m, p="I": 0 if m=="" else r2d(m[:-1],m[-1])+r[m[-1]]*(1 if r[m[-1]]>=r[p] else -1)


    This one's kinda cheating though, you're not supposed to make them recursive.

    Also, check out my cool C one-liner:

    public string rom2num(string r){if(r == "I") return "1"; if (r == "II") return "2"; if (r == "III") return "3"; if (r == "IV") return "4"; if (r == "V") return "5"; if (r == "VI") return "6"; /*...*/ if (r == "MMXI") return "2011"; return "E"; }
  • Brendan 2012-04-03 19:54
    Kuba:
    If you know Haskell, functional constructs are natural.


    For me (and I doubt I'm the only one here), inhaling toxic smoke seems natural. Does this mean inhaling toxic smoke actually is natural?

    After you know Haskell (or some other functional programming language) functional constructs may seem natural to you, but they won't seem natural before you get used to them, and won't seem natural to anyone else who hasn't become used to them.

    For an ideal language, you wouldn't have to get used to anything before it seems natural. There isn't a language that comes close to this (and I doubt there ever will be), but some are closer to this ideal than others.
  • briverymouse 2012-04-03 20:10
    Brendan:
    briverymouse:
    What do you think foldl1 does? It loops over a list from the left, combining the results using the provided function.


    In Haskell, "mapM_" is "foreach". Their "foldl1" is very different concept.

    For the list (1, 2, 3, 4) and the functions f(x) and g(x, y); "f(1); f(2); f(3); f(4);" is very different conceptually from "g(1, g(2, g(3, 4)));".

    Perhaps you need to read a book about Haskell?


    LOL, what? Did you look up "foreach in Haskell" on Google, read something about mapM_, and now think you're an expert on functional programming?

    This will probably go way over your head, but mapM_ maps a function returning a monad over a list, and returns a monad containing the empty tuple. It behaves roughly foreach-loop-like only for IO, and does something wildly different in e.g. the Maybe or list monad (fun exercise: see if you can find out what).

    foldl1 corresponds to the following foreach loop (pseudo-code):
    let accumulator = list[0]
    
    foreach element in list[1 ..]
    accumulator = func(accumulator, element)


    Most other common uses for a foreach are available as well. Having the different uses as separate functions makes reading code easier, as just the name of the function is enough to know what exactly is happening.

    Brendan:
    So you're saying that for the list (1, 2, 3, 4) a real person wouldn't do "3 + 4 = 5", then "2 + 5 = 7" then "1 + 7 = 8" to get the sum? You're saying that a real person would assume addition is an operator and not a function? You're saying a real person would do something like "temp = list.next(); while(list.hasNext) { temp += list.next(); }"?

    You're saying a real person wouldn't do anything like foldl1, but you thought they might because you don't know how foldl1 works?


    I'm very sorry, but you stopped making sense. Are you saying foldl1 starts from the right, even though the l stands for left? And what is the difference between an operator and a function in your mind?

    Brendan:
    briverymouse:
    What I said was:


    What I said was "Haskell is poo because it forces people to use recursion". You replied with "modern compilers can do tailcall optimisation", completely missing the point that programmers still have to deal with the concept whether it makes sense for their problem or not (regardless of what the compiler generates). I played along and asked for a disassembly of the Haskell code we were talking about, with the intention of either showing that Haskell failed to use tail recursion to remove all of the recursion from it's own library functions or that the generated code is a huge bloated mess anyway, and you missed the point there too and showed C code where the compiler did do tail call optimisation. I restated my request for a disassembly of the Haskell code in question, and you've failed to produce it again.

    I'm not sure if, like me, you don't have Haskell installed on any of your computers and couldn't be bothered installing it (I couldn't blame you if that's the case), or if you're deliberately trying to avoid posting the disassembly because you're ashamed of it, or if you're honestly unable to follow the conversation.


    Wait, so I misunderstood you, thinking you said Haskell code runs slowly, while you actually mean programming Haskell is too difficult for you? Instead of just clarifying what you meant, you decided you now need the assembly code generated from a Haskell program (without mentioning which program)? Is that it? Indeed, I don't have "Haskell" installed, as it's a programming language, not a piece of software, but I assume GHC will do? If so, here is the Roman numerals program in assembly form:
    http://pastebin.com/LNUSq68u
    Do let me know if either the compiler or the compiled source are not exactly what you wanted, and I'll see what I can do.
  • doidl 2012-04-03 20:50
    root@box:~/tmp> awk -vr=mcmlxxxix '{gsub($1,$2,r); }END{printf r}' <<<'m dd
    cd cccc
    d ccccc
    lc l
    c ll
    xl xxxx
    l xxxxx
    vx v
    x vv
    iv iiii
    v iiiii' | wc -c
    1989
    root@box:~/tmp>
  • Eric Jablow 2012-04-03 20:53
    Isn't the correct language for this problem Lingua::Romana::Perligata? That's a language that deserves its own wtf book!
  • daddley 2012-04-03 21:00
    root@box:~/tmp> awk -vr=mcmlxxxix '{gsub($1,$2,r); }END{print length(r)}' <<<'m dd
    cd cccc
    d ccccc
    lc l
    c ll
    xl xxxx
    l xxxxx
    vx v
    x vv
    iv iiii
    v iiiii'
    1989
    root@box:~/tmp>
  • Franz Kafka 2012-04-03 21:10
    Brendan:

    What I said was "Haskell is poo because it forces people to use recursion". You replied with "modern compilers can do tailcall optimisation", completely missing the point that programmers still have to deal with the concept whether it makes sense for their problem or not (regardless of what the compiler generates). I played along and asked for a disassembly of the Haskell code we were talking about, with the intention of either showing that Haskell failed to use tail recursion to remove all of the recursion from it's own library functions or that the generated code is a huge bloated mess anyway, and you missed the point there too and showed C code where the compiler did do tail call optimisation. I restated my request for a disassembly of the Haskell code in question, and you've failed to produce it again.

    I'm not sure if, like me, you don't have Haskell installed on any of your computers and couldn't be bothered installing it (I couldn't blame you if that's the case), or if you're deliberately trying to avoid posting the disassembly because you're ashamed of it, or if you're honestly unable to follow the conversation.


    If you can't handle recursion reasonably well, you must not be much of a programmer. If you've got tail recursion in a language then of cours you're going to use it - it's the total shit, and combining it with functional constructs that replace calls with their results makes for a really simple and easy time of it.

    Shit, next you're going to tell me that obejcts are too hard.
  • herby 2012-04-03 21:21
    All this talk about Roman Numbers reminds me that "MMX" is a trademark of Intel.

    We now return you the regularly scheduled programming concerning Perl, Haskel, Caml, C, C++, Fortran, Basic, APL, and Lisp.
    Carry on!
  • doadley 2012-04-03 21:21
    Hey, you hyper meta functional, objectional uberinformationist, a COMPETITION here: can you post your roman->natural haskell code via 1 sms or 1 tweet in readable form like me with bash/awk? Correct code - no failed test cases allowed?

    daddley:
    awk -vr=$1 '{gsub($1,$2,r); }END{print length(r)}' <<<'m dd
    cd cccc
    d ccccc
    lc l
    c ll
    xl xxxx
    l xxxxx
    vx v
    x vv
    iv iiii
    v iiiii'
  • David S. 2012-04-03 21:47
    Whether or not MIM and the vast array of other disputed Roman forms are correct in some sense isn't relevant. Roman numerals are obviously going to be coming from human input, so we should be liberal in what we accept. What we output is debatable; personally, I think MIM is much more elegant and acceptable to most actual users of computer programs, as opposed to the long dead Romans.

    It's funny to hear complaints about needing to know Haskell before understanding code written in it from programmers who would write while(*a++ = *b++); without a second thought.
  • briverymouse 2012-04-03 21:50
    doadley:
    Hey, you hyper meta functional, objectional uberinformationist, a COMPETITION here: can you post your roman->natural haskell code via 1 sms or 1 tweet in readable form like me with bash/awk? Correct code - no failed test cases allowed?


    Sure:
    r2n = sum . map f . groupBy (<) . map (fromJust . (`lookup` zip "IVXLCDM" [1,5,10,50,100,500,1000]))
    
    f [n] = n
    f [p,n] = n-p


    Not great code, and Haskell certainly isn't ideal for code golf, but it works.
  • Brendan 2012-04-03 22:06
    briverymouse:
    Brendan:
    For the list (1, 2, 3, 4) and the functions f(x) and g(x, y); "f(1); f(2); f(3); f(4);" is very different conceptually from "g(1, g(2, g(3, 4)));".

    Perhaps you need to read a book about Haskell?


    LOL, what? Did you look up "foreach in Haskell" on Google, read something about mapM_, and now think you're an expert on functional programming?


    Yes :-)

    briverymouse:
    It behaves roughly foreach-loop-like only for IO, and does something wildly different in e.g. the Maybe or list monad (fun exercise: see if you can find out what).


    So, the exact same thing behaves wildy differently in different contexts?

    briverymouse:
    foldl1 corresponds to the following foreach loop (pseudo-code):
    let accumulator = list[0]
    
    foreach element in list[1 ..]
    accumulator = func(accumulator, element)


    More like:

    int foldl1( (*someFunction)(int a, int b), int *list, int count)
    
    )
    {
    if(count <= 0) {
    return 0;
    } else if (count == 1)
    return list[0];
    } else {
    return someFunction(list[0], foldl1(someFunction, &list[1], count--));
    }
    }


    briverymouse:
    Brendan:
    So you're saying that for the list (1, 2, 3, 4) a real person wouldn't do "3 + 4 = 5", then "2 + 5 = 7" then "1 + 7 = 8" to get the sum? You're saying that a real person would assume addition is an operator and not a function? You're saying a real person would do something like "temp = list.next(); while(list.hasNext) { temp += list.next(); }"?

    You're saying a real person wouldn't do anything like foldl1, but you thought they might because you don't know how foldl1 works?


    I'm very sorry, but you stopped making sense. Are you saying foldl1 starts from the right, even though the l stands for left? And what is the difference between an operator and a function in your mind?


    Look at the "recursive C with function pointer" example above. It starts from the left, but (with "add()" as the function) the values on the right would be the first ones added.

    You are right though - I don't know if foldl1 starts from the right (so that the left values are added first) or if fold1 starts from the left (so that the right values are added first). This also implies that the "recursive C with function pointer" example above may be around the wrong way.

    Of course it's irrelevant what the order is. For the list (1, 2, 3, 4) a real person wouldn't do "3 + 4 = 7", then "2 + 7 = 9" then "1 + 9 = 10"; and they also wouldn't do "1 + 2 = 3" then "3 + 3 = 6" then "6 + 4 = 10". Try it on a calculator yourself and see how you do it - I'll bet you key in something like "1 + 2 + 3 + 4 =" (and rely on the calculator to remember its accumulator) and don't do "1 + 2 = " then "3 + 3 = " then "6 + 4 = ".

    To understand the difference between what I meant by "function" and what I meant by "operator", try passing the address of the '+' operator to the "recursive C with function pointer" example above. You'd have to write a function that does nothing more than "return a + b;" and then hope the compiler is smart enough to optimise out your counter-intuitive folly.

    briverymouse:
    Brendan:
    I'm not sure if, like me, you don't have Haskell installed on any of your computers and couldn't be bothered installing it (I couldn't blame you if that's the case), or if you're deliberately trying to avoid posting the disassembly because you're ashamed of it, or if you're honestly unable to follow the conversation.


    Wait, so I misunderstood you, thinking you said Haskell code runs slowly, while you actually mean programming Haskell is too difficult for you? Instead of just clarifying what you meant, you decided you now need the assembly code generated from a Haskell program (without mentioning which program)? Is that it?


    I haven't said Haskell (or code generated by GHC if you'd like to be pedantic) is slow. Speed is relative, and I'm sure the generated code is quite fast when compared to some languages. Being about 36 times faster than Perl is quite an achievement (even if Intel Fortran and GCC's C are about twice as fast).

    briverymouse:
    Indeed, I don't have "Haskell" installed, as it's a programming language, not a piece of software, but I assume GHC will do? If so, here is the Roman numerals program in assembly form:
    http://pastebin.com/LNUSq68u
    Do let me know if either the compiler or the compiled source are not exactly what you wanted, and I'll see what I can do.


    While I can confirm that this is bloated enough to have been compiled from Haskell, and can also confirm that it *is* part of the Roman Enumeration code; sadly it's incomplete. The interesting part of the code disappears into a "jmp _stg_ap_n_fast" that isn't present, and various other parts of the code aren't included either.
  • PiisAWheeL 2012-04-03 22:25
    Gurth:
    PiisAWheeL:
    KattMan:
    CD/CXXVII = PI
    I. P is not a roman numeral.

    Better notation would have been CD ÷ CXXVII = π, yes. However:

    PiisAWheeL:
    II. Roman numerals didn't have decimal points.

    Who says they need to? If you work with traditional fractions, you don't need decimal points (or commas, or whatever). CD ÷ CXXVII is a close enough approximation of the value of π for day to day use.
    Accurate enough for the government to use for tax collecting purposes? Or did they just round up?

    Nagesh:
    Nobody notice that this code can only go up to 2011. Did program candidate think world going to end after that or did he think nobody is going to remember Roman Number greater than 2011?

    I would like to know his think process.
    You missed that boat on page 1
    PiisAWheeL:
    Toodle:
    Code fail on
    IIX
    8 being written as VIII aside, wouldn't it also fail on IV first?

    Black Bart:
    The new hire was obviously an Aztec, since he knew from hist calendar that there was no need for years beyond 2012.
    Wrong. That is a reason not to include 2013. You still need to include the last year that will exist. December 20th is most of the year.


    And now I have the 1 clincher that will ruin roman numerals for all of you:

    No way to represent 0. This means no binary. All other arguments are invalid.
  • briverymouse 2012-04-03 22:34
    Brendan:
    briverymouse:
    It behaves roughly foreach-loop-like only for IO, and does something wildly different in e.g. the Maybe or list monad (fun exercise: see if you can find out what).


    So, the exact same thing behaves wildy differently in different contexts?


    Interesting question. Monads are basically a way to have values with "context". This context can be failure (the Maybe monad), non-determinism (the list monad), contact with the outside world (the IO monad), and more. mapM_ executes all the "context", but returns no value. In the IO monad, this means it executes all the IO actions, and returns nothing interesting. This is more or less like a foreach loop doing IO and computing nothing in other languages. In the Maybe monad, mapM_ tries to compute all values, but only returns the context: whether one of them failed or not. In the list monad, it tries to compute all values, and sees if there is still non-determinism left. So, yes, in a way they're very different things, but the general idea is the same.

    Brendan:
    briverymouse:
    foldl1 corresponds to the following foreach loop (pseudo-code):
    let accumulator = list[0]
    
    foreach element in list[1 ..]
    accumulator = func(accumulator, element)


    More like:

    ...


    Yes, that is the recursive version. You seem quite fond of recursion!

    Brendan:
    Of course it's irrelevant what the order is. For the list (1, 2, 3, 4) a real person wouldn't do "3 + 4 = 7", then "2 + 7 = 9" then "1 + 9 = 10"; and they also wouldn't do "1 + 2 = 3" then "3 + 3 = 6" then "6 + 4 = 10". Try it on a calculator yourself and see how you do it - I'll bet you key in something like "1 + 2 + 3 + 4 =" (and rely on the calculator to remember its accumulator) and don't do "1 + 2 = " then "3 + 3 = " then "6 + 4 = ".


    Indeed! That's why "foldl1 (+) list", which means "throw a plus sign between the elements of the list", is more natural than a raw loop, where you explicitly write out all the steps.

    Brendan:
    To understand the difference between what I meant by "function" and what I meant by "operator", try passing the address of the '+' operator to the "recursive C with function pointer" example above. You'd have to write a function that does nothing more than "return a + b;" and then hope the compiler is smart enough to optimise out your counter-intuitive folly.


    Yes, but that's a C-specific concept. The only difference between an operator and a function in Haskell is the name (special characters or not), and that an operator is infix, while a function is prefix.

    Brendan:
    While I can confirm that this is bloated enough to have been compiled from Haskell, and can also confirm that it *is* part of the Roman Enumeration code; sadly it's incomplete. The interesting part of the code disappears into a "jmp _stg_ap_n_fast" that isn't present, and various other parts of the code aren't included either.


    So, what, you now want me to give you assembly code for all libraries used?
  • Brendan 2012-04-03 23:43
    briverymouse:
    More like:

    ...


    Yes, that is the recursive version. You seem quite fond of recursion!


    There are some things that are naturally recursive (traversing hierarchical trees for example), and I have no objection to recursion when it's the right tool for the job. This is not the case here - if I actually saw that code in a project being used to add a list of numbers I'd submit it to TDWTF (but it is about as close as I can get to mimicking Haskell's foldl1 (or foldr1?) in C).

    briverymouse:
    Indeed! That's why "foldl1 (+) list", which means "throw a plus sign between the elements of the list", is more natural than a raw loop, where you explicitly write out all the steps.


    http://zvon.org/other/haskell/Outputprelude/foldl1_f.html says:
    "it takes the first 2 items of the list and applies the function to them, then feeds the function with this result and the third argument and so on."

    If the function you use has side effects, then it seems obvious to me that it isn't equivalent to inserting an operator between the elements of the list. Perhaps this is another case of "behaves wildly different when you're using the wrong concept to describe it".

    briverymouse:
    Brendan:
    While I can confirm that this is bloated enough to have been compiled from Haskell, and can also confirm that it *is* part of the Roman Enumeration code; sadly it's incomplete. The interesting part of the code disappears into a "jmp _stg_ap_n_fast" that isn't present, and various other parts of the code aren't included either.


    So, what, you now want me to give you assembly code for all libraries used?


    Maybe "ghc -static -optl-static" would help with the missing pieces, while hopefully avoiding a lot of unnecessary/unused code.
  • RobTF 2012-04-04 05:14
    My 5 minute attempt with handling for invalid values (e.g. IIIII).


    private static int Rom2Num(string value)
    {
    // HACK: this table should be static.. but for purposes of demo
    var values = new int[] { 1, 5, 10, 100, 500, 1000 };
    var dict = new Dictionary<char, int>();
    dict.Add('I', 0);
    dict.Add('V', 1);
    dict.Add('X', 2);
    dict.Add('C', 3);
    dict.Add('D', 4);
    dict.Add('M', 5);

    // check for null/empty input
    if (String.IsNullOrEmpty(value))
    {
    throw new ArgumentOutOfRangeException("Input cannot be a null or empty string.", value, value);
    }

    value = value.ToUpperInvariant();

    // determine if string contains any invalid characters
    foreach (var c in value)
    {
    if (!dict.ContainsKey(c))
    {
    throw new ArgumentException(String.Format("Input contains invalid character \"{0}\".", c), "value");
    }
    }

    int total = 0;
    int charamt;
    int curvalueidx;
    int curfactor = values[0];
    char curchar;

    // work from the back of the string to the front
    for (int i = value.Length - 1; i >= 0; i--)
    {
    curchar = value[i];

    // current position of value in values array
    curvalueidx = dict[curchar];

    // value of the current character
    charamt = values[curvalueidx];

    if (charamt < curfactor)
    {
    // value has appeared after higer value character? subtract it
    total -= charamt;
    }
    else
    {
    // add the value, change the current factor
    total += charamt;
    curfactor = charamt;
    }

    // are there characters worth more than the current character?
    if (curvalueidx < (values.Length - 1))
    {
    /*
    if the total of the value so far is greater than the value of the next character, the
    user has used too many of the current character and should replace them with the next
    character instead (e.g. IIIII => V).
    */
    if (total >= values[curvalueidx + 1])
    {
    throw new ArgumentException("value", String.Format("Value specified is not a valid roman numeral (too many \"{0}\" characters).", curchar));
    }
    }
    }

    return total;
    }
  • the beholder 2012-04-04 07:33
    Nagesh:
    Nobody notice that this code can only go up to 2011. Did program candidate think world going to end after that or did he think nobody is going to remember Roman Number greater than 2011?

    I would like to know his think process.
    Uh, I don't think he has one
  • Nagesh 2012-04-04 07:45
    the beholder:
    Nagesh:
    Nobody notice that this code can only go up to 2011. Did program candidate think world going to end after that or did he think nobody is going to remember Roman Number greater than 2011?

    I would like to know his think process.
    Uh, I don't think he has one


    Yes lack of think is causing major problems in universe.
  • PedanticCurmudgeon 2012-04-04 08:28
    Brendan:
    Kuba:
    If you know Haskell, functional constructs are natural.


    For me (and I doubt I'm the only one here), inhaling toxic smoke seems natural. Does this mean inhaling toxic smoke actually is natural?

    After you know Haskell (or some other functional programming language) functional constructs may seem natural to you, but they won't seem natural before you get used to them, and won't seem natural to anyone else who hasn't become used to them.

    For an ideal language, you wouldn't have to get used to anything before it seems natural. There isn't a language that comes close to this (and I doubt there ever will be), but some are closer to this ideal than others.
    All you trolls need to pay attention to this guy. He's got the art mastered.
  • Evil Hamster 2012-04-04 08:36
    %m = qw/I 1 V 5 X 10 L 50 C 100 D 500 M 1000/;
    @n = map {$m{uc($_)}} split //, $ARGV[0];
    $r+=$n[$_]*(($n[$_+1] > $n[$_]) ? -1 : 1) for (0..$#n);
    print $r , "\n";
  • briverymouse 2012-04-04 10:09
    Brendan:
    This is not the case here - if I actually saw that code in a project being used to add a list of numbers I'd submit it to TDWTF (but it is about as close as I can get to mimicking Haskell's foldl1 (or foldr1?) in C).


    Why wouldn't you use a for loop to implement foldl1 instead of recursion? In what way does your code differ from mine? Haskell has implemented foldl1 for you, so you don't need to worry about the implementation details. When you're using a fold, you're not using recursion. A for loop in C is implemented with jmp, but I'm not saying using a for loop means using goto.

    Brendan:
    http://zvon.org/other/haskell/Outputprelude/foldl1_f.html says:
    "it takes the first 2 items of the list and applies the function to them, then feeds the function with this result and the third argument and so on."

    If the function you use has side effects, then it seems obvious to me that it isn't equivalent to inserting an operator between the elements of the list. Perhaps this is another case of "behaves wildly different when you're using the wrong concept to describe it".


    What? Functions don't have side effects in Haskell. I hope you see how "a + b + c + d" is equivalent to "((a + b) + c) + d". It is the way most people would calculate it if they have no calculator, and it is also the way both C and Haskell will actually calculate it. If functions and operators could have side effects, say incrementing a variable "count", both "a + b + c + d" and "foldl1 (+) [a, b, c, d]" will result in count being incremented by 3. Or are you saying only functions can have side effects, while operators can't? That's not even true in C, if you think about the ++ and -- operators.

    Brendan:
    Maybe "ghc -static -optl-static" would help with the missing pieces, while hopefully avoiding a lot of unnecessary/unused code.


    Oh, you want me to actually disassemble the entire executable, not just my own code? Have fun with it: http://dl.dropbox.com/u/24516255/rom2num.asm
  • The Nitpicker 2012-04-04 11:48
    And he totally missed that there are two ways to say 4: "IV" and "IIII"
  • Mike 2012-04-04 12:10
    "I can only hope that the powers-that-be will determine that we are ineffective at training and shift the responsibility of teaching programmers to program to corporate training."

    Well, that would require HR to do something constructive for a change, instead of merely continuing to justify their existence. They're *gods* you know, and so much more efficient and knowledgeable than any IT person ever could be.
  • CarnivorousHippie 2012-04-04 16:06
    herby:
    We now return you the regularly scheduled programming concerning Perl, Haskel, Caml, C, C++, Fortran, Basic, APL, and Lisp.
    Carry on!

    Hey, you forgot about VB.
    herby:
    ... programming ...

    Or, maybe not.
  • Jay 2012-04-04 16:27
    PiisAWheeL:
    And now I have the 1 clincher that will ruin roman numerals for all of you:

    No way to represent 0. This means no binary. All other arguments are invalid.


    Of course there's a way to write zero. It's the representation made up of everything from the following colon to the end of the line:

    That is, don't write any Roman numerals. That's zero.

    This does, of course, create the problem that there's no clear way to tell whether you mean the number zero, or you don't mean to convey any number at all. Of course we can't be too hard on the Romans: the idea of distinguishing a string with zero characters from a null string (or nothing string for you VB folks) is pretty recent, and still continues to confuse many programmers.

    Reminds me: In the book "Lest Darkness Fall", there's a seen where a time traveller is trying to explain the value of the digit 0 to people who use Roman numerals. One of them asks in bafflement, "You have a symbol for nothing?" And the time traveller replies, "Why not? You have a word for 'nothing'." (Quoting from decades-old memory, excuse me if it's not an exact quote.)
  • Jay 2012-04-04 16:28
    Mike:
    "I can only hope that the powers-that-be will determine that we are ineffective at training and shift the responsibility of teaching programmers to program to corporate training."

    Well, that would require HR to do something constructive for a change, instead of merely continuing to justify their existence. They're *gods* you know, and so much more efficient and knowledgeable than any IT person ever could be.


    Those who can, do. Those who can't, teach. Those who can't teach, recruit teachers.
  • Brendan 2012-04-04 16:54
    briverymouse:
    Brendan:
    This is not the case here - if I actually saw that code in a project being used to add a list of numbers I'd submit it to TDWTF (but it is about as close as I can get to mimicking Haskell's foldl1 (or foldr1?) in C).


    Why wouldn't you use a for loop to implement foldl1 instead of recursion? In what way does your code differ from mine? Haskell has implemented foldl1 for you, so you don't need to worry about the implementation details. When you're using a fold, you're not using recursion. A for loop in C is implemented with jmp, but I'm not saying using a for loop means using goto.


    I didn't use a for loop in that C example because I was trying to mimic Haskell, and therefore trying to avoid the use of mutable variables.

    I probably should have made that clearer:

    int foldl1( (*someFunction)(const int a, const int b), const int *list, const int count)
    
    )
    {
    if(count <= 0) {
    return 0;
    } else if (count == 1)
    return list[0];
    } else {
    return someFunction(list[0], foldl1(someFunction, &list[1], count - 1));
    }
    }


    briverymouse:
    Brendan:
    http://zvon.org/other/haskell/Outputprelude/foldl1_f.html says:
    "it takes the first 2 items of the list and applies the function to them, then feeds the function with this result and the third argument and so on."

    If the function you use has side effects, then it seems obvious to me that it isn't equivalent to inserting an operator between the elements of the list. Perhaps this is another case of "behaves wildly different when you're using the wrong concept to describe it".


    What? Functions don't have side effects in Haskell.


    D'oh - sorry, I'm too used to useful languages. Can a function use a monad (or whatever they call their "things that do have side-effects that aren't functions but were necessary because the language designers removed required functionality and had to reintroduce it as something different for their bait and switch trick to work")?

    briverymouse:
    I hope you see how "a + b + c + d" is equivalent to "((a + b) + c) + d".


    And I hope you'll be able to see that this "insert the operator" description only works to describe a limited number of cases that (I assume) foldl1 supports. E.g. when the function is "return a + b;" or "return a - b;", but not when the function is "return a / (a + b);" or even just "return b - a;".

    briverymouse:
    Brendan:
    Maybe "ghc -static -optl-static" would help with the missing pieces, while hopefully avoiding a lot of unnecessary/unused code.


    Oh, you want me to actually disassemble the entire executable, not just my own code? Have fun with it: http://dl.dropbox.com/u/24516255/rom2num.asm


    Hehee - knowing that horrendous mess came from just one line of Haskell made me laugh more than the original article did. Perhaps you could improve performance and executable size by replacing the one liner with:

    public string rom2num(string r)
    
    {
    if (r == "I") return "1";
    if (r == "II") return "2";
    if (r == "III") return "3";
    if (r == "IV") return "4";
    if (r == "V") return "5";
    if (r == "VI") return "6";
    if (r == "VII") return "7";
    if (r == "VIII") return "8";
    if (r == "IX") return "9";
    //
    // Snipped LOTS of "code" here
    //
    if (r == "MMVIII") return "2008";
    if (r == "MMIX") return "2009";
    if (r == "MMX") return "2010";
    if (r == "MMXI") return "2011";
    return "E";
    }

  • briverymouse 2012-04-04 18:01
    Brendan:
    I didn't use a for loop in that C example because I was trying to mimic Haskell, and therefore trying to avoid the use of mutable variables.


    Don't try to "mimic" Haskell in C, C wasn't designed for functional programming. If I tried to mimic C code in Haskell, the result would be equally messy. The C implementation of foldl1 would be a foreach loop, not recursion. The Haskell implementation uses recursion. This is fine: the underlying implementation does not matter to an everyday programmer, as long as the result is the same.

    What Brendan said:
    Can a function use a monad?


    Yes, a function can use a monad.

    What Brendan actually meant:
    Can a function use a monad to create side-effects?


    No.

    Brendan:
    a monad (or whatever they call their "things that do have side-effects that aren't functions but were necessary because the language designers removed required functionality and had to reintroduce it as something different for their bait and switch trick to work")


    Haskell didn't "remove" required functionality and "reintroduce" it using monads. Haskell introduced monads, and got that required functionality (and more) for free, where other programming languages have a half-working implementation for some of the things monads can do.

    Brendan:
    And I hope you'll be able to see that this "insert the operator" description only works to describe a limited number of cases that (I assume) foldl1 supports. E.g. when the function is "return a + b;" or "return a - b;", but not when the function is "return a / (a + b);" or even just "return b - a;".


    Indeed, foldl1 is more powerful. In general, it's equivalent to the foreach loop I mentioned earlier:
    let accumulator = list[0]
    
    foreach element in list[1 ..]
    accumulator = func(accumulator, element)

    For every left-associative binary operator, that's the same as just inserting the operator. In other cases, it's equivalent to a foreach loop, so it's just as "natural" as just writing that loop out, but a lot easier to read.

    Brendan:
    Hehee - knowing that horrendous mess came from just one line of Haskell made me laugh more than the original article did. Perhaps you could improve performance and executable size by replacing the one liner with:

    ...



    Glad I made you laugh. Look, if you want to argue that compiled Haskell code is a mess, the argument is over and you win. Obviously it is. It has its own little "runtime" to support lazy evaluation. Try to implement lazy evaluation in C, and see if you can do it in a cleaner way than the GHC people did. But anyone programming today that thinks executable size and performance are more important than maintainability and ease of programming, should not have a job with computers.
  • Faxmachinen 2012-04-04 22:27
    tundog:
    Clearly this problem is screaming for a Perl REGEX!

    Certainly, sir:
    %m = qw(M 1000 D 500 C 100 L 50 X 10 V 5 I 1);
    scalar(<>) =~ /(?:(I(?=[MDCLXV])|V(?=[MDCLX])|X(?=[MDCL])|L(?=[MDC])|C(?=[MD])|D(?=M))(?{$a-=$m{$1}})|([MDCLXVI])(?{$a+=$m{$2}}))+/i;
    print $a;

  • hikari 2012-04-05 00:49
    ObiWayneKenobi:
    What the hell is it with people and having to return "error codes" from everything? THIS ISN'T VB6. There are sophisticated error handling in modern languages, you don't need to return ints or bools all over the place.


    Depends on the circumstances. When something is a predictable and expected occurrence, e.g. there's no more data to read, returning a value that indicates that is preferable to the expense of throwing an exception.

    Methods and properties that return bool often go hand-in-hand with ones that generate exceptions. Methods like int.Parse() in .NET have a corresponding int.TryParse() for a reason. Sometimes you don't know if your input is actually a valid value for the method; the Try* methods parse the input without generating an exception if it's not valid. Similarly Stream derived classes have things like the "bool CanRead" properties so you can avoid the exception that would occur if you did Read() on a stream that can't be read from.

    If you have a method that has the possibility to generate an exception, make sure you provide a way of avoiding the exception.
  • PedanticCurmudgeon 2012-04-05 09:13
    Any bets on how long before briverymouse figures out he's being trolled?
  • Joey 2012-04-05 18:55
    Matt Westwood:

    Instead they offer verbal examples culled from textbooks -- 'manipulate an algebraic expression', 'attack a problem', 'exploit a theorem' -- as evidence that mathematics is a nest of aggression, violence, domination and sexism.


    Has this person EVER interacted with women?

    I) Manipulation, via the emotions, is so common as to render this example ludicrous in itself.

    II) Exploit, just look at dating and the common assumption that the man will pay.

    III) Attack; apparently they've never been to a divorce-court. More oftan than not, the woman is downright vindictive.
  • blank 2012-04-06 12:13
    D-Coder:
    PoPSiCLe:
    Why would you call it a Roman Numerals to decimal numbers converter? A Roman Numeral can, by definition, not be a decimal (the Romans didn't have "0"), and neither did they use decimals (only whole numbers).

    A better title for the "project" would be Roman Numerals to Integers (although this would also be wrong, as "integers" both incorporates negative numbers and zero), so the absolute correct naming would be Roman Numerals to Natural numbers (the numbers we learn when we learn to count, which are normally 1,2,3,4,5,6,7,8,9,10 etc)
    I can always count on TDWTF for my daily dose of pedantic dickweedery.


    i think you meant dickweedal pedantry
  • Klaus 2012-04-09 13:01
    TRWTF is that his "code" counts as "managed to solve the problem"...
  • Roy Rasmussen 2012-04-10 05:26
    PaulaBean:
    easy peasy.

    private int toInt(string roman) {
    int lastnum = 0;
    int total = 0;
    for (int c = roman.Length - 1; c >= 0; c--) {
    string number = roman.Substring(c, 1);
    int value = singleRomanToInt(number);
    if (value < lastnum) total -= value;
    else {
    lastnum = value;
    total += value;
    }
    }
    return total;
    }

    private int singleRomanToInt(string romanchar) {
    switch (romanchar.ToUpper()) {
    case "I": return 1;
    case "V": return 5;
    case "X": return 10;
    case "L": return 50;
    case "C": return 100;
    case "M": return 1000;
    default:
    return Convert.ToInt32("PaulaBean!");
    }
    }


    Almost, this will work if you only set LASTNUM = VALUE when LASTNUM != VALUE
  • zirias 2012-04-11 04:54
    Ok, this is a lengthy one, but just for the fun accepts ANYTHING remotely looking like a roman number (ignoring all non-roman-numerical characters) -- and also returns the canonical roman form.

    > cat r2l.c
    

    #include <stdio.h>

    int result = 0;
    int intermediate = 0;
    int current = 0;
    int next = 0;

    int rdigit(char r)
    {
    switch(r)
    {
    case 'i':
    case 'I':
    return 1;
    case 'v':
    case 'V':
    return 5;
    case 'x':
    case 'X':
    return 10;
    case 'l':
    case 'L':
    return 50;
    case 'c':
    case 'C':
    return 100;
    case 'd':
    case 'D':
    return 500;
    case 'm':
    case 'M':
    return 1000;
    }
    return 0;
    }

    int rformat_pat(int *num, int dec, size_t *c, char **pos, int count, char r1, char r2)
    {
    while (*num >= dec)
    {
    if (*c < count)
    {
    **pos = '\0';
    return 0;
    }

    *c -= count;
    *(*pos)++ = r1;
    if (count == 2) *(*pos)++ = r2;
    *num -= dec;
    }
    return 1;
    }

    int rformat(char *buf, size_t n, int num)
    {
    size_t c = n - 1;
    char *pos = buf;

    if (!rformat_pat(&num, 1000, &c, &pos, 1, 'M', '\0')) return 0;
    if (!rformat_pat(&num, 900, &c, &pos, 2, 'C', 'M')) return 0;
    if (!rformat_pat(&num, 500, &c, &pos, 1, 'D', '\0')) return 0;
    if (!rformat_pat(&num, 400, &c, &pos, 2, 'C', 'D')) return 0;
    if (!rformat_pat(&num, 100, &c, &pos, 1, 'C', '\0')) return 0;
    if (!rformat_pat(&num, 90, &c, &pos, 2, 'X', 'C')) return 0;
    if (!rformat_pat(&num, 50, &c, &pos, 1, 'L', '\0')) return 0;
    if (!rformat_pat(&num, 40, &c, &pos, 2, 'X', 'L')) return 0;
    if (!rformat_pat(&num, 10, &c, &pos, 1, 'X', '\0')) return 0;
    if (!rformat_pat(&num, 9, &c, &pos, 2, 'I', 'X')) return 0;
    if (!rformat_pat(&num, 5, &c, &pos, 1, 'V', '\0')) return 0;
    if (!rformat_pat(&num, 4, &c, &pos, 2, 'I', 'V')) return 0;
    if (!rformat_pat(&num, 1, &c, &pos, 1, 'I', '\0')) return 0;
    *pos = '\0';
    return 1;
    }

    char line[1024];

    int main()
    {
    while (!feof(stdin))
    {
    char *c = fgets(line, 1024, stdin);
    if (!c) return;

    do
    {
    next = rdigit(*c++);
    if (next > 0)
    {
    if (intermediate > 0 && current < next)
    {
    intermediate = next - intermediate;
    if (intermediate < 1)
    {
    puts("undefined format.");
    goto nextline;
    }
    }
    else
    {
    if (current > 0 && current != next)
    {
    result += intermediate;
    intermediate = 0;
    }
    intermediate += next;
    }
    current = next;
    }
    } while (*c != '\0');

    result += intermediate;
    rformat(line, 1024, result);

    printf("%d [%s]\n", result, line);

    nextline:
    result = 0;
    intermediate = 0;
    current = 0;
    next = 0;
    }
    }


    Well, i still like C ...
  • Romain 2012-04-16 03:29
    briverymouse:

    Haskell:
    foldl1 (+) [1 .. 10]

    Python:
    sum(range(11))


    Which one would you most easily understand? Obviously the Python one. Which one would you most easily understand once you know what foldl1 does? Obviously the Python one.
  • Cbuttius 2012-08-14 06:05
    should go up to 3999 which is MMMCMXCIX
  • Cbuttius 2012-08-14 06:06
    by the way, the real WTF is inhuman resources
  • Lee 2012-11-29 14:45
    Had to comment on this one, even though its dead. Necro alert.

    First, this test problem is a clunker. When will you need to convert from a more complicated number system to a standard one? Did you accidentally store your data in Roman numerals.

    Secondly, If I were programming that ridiculous test, I might convert a decimal as a string as well. What other reason to convert from Roman Numeral other than display purposes? Stupid problem, stupid answer.

    Thirdly, this isn't a failure on the programmer. You told to help the knowledge gap. The issues you had with his work is good coding practice issues, not syntax, not mechanical, etc. If you can't teach a new programmer good coding practices, then how can you expect to develop good coding style at your workplace.

    No, I think your work environment would likely cause more WTF than your bosses decisions about hiring practices.

    The only thing you can really point your finger at is the crappy education system in place for programmers. They spend more time on sounding fancy for their class titles, than they do trying to teach good coding practice: coding clean, maintainable, well-documented, and flexible code. Knowing when to be dynamic or static, not over-coding, etc.