Python Forum
i scored 1/8 on python assessment where did i mess up?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
i scored 1/8 on python assessment where did i mess up?
#1
This wasn't assessment given by an instructor in class it was to test for a tech talent development program through a recruiter etc so there's no way of asking for an explanation on what's incorrect.

goal: Stack plates, one on top of another. A larger plate cannot be stacked on top of a smaller plate. Plates are ordered from the largest at the bottom, to the smallest at the top.

The plate "stack" is represented as a Python list. The bottom plate is the first index. The stack can grow to any size. A plate is represented by a positive integer, which is also the plate's size.

High Level Requirements: Add a plate: add a plate to the top of the stack. Print plates: display the stack of plates in the terminal. Remove plates: remove 1-to-n plates from the top of the stack.

Requirements Add a Plate Add a plate to the top of the stack. Plates are represented by a positive integer. If the plate is less than or equal to zero, issue a warning and don't add the plate.

If there are no plates on the stack, add it.

The plate "below" must be greater than or equal to the current plate size. If the current plate is too big, issue a warning and don't add the plate. If not, add it to the top of the stack.

Prints plates to the terminal.

Plates should stack vertically, with the largest plate on the bottom and the smallest plate on the top.

If there are no plates, display a message.

Remove Plates Remove a given number of plates from the top of the stack. The value should be a positive integer. If the value is less than or equal to zero, reject the operation and issue a warning.

If there are too many plates selected, reject the operation and issue a warning. Otherwise, remove plates from the stack and print a message.

Technical Requirements Use a Python list to track plates. Don't define the list inside a function. Keep it at file scope. Each menu item should be a function. You can add additional utility functions as well. (This isn't a hard requirement. You can solve the problem any way you see fit.) To collect positive integers from the user, convert the string value from the input function to an integer using the int function.
Plates =[]
def addplate() :
   
   addplate =int(input(" enter number of plates "))
   while addplate >= min(Plates, default =100000000000) :
      print(" Plate has to be smaller then previous entry")
      
      addplate =int(input(" enter number of plates "))
   else:
    Plates.append(addplate)



def printplate():
   print("plates: ")
   if len(Plates) == 0 :
      print(" there are no plates")
   elif len(Plates) > 0:
      print( *sorted(Plates,reverse = True,))

def removeplate():
   addplate =int(input(" enter number of plates "))
   while addplate > min(Plates, default =0):
      print( " You cannot subtract more then "+ str(min(Plates)) + " plates ")
      addplate =int(input(" enter number of plates "))
   if addplate in Plates:
    subtract =Plates.remove(addplate) 
    print(f" {addplate} plates removed,sucess ")
   else:
      print(" number of plates not found")
def run():
 
    print( "")
    number = ""
    while number != "4":
        
        print( " 1. Add a plate ")
        print( " 2. Print Plates")
        print( " 3. Remove Plates")
        print( " 4. Exit ")
        number = input(" select a number : ")
       
        if number == "1" :
           addplate()
        elif number == "2" :
           printplate()
        elif number == "3" :
           removeplate()
       
        elif number == "4" : 
         print(" thanks for playing ")
        else: 
           print(" error ")

   run()
Reply
#2
From what I am reading, you got quite a fair grade. Ok, here we go. First, let's look at your assignment specification.
goal: Stack plates, one on top of another
You have to build a version of a data structure called Stack.
Now, read requirements to the add_plate function. You have 2 requirements, basically
  1. The argument to the function must be a positive integer greater than zero
  2. Each new plate must be smaller than the last or of the same size.

Now, let's look at your function

def addplate() :
    
   addplate =int(input(" enter number of plates "))
   while addplate >= min(Plates, default =100000000000) :
      print(" Plate has to be smaller then previous entry")
       
      addplate =int(input(" enter number of plates "))
   else:
    Plates.append(addplate)
You do not have an argument in your function, your prompt is incorrect and you are doing a very inefficient check that will perform a linear search every time you try to do it and you also do not check for negative numbers and 0. You are also overwriting your function name with a local variable, which can cause issues. Also, you should not put a user input request inside a function like this. Overall it's just bad design. This function should be something like this:
def add_plate(p: int) -> bool:
    if p < 0:
        return False
    if len(Plates) > 0 and p > Plates[-1]:
        return False
    Plates.append(p)
    return True
I am assuming the global variable list as you have now, which was the requirement. The reason you return a boolean is for your user interface to handle the error message that the addition failed, instead of putting that inside your data structure.

Your printplates function prints a list as a data structure instead of printing plates, and it also sorts the list, which is the wrong thing to do. You only should iterate over your plates and print them.

Your removeplate for some reason does the same logic as addplate, but it shouldn't do that because it only specified how many plates to remove and the number for obvious reasons should be greater than 0. Overall the whole logic of this function is incorrect, you should use pop() instead.

If you fix these issues, then modify your interface to use them correctly, you would have overall a better program.
Reply
#3
You are clearly a very inexperienced Python coder, but don't be too dismayed by this assessment: there is not one of use here, that did not have a learn Python, from first principles, so learn from your mistakes and apply what you've learn so that you can improve your skills.

I'll use your menu as an example of just some of your coding errors:

You have print( " 1. Add a plate "), which is wrong. There should not be a space before the first quotation mark, so it should look like this:
print(" 1. Add a plate ")

When coding a menu like that, you could use something like this:

def display_menu(*items):
    """
    display the menu items and return the chosen option
    takes one tuple object as its argument
    """
    options = [str(option) for option in range(1, len(items)+1)]
    selected = ""
    while selected not in options:
        for index, option in enumerate(options):
            print(f"{options[index]}: {items[index]}")
        print()
        selected = input("    Option: ")
    return selected

option = display_menu(
    "Add a plate",
    "Print plates",
    "Remove plates",
    "Exit"
    )
That function code can be reused for a number of different applications, by simply changing the tuple object that is passed to it. It also error checks the user input, which is something that should always be done, whenever a application gets any user input. This is basic security and should never be omitted: your code never checks any of the user input.

As another general observation: you have not one docstring in the entire code base. Every function and every module should have a docstring.

There are other fundamental errors in your code, but that's down to your inexperience and you'll learn as you go, so keep a copy of your code and look back on it from time to time. I have many scripts that I coded years back, and when I look at them now, I can see just how green I was and how much I've learned; do the same.
Sig:
>>> import this

The UNIX philosophy: "Do one thing, and do it well."

"The danger of computers becoming like humans is not as great as the danger of humans becoming like computers." :~ Konrad Zuse

"Everything should be made as simple as possible, but not simpler." :~ Albert Einstein
Reply
#4
I've been thinking about how my "menu function" could be made to work even better, for any cli app that needs a options menu, and I've come up with this.

def display_menu(items):
    """
    display the menu items and return the chosen option
    takes one tuple object as its argument
    """
    print()
    print("\tApp Menu\n")
    options = [str(option) for option in range(1, len(items) + 1)]
    selected = ""
    while selected not in options:
        for index, option in enumerate(options):
            print(f"\t{options[index]}: {items[index]}")
        print()
        selected = input("\tOption: ")
    return items[int(selected) - 1]

# set up
app_menu = {
    "Add a plate": add_a_plate,
    "Print plates": print_plates,
    "Remove plates": remove_plates,
    "Exit": app_exit,
}
options = tuple(app_menu.keys())

while True:
    option = display_menu(options)
    app_menu[option]()
It's a first draft and maybe someone will come along and offer some constructive criticism, but on the face of it, I see no reason why this would be a bad idea.

The idea I have is to have a system that could be modified, in very simple way, to fit almost any cli app where a said app needs a options menu, and do away with all that tedious if/else stuff, for the action of whatever option a user has chosen. So, to use this in such a way, one would only need to modify the dictionary object, with a new set of options and function names, to reflect whatever app it's being used with.
Sig:
>>> import this

The UNIX philosophy: "Do one thing, and do it well."

"The danger of computers becoming like humans is not as great as the danger of humans becoming like computers." :~ Konrad Zuse

"Everything should be made as simple as possible, but not simpler." :~ Albert Einstein
Reply
#5
It is really important to follow instructions. This is the first requirement:
Quote:Add a Plate Add a plate to the top of the stack.
Plates are represented by a positive integer. If the plate is less than or equal to zero, issue a warning and don't add the plate.
If there are no plates on the stack, add it.
The plate "below" must be greater than or equal to the current plate size. If the current plate is too big, issue a warning and don't add the plate. If not, add it to the top of the stack.
Compare to what you did:
def addplate() :
    
   addplate =int(input(" enter number of plates "))
   while addplate >= min(Plates, default =100000000000) :
      print(" Plate has to be smaller then previous entry")
       
      addplate =int(input(" enter number of plates "))
   else:
    Plates.append(addplate)
The instruction said add a plate, not add multiple plates. That is a fail right there. Additionally, the instructions say the plate size must be an int >= 0. If the plate size is not an int >= 0 you are supposed to "issue a warning". Your code does not test if the plate size is >= 0.

Finally, the instructions say that you cannot place a larger plate on top of a smaller plate. If the new plate is too large you should issue a warning. Your program fails to do this also.

Of the three requirements for the function your code successfully implemented none of them. The most damning thing is that none of the problems are related to coding, they are all not understanding the requirements. That is the works mistake you can make.

You do a little better on print plates. The requirements.
Quote:Prints plates to the terminal.
Plates should stack vertically, with the largest plate on the bottom and the smallest plate on the top.
If there are no plates, display a message.
This is your code:
def printplate():
   print("plates: ")
   if len(Plates) == 0 :
      print(" there are no plates")
   elif len(Plates) > 0:
      print( *sorted(Plates,reverse = True,))
You correctly print a message if there are no plates, and you print the plates if there are plates on the stack. Good job! But there is another indication that you don't understand the requirements. If the stack starts out empty, and you are never allowed to stack a larger plate on top of a smaller plate, the plates will always be sorted from largest (at the front of the stack) to smallest (at the end of the stack). There is no need to sort the plates. The instructions also mention the stack is vertical, and I would take that as a hint to print the stack vertically instead of horizontally. You get half credit here.

These are the requirements for remove plates:
Quote:Remove Plates
Remove a given number of plates from the top of the stack. The value should be a positive integer. If the value is less than or equal to zero, reject the operation and issue a warning.
If there are too many plates selected, reject the operation and issue a warning. Otherwise, remove plates from the stack and print a message.
This is your code:
def removeplate():
   addplate =int(input(" enter number of plates "))
   while addplate > min(Plates, default =0):
      print( " You cannot subtract more then "+ str(min(Plates)) + " plates ")
      addplate =int(input(" enter number of plates "))
   if addplate in Plates:
    subtract =Plates.remove(addplate) 
    print(f" {addplate} plates removed,sucess ")
   else:
      print(" number of plates not found")
The requirements say enter the number of plates to remove. If the value entered is not an int > 0, print a message. There is no entry verification in your code.

The requirements say that the requested number cannot exceed the number of plates in the stack. You do this check, but the corrective action is to print a message. You print a message, but you also allow entering a different count. That's not what were asked to do. I suppose you could call it a refinement, but it is implemented in a clumsy way. What if I enter too large a count the second time? You do not test.

If you enter a valid count, the function should remove that number of plates from the top of the stack and print a message. Your code runs off the rails here and does something completely different. It removes 1 plate, and only removes 1 plate if the plate size equals the number entered when the program asked the user how many plates they wanted to remove. If the count entered does not match any of the plate sizes, the program crashes with a ValueError.

Then you have a statement that makes it look like you don't know python, or maybe that you are just lazy. Both are bad impressions.
subtract =Plates.remove(addplate) 
list.remove(x) removes the first occurrence of x in list. The list is modified, and the function returns None. If the list is not modified the program crashes. Never is there a time when Plates.remove(addplate) will return a useful value, yet you save this value in a variable named "subtract" that you never use.

Your run() function is pretty good. You were smart to not convert the user input to a number. This is likely where you got your 1 point. I would give you 2. Unfortunately you either misread of misunderstood the requirements and most of your code is solving the wrong problem. Nex time you do something like this, re-read the instructions until you are positive you understand what is being asked.
Reply
#6
I don't know much about classes, but I found this example of a stack in a book, well, not about plates, but easily adaptable. It might be just what you needed. Of course, you can change it, modify it, to do what you want. Stacks are LIFO, Last In First Out (unless you try to pull plates from the bottom of the stack, FIFO, and topple the whole pile!

class Plates:
    def __init__(self):
        self.plates = []
    def isEmpty(self):
        return self.plates == []
    def push(self, item):
        if self.isEmpty():
            self.plates.append(item)
        elif item > self.plates[-1]:
            return f'Error: you shouldn\'t stack a bigger plate {item} on a smaller plate {self.plates[-1]}'
        else:
            self.plates.append(item)
    def pop(self):
        if self.isEmpty():
            return 'No plates to pop!'
        else:
            return self.plates.pop()
    def peek(self):
        if self.isEmpty():
            return 'No plates in the pile!'
        return self.plates[len(self.plates)-1]
    def size(self):
        return len(self.plates)

P = Plates()
P.isEmpty() # returns True
for p in range(100, 70, -5):
    for q in range(3):
        P.push(p)
P.push(120) # returns "Error: you shouldn't stack a bigger plate 120 on a smaller plate 75"
P.peek()
for p in P.plates:
    print('Plates, from bottom to top are:', p)
P.size()
P.pop()
I hope the people here who know about classes can improve it!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Doctesting a function which prints a students name along with the maximum mark scored sean1 5 2,294 Feb-01-2022, 12:20 PM
Last Post: Pedroski55

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020