Python Forum
Pre-release practice help!
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pre-release practice help!
#1
Myself and a friend have been trying to do the pre-release of a previous year's iGCSE as practice. We tend to write short and simple code, rather than the 150+ line answers I've seen elsewhere. We fixed a few errors but there is one that we cannot fix, and neither can our teacher.

The code given is meant to ask you for how many sacks of each material you want, and then for how heavy each sack is. Then, using a self-made function the sacks are either accepted with their weight added to the total weight or rejected and put on to the rejected counter. Then at the end it prints the total weight of the accepted sacks and the number of sacks that were rejected.

The problem is that the total weight and rejected counter reset every time the code exits our function, resulting in it telling us that there is 0kg and 0 rejected sacks. Can anyone help without altering the code too dramatically? Thanks!

import sys
import time

#-------------------------------------------------------------------------------------------------------------------------------------------------------

def bag_check(material, weight, total_kg, rejected):
    valid_kg = False
    
    if material == "Sand" or material == "Gravel":
        if weight < 49.9:
            valid_kg = False
        elif weight > 50.1:
            valid_kg = False
        else:
            valid_kg = True
    elif material == "Cement":
        if weight < 24.9:
            valid_kg = False
        elif weight > 25.1:
            valid_kg = False
        else:
            valid_kg = True
    
    if valid_kg:
        total_kg += weight
    else:
        rejected += 1

#-------------------------------------------------------------------------------------------------------------------------------------------------------

total_kg = 0
rejected = 0


num_C = int(input("How many bags of cement are needed?"))
if num_C < 0:
    print("You cannot have a negative amount of sacks.")
    time.sleep(2)
    sys.exit()
num_G = int(input("How many bags of gravel are needed?"))
if num_G < 0:
    print("You cannot have a negative amount of sacks.")
    time.sleep(2)
    sys.exit()
num_S = int(input("How many bags of sand are needed?"))
if num_S < 0:
    print("You cannot have a negative amount of sacks.")
    time.sleep(2)
    sys.exit()


if num_C > 0:
    print("The following questions are for cement sacks:")
    for sacks in range(0,num_C):
        bag_check("Cement", float(input("How heavy is the sack in kg?")), total_kg, rejected)

if num_G > 0:
    print("The following questions are for gravel sacks:")
    for sacks in range(0,num_G):
        bag_check("Gravel", float(input("How heavy is the sack in kg?")), total_kg, rejected)

if num_S > 0:
    print("The following questions are for sand sacks:")
    for sacks in range(0,num_S):
        bag_check("Sand", float(input("How heavy is the sack in kg?")), total_kg, rejected)


print("The total weight of the accepted sacks in the order is", total_kg, "kg and there are", rejected, "rejected sacks.")
Output:
How many bags of cement are needed?2 How many bags of gravel are needed?3 How many bags of sand are needed?4 The following questions are for cement sacks: How heavy is the sack in kg?25 How heavy is the sack in kg?25 The following questions are for gravel sacks: How heavy is the sack in kg?50 How heavy is the sack in kg?50 How heavy is the sack in kg?46787 The following questions are for sand sacks: How heavy is the sack in kg?50 How heavy is the sack in kg?50 How heavy is the sack in kg?4679 How heavy is the sack in kg?50 The total weight of the accepted sacks in the order is 0 kg and there are 0 rejected sacks.
Reply
#2
I think you need to declare your total_kg and rejected variables before the bag_check function, then use them globally, like this:
total_kg = 0
rejected = 0
def bag_check(material, weight, total_kg, rejected):
   global total_kg
   global rejected
   # the rest of the function
Reply
#3
(Nov-05-2017, 12:41 PM)Lux Wrote: I think you need to declare your total_kg and rejected variables before the bag_check function, then use them globally, like this:
total_kg = 0
rejected = 0
def bag_check(material, weight, total_kg, rejected):
   global total_kg
   global rejected
   # the rest of the function

It didn't work, I get the error "name 'total_kg' is parameter and global"

(Nov-05-2017, 02:47 PM)Wilson1218 Wrote:
(Nov-05-2017, 12:41 PM)Lux Wrote: I think you need to declare your total_kg and rejected variables before the bag_check function, then use them globally, like this:
total_kg = 0
rejected = 0
def bag_check(material, weight, total_kg, rejected):
   global total_kg
   global rejected
   # the rest of the function

It didn't work, I get the error "name 'total_kg' is parameter and global"


Fixed it, simple parameter error. Thanks!
Reply
#4
globals is not the way to go. it is discouraged to use globals. your function should return the result.
However it is better if your function return just True or False - if the bag is valid weight. Calculation should be outside it.

def number_bags(material):
    while True:
        try:
            num = int(input('How many bags of {} are needed?'.format(material)))
        except ValueError:
            continue
        if num > 0:
            return num
        else:
            print('You cannot have a negative amount of sacks.')


def bag_weight(bag_num):
    while True:
        try:
            weight = float(input('How heavy is the sack#{} in kg: '.format(bag)))
        except ValueError:
            continue
        if weight > 0:
            return weight
        else:
            print('You cannot have a negative weight of sacks.')


def check_bag(material, weight):
    valid_weights = {'sand':(49.9, 50.1),
                     'gravel':(49.9, 50.1),
                     'cement':(24.9, 25.1)}

    min_weight, max_weight = valid_weights[material]
    return min_weight <= weight <= max_weight
 

if __name__ == '__main__':
    materials = ['cement', 'gravel', 'sand']
    total = 0
    rejected = 0
    for material in materials:
        bags = number_bags(material)
        for bag in range(1, bags+1):
            weight = bag_weight(bag)
            if check_bag(material, weight):
                total += weight
            else:
                rejected += 1
    print('The total weight of the accepted sacks in the order is {:.1f}kg'.format(total))
    print('There are {} rejected sacks.'.format(rejected))
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  frustrating practice taubee 9 4,222 Nov-22-2020, 04:23 AM
Last Post: taubee
  Sorting a DataFrame - Best Practice? lummers 1 1,774 Feb-10-2020, 04:41 AM
Last Post: satyashetty
  Practice Question Excersizes A3G 5 6,267 Oct-16-2016, 12:38 PM
Last Post: A3G

Forum Jump:

User Panel Messages

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