2
\$\begingroup\$

I have written a program that simulates a TickeTron and allows the user to book seating in a virtual audience. The virtual audience is read in from a text file which will be included below. The program does work when run but I feel there are ways to greatly increase the efficiency of the program. Ugly code is a pet peeve of mine!

The program is slightly lengthy and therefore heavily commented so it is easier to follow along. The code is as follows:

#Purpose: Write a program that prompts users to pick either a seat or a #price.
#Mark sold seats by changing the price to 0. When a user specifies a seat, #make sure it is available.
#When a user specifies a price, find any seat with that price.

import csv
print("Welcome to TickeTron!")

# Format the text file
seats = open("tickets.txt", 'r')
seatsRead = open("tickets.txt", 'r').read()

# Convert the reader data into a formatted table/2d list (lines 18 to 24)
reader = csv.reader(seats)
seatsList = []
for row in list(reader):
    newRow = []
    # Add each seat into the row as an int
    for seat in row[0].split(" "):
        newRow.append(int(seat))
    # Add the row to the table
    seatsList.append(newRow)

# Convert a row index to an ascii row letter (EX: 0 -> A, 1 -> B, ...)
def rowToLetter(row):
    return chr(97+row)

# Convert a ascii row letter to a row index (EX: A -> 0, B -> 1, ...)
def letterToRow(letter):
    return ord(letter.lower())-97

# Get the seat price from the table with the highest number of digits
def getLongestSeatLength():
    largest = len(str(seatsList[0][0]))
    for row in seatsList:
        for seat in row:
            if len(str(seat)) > largest:
                largest = len(str(seat))
    return largest

# Print a table populated with the formatted text file
def printSeats():
    longest = getLongestSeatLength()
    numbers = "   "
    # Calculate the columns header for the table (1 2 3 4 5 6 7 8 9)
    for i in range(len(seatsList[0])):
        padding = longest-1
        numbers += " "*padding + str(i) + " "
    print(f"\n{numbers}")

    for row in range(len(seatsList)):
        # Print the row header (A B C D E F G H I)
        print(chr(65+row) + "  ", end="")
        # Calculate the position of each seat in the table
        for seat in seatsList[row]:
            padding = longest-len(str(seat))
            print(" "*padding + str(seat), "", end="")
        print()
    print()

print("Here is a listing of all available seats:")

printSeats()

# Check if a seat is available for purchase (seat price is not zero in seatsList)
def seatAvailable(row, col):
    return seatsList[row][col] != 0

def purchaseSeat(seat, cost=-1):
    row = letterToRow(seat[0])
    col = int(seat[1])
    # Only run next lines if the seat is available and the price is equal to the required price
    if seatAvailable(row, col) and (cost == -1 or seatsList[row][col] == cost):
        print("Your seat is now at %s%d!" % (rowToLetter(row).upper(), col))
        seatsList[row][col] = 0
        printSeats()
        return True
    # Print an error if the seat is not available
    elif not seatAvailable(row, col):
        print("That seat is unavailable. Please try again.")
        return False
    # Print an error if the requested seat does not have the required price
    else:
        print("Seat %s%d is not worth $%d. Please try again." % (rowToLetter(row).upper(), col, cost))
        return False

def findSeat(seatsList):
    selection1 = " "
    # Continue asking the user to purchase a seat until selection1 is not empty
    while (selection1 != ""):
        selection1 = str(input("Would you like to purchase a specific seat? "))
        if selection1.lower() == "y" or selection1.lower() == "yes":
            seat = str(input("Please enter the specific seat you wish to purchase: "))
            # If the purchase is not successful, ask the user again
            if len(seat) > 2:
                print("Sorry, it seems you have entered an incorrect input.")
                continue
            if not purchaseSeat(seat):
                selection1 = " "
        elif selection1.lower() == "n" or selection1.lower() == "no":
            selection2 = str(input("Would you like to purchase a seat for a specific price? "))
            if selection2 == "y" or selection2 == "yes":
                price = int(input("Please enter the price you would like to pay: ").replace("$", ""))
                seat = str(input("Please enter the specific seat you wish to purchase: "))
                # If the purchase if not successful, ask the user again
                if not purchaseSeat(seat, price):
                    selection1 = " "
            else:
                selection1 = ""

findSeat(seatsList)
print("Very well, ending the program.")

The text file (named "tickets.txt"):

10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 10 10 10 10 10 10 10 10
10 10 20 20 20 20 20 20 10 10
10 10 20 20 20 20 20 20 10 10
10 10 20 20 20 20 20 20 10 10
20 20 30 30 40 40 30 30 20 20
20 30 30 40 50 50 40 30 30 20
30 40 50 50 50 50 50 50 40 30

If you happen to spot a better way to implement any of my methods, please leave a comment letting me know.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ This code doesn't follow the assignment: "When a user specifies a price, find any seat with that price." So when a specific price is chosen, the code should automatically pick a seat of that price. But this code makes the user choose either a specific seat, or BOTH price and seat. \$\endgroup\$
    – Sedsarq
    May 23, 2019 at 7:52
  • \$\begingroup\$ Yes, unfortunately I am required to implement this test case case, regardless of it being quite inefficient. \$\endgroup\$ May 23, 2019 at 15:26
  • \$\begingroup\$ I don't think you understood me. As I understand it, you haven't done what the assignment says. Or am I the one misunderstanding the assignment? \$\endgroup\$
    – Sedsarq
    May 23, 2019 at 15:32

1 Answer 1

4
\$\begingroup\$
  1. You have very bad code ordering. Function definitions blocks contains main code between them, the start of the script is in the start of the file etc. There is a code convention for most languages: classes first, methods/functions second and main code third. Your code looks like this:

    import csv
    print("Welcome to TickeTron!")
    seats = open("tickets.txt", 'r')
    seatsRead = open("tickets.txt", 'r').read()
    reader = csv.reader(seats)
    seatsList = []
    for row in list(reader): ...
    
    def rowToLetter(row): ...
    def letterToRow(letter): ...
    def getLongestSeatLength(): ...
    def printSeats(): ...
    
    print("Here is a listing of all available seats:")
    
    printSeats()
    
    def seatAvailable(row, col):...
    
    def purchaseSeat(seat, cost=-1): ...
    
    def findSeat(seatsList): ...
    
    findSeat(seatsList)
    print("Very well, ending the program.")
    

    But should looks like this:

    import csv
    
    
    def rowToLetter(row): ...
    def letterToRow(letter): ...
    def getLongestSeatLength(): ...
    def printSeats(): ...
    def seatAvailable(row, col):...
    def purchaseSeat(seat, cost=-1): ...
    def findSeat(seatsList): ...
    
    print("Welcome to TickeTron!")
    seats = open("tickets.txt", 'r')
    seatsRead = open("tickets.txt", 'r').read()
    reader = csv.reader(seats)
    seatsList = []
    for row in list(reader): ...
    print("Here is a listing of all available seats:")
    printSeats()
    findSeat(seatsList)
    print("Very well, ending the program.")
    

  1. You are opening the file twice and don't close it later in your program. Don't do it, please. If you want to read file, you can replace this block of your code:

    # Format the text file
    seats = open("tickets.txt", 'r')
    seatsRead = open("tickets.txt", 'r').read()
    
    # Convert the reader data into a formatted table/2d list (lines 18 to 24)
    reader = csv.reader(seats)
    seatsList = []
    for row in list(reader):
        newRow = []
        # Add each seat into the row as an int
        for seat in row[0].split(" "):
            newRow.append(int(seat))
        # Add the row to the table
        seatsList.append(newRow)
    

    with this:

    with open("tickets.txt", 'r') as f:  # File will be automatically closed
        reader = csv.reader(f)
        for row in reader:
            seatsList.append([int(seat) for seat in row[0].split(" ")])
    

  1. getLongestSeatLength() just iterates through seats and searches for a maximum. Python has max() function so the whole your function can be replaced with this code using generators:

    def getLongestSeatLength():
        return max(len(str(seat)) for seat in row for row in seatsList)
    

  1. printSeats() is pretty OK. There are improvements that can be done, but mostly minor. One point - if I will write this program, I will try to avoid chr-ord transitions. I think they are rather confusing.

  1. input() returns strings so there is no need to wrap it with str(), like in your code:

    str(input(...))

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for all the advice. I am still relatively new to python and am trying to ensure I can write complex programs with simplicity. Means a lot, thank you. \$\endgroup\$ May 26, 2019 at 17:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.