SO I'm making a program about hockey players playing and I will record their goals.
Here's what should happen:
Who scored? 4
Who scored? 5
Who scored? 6
Who scored? 4
Who scored? 3
Game still going?(y/n) y
Who scored? 3
Who scored? 2
Who scored? 5
Who scored? 2
Who scored? 3
Game still going?(y/n) n
Creating a histogram from values:
Element Goals Histogram
1 0
2 2 **
3 2 ***
4 2 **
5 2 **
6 1 *
7 1 *
8 0
9 0
10 0
Here is my code:
def info():
ranking = [0,0,0,0,0,0,0,0,0,0,0]
survey = []
return ranking,survey
def info2(survey):
x = ''
for i in range(0,5):
x = int(input("Who scored?"))
survey.append(x)
again(x)
return survey
def info3(ranking,survey):
for i in range(len(survey)):
ranking[survey[i]]+=1
return ranking, survey
def again(x):
y = input("Game still on? y/n").lower()
if y == "yes" or y == "y":
info()
elif y == "n" or y =="no":
hg(x)
#create histogram
def hg():
print("\nCreating a histogram from values: ")
print("%3s %5s %7s"%("Element", "Goals", "Histogram"))
#start from element 1 instead of 0
for i in range(len(ranking)-1):
print("%7d %5d %-s"%(i+1, ranking[i+1], "*" * ranking[i+1]))
def main():
x,y = info()
a = info2(y)
d = again(x)
b,c = info3(x,a)
z = hg(x)
main()
When I run this as it is, I get the Who scored thing, and I enter 'y' on the y/n and it works, but when I enter y/n and i put n, it prints the "element goals histogram" then throws the following:
Traceback (most recent call last):
line 48, in <module>
main()
line 44, in main
a = info2(y)
line 17, in info2
again(x)
line 29, in again
hg(x)
line 39, in hg
for i in range(len(ranking)-1):
NameError: name 'ranking' is not defined
x = input("Game still on? y/n").lower
instead should be:
x = input("Game still on? y/n").lower()
There are a couple issues that I see with the code...
First, you've got lower instead of lower() in your again() function. This binds the function itself to x instead of calling it and assigning its return value.
Also, your hg() function expects an argument, but you don't pass one in here. The ranking defined in info() is local to that function, and not visible from hg().
Edit in response to OP after OP's code was updated based on my comments above:
Also, there are issues with your handling of the exit case in again(). I think you shouldn't call hg() at all there, and instead return the answer to a separate variable in info2().
So that code for those two functions would then look something like this:
def info2(survey):
x = ''
ans = 'y'
while ans in ('y', 'yes'):
for i in range(0,5):
x = int(input("Who scored?"))
survey.append(x)
ans = again()
return survey
def again():
x = input("Game still on? y/n").lower()
if x == "yes" or x == "y":
info()
return x
Note the use of the additional variable, and the pass.
Edit in response to 2nd comment from OP:
info3() is unchanged. I added again() and info2() with my changes. You would keep info3() as is (at least as regards this particular question).
Also, since my change just had pass in the No case, it can actually be removed entirely. Just check for the Yes case, and otherwise return (an else isn't even required in this particular case).
When I run the code with the changes I mentioned, it appears to work as required. This is example output:
Who scored?1
Who scored?1
Who scored?1
Who scored?2
Who scored?2
Game still on? y/ny
Who scored?3
Who scored?3
Who scored?3
Who scored?2
Who scored?2
Game still on? y/nn
Creating a histogram from values:
Element Goals Histogram
1 3 ***
2 4 ****
3 3 ***
4 0
5 0
6 0
7 0
8 0
9 0
10 0
I'm not sure what all of the functions and variables were supposed to do. It's easier to debug and understand code if you use sensible names for functions and variables.
from collections import OrderedDict
def main():
list_of_players = [str(number) for number in range(1, 11)]
ranking = play(list_of_players)
print_histogram(ranking)
def play(list_of_players):
ranking = OrderedDict([(player, 0) for player in list_of_players])
while True:
for i in range(5):
player = input('Who scored? ')
try:
ranking[player] += 1
except KeyError:
print('Not a player')
if input('Game still going?(y/n) ').lower() in ['n', 'no']:
return ranking
def print_histogram(ranking):
template = '{player:^7} {goals:^7} {stars}'
print('\nCreating a histogram from values: ')
print(template.format(player='Element', goals='Goals', stars='Histogram'))
for player, goals in ranking.items():
print(template.format(player=player, goals=goals, stars='*' * goals))
if __name__ == '__main__':
main()
Related
I am doing a question that gives me a start coordinate, a end coordinate and the number of times of moving.Every time you can add 1 or minus 1 to x or y coordinate based on previous coordinate and the number of moving limit the time the coordinate can move. At last, I need to identify whether there is a possibility to get to the end coordinate
I decide to use recursion to solve this problem however, it does not end even if I wrote return inside a if else statement. Do you mind to take a look at it.
This is the code
# https://cemc.uwaterloo.ca/contests/computing/2017/stage%201/juniorEF.pdf
# input
start = input()
end = input()
count = int(input())
coo_end = end.split(' ')
x_end = coo_end[0]
y_end = coo_end[1]
end_set = {int(x_end), int(y_end)}
#processing
coo = start.split(' ')
x = int(coo[0])
y = int(coo[1])
change_x = x
change_y = y
sum = x + y+count
set1 = set()
tim = 0
timer = 0
ways = 4** (count-1)
def elit(x, y, tim,timer, ways = ways):
print(tim,timer)
tim = tim +1
co1 = (x, y+1)
co2 = (x+1, y)
co3 = (x, y-1)
co4 = (x-1, y)
if tim == count:
tim =0
set1.add(co1)
set1.add(co2)
set1.add(co3)
set1.add(co4)
print(timer)
timer = timer +1
if timer == ways:
print('hiii')
return co1, co2, co3, co4 #### this is the place there is a problem
elit(co1[0],co1[1],tim,timer)
elit(co2[0],co2[1],tim,timer)
elit(co3[0],co3[1],tim, timer)
elit(co4[0],co4[1],tim, timer)
#print(elit(change_x,change_y,tim)) - none why
elit(change_x,change_y,tim, timer)
#print(list1)
for a in set1:
if end_set != a:
answer = 'N'
continue
else:
answer = "Y"
break
print(answer)
In addition, if you have any suggestions about writing this question, do you mind to tell me since I am not sure I am using the best solution.
one of example is
Sample Input
3 4 (start value)
3 3 (end value)
3 (count)
Output for Sample Input
Y
Explanation
One possibility is to travel from (3, 4) to (4, 4) to (4, 3) to (3, 3).
the detailed question can be seen in this file https://cemc.uwaterloo.ca/contests/computing/2017/stage%201/juniorEF.pdf
It is question 3. Thank you
thank you guys
the function is returning properly however by the time you reach the recursive depth to return anything you have called so many instances of the function that it seems like its in an infinite loop
when you call elite the first time the function calls itself four more times, in the example you have given timer is only incremented every 3 cycles and the function only return once timer hits 16 thus the function will need to run 48 times before returning anything and each time the function will be called 4 more times, this exponential growth means for this example the function will be called 19807040628566084398385987584 times, which depending on your machine may well take until the heat death of the universe
i thought i should add that i think you have somewhat over complicated the question, on a grid to get from one point to another the only options are the minimum distance or that same minimum with a diversion that must always be a multiple of 2 in length, so if t the movement is at least the minimum distance or any multiple of 2 over the result should be 'Y', the minimum distance will just be the difference between the coordinates on each axis this can be found by add in the difference between the x and y coordinates
abs(int(start[0]) - int(end[0])) + abs(int(start[1]) -int(end[1]))
the whole function therefore can just be:
def elit():
start = input('start: ').split(' ')
end = input('end: ').split(' ')
count = int(input('count: '))
distance = abs(int(start[0]) - int(end[0])) + abs(int(start[1]) -int(end[1]))
if (count - distance) % 2 == 0:
print('Y')
else:
print('N')
input:
3 4
3 3
3
output:
Y
input:
10 4
10 2
5
output:
N
My code successfully makes its way through all the possible paths in the maze... but it always returns True, even though true only updates if certain conditions are met (having reached the edge of the maze). It seems I have misunderstanding of scope. This is my first time using the global keyword.
Here's some sample input/output. Above is the maze, the two numbers are (x, y) coordinates of current position in the maze. 'k' is the starting position, '#' is a wall.
# # ## #
# #k# #
# # # ##
# # # #
# ##
########
3 2
3 3
3 4
3 5
4 5
5 5
5 4
6 4
5 3
5 2
6 2
6 1
2 5
1 5
1 4
1 3
1 2
1 1
3 1
True
found = False
def find_start(maze):
start = None
for i in range(len(maze)):
print(maze[i])
for j in range(len(maze[i])):
if maze[i][j] == 'k':
if start == None:
start = (i, j)
else:
raise "There should be no multiple Kates"
if not start:
raise "There should be one Kate"
return start
def has_exit(maze):
visited = [[False for _ in range(len(maze[i]))] for i in range(len(maze))]
y, x = find_start(maze)
def backtrack(maze, x, y):
visited[y][x] = True
print(x, y)
if x == 0 or x == (len(maze[y]) - 1) or y == 0 or y == (len(maze) - 1) or x > len(maze[y+1]) - 1 or x > len(maze[y-1]) - 1: # This last condition is the hard one.
print('Found edge')
global found
found = True
return
if maze[y][x+1] == ' ' and not visited[y][x+1]:
backtrack(maze, x+1, y)
if maze[y][x-1] == ' ' and not visited[y][x-1]:
backtrack(maze, x-1, y)
if maze[y+1][x] == ' ' and not visited[y+1][x]:
backtrack(maze, x, y+1)
if maze[y-1][x] == ' ' and not visited[y-1][x]:
backtrack(maze, x, y-1)
backtrack(maze, x, y)
if found:
print(found)
return True
else:
print(found)
return False
The only place found is assigned a value is the first time through the code =False Then whenever the code hits backtrack it assigns it True. Importantly for your question, you never reset found, so as soon as set to True one time, it will never reset. Since you are recursing over all possible paths, you will hit an edge eventually, so found=True eventually for any run.
I agree with the other suggestions about using return values from functions, but here you just need to reset your state appropriately for the recursive search.
You haven't provided start point for you code to debug further.
However the basic rules for global keyword in Python are:
When we create a variable inside a function, it is local by default.
When we define a variable outside of a function, it is global by
default.You don't have to use global keyword.
We use global keyword
to read and write a global variable inside a function.
Use of global
keyword outside a function has no effect.
Source - More examples are found in this source
I am a bit confused on how to get this to print either true or false, for example, you have 4 of Xobject which have a value of 2 each and you have 5 of Yobject which have a value of 5 each.
you have to see if 3 xobject and 2 yobject fit into 15. this should print false as you are not able to break the objects in half or count all of them together.
as in you can not do 3(2) + 2(5) = 16, which is larger than 15 but involves you adding the objects together which is not allowed as they are meant to be two completely different things
ok so here's one way of doing it:
x = 2 #value of each x object
y = 5 #value of each y object
xObjects = int(input('How many x objects:'))
yObjects = int(input('How many y objects:'))
if ((xObjects * x) + (yObjects * y)) == 15:
print("True")
else:
print("False")
I recently saw a video on Youtube about genetic algorithms and thought it was quite interesting and decided to give it a go. Me, being new to programming and not having experience with any language other than Python, thought C#, which seemed to be the most widely used language for genetic algorithms, was t0o hard and decided to give it a try in Python. And I am currently stuck because of an error, and I can't quite figure out what is wrong with the code.
This is the code:
import random
#Wanted String
STRING_NAME = "this is a genetic algorithm"
LENG = len(STRING_NAME)
#Used Characters
VALID_CHARACTERS = "abcdefghijklmopqrstuvwxyz "
#Generation Size
POPULATION_SIZE = 200
#List of String Objects
POPULATION = []
closest = 100
choiceList = []
#Generating random strings
def randomStringGeneration(size=len(STRING_NAME)):
return ''.join(random.choice(VALID_CHARACTERS) for _ in range(size))
#string object
class ranString:
def __init__(self,manualstr=""):
if manualstr == "":
self.string = randomStringGeneration()
else:
self.string = manualstr
self.fitness = fitnessCheck(self)
#fitness checking
def fitnessCheck(String):
result = 0;
for x in range(0,LENG-1):
if (String.string[x] == STRING_NAME[x]):
result += 1
return result
#order population list by fitness decrementaly
def sortByFitness(Obj):
Obj.sort(key=lambda x: x.fitness, reverse=True)
#mating two strings
def mate(x,y):
tempxstr = x.string
tempystr = y.string
child1 = tempxstr[0:10]+tempystr[14:20]+tempxstr[21:26]
child2 = tempystr[0:10]+tempxstr[14:20]+tempystr[21:26]
ranchild1 = ranString(manualstr = child1)
ranchild2 = ranString(manualstr = child2)
POPULATION.append(child1,child2)
#main function
def generatePopulation(num):
generation = 1
for x in range(num):
if (generation == 1):
for x in range(POPULATION_SIZE):
f = ranString()
POPULATION.append(f)
sortByFitness(POPULATION)
for x in POPULATION:
print(x.string + " " + str(x.fitness))
generation +=1
else:
sortByFitness(POPULATION)
del POPULATION[100:]
for x in POPULATION:
for j in range(x.fitness):
choiceList.append(x)
for j in range(100):
x = random.choice(choiceList)
y = random.choice(choiceList)
mate(x,y)
print("\n\n\n\nGeneration"+generation)
for x in POPULATION:
print(x.string + " " + str(x.fitness))
generation += 1
generatePopulation(10)
This is the log(do you call these log files?) file with the error:
egf ukcob uf oyhtuikmdritiz 4
ouaelyf ef wufsjh aqkcyacef 3
rbuwptsdjmwskfzyccsfgzlwdyo 3
fqyg zhhhswesdfetqjy ohrpyj 3
qfirzajzhafdv dicmueavdrguv 3
pxqsxtehe bckbvadapezgrqdkb 3
zvosvvsspgbpmxhadwxkfzkqjhi 3
tfsofiurlpyakhhwqqexoafhtxi 3
qkmslihwskukcecldykkp caiqo 3
fhfh ctluzbr vty skgozgqclg 3
dglsfwimwqfxdhdzx lkcvrraev 3
jbuwaoxua uteissqfpxodciaoa 3
if qpvpcsixe kagmxyludcicwl 3
vspwdxwqkewcaethcs g dxcxao 3
d jpylld gzuojvccuh gzjxbs 3
pvzsjkxtzrjgjegimalvcaxjbjw 3
zolqfli sdahohjiryerabkvmme 2
ufslbdexaa wrfuscfbkfdulzfr 2
*
* (middle part omitted because it would be too long)
*
jcjigwzhyxwwyikfoiyrtolclg 0
srjqfxjbuppfd drlrkjkuqegvb 0
zbsbkedazmxyghrmhzdzjytcqza 0
xqxmtxrkhctqayrmkvefkpy zad 0
waxpeefkvqjjwvylre jfvedyfa 0
udyetsjd lmhuzamrwt rip dqv 0
Traceback (most recent call last):
File "/Users/Johnwon/Desktop/Genetic String.py", line 80, in <module>
generatePopulation(10)
File "/Users/Johnwon/Desktop/Genetic String.py", line 73, in generatePopulation
mate(x,y)
File "/Users/Johnwon/Desktop/Genetic String.py", line 48, in mate
ranchild1 = ranString(manualstr = child1)
File "/Users/Johnwon/Desktop/Genetic String.py", line 28, in __init__
self.fitness = fitnessCheck(self)
File "/Users/Johnwon/Desktop/Genetic String.py", line 34, in fitnessCheck
if (String.string[x] == STRING_NAME[x]):
IndexError: string index out of range
I've searched the Internet for the out of index error and it seems that I incremented too much or searched for an index that is not existent but I can't find the cause for the error. What is wrong with my code?
Also, currently my mate() function works by adding the strings to a separate list multiplied by their fitness then randomly selecting 2 of them and swapping a third of their 'genes' and popping out 2 babies. This is the only way I could think of to give more fit objects a higher chance to mate but this seems horribly unoptimized as the generations go and fitness levels grow higher. What could be a good way to do this and implement mutation?
I'm a beginner in Python and I'm open to any opinions on how to improve my code. Thanks for reading!
child1 = tempxstr[0:10]+tempystr[14:20]+tempxstr[21:26]
child2 = tempystr[0:10]+tempxstr[14:20]+tempystr[21:26]
This doesn't look right to me. These strings will each have a length of 21. But inside fitnessCheck, you're comparing them against STRING_NAME, which has a length of 27. So once x reaches 21 inside fitnessCheck, you'll get an IndexError.
You should change how you create child1 and child2 so that they have the same length as STRING_NAME.
I want to toggle between two values in Python, that is, between 0 and 1.
For example, when I run a function the first time, it yields the number 0. Next time, it yields 1. Third time it's back to zero, and so on.
Sorry if this doesn't make sense, but does anyone know a way to do this?
Use itertools.cycle():
from itertools import cycle
myIterator = cycle(range(2))
myIterator.next() # or next(myIterator) which works in Python 3.x. Yields 0
myIterator.next() # or next(myIterator) which works in Python 3.x. Yields 1
# etc.
Note that if you need a more complicated cycle than [0, 1], this solution becomes much more attractive than the other ones posted here...
from itertools import cycle
mySmallSquareIterator = cycle(i*i for i in range(10))
# Will yield 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 0, 1, 4, ...
You can accomplish that with a generator like this:
>>> def alternate():
... while True:
... yield 0
... yield 1
...
>>>
>>> alternator = alternate()
>>>
>>> alternator.next()
0
>>> alternator.next()
1
>>> alternator.next()
0
You can use the mod (%) operator.
count = 0 # initialize count once
then
count = (count + 1) % 2
will toggle the value of count between 0 and 1 each time this statement is executed. The advantage of this approach is that you can cycle through a sequence of values (if needed) from 0 - (n-1) where n is the value you use with your % operator. And this technique does not depend on any Python specific features/libraries.
e.g.
count = 0
for i in range(5):
count = (count + 1) % 2
print(count)
gives:
1
0
1
0
1
You may find it useful to create a function alias like so:
import itertools
myfunc = itertools.cycle([0,1]).next
then
myfunc() # -> returns 0
myfunc() # -> returns 1
myfunc() # -> returns 0
myfunc() # -> returns 1
In python, True and False are integers (1 and 0 respectively). You could use a boolean (True or False) and the not operator:
var = not var
Of course, if you want to iterate between other numbers than 0 and 1, this trick becomes a little more difficult.
To pack this into an admittedly ugly function:
def alternate():
alternate.x=not alternate.x
return alternate.x
alternate.x=True #The first call to alternate will return False (0)
mylist=[5,3]
print(mylist[alternate()]) #5
print(mylist[alternate()]) #3
print(mylist[alternate()]) #5
from itertools import cycle
alternator = cycle((0,1))
next(alternator) # yields 0
next(alternator) # yields 1
next(alternator) # yields 0
next(alternator) # yields 1
#... forever
var = 1
var = 1 - var
That's the official tricky way of doing it ;)
Using xor works, and is a good visual way to toggle between two values.
count = 1
count = count ^ 1 # count is now 0
count = count ^ 1 # count is now 1
To toggle variable x between two arbitrary (integer) values,
e.g. a and b, use:
# start with either x == a or x == b
x = (a + b) - x
# case x == a:
# x = (a + b) - a ==> x becomes b
# case x == b:
# x = (a + b) - b ==> x becomes a
Example:
Toggle between 3 and 5
x = 3
x = 8 - x (now x == 5)
x = 8 - x (now x == 3)
x = 8 - x (now x == 5)
This works even with strings (sort of).
YesNo = 'YesNo'
answer = 'Yes'
answer = YesNo.replace(answer,'') (now answer == 'No')
answer = YesNo.replace(answer,'') (now answer == 'Yes')
answer = YesNo.replace(answer,'') (now answer == 'No')
Using the tuple subscript trick:
value = (1, 0)[value]
Using tuple subscripts is one good way to toggle between two values:
toggle_val = 1
toggle_val = (1,0)[toggle_val]
If you wrapped a function around this, you would have a nice alternating switch.
If a variable is previously defined and you want it to toggle between two values, you may use the
a if b else c form:
variable = 'value1'
variable = 'value2' if variable=='value1' else 'value1'
In addition, it works on Python 2.5+ and 3.x
See Expressions in the Python 3 documentation.
Simple and general solution without using any built-in. Just keep the track of current element and print/return the other one then change the current element status.
a, b = map(int, raw_input("Enter both number: ").split())
flag = input("Enter the first value: ")
length = input("Enter Number of iterations: ")
for i in range(length):
print flag
if flag == a:
flag = b;
else:
flag = a
Input:
3 835Output:38383
Means numbers to be toggled are 3 and 8
Second input, is the first value by which you want to start the sequence
And last input indicates the number of times you want to generate
One cool way you can do in any language:
variable = 0
variable = abs(variable - 1) // 1
variable = abs(variable - 1) // 0