4

I am writing a simple program that calculates a random addition math problem, and asks the user to enter the answer.

When the user enters an answer, the computer inputs the entered keys from left to right. I want the input to do the opposite: from right to left.

img

http://euclidmagazine.com/2010/12/why-do-we-carry-in-addition/

Of course, the way addition works is that you add the column on the rightmost side first - the single digits, then the ten's and hundred's, ect.

For example, if I type the answer to this addition problem above (635), and I type it in that order (6 then 3 then 5), I want the 6 to appear under the 9 + 6, then when I type 3 I want it to move the 6 (to the left) under the 5 + 7 and the 3 will appear under the 9 + 6, and then when I enter the 5 it moves the 6 under the 3 + 2, moves the 3 under the 5 + 7, then place the 5 under the 9 + 6.

Is there an alternative input function or module that I can use for this? Or a super-secret technique that you have? Thanks.

Here is my code:

# MAIN
def main():

    keepGoing = "Y"
    while keepGoing == "Y":
        keepGoing = "N"
        entranceMessage()
        number1, number2 = calculateProblem()
        userInput = getInput(number1, number2)
        calculateResults(userInput, number1, number2)
        keepGoing = input("Would you like to try another problem? \
(Enter \"Y\" for \"Yes\", or any other key for \"No\".): ")
    exitMessage()

# DISPLAY OPENING MESSAGE
def entranceMessage():

    print()
    print("2. Math Quiz (Page 235)")
    print("This program will prompt you to answer a series of random mathematical problems.")

# INPUT
def getInput(number1, number2):

        print("Answer the following math problem: ")
        print("")
        if (number1 < 10):
            print("  ", number1)
        else:
            print(" ", number1)
        if (number2 < 10):
            print("+ ", number2)
        else:
            print("+", number2)
        print("_____")
        print("          ")
        result = (number1 + number2)
        if (result >= 100):
            userInput = float(input(" "))
        elif ((result >= 10) and (result < 100)):
            userInput = float(input("  "))
        elif ((result >= 0) and (result < 10)):
            userInput = float(input("   "))
        return userInput


# PROCESS
def calculateProblem():

    import random
    number1 = random.randint(1, 100)
    number2 = random.randint(1, 100)
    return number1, number2

# OUTPUT
def calculateResults(userInput, number1, number2):

    result = (number1 + number2)
    if (userInput == result):
        print()
        print("Correct!")
    else:
        print()
        print("Sorry, the answer is:", result)


# DISPLAY CLOSING MESSAGE
def exitMessage():

    print("Thank you. Exiting the program..")

# CALL THE MAIN FUNCTION    
main()

If you notice that in my code in the function "getInput" (the last If-elif), at the very end it I have one method that places the initial cursor at a correct alignment pertaining to what the answer would be, but (A) This sort of gives a clue to what the answer would be, (B) Its not what I want.

Veedrac
  • 58,273
  • 15
  • 112
  • 169
Donald
  • 633
  • 5
  • 16
  • Just for clarity. Do you read a whole number or each digit separately? If you have the wohle number the problem is just reversing digits and right aligning your output text. – isaias-b Jun 14 '14 at 20:22
  • No, I am asking the user for input and I want it to do what I want in real-time. – Donald Jun 14 '14 at 20:31
  • If you notice that in my code in the function "getInput" (the last If-elif), at the very end it I have one method that places the initial cursor at a correct alignment pertaining to what the answer would be, but (A) This sort of gives a clue to what the answer would be, (B) Its not what I want. – Donald Jun 14 '14 at 20:34
  • your formatting requires one extra indention or 4 spaces ;) – isaias-b Jun 14 '14 at 20:39
  • You mean for a 3rd elif line? No, my random number generators only go up to 100 each. Plus they are integers so no decimal(s). – Donald Jun 14 '14 at 20:48
  • Still one question. You want the user to type in the numbers from L2R so that 635. Each digit should be processed separately as you said. What do you expect to happen after the user typed in the 6 where it should appear? On the very right? then after typing 3 the three stands on the very right and the previous 6 in front of the 3 and so on?? – isaias-b Jun 14 '14 at 20:49
  • I just realize that the tags dont work inside comments. hehe – isaias-b Jun 14 '14 at 20:50
  • As you already mentioned, i think you will always need to guess what the user will type in, in order to put the digits to their correct positions from the beginning. Or you require the user to type in the digits from R2L – isaias-b Jun 14 '14 at 20:56

2 Answers2

1

This worked for me on a UNIX system, using getch from this answer to read a single character from input.

import sys

def cursor_left():
    """Print control characters to move the cursor left one column."""
    sys.stdout.write(chr(27) + '[D')  # 27 is ESC

def print_blank(number):
    """Print blank character a given number of times."""
    for i in range(0, number):
    sys.stdout.write(" ")

def right_to_left_input(number_of_digits):
    """Have user input a number from right to left, digit by digit."""
    print_blank(number_of_digits)
    digits = ""
    while (1):
    cursor_left()
        userInput = getch()
    sys.stdout.write(userInput)
    digits = userInput + digits  # string concatenation, not addition
        if (len(digits) >= number_of_digits):
        break
    cursor_left()
    return(digits)

See this page for control sequences for moving the cursor around on an xterm.

Or, depending on the operating system or shell you're using, you could backspace over the last few characters and reprint them each time?

See also this chart of control characters. Try ASCII 8 (backspace); ASCII 127 (delete); or ASCII 10 (line feed; if you do line feed but no form feed it may allow you to retype over the same line again on some systems.)

You can print chr(8), for example, to print ASCII character 8 (backspace).

See this answer for how to read a single character at a time from the user.

If you get an error trying to run getch, the following code might still work; it worked for me on a UNIX system; but it requires the user to press enter after each digit. It assumes the user only enters one digit at a time.

def cursor_up():
    """Print control characters to move the cursor up one line."""
    sys.stdout.write(chr(27))  # ESC
    sys.stdout.write(chr(91))  # [
    sys.stdout.write(chr(65))  # A

def backspace(number):
    """Print backspace character a given number of times."""
    for i in range(0, number):
        sys.stdout.write(chr(8))  

def print_blank(number):
    """Print blank character a given number of times."""
    for i in range(0, number):
        sys.stdout.write(" ")

def print_cursor():
    sys.stdout.write("_")  # use as cursor

def right_to_left_input(number_of_digits):
    digits = ""
    print ""
    cursor_up()
    while(1):
        have_digits = len(digits)
        if(have_digits >= number_of_digits):
            break
        print_blank(number_of_digits - have_digits)
        print_cursor()
        sys.stdout.write(digits)
        print_blank(1)   # overwrite the user's previous input
        backspace(have_digits + 2)   # move back to cursor position
        userInput = sys.stdin.readline()
        cursor_up()  # undo the carriage-return entered by the user.
        digit = userInput[0]    # first character in string
        digits = digit + digits  # string concatenation, not addition
    return(digits)
Community
  • 1
  • 1
Linguist
  • 849
  • 7
  • 5
1

If you're on a Unix-based system, one way to do this would be to use the curses library. Curses is commonly used for advanced terminal manipulation, and makes it possible to write text anywhere in a terminal, change font color, etc, and variants are available for languages other than Python (including C) as well. It's also commonly used for text-based games like Rogue.

Here's a link to the official documentation.

Here's a good tutorial.

PandaConda
  • 3,396
  • 2
  • 20
  • 22