Problem in code


###  converting an integer number to a roman number

class py_solution:

    def int_roman(self,num):

# count iterations

        count = 0

# create a string to store the result

        answer = ""

# create a dictionary to store the roman numbers

        roman_num = {"M":1000,"D":500,"C":100,"L":50,"XX":20,"X":10,"V":5,"IV":4,"I":1}

# get floor division of num by the highest number

        for key,value in roman_num.items():

#Ensure that divisor is greater than value to pick the highest letter going down

            while num >= value:

                if num // value >= 1:

#Concatenate the letter for the first division

                    answer += key

                    print("the answer is ", answer)

# get the remainder of the division

                remainder = num - value

                print("the remainder is", remainder)

# Find the roman for the remainder

                if remainder // value == 0:

                    answer += key

                    print ("the second concatenation answer is", answer)

#If remainder is not wholly divisible send the num in the next iteration to check against the next value

                else:

                    num = remainder

                    print("number for the next iteration", remainder)

                    print("roman_num is", roman_num)

        count += 1

        print(count)

        return roman_num

print(py_solution().int_roman(1100))

After finding the value of the remainder variable in the code the rest of the code after that is not being executed, so just creating an infinite loop, cause the rest of the code is to make the while loop condition false, as it solves the problem, Please help

Thanks

here’s a walkthrough:

Starts with a while loop, followed with an if statment.

num // value = 1100 // 1000 = 1

The statement evaluates true, add the roman numeral to the answer.

this is outside the if statement, so it happens regardless of whether it executed.
remainder = 1100 - 1000 = 100

This is an if/else statement, if one happens the other does not

remainder // value = 100 // 1000 = 0

The if statement is satisfied and that code block is chosen over the else.
This ends the while loop block with num = 1100

Here instead of floor division, l wanted modulo operator

I have tried to correct it abit, but the next iterations seems to have problem with the logic of the code, it doesn’t work out


###  converting an integer number to a roman number

class py_solution:

    def int_roman(self,num):

# count iterations

        count = 0

# create a string to store the result

        answer = ""

# create a dictionary to store the roman numbers

        roman_num = {"M":1000,"D":500,"C":100,"L":50,"XX":20,"X":10,"V":5,"IV":4,"I":1}

# get floor division of num by the highest number

        for key,value in roman_num.items():

#Ensure that divisor is greater than value to pick the highest letter going down

            while num >= value:

                if num // value >= 1:

#Concatenate the letter for the first division

                    answer += key

                    print("the answer is ", answer)

# get the remainder of the division

                remainder = num - value

                print("the remainder is", remainder)

# Find the roman for the remainder

                if remainder % value == 0:

                    answer += key

                    print ("the second concatenation answer is", answer)

#If remainder is not wholly divisible send the num in the next iteration to check against the next value

                else:

                    num = remainder

                    print("number for the next iteration", remainder)

                    print("answer is", answer)

                count += 1

                print(count)

                return answer

print(py_solution().int_roman(1100))

return answer is being executed inside the while loop ending the entire function.
To help you troubleshoot, replace while num >= value: with while num >= value and count < 10: to prevent infinite loops.

What are you trying to accomplish with this piece of code, it looks redundant in conception.
edit: Perhaps the better question is what happens if you don’t find the roman numeral for the remainder and always run the else statement.

1 Like

I changed the code again and now it juts stops at the first iteration


###  converting an integer number to a roman number

class py_solution:

    def int_roman(self,num):

# count iterations

        count = 0

# create a string to store the result

        answer = ""

# create a dictionary to store the roman numbers

        roman_num = {"M":1000,"D":500,"C":100,"L":50,"XX":20,"X":10,"V":5,"IV":4,"I":1}

# get floor division of num by the highest number

        for key,value in roman_num.items():              

#Ensure that divisor is greater than value to pick the highest letter going down

                if num >= value:

                        if num // value >= 1:

#Concatenate the letter for the first division

                                answer += key

                                print("the answer is ", answer)

# get the remainder of the division


                        remainder = num - value

                        print("the remainder is", remainder)

                

                if num or remainder <= value:

# Find the roman for the remainder

                        if remainder % value == 0:

                                answer += key

                                print ("the second concatenation answer is", answer)

#If remainder is not wholly divisible send the num in the next iteration to check against the next value

                        else:

                                num = remainder

                                print("number for the next iteration", remainder)

                                print("answer is", answer)

                if num or remainder == 0:

                        return answer

                count += 1

                print(count)

        

print(py_solution().int_roman(1100))

Thanks

Having the while loop was a good idea, it just wasn’t really compatible with the remainder idea you’re working with. The if remainder statement I pointed out isn’t really different than the first if statement and the while loop instructs your program to repeat that first statement until it can’t remove another value from num.

To help with your code as written:

In an and/or if statement you have to define each statement, python reads that as these two statements:
if num:
or
if remainder == 0:

If number is truthy or remainder is 0, return out of the function
In this case the truthiness of number would mean non 0

so your function sees that num is 100 on the first iteration and returns ‘m’.

Something else to look at for efficiency:
What’s the difference between these statements?

if num >= value:
if num // value >= 1:

so what is the problem?

you are right it can be combined

thanks

Doing a return means the entire function ends, thus it doesn’t continue iterating
for key,value in roman_num.items():

You haven’t run into a problem with this yet, but remainder is only defined in the first if statement:

Once you get your code to iterate, try running the function with 900

But it only returns when the condition is met, which is when I want it to stop iterating

thanks

In that bit of code to end the function, if num is greater than 0 the code ends, that’s why it’s only doing one iteration.

if num = 1100 to start, at the end num will = 100 and it will return “M”

I think what you want is:

if num == 0 or remainder == 0:

which is not the same as

if num or remainder == 0:

###  converting an integer number to a roman number

class py_solution:

    def int_roman(self,num):

# count iterations

        count = 0

# create a string to store the result

        answer = ""

# create a dictionary to store the roman numbers

        roman_num = {"M":1000,"D":500,"C":100,"L":50,"XX":20,"X":10,"V":5,"IV":4,"I":1}

# get floor division of num by the highest number

        for key,value in roman_num.items():              

#Ensure that divisor is greater than value to pick the highest letter going down

                if num >= value and num // value >= 1:                      

                        answer += key

                        print("the answer is ", answer)

                        remainder = num - value

# get the remainder of the division

# ensure that remainder is non negative

                num = remainder

                print("the remainder is", remainder)

                if num == 0 or remainder == 0:

                        return answer

                

                if num < value or remainder < value:

# Find the roman for the remainder

                        if remainder % value == 0:

                                answer += key

                                print ("the second concatenation answer is", answer)

#If remainder is not wholly divisible send the num in the next iteration to check against the next value

                        else:

                                num = remainder

                                print("number for the next iteration", remainder)

                                print("answer is", answer)

                

                count += 1

                print(count)

        

print(py_solution().int_roman(900))

The program now works for 1100 but with 900, it shows the error below:

Traceback (most recent call last):
File “c:\Users\simmy.vscode\app.py”, line 50, in
print(py_solution().int_roman(900))
File “c:\Users\simmy.vscode\app.py”, line 28, in int_roman
num = remainder
UnboundLocalError: local variable ‘remainder’ referenced before assignment
PS C:\Users\simmy.vscode>

Thanks

This means that you’re trying to assign a variable name to an object that doesn’t exist. When you plug in 900, it’s less that your first iteration of the dictionary (“M”:1000) so your first if block doesn’t run.

Also, what I pointed out earlier about if num >= value and num // value >= 1: wasn’t that they could be combined. They’re mathmatically identical, if num >= value then num // value >=1, just pick one or the other.

Does that mean l need to define remainder, not sure how to Solve it

Thanks

You could start your code by setting remainder = num, but there isn’t really any point in using the extra variable. You can change num. Whenever you add a roman numeral, subtract that value from num.

1 Like

###  converting an integer number to a roman number

class py_solution:

    def int_roman(self,num):

# count iterations

        count = 0

# create a string to store the result

        answer = ""

# create a dictionary to store the roman numbers

        roman_num = {"M":1000,"D":500,"C":100,"L":50,"XX":20,"X":10,"V":5,"IV":4,"I":1}

# get floor division of num by the highest number

        for key,value in roman_num.items():              

#Ensure that divisor is greater than value to pick the highest letter going down

                if num >= value:

                        if num % value != 0:                      

                                answer += key

                                print("the answer is ", answer)

                                num = num - value

                        elif num % value == 0:

                               roman_needed = num // value

                               print("the roman needed is", roman_needed)

                               answer += (roman_needed * key)

                               print(f'the elif answer is {answer}')

                               num = num - (roman_needed * value)

                               print(f'the elif num is {num}')

# get the remainder of the division

# ensure that remainder is non negative

                

                print("the remainder is", num)

                if num == 0:

                        return answer

                

                if num < value:

# Find the roman for the remainder

                        if num % value == 0:

                                answer += key

                                print ("the second concatenation answer is", answer)

#If remainder is not wholly divisible send the num in the next iteration to check against the next value

                        else:

                                print("number for the next iteration", num)

                                print("answer is", answer)

                

                count += 1

                print(count)

        

print(py_solution().int_roman(900))

1 Like

Good job! Now, just have a look at this mod on your code and run it.

###  converting an integer number to a roman number

class py_solution:

    def int_roman(self,num):

# count iterations

        count = 0

# create a string to store the result

        answer = ""

# create a dictionary to store the roman numbers

        roman_num = {"M":1000,"D":500,"C":100,"L":50,"XX":20,"X":10,"V":5,"IV":4,"I":1}

# get floor division of num by the highest number

        for key,value in roman_num.items():              

#Ensure that divisor is greater than value to pick the highest letter going down

                if num >= value:

                        #if num % value != 0:                      

                        #        answer += key

                        #        print("the answer is ", answer)

                        #        num = num - value

                        #elif num % value == 0:

                               roman_needed = num // value

                               print("the roman needed is", roman_needed)

                               answer += (roman_needed * key)

                               print(f'the elif answer is {answer}')

                               num = num - (roman_needed * value)

                               print(f'the elif num is {num}')

# get the remainder of the division

# ensure that remainder is non negative

                

                #print("the remainder is", num)

                if num == 0:

                        return answer

                

                #if num < value:

# Find the roman for the remainder

                #        if num % value == 0:

                #                answer += key

                #                print ("the second concatenation answer is", answer)

#If remainder is not wholly divisible send the num in the next iteration to check against the next value

                #        else:

                #                print("number for the next iteration", num)

                #                print("answer is", answer)

                

                count += 1

                print(count)

        

print(py_solution().int_roman(900))

sorry bavarcarus for the late reply, what do you mean by mod

thanks

You got the right code in there to work, but there was a lot of repetition. I commented out the code that doesn’t need to be there.

Are you returning CM?

And what about XL and IX (40 and 9, respectively)?

1 Like

oh that is actually the correct way of writing it

1 Like