Python 3 input and if statement - validation

I am having some trouble with an input question that is supposed to allow the player to choose one of 5 starting races. I used the following code.
def racechoice():
players.race = input('After you get a chance to think, you choose to be...') #Here race is chosen
if players.race == "dwarf" or "Dwarf": #Race starting stats
players.race = "Dwarf"
players.level = 1
players.strength = 12
players.agility = 6
players.inteligence = 8
players.vitality = 14
elif players.race == "Orc" or "orc":
players.race = "Orc"
players.level = 1
players.strength = 14
players.agility = 10
players.inteligence = 4
players.vitality = 12
elif players.race == "elf" or "Elf":
players.level = 1
players.race = "Elf"
players.strength = 8
players.agility = 13
players.inteligence = 12
players.vitality = 7
elif players.race == "Human" or "human":
players.level = 1
players.race = "Human"
players.strength = 10
players.agility = 10
players.inteligence = 10
players.vitality = 10
elif players.race == "gnome" or "Gnome":
players.race = "Gnome"
players.strength = 5
players.agility = 11
players.intelligence = 17
players.vitality = 7
When called to display the player's stats:
def stats():
print(players.name)
print(players.race)
print("Level: "+ str(players.level) +" Strength: "+ str(players.strength) +" Agility: " + str(players.agility) +" Inteligence: "+ str(players.inteligence) +" Vitality: "+ str(players.vitality))
It comes back as Dwarf with Dwarf stats no matter what the player chooses. I'm new-ish to Python and was wondering, did I not use the if/elif statement(s) correctly?
ex) After you get a chance to think, you choose to be...Orc
Ecep
Dwarf
Level: 1 Strength: 12 Agility: 6 Inteligence: 8 Vitality: 14

There is a problem, you should do:
if players.race == "dwarf" or "players.race == Dwarf":
But even better, change your conditions to:
elif players.race.lower() == "orc":
It is also recommended that you use a class to encapsulate functionality, for example:
class Player(object):
def __init__(self, race, level, strength, agility, inteligence, vitality):
self.race = race
self.level = level
self.strength = strength
self.agility = agility
self.inteligence = inteligence
self.vitality = vitality
player = Player('Dwarf', 1, 12, 6, 8, 14)
then your racechoice function will look so:
def racechoice():
race = input('After you get a chance to think, you choose to be...')
if race.lower() == 'dwarf':
player = Player('Dwarf', 1, 12, 6, 8, 14)
elif race.lower() == 'orc':
player = Player('Orc', 1, 14, 10, 4, 12)
...
return player

You can't use or in that way. All your if/elif statements should be of the form:
if players.race == "dwarf" or players.race == "Dwarf":
"Dwarf" all by itself is considered True by Python and empty strings "" are considered False, so your first if always succeeds.

Related

PySpark Transform an algorithm to UDF and apply it on a DataFrame

I wrote an algorithm that does something and prints the output. The input for my algorithm is a list with some integers.
Here is the sample input as a list.
`mylist = [5,6,14,15,16,17,18,19,20,28,40,41,42,43,44,55]`
and here is my algorithm
```
tduration = 0
duration = 0
avg = 0
bottleneck = 0
y = 0
x = 0
while x<len(mylist)-4 and y<len(mylist)-1 :
if mylist[x+4] == mylist[x]+4:
y = x + 4
print("MY LIST X = ",mylist[x])
print("X = ", x)
print ("Y = ", y)
while True:
if y==len(mylist)-1 or mylist[y+1] > mylist[y]+10:
bottleneck = bottleneck + 1
duration = mylist[y] - mylist[x] + 1
tduration = tduration + duration
avg = tduration/bottleneck
x = y + 1
print("MY LIST Y = " , mylist[y])
print("Duration = " , duration)
break
else:
y = y + 1
else:
x = x + 1
print("BottleneckCount = ", bottleneck, "\nAverageDuration = ", avg)
```
Now I want to transform this "Algorithm" to a User Defined Function (UDF) in PySpark and then apply this UDF to a DataFrame with one column. There is one list in each row of this DataFrame. Sample DataFrame has 1 column and 2 rows. row1 is a list of [10,11,19,20,21,22,23,24,25,33,45] and row2 is a list of [55,56,57,58,59,60,80,81,82,83,84,85,92,115] so the UDF should be applied to each row of DataFrame separately and give the results for each row in another column.
Thank you in advance for your time and help. I will upvote your answers
Here's a way you can do:
import pyspark.sql.functions as F
from pyspark.sql.types import IntegerType, ArrayType
def calculate(mylist):
tduration = 0
duration = 0
avg = 0
bottleneck = 0
y = 0
x = 0
while x<len(mylist)-4 and y<len(mylist)-1 :
if mylist[x+4] == mylist[x]+4:
y = x + 4
print("MY LIST X = ",mylist[x])
print("X = ", x)
print ("Y = ", y)
while True:
if y==len(mylist)-1 or mylist[y+1] > mylist[y]+10:
bottleneck = bottleneck + 1
duration = mylist[y] - mylist[x] + 1
tduration = tduration + duration
avg = tduration/bottleneck
x = y + 1
print("MY LIST Y = " , mylist[y])
print("Duration = " , duration)
break
else:
y = y + 1
else:
x = x + 1
return bottleneck, avg
# sample data frame to use
df = spark.createDataFrame(
[
[[10,11,19,20,21,22,23,24,25,33,45]],
[[55,56,57,58,59,60,80,81,82,83,84,85,92,115]],
],
['col1',]
)
df.show()
+--------------------+
| col1|
+--------------------+
|[10, 11, 19, 20, ...|
|[55, 56, 57, 58, ...|
+--------------------+
# convert values to int --- edit
f_to_int = F.udf(lambda x: list(map(int, x)))
df = df.withColumn('col1', f_to_int('col1'))
# create udf
func = F.udf(lambda x: calculate(x), ArrayType(IntegerType()))
# apply udf
df = df.withColumn('vals', func('col1'))
# create new cols
df = df.select("col1", df.vals[0].alias('bottleneck'), df.vals[1].alias('avg'))
df.show()
+--------------------+----------+----+
| col1|bottleneck| avg|
+--------------------+----------+----+
|[10, 11, 19, 20, ...| 1|null|
|[55, 56, 57, 58, ...| 2|null|
+--------------------+----------+----+
YOLO answered this question and it is a complete answer. The only problem is that in the last column for "avg", we are getting NULL values.
I realized that I can solve this problem by using this "func" instead of that "func" in YOLO's answer.
import pyspark.sql.types as T
func = F.udf(lambda x: calculate(x), T.StructType(
[T.StructField("val1", T.IntegerType(), True),
T.StructField("val2", T.FloatType(), True)]))

Numerical sequence of 1 2 4

I need help in providing an algorithm for a numerical sequence which should display a series of 1 2 4 and its consecutive summations.
e.g. If my input value is 20, it should display
1 2 4 8 9 11 15 16 18
Wherein
1 = 1
2 = 1 + 1
4 = 2 + 2
8 = 4 + 4
And the summation of 1 and 2 and 4 will repeat again starting with the present number which is 8 and so on..
9 = 8 + 1
11 = 9 + 2
15 = 11 + 4
16 = 15 + 1
18 = 16 + 2
As you can see, it should not proceed to 22 (18 + 4) since our sample input value is 20. I hope you guys get my point. I'm having a problem in designing the algorithms in the for loop. What I have now which is not working is
$input = 20;
for ($i = $i; $i < $input; $i = $i+$i) {
if($i==0){
$i = 4;
$i = $i - 3;
}elseif($i % 4 == 0){
$i = $i + 1;
}
print_r("this is \$i = $i<br><br>");
}
NOTE: Only one variable and one for loop is required, it will not be accepted if we use functions or arrays. Please help me, this is one of the most difficult problems I've encountered in PHP..
you can use the code
$input = 20;
$current = 1;
$val = 1;
while($val < $input){
print_r("this is \$val = $val\n");
$val = $val + $current;
$current = ($current == 4 ? 1 : $current*2);
}
see the online compiler
Since you have mentioned Only one variable and one for loop is required
Try this,
$input = 20;
for ($i = 1; $i < $input; $i) {
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+1;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+2;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+4;
}
Online Compiler
def getSeq(n):
if n == 1:
return [1]
temp = [1]
seq = [ 1, 2, 4]
count, current, prev = 0, 0, 1
while True:
current = prev + seq[count]
if current > n:
break
prev = current
temp += [current]
count = (count + 1) % 3
return temp
print getSeq(20)
I'm pretty sure that this one is going to work
the case that we have to take care of is n == 1 and return a static result [1].
in other cases the second value is repeating circularly and adding up to previous value.
This Python solution should be implementable in any reasonable language:
limit = 20
n = 1 << 2
while n >> 2 < limit:
print(n >> 2)
n = (((n >> 2) + (2 ** (n & 3))) << 2) + ((n & 3) + 1) % 3
Perl Equivalent (using the style of for loop you expect):
$limit = 20;
for ($n = 1 << 2; $n >> 2 < $limit; $n = ((($n >> 2) + (2 ** ($n & 3))) << 2) + (($n & 3) + 1) % 3) {
print($n >> 2, "\n");
}
OUTPUT
1
2
4
8
9
11
15
16
18
EXPLANATION
The basic solution is this:
limit = 20
n = 1
i = 0
while n < limit:
print(n)
n = n + (2 ** i)
i = (i + 1) % 3
But we need to eliminate the extra variable i. Since i only cycles through 0, 1 and 2 we can store it in two bits. So we shift n up two bits and store the value for i in the lower two bits of n, adjusting the code accordingly.
Not only one variable and one for loop, no if statements either!

Why does my simulated annealing algorithm generate increasingly worse solutions and converge early?

Why does my program generate increasingly worse solutions and converge so early?
I've been reading up on optimization and various meta-heuristic techniques recently and I recently decided to try and implement simulated annealing as described in this post.
I believe that I understand the theory well enough.
There is an acceptance probability that is guided by the following function
math.exp(-cost_delta/temp)
where the cost delta is the difference between the "cost" of your current solution and the cost of your new randomly generated proposed solution. The greater the cost delta, the lower probability your new solution has of being accepted and as the number of iterations increases and your temperature "cools" and approaches 0, new solutions have a increasingly smaller change of being accepted.
Your cost is determined from some objective function that you either want to minimize or maximize and your objective function will change depending on your problem.
I implemented a simulated annealing function as mentioned in the post and wikipedia:
def simulated_annealing(initial_state):
current_state = initial_state
current_cost = cost_of_state(current_state)
temp = 3.0
num_iteration = 0
while current_cost > 0:
neighbour = get_random_neighbour(current_state)
neighbour_cost = cost_of_state(neighbour)
cost_delta = neighbour_cost - current_cost
if cost_delta <= 0 or random.random() < math.exp(-cost_delta/temp):
current_state = neighbour
current_cost = neighbour_cost
print('current cost: '+str(current_cost))
print('Num of iterations: '+str(num_iteration))
num_iteration += 1
if num_iteration % 500 == 0 and temp > 0.10:
temp -= 0.10
return current_state, num_iteration
as well as a function to get a random neighbor:
def get_random_neighbour(current_state):
neighbour = [house[:] for house in current_state]
i = random.randint(0, 4)
mRange = []
mRange.extend(range(0, i))
mRange.extend(range(i+1, 4))
j = random.choice(mRange)
#j = random.randint(0, 4)#.randint(opp1, opp2)
attr_idx = random.randint(0, 4)
neighbour[i][attr_idx] = neighbour[j][attr_idx]
neighbour[j][attr_idx] = neighbour[i][attr_idx]
return neighbour
and calculate the cost of the current state based on some objective function:
def cost_of_state(state):
cost = 15
for i , h in enumerate(state):
cost -= sum([
h[nat] == 'brit' and h[col] == 'red',
h[nat] == 'swede' and h[ani] == 'dog',
h[nat] == 'dane' and h[bev] == 'tea',
i< 4 and h[col] == 'green' and state[i+1][col] == 'white',
h[col] == 'green' and h[bev] == 'coffee',
h[cig] == 'pall mall' and h[ani] == 'bird',
h[col] == 'yellow' and h[cig] == 'dunhill',
i == 2 and h[bev] == 'milk',
i == 0 and h[nat] == 'norwegian',
h[cig] == 'blends' and ((i > 0 and state[i-1][ani] == 'cat') or (i < 4 and state[i+1][ani] == 'cat')),
h[ani] == 'horse' and ((i > 0 and state[i-1][cig] == 'dunhill') or (i < 4 and state[i-1][cig] == 'dunhill')),
h[cig] == 'blue master' and h[bev] == 'root beer',
h[nat] == 'german' and h[cig] == 'prince',
h[nat] == 'norwegian' and ((i > 0 and state[i-1][col] == 'blue') or (i < 4 and state[i+1][col] == 'blue')),
h[cig] == 'blends' and ((i > 0 and state[i-1][bev] == 'water') or (i < 4 and state[i+1][bev] == 'water')),
])
return cost
as well as the code to test/run everything:
nationalities = ['dane', 'brit', 'swede', 'norwegian', 'german']
colors = ['yellow', 'red', 'white', 'green', 'blue']
animals = ['horse', 'cat', 'bird', 'fish', 'dog']
beverages = ['water', 'tea', 'milk', 'coffee', 'root beer']
cigars = ['pall mall', 'prince', 'blue master', 'dunhill', 'blends']
attributes = [nationalities, colors, animals, beverages, cigars]
num_houses = 5
nat = 0
col = 1
ani = 2
bev = 3
cig = 4
initial = []
for i in range(0, num_houses):
initial.append([attr[i] for attr in attributes])
random.seed(100)
solution, iterations = simulated_annealing(initial)
for house in solution:
print(house)
print('Number of iterations:', iterations)
Now, my problem is that when I run everything, I only see a few state changes when I actually run my program. Below you can see the output that I get from the first 10 iterations.
current cost: 11
Num of iterations: 0
current cost: 11
Num of iterations: 1
current cost: 11
Num of iterations: 2
current cost: 10
Num of iterations: 3
current cost: 10
Num of iterations: 4
current cost: 10
Num of iterations: 5
current cost: 10
Num of iterations: 6
current cost: 11
Num of iterations: 7
current cost: 11
Num of iterations: 8
current cost: 11
Num of iterations: 9
current cost: 11
Num of iterations: 10
current cost: 11
and by the time I get to iteration 65, my solutions are actually getting worse and things seem to stall:
urrent cost: 12
Num of iterations: 63
current cost: 12
Num of iterations: 64
current cost: 13
Num of iterations: 65
current cost: 13

After Effects: Return value if variable equals part of a set of numbers

I'm writing an AE Expression that will spit out a number based on an Effect's keyframed value on the same layer. That is, if it's 1, value is 100, if it's 2, value is 101, if it's 3, 99, etc. Here's what I've got working:
x = effect("Mouth")("Slider");
if (x == 7 || x == 11 || x == 16) {
103
} else if (x == 6 || x == 10 || x == 15 || x == 25 || x == 26){
102
} else if (x == 5 || x == 9 || x == 12 || x == 14 || x == 19 || x == 24 || x == 27 || x == 28){
101
} else {
100
}
Surely there is a more elegant way to do this? I've tried writing it
if (x == 7 || 11 || 16)
but telling After Effects X absolutely equals "this" OR "that" just makes it assume it also equals "everything". Argh.
This is a little weird (arguably elegant?), but if you're just looking for something more compact, you could do:
x = effect("Mouth")("Slider");
if (",7,11,16,".indexOf(","+x+",") != -1) {
103
} else if (",6,10,15,25,26,".indexOf(","+x+",") != -1) {
102
} else if (",5,9,12,14,19,24,27,28,".indexOf(","+x+",") != -1) {
101
} else {
100
}
but don't forget the commas at both ends!
I thought about using ECMA's array.indexOf(x), but it is not supported in AE's JS expressions. [edit: mistakedly wrote 'offsetOf']
Here are two other approaches you could use. You can compress this code more, but I left it spread out for readability.
For shorter lists you can use a switch/case and have multiple options execute the same code. Like so:
thingToTest = effect("Mouth")("Slider");
switch (thingToTest) {
case 7:
case 11:
case 16:
result = 103;
break;
case 6:
case 10:
case 15:
case 25:
case 26:
result = 102;
break;
case 5:
case 9:
case 12:
case 14:
case 19:
case 24:
case 27:
case 28:
result = 101;
break;
default:
result = 100;
break;
}
The problem is that if you have a lot of possible outcomes to check for, that could become quite unwieldy. In which case, I'd make the values for each outcome case be an array and loop through them.
thingToTest = effect("Mouth")("Slider");
mySet1 = [7, 11, 16];
mySet2 = [6, 10, 15, 25, 26];
mySet3 = [5, 9, 12, 14, 19, 24, 27, 28];
result = 100; // Default
foundIt = 0;
for (i = 0; i < mySet1.length; i++) {
if (mySet1[i] == thingToTest) {
result = 103;
foundIt = 1;
break;
}
}
if(foundIt) {
for (i = 0; i < mySet2.length; i++) {
if (mySet2[i] == thingToTest) {
result = 102;
foundIt = 1;
break;
}
}
}
if(foundIt) {
for (i = 0; i < mySet3.length; i++) {
if (mySet3[i] == thingToTest) {
result = 101;
foundIt = 1;
break;
}
}
}
result;
Putting the successive groups in a conditional statement marginally improves performance by not iterating through those arrays if a match has already been found. For efficiency, it would make sense to test against the contents of your longest list of numbers first, because it's more likely to contain the match.
These solutions may not be as compact but are definitely scaleable.

DRYer method for if-else conditional statement?

How to write DRYer code for this in a model:
a = 10
b = 6
if a == b
a = 20
else
a
end
Basically, a remains a = 10 when a != b.
a = 10
b = 6
a = 20 if a == b
If this is in a method and you want the last value of a to be returned:
a = 10
b = 6
a == b ? a = 20 : a
Here's the third one :
You can also use short circuit operator and
a = 10
b = 6
a == b and a = 20

Resources