How to count somekind of results of a request? - python

I am pursuing a MSc in Data Science and in the subject of Python I have the statement below:
Call 100 times the following URL and count how many calls have three or less participants.
The API is: http://www.boredapi.com/api/activity/
After I understood the statement I build up the function below:
import requests
total_calls = 100
call_0 = 0
def calls(total_calls, call_0):
while total_calls > call_0:
activity = ('http://www.boredapi.com/api/activity/')
call_n = requests.get(activity)
print(call_n.text)
call_0 += 1
if total_calls - call_0 < 0:
print(call_0)
elif total_calls - call_0 == 0:
break
return output_call
output_call = calls(total_calls, call_0)
output_call
I am stuck up because I don't know how to count how many times "output_call" have <= 3 participants.
If I run for example 9 times instead of 100 there is a result:
{"activity":"Hold a yard sale","type":"social","participants":1,"price":0,"link":"","key":"1432113","accessibility":0.1}
{"activity":"Meditate for five minutes","type":"relaxation","participants":1,"price":0,"link":"","key":"3699502","accessibility":0.05}
{"activity":"Draw and color a Mandala","type":"relaxation","participants":1,"price":0.05,"link":"https://en.wikipedia.org/wiki/Mandala","key":"4614092","accessibility":0.1}
{"activity":"Go to a local thrift shop","type":"recreational","participants":1,"price":0.1,"link":"","key":"8503795","accessibility":0.2}
{"activity":"Organize your basement","type":"busywork","participants":1,"price":0,"link":"","key":"8203595","accessibility":0.9}
{"activity":"Back up important computer files","type":"busywork","participants":1,"price":0.2,"link":"","key":"9081214","accessibility":0.2}
{"activity":"Fix something that's broken in your house","type":"diy","participants":1,"price":0.1,"link":"","key":"6925988","accessibility":0.3}
{"activity":"Clean out your closet and donate the clothes you've outgrown","type":"charity","participants":1,"price":0,"link":"","key":"9026787","accessibility":0.1}
{"activity":"Go to the gym","type":"recreational","participants":1,"price":0.2,"link":"","key":"4387026","accessibility":0.1}
{}

Following should work fine for you:
import requests, json
total_calls = 100
call_0 = 0
def calls(total_calls, call_0):
less_than_3_count = 0
while total_calls > call_0:
# Check break condition in the beginning
if total_calls - call_0 == 0:
break
activity = 'http://www.boredapi.com/api/activity/'
response = requests.get(activity)
call_0 += 1
print(call_0, response.text)
json_object = json.loads(response.text)
if json_object['participants'] <= 3:
less_than_3_count += 1
return less_than_3_count
output_call = calls(total_calls, call_0)
output_call

You could proceed like that.
Design your calls() function to return the number of calls you're interested in.
Then initialize a counter to 0 and increment it when number of participants lte 3.
range() is the builtin Python function you use very often to loop n times.
From the request result you'd better ask for JSON instead of text, which gives you a Python dictionary (equivalent to its JSON counterpart).
Access the value number of participants by using the participant key.
activity = "http://www.boredapi.com/api/activity/"
total_calls = 100
def calls(total_calls: int) -> int:
counter = 0
for _ in range(total_calls):
r = requests.get(activity)
if r.ok:
if r.json()["participants"] <= 3:
counter += 1
return counter
calls(total_calls)

import requests
def calls(total_calls):
output_calls = 0
activity = 'http://www.boredapi.com/api/activity/'
while total_calls > 0:
call_n = requests.get(activity).json()
if call_n['participants'] <= 3:
output_calls += 1
total_calls -= 1
return output_calls
output_call = calls(total_calls=100) # change the total call value here
print(output_call)
Assuming you will handle exceptions for requests.

Here is the simplified and pythonic version;
import requests
from pprint import pp
def calls(count=100):
bigger_then_3 = 0
bigger_then_3_calls = []
for cal in range(count):
resp = requests.get("http://www.boredapi.com/api/activity/").json()
if resp["participants"] <= 3:
bigger_then_3_calls.append(resp)
bigger_then_3 += 1
return bigger_then_3, bigger_then_3_calls
if __name__ == '__main__':
bigger_count, bigger_calls = calls(10)
print(f"Bigger count: {bigger_count}")
pp(bigger_calls)

Related

Python scips executing of a function (CS50x Lab 6: World Cup)

Currently, I am writing a code on Python to make lab 6 for CS50x. When I am trying to debug my code, it seems just to skip the function simulate_tournament() and produces anything as an output. I would appreciate suggestions on how to debug this code and make the program running:)
My code with the mentioned problem:
# Simulate a sports tournament
import csv
import sys
import random
# Number of simluations to run
N = 1000
def main():
# Ensure correct usage
if len(sys.argv) != 2:
sys.exit("Usage: python tournament.py FILENAME")
teams = []
# TODO: Read teams into memory from file
with open(sys.argv[1], "r") as file:
reader = csv.DictReader(file)
for row in reader:
row["team"]
row["rating"] = int(row["rating"])
teams.append(row)
counts = {}
# TODO: Simulate N tournaments and keep track of win counts
i = 0
while i < N:
winner = simulate_tournament(teams)
if winner in counts:
counts["winner"] += 1
else:
counts["winner"] = 1
# Print each team's chances of winning, according to simulation
for team in sorted(counts, key=lambda team: counts[team], reverse=True):
print(f"{team}: {counts[team] * 100 / N:.1f}% chance of winning")
def simulate_game(team1, team2):
"""Simulate a game. Return True if team1 wins, False otherwise."""
rating1 = team1["rating"]
rating2 = team2["rating"]
probability = 1 / (1 + 10 ** ((rating2 - rating1) / 600))
return random.random() < probability
def simulate_round(teams):
"""Simulate a round. Return a list of winning teams."""
winners = []
# Simulate games for all pairs of teams
for i in range(0, len(teams), 2):
if simulate_game(teams[i], teams[i + 1]):
winners.append(teams[i])
else:
winners.append(teams[i + 1])
return winners
def simulate_tournament(teams):
"""Simulate a tournament. Return name of winning team."""
# TODO
while len(teams) > 1:
teams = simulate_round(teams)
return teams[0]["team"]
if __name__ == "__main__":
main()
I think it is because you don't increment i your while loop?
i = 0
while i < N:
winner = simulate_tournament(teams)
if winner in counts:
counts["winner"] += 1
else:
counts["winner"] = 1
I think your simulate_tournament function is not returning a value.
Try with:
if len(teams) > 2:
winners = simulate_round(teams)
ganador = simulate_tournament(winners)
else:
ganador = simulate_round(teams)
return ganador[0]['team']
return ganador
i donĀ“t know if its the most efficient function, but it worked fine for me!
I was working on the same lab today. I think your mistake is here:
with open(sys.argv[1], "r") as file:
It should be only, with open(sys.argv[1]) as file.
You need to have keys/values inside your count variable. The reason why it is not printing anything is because there is nothing in count. Also you are not supposed to use winner as a string, the function returns a string so python automatically makes winner a string variable. You are supposed to hash the string returned for winner to the counts variable and thus update count to the correct name.

Error: List indices are supposed to be an integer but it is an integer

I'm trying to create a while loop and have the index increase by 1 every time the loop runs.
I have n set to zero, which should tell python that this is an integer. However, when it gets to if contact_list[n]['vid'] == '':, it sees n as a string.
Here is the loop. Any help is greatly appreciated:
has_more = True
n = 0
while has_more:
parameters = urllib.parse.urlencode(parameter_dict)
get_url = get_all_contacts_url + parameters + property_params
r = requests.get(url= get_url, headers = headers)
response_dict = json.loads(r.text)
has_more = response_dict['has-more']
contact_list.append(response_dict['contacts'])
parameter_dict['vidOffset']= response_dict['vid-offset']
if len(contact_list) >= max_results:
max_results += 100
if contact_list[n]['vid'] == '':
break
contact_count += 1
print('loop finished')
list_length = len(contact_list)
print("List Length:",list_length)
print("You've succesfully parsed through {} contact records and added them to a list".format(list_length))
Try this:
if 'vid' in contact_list:
if contact_list[n] == '':
break
Hope that helps!
Yes, and realized n is actually not being incremented, if that's the case just call 0 as the list index without having to assign n=0.

Python issue with return statement

The code takes a list as input for example:
[1995, 1750, 2018]
and I am expecting it to give back
Basically, this code searches for the closest leap year for each year in a list of years
1996
1948
2016
all in a separate line.
The output I get back with the return statement is:
1996 1748 2016
But the thing is I must use return because I use a map thing to write it to file, but I get
map argument #1 must support iteration
Is there a solution to my problem?
#!/bin/python3
import math
import os
import random
import re
import sys
def is_leap(year):
leap = False
if year % 4 == 0:
if year % 100 != 0 or year % 400 == 0:
leap = True
return leap
forward_list = {}
back_list = {}
newLst = []
def year_forward(yearBounds):
for item in yearBounds:
counter = 0
# forwad list
while not is_leap(item):
item = item + 1
counter += 1
#forward_list.append(item)
forward_list[item] = counter
return forward_list
def year_backward(yearBounds):
# back_list
for item in yearBounds:
counter = 0
while not is_leap(item):
item = item - 1
counter -= 1
#back_list.append(item)
back_list[item] = counter
return back_list
def findLastLeapYears(yearBounds):
forward = (year_forward(yearBounds))
backward = (year_backward(yearBounds))
tuple_forward = list(forward.items())
tuple_backward = list(backward.items())
counter = 0
for item in tuple_forward:
if abs(item[1]) < abs(tuple_backward[counter][1]):
newLst.append (item[0])
counter+=1
elif abs(item[1]) == abs(tuple_backward[counter][1]):
if item[0] < tuple_backward[counter][0]:
newLst.append (item[0])
counter += 1
else:
newLst.append (tuple_backward[counter][0])
counter += 1
else:
newLst.append (tuple_backward[counter][0])
counter+=1
return newLst
The call:
leapYears = findLastLeapYears(years)
fptr.write(' '.join(map(str, leapYears)))
fptr.write('\n')
fptr.close()
Your code runs fine, if you want it to be on separate line use '\n'.join(...) instead.
For me, using your code, I can't reproduce the error and everything works fine.
The error map argument #1 must support iteration suggests that you're using str as a variable or function that overwrites the default str.

Undefined dictionaries in my main function

def monday_availability(openhours_M): #openhours_M = number hours pool is open
hourone = int(input('Input the first hour in the range of hours the guard can work'))
hourlast = int(input('Input the last hour in the range of hours the guard'))
hour = 1
availability_M = []
while hour <= openhours_M:
if hour >= hourone & hour <= hourlast:
availability_M.append(1)
else:
availability_M.append(0)
return availability_M
Above is a function gathering the availability of a lifeguard and storing the hours a guard can work as a 1 in availability list or a 0 if they cannot. I return this list with the intent of adding it to a dictionary in the function below.
def guard_availability(guards, openhours_M, openhours_T, openhours_W,
openhours_R, openhours_F, openhours_S, openhours_Su):
continueon = 1
while continueon == 1:
name = input('Input guards name of lifeguard to update availability' )
availability = {}
days = {}
if openhours_M != 0:
monday_availability(openhours_M)
if openhours_T != 0:
tuesday_availability(openhours_T)
if openhours_W != 0:
wednesday_availability(openhours_W)
if openhours_R != 0:
thursday_availability(openhours_R)
if openhours_F != 0:
friday_availability(openhours_F)
if openhours_S != 0:
saturday_availability(openhours_S)
if openhours_Su != 0:
sunday_availability(openhours_Su)
days['Monday'] = availability_M
days['Tuesday'] = availability_T
days['Wednesday'] = availability_W
days['Thursday'] = availability_R
days['Friday'] = availability_F
days['Saturday'] = availability_S
days['Sunday'] = availability_Su
availability[name]= days
continueon = input('Enter 1 to add availability for another guard, 0 to stop: ')
return days
When I run this code, I get an error saying my availability lists are undefined even though I returned them in the functions above. Where is the error in my understanding of returning in functions, and how can I remedy this problem.
monday_availability(openhours_M) returns a value.
Returning a variable does not assign it to anything outside the scope of that function.
If you renamed return availability_M to use return foo and update the other uses only within that function accordingly, would the error make more sense?
Now, actually capture the result
availability_M = monday_availability(openhours_M)
Or even just
days['Monday'] = monday_availability(openhours_M)
Also, not seeing how that function has anything to do with Mondays. Try to write DRY code
You return the dic value in your function but don't assign it to any variable. You should do it like this:
if openhours_M != 0:
availability_M=monday_availability(openhours_M)
if openhours_T != 0:
availability_T=tuesday_availability(openhours_T)
if openhours_W != 0:
availability_W=wednesday_availability(openhours_W)
if openhours_R != 0:
availability_R=thursday_availability(openhours_R)
if openhours_F != 0:
availability_F=friday_availability(openhours_F)
if openhours_S != 0:
availability_S=saturday_availability(openhours_S)
if openhours_Su != 0:
availability_Su=sunday_availability(openhours_Su)

How to specify the amount of numbers needed in a range with user input

I need the user input to specify the amount of numbers to be printed in the range.
I have the following code for that:
i = 0;
start_char = 65
end_char = 65
x = input("Enter numbers of plates:")
while (i < int(x)):
if i%26 == 0 and i!= 0:
end_char = (65)
start_char += 1
print((chr(start_char))+(chr(end_char)))
end_char =end_char + 1
i = i + 1
for plate_code in (range(1000)):
print(str(plate_code) + ((chr(start_char))+(chr(end_char))))
You are incrementing i only inside of if and since i = 0 initially, your code never enters if and stucks in an infinite loop.
Move i = i + 1 outside of if.
while (i < int(x)):
if i%26 == 0 and i!= 0:
end_char = (65)
start_char += 1
print((chr(start_char))+(chr(end_char)))
end_char =end_char + 1
i = i + 1 #move incrementation outside of if
for plate_code in (range(1000)):
print(str(plate_code) + ((chr(start_char))+(chr(end_char))))
Just don't try to reinvent for loops:
def main():
start_char = end_char = 65
plate_count = int(input('Enter numbers of plates:'))
for i in range(plate_count):
if i and i % 26 == 0:
end_char = 65
start_char += 1
print(chr(start_char) + chr(end_char))
end_char += 1
for plate_code in range(1000):
print('{}{}{}'.format(plate_code, chr(start_char), chr(end_char)))
if __name__ == '__main__':
main()
Alternativly make use of the power of the standard library:
from itertools import islice, product
from string import ascii_uppercase
def main():
plate_count = int(input('Enter numbers of plates: '))
for start_char, end_char in islice(
product(ascii_uppercase, ascii_uppercase), plate_count
):
print('{}{}'.format(start_char, end_char))
for plate_code in range(1000):
print('{}{}{}'.format(plate_code, start_char, end_char))
if __name__ == '__main__':
main()

Categories