Basic Python Function replacing values - python

I am attempting to create a function with the following characteristics;
function name: new_scores,
parameters: (p1_score,p2_score,current_score,current_player)
p1_score: user inputed player 1 score,
p2_score: user inputed player 2 score,
current_score: the current score of set player after any actions performed
current_player: either 'PLAYER_ONE' or 'PLAYER_TWO'
the problem with my code is that it doesnt work in all cases, for example try replacing values in PLAYER_ONE, it just spits back out the p1_score, and p2_score that i inputed. Thanks for the help
def new_scores(p1_score,p2_score,current_score,current_player):
if current_player == 'PLAYER_ONE':
p1_score = current_score
return (p1_score,p2_score)
elif current_player == 'PLAYER_TWO':
p2_score = current_score
return (p1_score,p2_score)

Your code is needlessly complex, which is quite the feat for so few lines. :) There's no point in the assignment, just return the intended data directly:
def new_scores(p1_score, p2_score, current_score, current_player):
if current_player == 'PLAYER_ONE':
return (current_score, p2_score)
elif current_player == 'PLAYER_TWO':
return (p1_score, current_score)
Still, your code looks correct. Verify that the parameters are correct, using strings for semantics like this is a bit error-prone.

Make sure you are using the returned value and not expecting the parameters you passed in to be altered as a side effect.
>>> new_scores(3, 4, 5, "PLAYER_ONE")
(5, 4)
>>> new_scores(3, 4, 7, "PLAYER_TWO")
(3, 7)
Running your function as above shows it works as expected

Related

I'm trying to simulate a coin flip game between two people using OOP, but for some reason my for loop through 1000 is only going through once

The point of this game is to have two people flip a coin, and if the first person gets heads and the second person gets heads, the first person wins, but if the second person gets the opposite coin they win. My code's output just displays "True" a thousand times, but I have a for loop in my method that isn't working?
import numpy as np
class Students():
def __init__(self,flip,history):
self.flip=flip
self.history=history
def flipcoin(self):
for self.flip in range (0,1000):
self.flip= np.random.random()
if (self.flip<0.5):
self.flip=0
else:
self.flip=1
print (str(self.flip))
self.history= self.flip
print(self.history)
return (str(self.flip))
student1=Students(flip=0,history=[])
student1.flipcoin()
student2=Students(flip=0,history=[])
student2.flipcoin()
for Students in range (0,1000):
if (student1==student2):
print('False')
else:
print('True')
print(student1.flip,student1.history)
So to answer your immediate question, your first problem is here:
for Students in range(0, 1000):
if student1 == student2:
print('False')
else:
print('True')
What you are comparing here are two instances of "Students". Since those are different instances, they are not equal. (And I'm not sure if you have your print statements reversed -- when that comparison returns False, the code prints 'True'.)

What is the pythonic way of writing a long if-else statement?

I am quite new to Python though I have had experience in Java before.
I have the following code to convert a score into an interval delta (as part of a Spaced Repetition System (SRS) program I am implementing). This code looks ugly and not very readable. Typically I would have used a switch statement in Java. But in python I could not find an equivalent. Hence I have written this code which produces the result. But I want to take this opportunity to learn different options for achieving the same output using more pythonic ways. I would appreciate any help, even if they are pointers to resources that I can read to improve this code.
# Convert score into an interval delta
if score == 0: # Perfect page
intervalDelta = +3
elif score == 1: # 1 Word Mistake
intervalDelta = +2
elif score <= 3: # 3 Word Mistakes
intervalDelta = +1
elif score == 4: # 1 Line Mistake
intervalDelta = 0
elif score <= 8: # 2 Line Mistakes
intervalDelta = -1
elif score <= 12: # 3 Line Mistakes
intervalDelta = -2
elif score <= 20: # 5 Line Mistakes
intervalDelta = -3
elif score <= 30: # 7.5 Line Mistakes - Half a page
intervalDelta = -5
else: # More than half a page
intervalDelta = -7
I don't find the long if statement that unreadable, although I'd change to using <= for consistency (since the == cases are already single possibilities using <=). If I were implementing it from scratch, I'd probably write something like the following simply to have the associations more visible:
from math import inf
SCORE_DELTAS = (
(0, +3),
(1, +2),
(3, +1),
(4, +0),
(8, -1),
(12, -2),
(20, -3),
(30, -5),
(inf, -7),
)
def score_to_delta(score):
for bound, delta in SCORE_DELTAS:
if score <= bound:
return delta
The official position on switch statements is that switch statements are easily done with if statements, so writing long if statements is the Python way. PEP 275 and PEP3103 document the reasons why switch statements were omitted. In practice though there are several alternatives to the switch statement.. The most common is the dictionary approach to switches.
def case_a():
print('Executing case A')
def case_b():
print('Executing case B')
def case_else()
print('Executing default case')
def dict_switch(argument):
switch = {
'a': case_a
'b': case_b
}
return switch.get(argument, case_else)()
dict_switch(x)
Another approach is to keep all of the conditional logic in a class, but I find this is only necessary when there is a significant amount of conditional logic.
class Switcher:
def numbers_to_methods_to_strings(self, argument):
"""Dispatch method"""
# prefix the method_name with 'number_' because method names
# cannot begin with an integer.
method_name = 'number_' + str(argument)
# Get the method from 'self'. Default to a lambda.
method = getattr(self, method_name, lambda: "nothing")
# Call the method as we return it
return method()
def number_0(self):
return "zero"
def number_1(self):
return "one"
def number_2(self):
return "two"
In your case, however, I think #asthasr approach is the cleanest.

How to keep track the amount of even integers when looking through randomized list using recursion

Sorta newbie here. So in trying to wrap my head around using recursive functions I wanted to try to make a program that:
1: Generates a list containing 10 random integers ranging from 0 - 20
2: Using a recursive function goes trough the list and finds out what elements of the list are even integers
3: Prints out only the aformentioned even numbers
Where I have gotten stuck is in how to print out the result. I can't seem to figure out what value i want to put inside the function when calling it ( F(?) )
I tried to integrate a counter that kept track on how many times the program found a even number but it always resulted in an error that the variable is not defined no matter how hard I tried to make it global.
How could I go about this? Am I totally in the wrong?
import random
numL = []
for i in range(10):
x = random.randint(0,20)
numL.append(x)
print(numL)
def F(x):
if numL[x] % 2 == 0:
return numL[x]
else:
return F(x+1)
print(F( ??? ))
First question asked on this forum, hopefully I did okay, appreciate any help!
Assuming you want to return a list of the even numbers then you have 4 cases to consider
This is the last number in the list and its even so return this number
This is the last number in the list and its odd dont retrun this number
There are more numbers to check and this number is even so return
this plus the function result
There are more numbers to check and this number is odd to return
only the function result and not this num
So we can code this as
import random
def get_even_nums(nums):
num = nums[0]
#This is our terminating case we definitivly return a value here
if len(nums) == 1:
return [num] if num % 2 == 0 else []
else:
#If we got here we will be recursivly calling the function
#If its even number return that number plus the result of the function
#it its not even then just return the reult of the function and not this num
if num % 2 == 0:
return [num] + get_even_nums(nums[1:])
else:
return get_even_nums(nums[1:])
numL = [random.randint(0, 20) for _ in range(10)]
print(numL)
print(get_even_nums(numL))
OUTPUT
[3, 6, 5, 10, 20, 18, 5, 0, 3, 9]
[6, 10, 20, 18, 0]
So I took your function and changed it up slightly (using a slightly different approach). There's no need to a global list, though you could do that as well, if you wanted. The problem that you have is the lack of a base case or rather an incorrect one.
If you run your original function with an argument 0, which basically is the first element of your generated array, the fucntion will run until it hits one even number. At that point it'll exit recursion, because the base case basically stops recursive calls once you hit an even number.
Now, to fix this, you have to approach the problem differently. I would put your generated array as the input argument to your function, then ask myself "What would be a good base case?" Probably one that stops your recursive calls once you reach the end of the input list.
if len(numL) == 0:
return ...
Also, we need a way to return the even numbers that we found during our search through the list. For that reason I'd introduce a new acc list, where we would append the even numbers that we found. Thus the function input arguments would be
def F(numL, acc):
...
Now, in the recursive call we should check wether the current element is even or not. If it is, great, we add it to the acc list and continue into the recursive call. If it's not, we don't add anything to the acc but just continue with recursion.
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
Putting it all together, we get:
def F(numL, acc):
if len(numL) == 0:
return acc
else:
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
where numL represents your generated list and acc represents the resulting list we'll return after we traverse the list.
This is your function (as I understand it, you wanted this):
import random
def F(i):
r = random.randint(0,20)
if r % 2 == 0:
print(r)
i += 1
if i != 10:
F(i)
F(0)

Python programming function call scope changes

I am not a newbie to python. But recently I encountered an error, due to some misconception. Someone please help me to clarify it. Entire program is here : http://www.codeskulptor.org/#user39_cFs3Z8mAtf_0.py
I am having a function
def mc_trial(board, player):
"""
Plays a game starting with the given player by making random
moves and alternating between players.
"""
while board.check_win() == None:
# Get a random empty square
empty_squares = random.choice(board.get_empty_squares())
# Move the player in a random position
board.move(empty_squares[0], empty_squares[1], player)
# Switch the player
player = provided.switch_player(player)
# Game has ended
return
scores = [[0 for dummy in range(board.get_dim())] \
for dummy in range(board.get_dim())]
board_clone = board.clone()
for dummy in range(trials):
print board_clone ## Empty board
mc_trial(board_clone, player)
print board_clone #### Here value is changing after function call. How ??
My doubt is "board_clone" is passing to a function mc_trial(). the return statement there is not providing anything relating to return a value except None. But after the call, when I am printing "board_clone" the value is changing. I tried to clarify it with ipython through a sample program. But, there value remains unchanged as in the local scope . For clarification, i run a sample program, there it behaves as i expected.
def func1(var):
x = 0
while x < 1:
var[1:5]
x = x+1
return
var1 = [1,2,3,4,5,6,7,8,9]
print "B F", var1
func1(var1)
print "A F", var1
This is normal Python behaviour. Lists are passed by reference, so if you change the items in a list in a function, the changes will persist:
def f(mylist):
mylist[0] = 1
>>> l = [0, 0, 0]
>>> mylist(l)
>>> l
[1, 0, 0]
The reason your second example isn't changing the list is because the var[1:5] statement doesn't do anything. It just creates a temporary variable which is a slice of the var list, and then throws it away. It's just like saying a + 1; this would create a temporary variable but would not modify a even inside the function, let alone outside of it.
I'd guess your problem is that your "clone" has references to datastructs in the board object. The clone code doesn't appear in the link you posted?.. and as far as I can recall it's not an in-built python thing (I may be wrong there).?
Read this How to clone or copy a list?
and/or this
https://docs.python.org/2/library/copy.html

Python 3 Passing a Function into Another Function

I am somewhat new to Python, and this is a homework question, so I would appreciate no answers, just advice to help me understand. I am writing a game program that plays two different strategies against each other - a greedy strategy and a zoom-in strategy, which I have written as function. I have a game function that needs to pass in my greedy and zoom-in functions, as well as a game board. I need to be able to have either strategy function go first. So far I can only get it to where my greedy strategy goes first.
def game(P1,P2,board):
P1 = 0
P2 = 0
for x in range(len(board)):
if x%2 == 0:
move = greedy(board)
P1 += board[move]
board.remove(board[move])
else:
move = zoomin(board)
P2 += board[move]
board.remove(board[move])
if P1 > P2:
return 1
elif P1 == P2:
return 0.5
else:
return 0
This strategy always assumes that P1 is the greedy function, but I need to be able to play either first. I thought I could pass in the functions, so my call would be
game(greedy,zoomin,board)
but I am not sure how to actually implement it so that it can recognize who is playing first.
Thank you in advance for your help!
EDIT:
Here are my greedy and zoomin functions:
def greedy(board):
if board[0] > board[len(board)-1]:
#returns position of first item
return 0
elif board[len(board)-1] > board[0]:
#returns position of last item
return len(board)-1
else:
#if board[-1] == board[0]
return 0
def zoomin(board):
if len(board)%2 == 0:
evens = 0
odds = 0
for x in range(len(board)):
if x%2 ==0:
evens += board[x]
else:
odds += board[x]
if evens > odds:
return 0
else:
return len(board)-1
else:
#choose the larger value (greedy)
if board[0] < board[len(board)-1]:
return len(board)-1
else:
return 0
This is not a direct answer to your question (since senshin already answered it), but I wanted to point out that you can decrease your code duplication by using arrays instead. For instance, like this:
def game(players, board):
scores = [0] * len(players)
while i in range(len(board))
p = i % len(players)
move = players[p](board)
scores[p] += board[move]
del board[move] # <-- This is also a faster and more fail-safe version of your "board.remove(board[move])"
return scores
You can then call this function as game([greedy, zoomin], board). Also note how it extends to an arbitrary number of players, although that may not actually be useful for you. :)
You will want to rewrite your game function slightly. Notice that your game function accepts P1 and P2, but you don't do anything with them - you immediately assign 0 to both of them.
The correct way to approach this is to have your game function accept two strategies, which can be greedy or zoomin, or whatever else you might come up with later.
def game(strategy1, strategy2, board):
You will also need to replace the explicit calls to greedy and zoomin in the function body (e.g. move = greedy(board)) with calls to the strategies passed into your function instead - something like move = strategy1(board).
Then, in order to have greedy play first and zoomin play second, you could call:
game(greedy, zoomin, board)
Or if you wanted zoomin first and greedy second, you could call:
game(zoomin, greedy, board)
As you can see, the order of play is determined by the order in which you pass the two strategies into your function. Let me know if this needs clarification.

Categories

Resources