Python. displaying items in a random order - python

I'm a beginner at python and i've got this code for a flash card game that I have wrote. The following code is only a small part of it.
remove = 0
while remove < 2:
a = random.choice(list(key))
if (a) == line27:
print(a)
x = input(random.choice(defi))
x = input(random.choice(defi))
x = input(line28)
if x == ('c'):
remove = remove + 1
print('you got it right')
score = (score + 1)
print('score =', score)
if x == ('b', 'a'):
print('thats wrong')
print()
t = t + 1
if remove == 2:
key.remove(line27)
I have to be able to display this :
x = input(random.choice(defi))
x = input(random.choice(defi))
x = input(line28)
in a random order every time it displays. so the two random choices have to display in different positions and so does the line 28.
the two random choices are in a list and the line 28 is in another list if that is any help.

Would something like this be sufficient? It seems like this is what you are asking for, but I don't really know...
def randomInput(list):
randIdx = random.randint(0, len(list)-1)
in = input(list[randIdx])
list.remove(randIdx)
return in, list
inputs = [random.choice(defi), random.choice(defi), line28]
x, inputs = randomInput(inputs)
x, inputs = randomInput(inputs)
x, inputs = randomInput(inputs)
Also, as Burhan Khalid said, x is never going to be equal to the tuple ('b', 'a')... I suppose what you meant was
x == 'b' or x == 'a'

Related

combinations with python

I am trying to generate combination of ID's
Input: cid = SPARK
oupout: list of all the comibnations as below, position of each element should be constant. I am a beginner in python any help here is much appreciated.
'S****'
'S***K'
'S**R*'
'S**RK'
'S*A**'
'S*A*K'
'S*AR*'
'S*ARK'
'SP***'
'SP**K'
'SP*R*'
'SP*RK'
'SPA**'
'SPA*K'
'SPAR*'
'SPARK'
I tried below, I need a dynamic code:
cid = 'SPARK'
# print(cid.replace(cid[1],'*'))
# cu_len = lenth of cid [SPARK] here which is 5
# com_stars = how many stars i.e '*' or '**'
def cubiod_combo_gen(cu_len, com_stars, j_ite, i_ite):
cubiodList = []
crange = cu_len
i = i_ite #2 #3
j = j_ite #1
# com_stars = ['*','**','***','****']
while( i <= crange):
# print(j,i)
if len(com_stars) == 1:
x = len(com_stars)
n_cid = cid.replace(cid[j:i],com_stars)
i += x
j += x
cubiodList.append(n_cid)
elif len(com_stars) == 2:
x = len(com_stars)
n_cid = cid.replace(cid[j:i],com_stars)
i += x
j += x
cubiodList.append(n_cid)
elif len(com_stars) == 3:
x = len(com_stars)
n_cid = cid.replace(cid[j:i],com_stars)
i += x
j += x
cubiodList.append(n_cid)
return cubiodList
#print(i)
#print(n_cid)
# for item in cubiodList:
# print(item)
print(cubiod_combo_gen(5,'*',1,2))
print(cubiod_combo_gen(5,'**',1,3))
For every character in your given string, you can represent it as a binary string, using a 1 for a character that stays the same and a 0 for a character to replace with an asterisk.
def cubiod_combo_gen(string, count_star):
str_list = [char0 for char0 in string] # a list with the characters of the string
itercount = 2 ** (len(str_list)) # 2 to the power of the length of the input string
results = []
for config in range(itercount):
# return a string of i in binary representation
binary_repr = bin(config)[2:]
while len(binary_repr) < len(str_list):
binary_repr = '0' + binary_repr # add padding
# construct a list with asterisks
i = -1
result_list = str_list.copy() # soft copy, this made me spend like 10 minutes debugging lol
for char in binary_repr:
i += 1
if char == '0':
result_list[i] = '*'
if char == '1':
result_list[i] = str_list[i]
# now we have a possible string value
if result_list.count('*') == count_star:
# convert back to string and add to list of accepted strings
result = ''
for i in result_list:
result = result + i
results.append(result)
return results
# this function returns the value, so you have to use `print(cubiod_combo_gen(args))`
# comment this stuff out if you don't want an interactive user prompt
string = input('Enter a string : ')
count_star = input('Enter number of stars : ')
print(cubiod_combo_gen(string, int(count_star)))
It iterates through 16 characters in about 4 seconds and 18 characters in about 17 seconds. Also you made a typo on "cuboid" but I left the original spelling
Enter a string : DPSCT
Enter number of stars : 2
['**SCT', '*P*CT', '*PS*T', '*PSC*', 'D**CT', 'D*S*T', 'D*SC*', 'DP**T', 'DP*C*', 'DPS**']
As a side effect of this binary counting, the list is ordered by the asterisks, where the earliest asterisk takes precedence, with next earliest asterisks breaking ties.
If you want a cumulative count like 1, 4, 5, and 6 asterisks from for example "ABCDEFG", you can use something like
star_counts = (1, 4, 5, 6)
string = 'ABCDEFG'
for i in star_counts:
print(cubiod_combo_gen(string, star_counts))
If you want the nice formatting you have in your answer, try adding this block at the end of your code:
def formatted_cuboid(string, count_star):
values = cubiod_combo_gen(string, count_star)
for i in values:
print(values[i])
I honestly do not know what your j_ite and i_ite are, but it seems like they have no use so this should work. If you still want to pass these arguments, change the first line to def cubiod_combo_gen(string, count_star, *args, **kwargs):
I am not sure what com_stars does, but to produce your sample output, the following code does.
def cuboid_combo(cid):
fill_len = len(cid)-1
items = []
for i in range(2 ** fill_len):
binary = f'{i:0{fill_len}b}'
#print(binary, 'binary', 'num', i)
s = cid[0]
for idx, bit in enumerate(binary,start=1):
if bit == '0':
s += '*'
else: # 'bit' == 1
s += cid[idx]
items.append(s)
return items
#cid = 'ABCDEFGHI'
cid = 'DPSCT'
result = cuboid_combo(cid)
for item in result:
print(item)
Prints:
D****
D***T
D**C*
D**CT
D*S**
D*S*T
D*SC*
D*SCT
DP***
DP**T
DP*C*
DP*CT
DPS**
DPS*T
DPSC*
DPSCT

How do I create a percentage increase calculation in python?

I need to create a percentage increase in python.
My code is as follows:
(x = 135,000)
x = x_1.strip()
xspl = x.split(",")
i=0
for i in range(len(xspl)-1):
if i == 0:
xnum = xspl[i].join(xspl[i+1])
else:
xnum = xnum.join(xspl[i])
calcnum2 = (int(xnum)-xPrev/xPrev)*100
k=0
for k in range(len(str((calcnum2)))):
if str(calcnum2)[k] == '.': #looks for decimal place to make 2 d.p.
subnum2 = str(calcnum2)[:k+3]
break
else:
pass
print(deceased,'(+',subnum2 + '%)')
xPrev = int(xnum)
However, it does not make the number to 2 decimal places and actually outputs:
(+ 61356135100.0%)
Does anyone know what is happening here?

Iterating through existing list values while creating it with a list comprehension

while this is completely not needed I still want to try and put everything I can in as little lines of code as possible while also using OOP
I have the code done without OOP but someone asked whether it can be done with OOP, the problem can be solved in more lines of code but I want to put as much into just 1 as possible
class Player:
def __init__(self,x,y,z,a):
self.id = x
self.prompt = y
self.score = z
self.overall_scores = a
players = [Player(x,y,random.randint(1,6),{z.id:z.score for z in players}
if x == 3 else None) for x,y in zip(range(0,4),["First", "Second", "Third",
"Fourth"])]
I expect to have each player with their own score and last player to hold the overall scores so that I could sort them by their value to determine the player with the highest score. Note that OOP is not the best way to approach this task but I was asked how it would look with OOP
What the program should do: each player is given a random score and then ranked based on the highest score
Edit:
Since the code without OOP was requested, here it is:
import operator,random
players = {x:0 for x in range(0,4)}
prompts = ["First", "Second", "Third", "Fourth"]
for a in players:
players[a] = random.randint(1,6)
print("%s:\nDice: %s" % (prompts[a],players[a]))
sorted_players = sorted(players.items(),key=operator.itemgetter(1))
draw = True
previous = 0
draw_between = []
first = True
for a in sorted_players[::-1]:
if first:
previous = a[1]
first = False
elif previous != a[1]:
draw = False
if draw:
draw_between.append(a[0])
if draw:
print("The chances of this were astronomically low but it happened anyway!")
print("It's a draw!")
elif len(draw_between) <= 1:
print("%s Player Wins!" % (prompts[sorted_players[-1][0]]))
else:
out = "First place is a draw between Players:\n"
draw_between.sort()
for b,a in enumerate(draw_between):
out += str(prompts[a])
if b < len(draw_between)-1:
out += ", "
print(out)
The comments and the end of the question indicate, you do not need the "overall score" as well as you do not need to collect the score of the last player. If that is the case, then this does what you want, i.e. "each player is given a random score and then ranked based on the highest score" (I assumed you wanted them ranked from first to last):
import random
class Player:
def __init__(self, x, y, z):
self.id = x
self.prompt = y
self.score = z
players = [Player(x,
y,
random.randint(1, 6))
for x, y in zip(range(0, 4), ["First", "Second", "Third", "Fourth"])]
sorted_players = sorted([Player(x,
y,
random.randint(1, 6))
for x, y in zip(range(0, 4), ["First", "Second", "Third", "Fourth"])],
key=lambda dude: dude.score, reverse=True)

Python: Get number from a non-sepreted string. Using regex?

I am working on convert a chemical formular to the proportion of elements by using python.
for example:
I have a list of ["Ti5Cu3", "TiCu2", "Ti2Cu3"] as input list, and want to convert it to [5/(5+3), 1/(1+2), 2/(2+3)].
How can I get the number behind the element mark? I think that re library might be useful? And how to use it to solve my problem?
My solution now is:
def formula2por(s):
if s == "Ti":
return 1
elseif s == "Cu":
return 0
else:
t = re.match(r'Ti(.*)Cu(.*)', s).groups()
# pdb.set_trace()
if t[0] is not '':
x = int(t[0])
else:
x = 1
if t[1] is not '':
y = int(t[1])
else:
y = 1
return round(x/(x+y), 4)
However, I think it is mussy and not a pythonic way for this question.
Thanks.
You can use Ti(\d*)Cu(\d*) to capture the digits and pass the matched object to a replacement function; where the digits can be accessed as the first and second captured group respectively:
lst = ["Ti5Cu3", "TiCu2", "Ti2Cu3"]
​
def div_sub(match):
x, y = match.group(1), match.group(2)
x = 1 if x == '' else int(x)
y = 1 if y == '' else int(y)
return str(x/(x+y))
​
import re
[float(re.sub(r"Ti(\d*)Cu(\d*)", div_sub, s)) for s in lst]
# [0.625, 0.3333333333333333, 0.4]
You can easily handle this if we make the assumption that you have none of the three letter codes. Then,
def calculate(match):
i = 1, tmp = []
while match.group(i) != '':
if match.group(i+1) == '':
tmp.append(1.0)
else:
tmp.append(float(match.group(i+1)))
i += 2
if i == 1:
return 0
else:
return tmp[0]/sum(tmp)
import re
required_list = []
pattern = re.compile("^([A-Z][a-z]?)(\d*\.?\d*)([A-Z][a-z]?)(\d*\.?\d*)")
for compound in lst:
required_list.append(calculate(pattern.match(compound)))
As you can see, this code can easily be adapted to multi element compounds like potassium permanganate and handles floating point indices.

Check whether the last three flips were all heads or all tails in Python

So I have a challenge, in which I have to create a programme that simulates a coin flip, by generating a random number corresponding to either heads or tails. When three simultaneous 'H' (heads) or 'T' (tails) are outputted my programme should stop. I have tried to get this to work, here is my code so far:
import random
active=True
list1 = []
b = 0
while active:
l=random.randint(0,1)
b += 1
i='a'
if l == 0:
i = 'H'
else:
i = 'T'
list1.append(i)
if list1[:-3] is ['H','H','H']:
active = False
elif list1[:-3] is ['T','T','T']:
active = False
else:
active = True
print(list1),
It seems that the only thing not working is the part that checks for 3 corresponding heads or tails, does anybody know how I may code this part correctly?
The problem, as was mentioned in the comments above, is that list1[:-3] should be list1[-3:] (getting the last three elements of the list, instead of everything up to the last three elements) and comparisons should be done with == instead of is. The adjusted program would be:
import random
active=True
list1 = []
b = 0
while active:
l=random.randint(0,1)
b += 1
i='a'
if l == 0:
i = 'H'
else:
i = 'T'
list1.append(i)
if list1[-3:] == ['H','H','H']:
active = False
elif list1[-3:] == ['T','T','T']:
active = False
else:
active = True
print(list1)
However, I think it might also be useful to see a condensed approach at writing the same program:
import random
flips = []
while flips[-3:] not in (['H'] * 3, ['T'] * 3):
flips.append(random.choice('HT'))
print(flips)
You can do this by tracking a running list of flips. If the new flip is the same as the previous, append it to the list. Else, if the new flip is not the same as the previous, clear the list and append the new flip. Once the length reaches 3, break from the while loop:
import random
flipping = True
flips = []
flip_status = {0: "H", 1: "T"}
current_flip = None
while flipping:
current_flip = flip_status[random.randint(0,1)]
print current_flip
if len(flips) == 0:
flips.append(current_flip)
else:
if current_flip == flips[-1]:
flips.append(current_flip)
if len(flips) == 3:
break
else:
flips = []
flips.append(current_flip)
print "Flips: " + str(flips)
Here's a sample run:
T
T
H
T
T
H
T
H
H
T
T
T
Flips: ['T', 'T', 'T']

Categories

Resources