Hi could you assist with this python assignment? - python-3.x

trying to make a bill
price = {'sugar' : 45,'rice': 60,'tealeaves':450,'wheat':40,'oil':100};
ordered = {'sugar':2,'rice': 3,'tealeaves':0.5,'wheat':4,'oil':1}
total = list()
for k,v in price:
value = price[k]*kgsordered[k]
print (k,':',value)
total.append(value)
print('*'*4,'CG Grocery Store','*'*4)
print('Your final bill is ₹',total.sum())
print('Thank you for shopping with us!!')
traceback coming
Traceback (most recent call last):
File "C:\Users\user\Desktop\My Python Files\curiosity gym python
HW.py", line 4, in
for k,v in price: ValueError: too many values to unpack (expected 2)

Firstly, you have to use .items() to iterate through a dictionary.
Secondly, you were using kgsordered[k] instead of ordered[k], which gives you an error, since kgsordered isn't defined.
And in the end, in you want to calculate the sum of all the elements in a list, you do it by doing sum(total), where total is your list
price = {'sugar' : 45,'rice': 60,'tealeaves':450,'wheat':40,'oil':100};
ordered = {'sugar':2,'rice': 3,'tealeaves':0.5,'wheat':4,'oil':1}
total = list()
for k,v in price.items():
value = price[k]*ordered[k]
print (k,':',value)
total.append(value)
print('*'*4,'CG Grocery Store','*'*4)
print('Your final bill is ₹',sum(total))
print('Thank you for shopping with us!!')
# output
sugar : 90
rice : 180
tealeaves : 225.0
wheat : 160
oil : 100
**** CG Grocery Store ****
Your final bill is ₹ 755.0
Thank you for shopping with us!!

Related

"sample larger than population or is negative" but list contains more elements than sample size in list retrieved from url?

python 3: I am trying to code a bingo game which asks the user for 1-3 players, assigns each player a name, and then creates their Bingo card by choosing 25 elements from the list listOfStrings. the list contains 53 elements which are all strings. I am getting the error "ValueError: Sample larger than population or is negative" but 25<53 ? is the size of my list incorrect or do I have to assign each element a number? not sure why this is happening. im new to programming so probably a simple mistake or miscomprehension
import urllib.request
import random
listOfStrings = []
def createList():
try:
with urllib.request.urlopen('https://www.cs.queensu.ca/home/cords2/bingo.txt') as f:
d = f.read().decode('utf-8')
split= d.split("\n")
listOfStrings = split
except urllib.error.URLError as e:
print(e.reason)
def players(listOfStrings):
noPlayers = input("How many players would like to play Bingo? Choose 1-3: ")
if noPlayers == "1":
name = input("What is the name of player 1? ")
player1card = random.sample(list(listOfStrings), 25)
createList()
players(listOfStrings)
print(player1card)

How to ignore find() errors

Again, I'm new to python, but in other languages error handling is easy. I'm not sure how to do this in python. The temperature variable on the web page doesn't hold a value for the 1st item in the list, but the other items have it. How do I ignore an item is it doesn't return something back. I want it to continue with the other code and skip the list that doesn't have a class.
Code
import requests
from bs4 import BeautifulSoup
page = requests.get('https://forecast.weather.gov/MapClick.php?lat=28.57117500000004&lon=-81.38776499999994#.YHH8fehKiUk')
soup = BeautifulSoup(page.content, 'html.parser')
week = soup.find(id='seven-day-forecast-body')
items=week.find_all(class_='tombstone-container')
period_names = [item.find(class_='period-name').get_text() for item in items]
short_descriptions = [item.find(class_='short-desc').get_text() for item in items]
temperatures = [item.find(class_='temp').get_text() for item in items]
print(period_names)
print(short_descriptions)
print(temperatures)
Error
Traceback (most recent call last): File
"c:\Users\14074\AppData\Local\Programs\Python\Python39\Youtube_posting.py",
line 12, in
temperatures = [item.find(class_='temp').get_text() for item in items] File
"c:\Users\14074\AppData\Local\Programs\Python\Python39\Youtube_posting.py",
line 12, in
temperatures = [item.find(class_='temp').get_text() for item in items] AttributeError: 'NoneType' object has no attribute 'get_text'
You can first check if the element with class="temp" exists in item and if not, return a default value (e.g "N/A"):
import requests
from bs4 import BeautifulSoup
url = "https://forecast.weather.gov/MapClick.php?lat=28.57117500000004&lon=-81.38776499999994#.YHH8fehKiUk"
soup = BeautifulSoup(requests.get(url).content, "html.parser")
week = soup.find(id="seven-day-forecast-body")
items = week.find_all(class_="tombstone-container")
period_names = [
item.find(class_="period-name").get_text(separator=" ") for item in items
]
short_descriptions = [
item.find(class_="short-desc").get_text(separator=" ") for item in items
]
temperatures = [
i.get_text(separator=" ") if (i := item.find(class_="temp")) else "N/A"
for item in items
]
for p, d, t in zip(period_names, short_descriptions, temperatures):
print("{:<30} {:<40} {}".format(p, d, t))
Prints:
NOW until 7:00pm Sat Red Flag Warning N/A
This Afternoon Chance T-storms High: 90 °F
Tonight Showers Likely then Chance Showers Low: 69 °F
Sunday Heavy Rain High: 79 °F
Sunday Night Chance Showers Low: 67 °F
Monday Mostly Sunny High: 86 °F
Monday Night Mostly Clear Low: 62 °F
Tuesday Sunny High: 87 °F
Tuesday Night Partly Cloudy Low: 65 °F
An alternative is to use a try/except clause and catch the AttributeError exception and pass on it.
try:
temperatures = [item.find(class_='temp').get_text() for item in items]
except AttributeError:
pass
This will do exactly what you asked, which is ignore an item if item.find(class_='temp') returned a NoneType and move on to the next item.

Was solving a hacker problem and some test cases didnt pass

Given the names and grades for each student in a Physics class of students, store them in a nested list and print the name(s) of any student(s) having the second lowest grade.
Note: If there are multiple students with the same grade, order their names alphabetically and print each name on a new line.
Input Format
The first line contains an integer, , the number of students.
The subsequent lines describe each student over lines; the first line contains a student's name, and the second line contains their grade.
Constraints
There will always be one or more students having the second lowest grade.
Output Format
Print the name(s) of any student(s) having the second lowest grade in Physics; if there are multiple students, order their names alphabetically and print each one on a new line.
This is my code:
list = []
for _ in range(int(input())):
name = input()
score = float(input())
new = [name, score]
list.append(new)
def snd_highest(val):
return val[1]
list.sort(key = snd_highest)
list.sort()
value = list[1]
grade = value[1]
for a,b in list:
if b == grade:
print (a)
This is the test case:
4
Rachel
-50
Mawer
-50
Sheen
-50
Shaheen
51
And the expected output is Shaheen but i got the other 3.
Please explain.
To find the second lowest value, you have actually just sorted your list in ascending order and just taken the second value in the list by using the below code
value = list[1]
grade = value[1]
Imagine this is your list after sorting:
[['Sheen', 50.0], ['mawer', 50.0], ['rachel', 50.0], ['shaheen', 51.0]]
According to value = list[1], the program chooses "value = ['mawer', 50.0]".
Then the rest of your program takes the grade from this value and outputs the corresponding name, that's why this isn't working as per what you need, you need to write logic to find the lowest value and then find the second lowest, this current program just assumes the lowest value is in the second position in the list.
Try doing this
if __name__ == '__main__':
students = []
for _ in range(int(input())):
name = input()
score = float(input())
new = [name, score]
students.append(new)
def removeMinimum(oldlist):
oldlist = sorted(oldlist, key=lambda x: x[1])
min_ = min(students, key=lambda x: x[1])
newlist = []
for a in range(0, len(oldlist)):
if min_[1] != oldlist[a][1]:
newlist.append(oldlist[a])
return newlist
students = removeMinimum(students);
# find the second minimum value
min_ = min(students, key=lambda x: x[1])
# sort alphabetic order
students = sorted(students, key=lambda x: x[0])
for a in range(0, len(students)):
if min_[1] == students[a][1]:
print(students[a][0])
I hope this may help you to pass all your test cases. Thank you.
# These functions will be used for sorting
def getSecond(ele):
return ele[1]
def getFirst(ele):
return ele[0]
studendList = []
sortedList = []
secondLowestStudents = []
# Reading input from STDIN and saving in nested list [["stud1": <score>], ["stud2", <score>]]
for _ in range(int(input())):
name = input()
score = float(input())
studendList.append([name, score])
# sort the list by score and save it in a new list studendList (remove the duplicate score as well - see, if x[1] not in sortedList)
studendList.sort(key=getSecond)
[sortedList.append(x[1]) for x in studendList if x[1] not in sortedList]
# Get the second lowest grade
secondLowest = sortedList[1]
# Now sort the origin list by the name fetch the student list having the secondLowest grade
studendList.sort(key=getFirst)
[secondLowestStudents.append(x[0]) for x in studendList if x[1] == secondLowest]
# Print the student's name having second-lowest grade
for st in secondLowestStudents:
print(st)

Getting error in list assignment about index?

I recently started to study Python, and as I was trying to run a code from a book (with my modification) I got the error:
IndexError: list assignment index out of range
in : `Names[len(Names)]=name`
I read some questions with this error on web but can't figure it out.
Names=[]
num=0
name=''
while True :
print('Enter the name of person '+str(len(Names)+1) + '(or Enter nothing to stop)')
name=input()
if name == '' :
break
Names[len(Names)]=name
print('the person names are:')
for num in range(len(Names)+1) :
print(' '+Names[num])
Looks like you want to append something to an existing list. Why not use .append()? This won't give you the IndexError.
Names.append(name)
Another same error: You shouldn't write range(len(Names) + 1). range(len(Names)) is enough for you to iterate through the whole list:
for num in range(len(Names)):
print(' '+Names[num])
Another suggestion: You don't need the for loop to print the result, at all. Just use str.join():
print(' '.join(Names))
You can not access out of range index
Ex:
>>> l = [1,2,3]
>>> l = [0,1,2]
>>> l[3] = "New"
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
l[3] = "New"
IndexError: list assignment index out of range
For that, you have to append new data to the list.
>>> l.append("new")
>>> l
[0, 1, 2, 'new']
You can try:
Names=[]
num=0
name=''
while True :
print('Enter the name of person '+str(len(Names)+1) + '(or Enter nothing to stop)')
name=input()
if name == '' :
break
Names.append(name)
print('the person names are:')
for num in range(len(Names)) :
print(' '+Names[num])
just use the append function to insert the new name to the existing list of names.
Syntax:-
if you want to append 'foo' to the list of existing names i.e 'Names',type Names.append('foo').

Specific Fields Python3

I try to select specific fields from my Qdata.txt file and use field[2] to calculate average for every years separate. My code give only total average.
data file looks like: (1. day of year: 101 and last: 1231)
Date 3700300 6701500
20000101 21.00 223.00
20000102 20.00 218.00
. .
20001231 7.40 104.00
20010101 6.70 104.00
. .
20130101 8.37 111.63
. .
20131231 45.00 120.98
import sys
td=open("Qdata.txt","r") # open file Qdata
total=0
count=0
row1=True
for row in td :
if (row1) :
row1=False # row1 is for topic
else:
fields=row.split()
try:
total=total+float(fields[2])
count=count+1
# Errors.
except IndexError:
continue
except ValueError:
print("File is incorrect.")
sys.exit()
print("Average in 2000 was: ",total/count)
You could use itertools.groupby using the first four characters as the key for grouping.
with open("data.txt") as f:
next(f) # skip first line
groups = itertools.groupby(f, key=lambda s: s[:4])
for k, g in groups:
print(k, [s.split() for s in g])
This gives you the entries grouped by year, for further processing.
Output for your example data:
2000 [['20000101', '21.00', '223.00'], ['20000102', '20.00', '218.00'], ['20001231', '7.40', '104.00']]
2001 [['20010101', '6.70', '104.00']]
2013 [['20130101', '8.37', '111.63'], ['20131231', '45.00', '120.98']]
You could create a dict (or even a defaultdict) for total and count instead:
import sys
from collections import defaultdict
td=open("Qdata.txt","r") # open file Qdata
total=defaultdict(float)
count=defaultdict(int)
row1=True
for row in td :
if (row1) :
row1=False # row1 is for topic
else:
fields=row.split()
try:
year = int(fields[0][:4])
total[year] += float(fields[2])
count[year] += 1
# Errors.
except IndexError:
continue
except ValueError:
print("File is incorrect.")
sys.exit()
print("Average in 2000 was: ",total[2000]/count[2000])
Every year separate? You have to divide your input into groups, something like this might be what you want:
from collections import defaultdict
row1 = True
year_sums = defaultdict(list)
for row in td:
if row1:
row1 = False
continue
fields = row.split()
year = fields[0][:4]
year_sums[year].append(float(fields[2]))
for year in year_sums:
avarage = sum(year_sums[year])/count(year_sums[year])
print("Avarage in {} was: {}".format(year, avarage)
That is just some example code, I don't know if it works for sure, but should give you an idea what you can do. year_sums is a defaultdict containing lists of values grouped by years. You can then use it for other statistics if you want.

Resources