Emily Lauren
Emily Lauren

Reputation: 21

Pounds and Ounces in Python

I just started to learn coding and I'm having an issue trying to get the pounds converted over to ounces. We're suppose to allow the user to input their data like 6 pounds 2 ounces. I'm stuck at the moment and I'm not even sure if I'm going about this right. Any help would be appreciated.

Your program will accept as input the weights in pounds and ounces for a set of rabbits fed with one type of food. Let the user provide the name of food. Accept input until the user types a zero weight. Make life easier by converting weights to ounces. Compute the arithmetic mean (average) of each set of rabbits. Determine which set of rabbits weighs the most, reporting their average weight.

This was my orignal code before using pounds and ounces and it worked fine using simple number like 13.

f1 = input("Name of Food:")

print (f1)

counter = 0
sum = 0

question = input('''Enter a weight? Type "Yes" or "No" \n\n''')

while question == "Yes" :
    ent_num = int(input("Weight of Rabbit:"))
    sum = sum + ent_num
    counter = counter + 1
    question = input('''Enter another weight? Type "Yes" or "No". \n ''')

print ("Average weight " + str(sum/counter))

My current code looks like this after I tried to implement pounds and ounces into the input.

f1 = input("Name of Food: ")
print (f1)

counter = 0
sum = 0

print ("Please enter inforamtion in pounds and ounces. End")
question = input('''Enter a weight? Type "Yes" or "No" \n\n''')

while question == "Yes" :
    ent_num = int(input("Weight of Rabbit:"))
    sum = sum + ent_num
    counter = counter + 1
if pounds * ounces == 0:
    allOunces = pounds * 16 + ounces
    sum = sum + allOunces

print ("Average weight " + str(sum/counter))

Upvotes: 2

Views: 4327

Answers (3)

Hugh Bothwell
Hugh Bothwell

Reputation: 56684

A big part of programming is learning how to cleanly break a big problem into smaller pieces.

Let's start by getting a single weight:

POUND_WORDS = {"pound", "pounds", "lb", "lbs"}
OUNCE_WORDS = {"ounce", "ounces", "oz", "ozs"}
OUNCES_PER_POUND = 16

def is_float(s):
    """
    Return True if the string can be parsed as a floating value, else False
    """
    try:
        float(s)
        return True
    except ValueError:
        return False

def get_weight(prompt):
    """
    Prompt for a weight in pounds and ounces
    Return the weight in ounces
    """
    # We will recognize the following formats:
    # 12 lb       # assume 0 ounces
    # 42 oz       # assume 0 pounds
    # 12 6        # pounds and ounces are implied
    # 3 lbs 5 oz  # fully specified

    # repeat until we get input we recognize
    good_input = False
    while not good_input:
        # get input, chunked into words
        inp = input(prompt).lower().split()

        if len(inp) not in {2, 4}:
            # we only recognize 2-word or 4-word formats
            continue    # start the while loop over again

        if not is_float(inp[0]):
            # we only recognize formats that begin with a number
            continue

        # get the first number
        v1 = float(inp[0])

        if len(inp) == 2:
            if inp[1] in POUND_WORDS:
                # first input format
                lbs = v1
                ozs = 0
                good_input = True
            elif inp[1] in OUNCE_WORDS:
                # second input format
                lbs = 0
                ozs = v1
                good_input = True
            elif is_float(inp[1]):
                # third input format
                lbs = v1
                ozs = float(inp[1])
                good_input = True
        else:
            # 4 words
            if inp[1] in POUND_WORDS and is_float(inp[2]) and inp[3] in OUNCE_WORDS:
                lbs = v1
                ozs = float(inp[2])
                good_input = True

    return lbs * OUNCES_PER_POUND + ozs

Now we can use that to get the average of a bunch of weights:

def get_average_weight(prompt):
    """
    Prompt for a series of weights,
    Return the average
    """
    weights = []
    while True:
        wt = get_weight(prompt)
        if wt:
            weights.append(wt)
        else:
            break
    return sum(weights) / len(weights)

Now we want to get the average for each food type:

def main():
    # get average weight for each feed type
    food_avg = {}
    while True:
        food = input("\nFood name (just hit Enter to quit): ").strip()
        if food:
            avg = get_average_weight("Rabbit weight in lbs and ozs (enter 0 0 to quit): ")
            food_avg[food] = avg
        else:
            break

    # now we want to print the results, sorted from highest average weight
    # Note: the result is a list of tuples, not a dict
    food_avg = sorted(food_avg.items(), key = lambda fw: fw[1], reverse=True)

    # and print the result
    for food, avg in food_avg:
        lbs = int(avg // 16)
        ozs = avg % 16
        print("{:<20s} {} lb {:0.1f} oz".format(food, lbs, ozs))

and then run it:

main()

This still takes some fussing around to get the average weight to print properly - our program needs to "know about" how weights are represented. The next step would be to push this back into a Weight class - ideally one which is agnostic about weight units (ie can accept arbitrary units like kilograms or pounds or stone).

Upvotes: 2

Saedeas
Saedeas

Reputation: 1578

There are a few issues with the second block of code.

1.

question = input('''Enter a weight? Type "Yes" or "No" \n\n''')
while question == "Yes" :
...

You need to ask your question inside the loop. You will loop endlessly because they never get asked to change question again inside the loop. What I would do is set question = "Yes" before the loop and then have the first line inside your loop be

question = input('''Enter a weight? Type "Yes" or "No" \n\n''')

2.

You need to decide how you want the user to enter input. You currently have

ent_num = int(input("Weight of Rabbit:"))

But ent_num could be anything from "6lbs 12oz" to "7pounds11ounces" to "potato". There's no consistent way to parse it unless you specifically tell them how to type out the weight. A less ambiguous way to ask this would be to say something like:

raw_input = input("Please enter the weight of the rabbit in pounds 
and ounces with a space separating the two numbers (e.g. 7lbs 12oz):")

Then you can do something to recover the two separate numbers. Something like this should work.

#split the string by the space.
chunked_input = raw_input.split()
#get the digits in the two chunks
lbs, ounces = map(lambda x: int(filter(str.isdigit, x)), chunked_input)

Now that bit probably requires a bit of explanation. map here is taking a function (the lambda x bit) and applying that function to all the members of chunked_input. map(lambda x: x+2, [4, 6, 7]) == [6, 8, 9].

Lambdas are just a tool to make a quick function without having to name it. You could accomplish the same thing as the lbs, ounces line by writing your own function:

def get_digit(my_substring):
    return int(filter(str.isdigit, my_substring)

and then mapping it:

lbs, ounces = map(get_digit, chunked_input)

Regardless, once you have the lbs and ounces as two separate variables, you're good to go. You can normalize them with the same formula you used:

weight = pounds * 16 + ounces

And then you'll eventually have the total weight in ounces of every weight entered.

To print out the average weight at the end you can do the division the way you did before:

#the * 1.0 is because if you can have fractional results, one of 
#either the divisor or the dividend must be a float
avg_oz_weight = sum * 1.0/counter 

and then if you want to display it in lbs and ounces, you need two useful operators, % and //. % is called the modulo operator, it returns the remainder when you're doing division so (7 % 3 == 1, 6 % 2 == 0). The // operator is floor division, so (7 // 3 == 2, 6 // 2 == 3).

So you can print a nice result with:

print("The average weight is: {}lbs {}oz".format(avg_oz_weight // 16,
                                                 avg_oz_weight % 16))

Upvotes: 0

Daniyal Ahmed
Daniyal Ahmed

Reputation: 755

You need to save the pounds and ounces in separate variable so something like this is needed.

f1 = input("Name of Food: ")
print (f1)

counter = 0
sum = 0
print ("Please enter inforamtion in pounds and ounces. End")
question = input('''Enter a weight? Type "Yes" or "No" \n\n''')
while question == "Yes" :
    pounds, ounces = map(int, input().split())
    weight = pounds * 16 + ounces
    sum = sum + weight
    counter = counter + 1
if pounds * ounces == 0:

print ("Average weight " + str(sum/counter))

Upvotes: 0

Related Questions