#πŸ”’ Roman Numerals

118 messages Β· Page 1 of 1 (latest)

brisk inlet
#

I am currently working on something with roman numerals and it has to follow these certain rules, I gotten most of the rules, I'm currently stuck on one of these rules. I need MCXIV to be True, and VL and LLL to be false, I think my problem is round here.

    previous_value = float('inf')
    for char in test_case:
        value = roman_numeral.get(char)
        if value <= previous_value:
            if value not in [1, 10, 100, 1000] or previous_value / value not in [5, 10]:
                print(value)
                return False
        else:
            previous_value = value```

This has been bugging me, and if I could get some help on finding out what is wrong, that would be greatful.
grizzled spindleBOT
#

@brisk inlet

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

dreamy surge
#

roman numerals are quite stupid and unnecessary cumbersome
they should have died out with the roman empire well over 1500 years ago

#

or is it just XLV that is valid for 45?

brisk inlet
#

VL isn't valid because it doesn't follow two of the rules, and I agree roman numerals are just so stupid to do, but it's something to do.

ruby panther
#

!paste

grizzled spindleBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

ruby panther
#

can you upload the whole code?

dreamy surge
#

and why are you using float('inf') when working with integers?

brisk inlet
#

i can do that

#

was testing somethin, but switched it back to previous_value = 0

#
``` def valid_numeral(test_case):
    valid_chars = "IVXLCDM"
    # Rule 1: A valid Roman numeral consists only of alphabetic characters
    
    # Rule 2: A valid Roman numeral only contains the characters I, V, X, L, C, D, and M
    # if any(char.lower() in valid_chars for char in test_case):
    #    return False
    for char in test_case:
        if char not in valid_chars:
            return False
                           
    # Rule 3: A valid Roman numeral should not have 4 of the same character in a row
    previous_char = ""
    count = 0
    for char in test_case:
        if previous_char == char:
            count += 1
        elif previous_char == "":
            count += 1
        else:
            count = 0
            previous_char = char
    if count == 4:
        return False
  
    # rule 4, 5, 6            
    roman_numeral = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
    previous_value = 0
    for char in test_case:
        value = roman_numeral.get(char)
        if previous_value == 0:
            previous_value = value
        if value < previous_value:
            if value in [1, 10, 100]:
                if previous_value // value not in [1, 5, 10]:
                    return False
            else:
                return False
        previous_value = value
      
    # Rule 7: A valid Roman number can have a sequence of 2 or 3 symbols in a row if they are integer powers of 10
    for char in ['I', 'X', 'C']:
        if char * 2 in test_case or char * 3 in test_case:
            return True

    return True

def main():
    print(valid_numeral('XVIII'))  # True
    print(valid_numeral('MCXIV'))  # True
    print(valid_numeral('CCCC'))   # False
    print(valid_numeral('CIL'))    # False
    print(valid_numeral('M2C'))    # False
    print(valid_numeral('ASDF'))   # False
    print(valid_numeral('VL'))     # False
    print(valid_numeral('XXX'))    # True
    print(valid_numeral('LLL'))    # False ```
ruby panther
#

add py behind the backticks

brisk inlet
#

don't got enough space

brisk inlet
ruby panther
#

i mean the discord message

```py
brisk inlet
#

I did

sweet maple
#

Please also post the rules you want to apply to the numbers.

late hollow
#

```py
code
```

late hollow
dreamy surge
#

!paste if you got to much code for the above

grizzled spindleBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

late hollow
#

I guess rule 4,5,6 aren't

brisk inlet
#

I can get that for you

#
5. A valid Roman numeral can have a small-valued symbol precede a large-valued symbol, only if the small-valued symbol is an integer power of 10 (IX is valid, VX is not).
6. A valid Roman numeral can have a small-valued symbol precede a large-valued symbol, only if the small-valued symbol is an integer power of 10 AND the small-valued symbol is one of the two symbols in size order before the large-valued symbol (IV and IX are valid, IL and IC are not).
#

but I did make it py now, so there you go

late hollow
#

nice

ruby panther
#

def valid(n):
    a = {"M": "CX", "D": "CX", "C": "XI", "L": "XI", "X": "I", "V": "I"}
    b = {k: v for k, v in zip("MDCLXVI", [1000, 500, 100, 50, 10, 5, 1])}
    # Rule 1: A valid Roman numeral consists only of alphabetic characters
    if not all(map(lambda x: x in "IVXLCDM", (n := n.upper()))):
        return False
    # Rule 3: A valid Roman numeral should not have 4 of the same character in a row
    if  not all(map(lambda x: x < 4, {i: n.count(i) for i in set(n)}.values())):
        return False
    #  4. A valid Roman numeral should be ordered from large-valued symbol to small-valued symbol. Unless
    acc = n[0]
    for i in n[1:]:
        if b[acc] < b[i]:
            #  A valid Roman numeral can have a small-valued symbol precede a large-valued symbol, only if the small-valued symbol is an integer power of 10 (IX is valid, VX is not).
            if acc not in "IXC":
                return False
            else:
                # A valid Roman numeral can have a small-valued symbol precede a large-valued symbol, only if the small-valued symbol is an integer power of 10 AND the small-valued symbol is one of the two symbols in size order before the large-valued symbol (IV and IX are valid, IL and IC are not).
                if acc != a[i]:
                    return False
        acc = i

    # # Rule 7: A valid Roman number can have a sequence of 2 or 3 symbols in a row if they are integer powers of 10
    acc = [0]
    count = acc
    for i in n[1:]:
        if i == acc:
            if i in "IXCM":
                count += i
                if len(count) > 3:
                    return False
            else:
                return False
        else:
            count = i
        acc = i

    return True

i think explaining it to you step by step is hard, so i give you my solution and you ask about everything you do not understand, ok?

#

it passes all you test cases

#

@brisk inlet

brisk inlet
#

I'm kinda curious about Rule 3 and 4, if you could possibly explain those

ruby panther
#

do you know: all, map and lambda?

brisk inlet
#

no, as you saw with my earlier code, I have not implied that.

ruby panther
#

ok, then lets go through it

#

first of all instead of (n:= n.upper) you could make n = n.upper() one line above and then use only n in this line

late hollow
#

also this is totally spoonfeeding

ruby panther
#

my english skills are limited

#

and i guess if i am explaining everything he do not understand, it is all good?

late hollow
#

no because it's still spoonfeeding 🀨

brisk inlet
#

I can learn about it some other time then or on my free time

late hollow
#

you have provided a full answer to their homework

ruby panther
#

there was no homework tag

brisk inlet
#

I think I forgot to add the tag, but that is completely on me... because I didn't see it, my eyes arent the best...

late hollow
#

I mean, it's clear that it's homework, even without a tag

ruby panther
#

for me it was not

late hollow
#

why would there be instructions if it's not homework?

ruby panther
#

i thougt he googled like an algorithm how to check if a number is a valid roman number

brisk inlet
ruby panther
#

but ok my bad, sorry

brisk inlet
ruby panther
#

but lets explain then

#

!e

print(all([True, True, True]))
print(all([True, False, True]))
print(all([True, True, True, True, True, False]))
brisk inlet
#

Sean, I do have a question with code and such, and is there anyway you can make it into a Boolean?

grizzled spindleBOT
#

@ruby panther :white_check_mark: Your 3.12 eval job has completed with return code 0.

001 | True
002 | False
003 | False
ruby panther
#
square = lambda x: x ** 2
print(square(4))
#

!e

square = lambda x: x ** 2
print(square(4))
grizzled spindleBOT
#

@ruby panther :white_check_mark: Your 3.12 eval job has completed with return code 0.

16
ruby panther
#

lambda is an anonymous function, which works like that: lambda parameters: return expression

late hollow
brisk inlet
brisk inlet
#

since I am getting the other right True or False, but the wrong ones for MCIXV, VL, and LLL

#

does that explain a little better @ruby panther

ruby panther
brisk inlet
ruby panther
#

i do not understand what you mean with, you need everything boolean?

brisk inlet
#

since I am currently having trouble with how can I make it give the True or False I need, since each roman numeral has to go through each Rule

#

does that make a little more sense? or what I'm trying to say is, what is wrong with my code, and what changes do I need to make so I can get this outcome

ruby panther
#
roman_numeral = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
    previous_value = 0
    for char in test_case:
        value = roman_numeral.get(char)
        if previous_value == 0:
            previous_value = value
        if value < previous_value:
            if value in [1, 10, 100]:
                if previous_value // value not in [1, 5, 10]:
                    return False
            else:
                return False
        previous_value = value

you should not make the previous value 0, better make it the first value and iterate through the rest, then if the current value is lower then the previous value the value must be an integer power of 10 and can only be the 2 direct lower ones of them so if it ist NOT a power of 10 or NOT in the 2 direct lower powers of 10, then you return false

#

for checking if the value is in the 2 lower powers of 10 i made this dictionary: b = {k: v for k, v in zip("MDCLXVI", [1000, 500, 100, 50, 10, 5, 1])}

brisk inlet
#

Now when I run it, is comes up with not the correct answers, so something else might be wrong with my code, but I don't know what is wrong

#

let me just send screenshot

#
    print(valid_numeral('XVIII'))  # True, I got False
    print(valid_numeral('MCXIV'))  # True, I got True
    print(valid_numeral('CCCC'))   # False, I got False
    print(valid_numeral('CIL'))    # False, I got False
    print(valid_numeral('M2C'))    # False, I got False
    print(valid_numeral('ASDF'))   # False, I got False
    print(valid_numeral('VL'))     # False, I got True
    print(valid_numeral('XXX'))    # True, I got True
    print(valid_numeral('LLL'))    # False, I got True
#

I added what I got on the sides, so something I did with my code is messed up, but I don't know what @ruby panther

#

XVIII, VL, and LLL have the wrong outputs

ruby panther
#

how did you change your code?

brisk inlet
#

might be something else with my code, that I'm just not understanding

ruby panther
#

yes because you have to return False if value is not in [1,10,100] because you want it to be in

brisk inlet
#

correct, I think, so it might be something with one of the other rules I have, or it is rule 4, 5 and 6

ruby panther
#
a = {"M": "CX", "D": "CX", "C": "XI", "L": "XI", "X": "I", "V": "I"}
b = {'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}
    previous_value = test_case[0]
    for char in test_case[1:]:
        if b[previous_value] < b[char]:
            if previous_value not in "IXC":
                  return False
            else:
                if previous_value != a[char]:
                    return False
                
        previous_value = char

do this

#
instead of this:
roman_numeral = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
    previous_value = 0
    for char in test_case:
        value = roman_numeral.get(char)
        if previous_value == 0:
            previous_value = value
        if value < previous_value:
            if value in [1, 10, 100]:
                if previous_value // value not in [1, 5, 10]:
                    return False
            else:
                return False
        previous_value = value
brisk inlet
#

Ok, when I put that in, everything works, and is the right one, except the last one, and that one fails on rule 7, last one is giving me True

#

which is needs to be false

#

which here is rule 7

#
# Rule 7: A valid Roman number can have a sequence of 2 or 3 symbols in a row if they are integer powers of 10
    for char in ['I', 'X', 'C']:
        if char * 2 in test_case or char * 3 in test_case:
            return True

    return True```
ruby panther
#
   for char in ['I', 'X', 'C']:
        if char * 2 in test_case or char * 3 in test_case:
            return True

this is you rule 7 implementation, but you are not checking what the rule is demanding

#

you have to check for 2 or 3 in a row, not if there are 2 or 3 in it

brisk inlet
#

so, I would have to remove the or, and make them apart of the loop?

ruby panther
#

no

#

you have to accumulate the previous char and check if the following is the same

#

furthermore you have to iterate through the test_case string again

#

and then if you have more then three chars in a row you return false

#

also if the privious one and the current are the same, but they are not powers of 10 you also return False

brisk inlet
#

could you write that in code?

ruby panther
#
acc = n[0]
count = acc
for i in n[1:]:
    if i == acc:
        if i in "IXCM":
            count += i
            if len(count) > 3:
                return False
         else:
             return False
    else:
        count = i
    acc = i
brisk inlet
#

n would be test_case?

ruby panther
#

and you only return True at the end of the funktion when all controlls passed through because you only reach this, when no return False where the case

ruby panther
brisk inlet
#

and what about acc?

#

would I need to change acc into something else, or am I good?

brisk inlet
ruby panther
#

sorry for my bad english

brisk inlet
#

it's alright

#

but I think I am all set, my code now works, and there is no errors, Thank you Sean

ruby panther
#

no problem

#

but important change acc = test_case[0] not acc = [0]

brisk inlet
#

already did

grizzled spindleBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.