Need help about Arithmetic Formatter project

Hello guys,
I’m totally new in this world, python is first language that I’m learning. Just finished free code camp lessons and tried to complete this project. I passed all of situations that will return an error, but I’m struggling with arranging problems vertically. This is my code so far, I managed to align them if problems are 4 digit numbers, but when I try it with 2 digit numbers it gets really messed. Where is my mistake? Thanks!

def arithmetic_arranger(problems, i=False):
def init_check(a):
try:
broj = int(a)
return True
except:
return False

a = list()
nazivnik = list()
brojnik = list()
operacija = list()
for lines in problems:
    a.append(lines.split(" "))
for line in a:
    nazivnik.append(line[0])
    brojnik.append(line[2])
    operacija.append(line[1])

if len(problems) > 5:
    return "Error: Too many problems."
for x in operacija:
    if x == "+" or x == "-":
        continue
    else:
        return "Error: Operator must be '+' or '-'."
for y in nazivnik:
    if len(y) > 4:
        return "Error: Numbers cannot be more than four digits."
    else:
        continue
for z in brojnik:
    if len(z) > 4:
        return "Error: Numbers cannot be more than four digits."
    else:
        continue
for xy in nazivnik:
    if init_check(xy) is False:
        return "Error: Numbers must only contain digits."
for xz in brojnik:
    if init_check(xz) is False:
        return "Error: Numbers must only contain digits."

def print_if_false():
    lista = list()
    for x in range(len(nazivnik)):
        lista.append(len(nazivnik[x]) - len(brojnik[x]))
    count = 0
    for x in range(len(nazivnik)):
        razmak = lista[x]
        space = " "
        print(space.ljust(razmak), "{:>3}".format(nazivnik[x]), end="    ")
        count = count + 1

        if count == len(nazivnik):
            print("")
            for y in range(len(brojnik)):
                razmak = lista[y]
                print(operacija[y].ljust(razmak-1), "{:>3}".format(brojnik[y]), end="    ")


if i is False:
    print_if_false()

Edit: This is function call example where it goes wrong, if I got same digits numbers it works, but in this situation not
arithmetic_arranger([“326 + 2642”, “16 - 252”, “452 + 452”, “152 + 42”])

can you explain what are you trying to achieve with this code?

Sure, This is what I’m trying to achieve :

example

And this are rules of that:

  • There should be a single space between the operator and the longest of the two operands, the operator will be on the same line as the second operand, both operands will be in the same order as provided (the first will be the top one and the second will be the bottom.
  • Numbers should be right-aligned.
  • There should be four spaces between each problem.
  • There should be dashes at the bottom of each problem. The dashes should run along the entire length of each problem individually. (The example above shows what this should look like.).

Today I managed to allign digits no matter what is their lenght, but I can’t complete this condition: “single space between the operator and the longest of the two operands”.
Don’t worry about dashes I know how to do that part, but useless untill i manage upper part.
This is my updated code that I worked on:

def arithmetic_arranger(problems, i=False):
    def init_check(a):
        try:
            broj = int(a)
            return True
        except:
            return False

    a = list()
    nazivnik = list()
    brojnik = list()
    operacija = list()
    for lines in problems:
        a.append(lines.split(" "))
    for line in a:
        nazivnik.append(line[0])
        brojnik.append(line[2])
        operacija.append(line[1])

# Part where I'm checking for errors
    if len(problems) > 5:
        return print("Error: Too many problems.")
    for x in operacija:
        if x == "+" or x == "-":
            continue
        else:
            return print("Error: Operator must be '+' or '-'.")
    for y in nazivnik:
        if len(y) > 4:
            return print("Error: Numbers cannot be more than four digits.")
        else:
            continue
    for z in brojnik:
        if len(z) > 4:
            return print("Error: Numbers cannot be more than four digits.")
        else:
            continue
    for xy in nazivnik:
        if init_check(xy) is False:
            return print("Error: Numbers must only contain digits.")
    for xz in brojnik:
        if init_check(xz) is False:
            return print("Error: Numbers must only contain digits.")
# print alligned problems
    def print_if_false():
        lista = list()
        for x in range(len(nazivnik)):
            lista.append(len(nazivnik[x]) - len(brojnik[x]))
        count = 0
        for x in range(len(nazivnik)):
            space = " "
            print(space.rjust(1), "{:>4}".format(nazivnik[x]), end="    ")
            count = count + 1
        
            if count == len(nazivnik):
                print("")
                for y in range(len(brojnik)):
                    print(operacija[y], "{:>4}".format(brojnik[y]), end="    ")

    if i is False:
        print_if_false()
#Code caller
arithmetic_arranger(["2222 + 4443", "54 - 35", "54 + 2", "225 + 44"]) 

This is my output:

output

Can’t put 2 images in 1 post sorry.

ok, if I’m getting it right (and analyzing the one-operation case):
you could possibly define two lines and then print them:

first_line = "  "  # two spaces
second_line = operator + " "  # the operator (+ or -) and one space

shift = len(first_operand) - len(second_operand)  # like len('54') - len('4')
if shift < 0:
    first_line += ' '*(shift*(-1))
elif shift > 0:
    second_line += ' '*shift

# now add each operand to each line
first_line += first_operand
second_line += second_operand

# then just print the two lines
print(first_line, second_line, sep='\n')

some advice for your code:

  • comment it as much as possible: it will be more readable for others (and for a future-you)
  • name variables and functions in the most self-explaining way you can (it will improve readability too)
1 Like

important distinction: you still need to return the numbers, not just print them

1 Like

yes, of course. I printed them only to complete my snippet

1 Like

Thanks a lot guys, let me try to implement that into my code. I’m on work atm so got only online compiler its a bit messy for me. As I’m used to work in py charm

1 Like

I just figured out that my “only digits check” don’t work so have to fix that first haha, seems like its an infinite loop

Using regex for input validation would be the best practice

2 Likes

Just 1 more question, should i use return print(“erorr:”)
to display error ? When I copy code into test module with print joined next to return its failure, and without print it’s correct. But my question is how would user know what he did wrong if its not printed out for him

you need to follow the requirements

also return print() doesn’t work because print returns Null (or None, something like that), and that means that the function ends without an output

I explained it in wrong way.
when i try with return “Error: Numbers must only contain digits.” – Test module check it as correct
but when i try it return print( “Error: Numbers must only contain digits.”) its failure

yes, because print’s returned value is None or Null or something like that, so that is what your function ends returning, which is not the expected value

Oh I think I get it now. Sorry in my lessons there wasn’t much of Def() explanation so I’m still learning that. So print should be after function ends and it will print if there is error right?

you should use a try/except block:

try:
     if (error_condition):
         raise ValueError("Error message you want to print")
except ValueError as error:
     print(error)
1 Like

the requirements for this challenge are about what the function should return, do not try to make it more complex than needed, it is not necessary

1 Like

Okay mate, ty guys for everything. You really helped me a lot. I was stuck on this alligned numbers for 2 days.

1 Like

I deleted function arranged_problems and now when I use print(arithmetic_arranger([“3 + 4855”, “3801 - 2”, “45 + 43”, “123 + 49”, “3801 - 2”], True)) for example or print(arithmetic_arranger([“3 + 4855”, “3801 - 2”, “45 + 43”, “123 + 49”, “3801 - 2”])). Everything is printed correctly. But when I post code in test It fails again. Don’t know where is problem really. (posting code without calling function ofc)

def arithmetic_arranger(problems, i=False):
    def init_check(a):
        try:
            broj = int(a)
            return True
        except:
            return False

    a = list()
    nazivnik = list()
    brojnik = list()
    operacija = list()

    for lines in problems:
        a.append(lines.split(" "))
    for line in a:
        nazivnik.append(line[0])
        brojnik.append(line[2])
        operacija.append(line[1])

    # Part where I'm checking for errors
    if len(problems) > 5:
        return "Error: Too many problems."
    for x in operacija:
        if x == "+" or x == "-":
            continue
        else:
            return "Error: Operator must be '+' or '-'."
    for y in nazivnik:
        if len(y) > 4:
            return "Error: Numbers cannot be more than four digits."
        else:
            continue
    for z in brojnik:
        if len(z) > 4:
            return "Error: Numbers cannot be more than four digits."
        else:
            continue
    for xy in nazivnik:
        if init_check(xy) is False:
            return "Error: Numbers must only contain digits."
    for xz in brojnik:
        if init_check(xz) is False:
            return "Error: Numbers must only contain digits."


    lista_gore = list()     # list for first line
    lista_dolje = list()    # list for second line
    lista_crte = list()     # list for lines under first and second line
    odmak = "    "      # space between operations
    for b in range(len(problems)):
        first_line = "  " + ""  # two spaces
        shift = len(nazivnik[b]) - len(brojnik[b])  # like len('54') - len('4')
        if shift < 0:
            first_line += " " * abs(shift)
        first_line += nazivnik[b]
        # print(first_line, end="    ")
        lista_gore.append(first_line + odmak)   # list of first line numbers on distance of 4 whitespaces

    for c in range(len(brojnik)):
        second_line = operacija[c] + " "  # the operator (+ or -) and one space
        shift = len(nazivnik[c]) - len(brojnik[c])
        if shift > 0:
            second_line += ' ' * shift
        second_line += brojnik[c]
        # print(second_line, end="    ")
        lista_dolje.append(second_line + odmak)     # list of second line numbers on distance of 4 whitespaces

    for d in range(len(nazivnik)):

        if len(brojnik[d]) > len(nazivnik[d]):

            crtice = "-" * (len(operacija[d]) + len(brojnik[d]) + 1)    # operator + len of upper number if upper number is greater than under number
            # print("-" * (len(operacija[d]) + len(brojnik[d]) + 1), end="    ")

        else:
            crtice = "-" * (len(operacija[d]) + len(nazivnik[d]) + 1)   # if under number is greater than upper number
            # print("-" * (len(operacija[d]) + len(nazivnik[d]) + 1), end="    ")
        lista_crte.append(crtice + odmak)   # list of dashes + shift of 4 whitespaces

    # aligned is all 3 lists joined with new line between
    aligned = "".join(lista_gore) + "\n" + "".join(lista_dolje) + "\n" + "".join(lista_crte)

    lista_rezultat = list()     # list for result if i is True
    for e in range(len(problems)):

        if operacija[e] == "+":     # if operator is + then upper numbers + under number
            add = str(int(nazivnik[e]) + int(brojnik[e]))
        else:       # if operator is - then upper numbers - under number
            add = str(int(nazivnik[e]) - int(brojnik[e]))
        line_1 = " "

        if len(nazivnik[e]) - len(brojnik[e]) == 0:     # if upper number - under number is 0:
            if operacija[e] == "+":     # operator is +
                if len(add) == len(nazivnik[e]) or len(add) == len(brojnik[e]):     # if lenght of sum = lenght of upper or lower number(44 = 22)
                    line_1 += line_1 + add
                    # print(line_1, end="    ")
                else:
                    line_1 += add
                    # print(line_1, end="    ")
            else:   # if operator is "-"
                if add[0] == "-":   # if result is negative number
                    line_1 += add
                    # print(line_1, end="    ")
                else:   # if result is positive number
                    line_1 += line_1 * len(nazivnik[e]) + add
                    # print(line_1, end="    ")

        elif len(nazivnik[e]) - len(brojnik[e]) == -1 or len(nazivnik[e]) - len(brojnik[e]) == 1:   # upper - lower is -1 or 1 (432-22, 22-432)
            if len(add) == len(nazivnik[e]) or len(add) == len(brojnik[e]):     # result = upper, or under number (22+22=44)
                line_1 += line_1 + add
                # print(line_1, end="    ")
            else:
                line_1 += add
                # print(line_1, end="    ")

        elif len(add) == len(nazivnik[e]) + len(brojnik[e]):    # result = upper + lower (999 + 2 = 1000)
            line_1 += add
            # print(line_1, end="    ")

        else:       # lenght between upper and lower num is greater than 1 or lowe than -1
            if add[0] == "-":   #
                line_1 += add
                # print(line_1, end="    ")

            else:
                line_1 += line_1 + add
                # print(line_1, end="    ")
        lista_rezultat.append(line_1 + odmak)   # list of results

    rezultat = "\n" + "".join(lista_rezultat)  # new line + list of results
    rjesenje = aligned + rezultat
    if i is False:
        return aligned
    if i is True:
        return rjesenje
type or paste code here

Okay guys I figured out what was the problems. It was 4 whitespaces after last operation. I finally did it !! Ty for tips. Have a great night