It's about a quite simple dice game with the following rules:
Chose a number between 1 and 100
Role three dices at once
Get as close as possible to the chosen number with the rolled points and the following options:
addition, subtraction, multiplication and/or
multiply the points with 10
Example 1:
Dice1 = 2, Dice2 = 3, Dice3 = 1, Chosen number = 5
Possible calculations:
2 + 3 * 1 = 5 or
2 * 3 - 1 = 5
Example 2:
Dice1 = 6, Dice2 = 2, Dice3 = 2, Chosen number = 42
Possible calculation:
(6*10) - (2*10) + 2 = 42
Goal of my program is to find the best possible ways for combining points and operators.
What I have so far:
import sys
import operator
a = int (sys.argv[1]) # Dice 1
b = int (sys.argv[2]) # Dice 2
c = int (sys.argv[3]) # Dice 3
d = int (sys.argv[4]) # Number to reach
class Calc():
def __init__(self):
self.resultsdict = dict()
self.werte = dict()
permutations = [[a,b,c], [a,c,b], [b,a,c], [b,c,a], [c,a,b], [c,b,a]]
for p in permutations:
aa = int(p[0])
bb = int(p[1])
cc = int(p[2])
self.compute(aa,bb,cc, d)
self.getBest(d, a, b, c)
def compute(self, a,b,c,d):
func = [a+b+c, a+b-c, a+b*c, (a+b)*c, (a-b)+c, a-(b+c), a-b-c, a-b*c, (a-b)*c, a*b+c, a*(b+c), a*b-c, a*(b-c), a*b*c]
func1 = ["a+b+c", "a+b-c", "a+b*c", "(a+b)*c", "(a-b)+c", "a-(b+c)", "a-b-c", "a-b*c", "(a-b)*c", "a*b+c", "a*(b+c)", "a*b-c", "a*(b-c)", "a*b*c"]
i = 0
while i < len(func):
dictkey = str(a)+str(b)+str(c)+ ", " +str(func1[i])
if not func[i] < 0 :
self.resultsdict[dictkey] = abs(d-func[i])
self.werte[dictkey] = func[i]
i += 1
def getBest(self, d, d1, d2, d3):
self.bestresults = dict()
keys = self.resultsdict.keys()
minval = 1000000000
for k in keys:
if int(self.resultsdict[k]) <= int(minval):
minval = int(self.resultsdict[k])
print("THE BEST COMBINATION FOR REACHING " + str(d) + " WITH " + str(d1) + ", " + str(d2) + ", " + str(d3) + " HAS BEEN GAINED WITH REST: " + str(minval))
for k in keys:
if int(self.resultsdict[k]) == int(minval):
ergebnis = self.werte[k]
print('\t' + "Combination: " + str(k) + ", Result: " + str(ergebnis))
t = Calc()
In func I hardcoded part of possible combinations.
Now I'm looking for an algorithm that generates these combinations automatically so I don't have to write them all down manually.
How would you do that?
You can use
python "itertools"
http://docs.python.org/2/library/itertools.html
to genrate all combinations of ['+','-','*','a','b','c',10]
So that you can get all possible combinations and then just filter out the valid expressions.
but it won't generate paranthesis.
You can include ['(',')']
but it will take more time.
Related
I am creating a passkey of 16 alphanumeric characters where I am generating starting 4 digits with A001, A002, A003 till A999. Once it goes till A999, the alphabet will auto increase to B and digits will again start with 001. And the same process will go till Z999. Once the A-Z series will over, then it will start with AA01 and so on. How to do this thing in python? As I am new in python so I tried it on my own and also tried some examples but I am unable to make the increment of characters.
Any ideas or thoughts would be greatly appreciated.
Many thanks
rec=0
new_list16 = []
def autoIncrement():
global rec
first = 'A'
i = chr(ord(first))
new_list16.append(i)
while True:
pStart = 1 #adjust start value, if req'd
pInterval = 1 #adjust interval value, if req'd
if (rec == 0):
rec += pStart
else:
rec = rec + pInterval
return str(rec).zfill(3)
#print(autoIncrement())
new_list16.append(autoIncrement())
print(*new_list16, sep = '')
Going from A999 to B001 instead of B000 really messes things up a bit, but you can still use this for the A-Z part, and a simple modulo operation for the numbers.
def excel_format(num):
# see https://stackoverflow.com/a/182924/1639625
res = ""
while num:
mod = (num - 1) % 26
res = chr(65 + mod) + res
num = (num - mod) // 26
return res
def full_format(num, d=3):
chars = num // (10**d-1) + 1 # this becomes A..ZZZ
digit = num % (10**d-1) + 1 # this becomes 001..999
return excel_format(chars) + "{:0{}d}".format(digit, d)
for i in range(10000):
print(i, full_format(i, d=2))
Number of digits in the numeric part is controlled with the optional d parameter. I'll use 2 for purpose of demonstration, but 3 works just as well.
0 A01
...
98 A99
99 B01
...
2573 Z99
2574 AA01
...
9998 CW99
9999 CX01
def auto_increment(number):
if number == 'ZZZZ':
return 'ZZZZ'
digits = "".join([i for i in number if i.isdigit()])
chars = "".join([i for i in number if not i.isdigit()])
if int(digits) == int('9' * len(digits)):
digits = "000"
new_char = [ord(i) for i in chars]
if new_char[-1] % ord('Z') == 0:
new_char = "".join([chr(i) for i in new_char]) + 'A'
else:
new_char[-1] = new_char[-1] + 1
new_char = "".join([chr(i) for i in new_char])
else:
new_char = chars
new_digit = int(digits) + 1
l = len(new_char)
ll = len(str(new_digit))
new_digit = (("0" * (3-ll)) + str(new_digit))[(l-1):]
return f"{new_char}{new_digit}"
This function return you the next number, given any number.
for example: A999 will return AB01.
you can now just use this function in a loop.
This probably needs to be tested and refactored more, but here's a start for you:
def leadingZeros(number, digits):
numberString = str(number)
for digit in range(1, digits):
if number < 10**digit:
numberString = '0' + numberString
return numberString
def autoIncrement(oldNumber):
order = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!'
lastDigitOrder = order.find(oldNumber[3])
newNumber = ''
if order.find(oldNumber[1]) <= 9:
# 3 digit number
number = int(oldNumber[1:]) + 1
letter = oldNumber[0]
if 1000 == number:
letterOrder = order.find(oldNumber[0])
letter = order[letterOrder + 1]
newNumber = letter + leadingZeros(number % 1000, 3)
elif order.find(oldNumber[2]) <= 9:
# 2 digit number
number = int(oldNumber[2:]) + 1
letters = oldNumber[0:2]
if 100 == number:
letterOrder = order.find(oldNumber[1])
letter = order[letterOrder + 1]
letters = oldNumber[0] + letter
newNumber = letters + leadingZeros(number % 100, 2)
elif order.find(oldNumber[3]) <= 9:
# 1 digit number
number = int(oldNumber[3]) + 1
letters = oldNumber[0:3]
if 10 == number:
letterOrder = order.find(oldNumber[2])
letter = order[letterOrder + 1]
letters = oldNumber[0:2] + letter
newNumber = letters + leadingZeros(number % 10, 1)
else:
# just letters
print(oldNumber)
letterOrder = order.find(oldNumber[3])
letter = order[letterOrder + 1]
newNumber = oldNumber[0:3] + letter
# if one of the digits has gone past Z then we need to update the letters
if '!' == newNumber[3]:
# past Z in 4th digit
letterOrder = order.find(oldNumber[2])
newNumber = newNumber[0:2] + order[letterOrder + 1] + 'A'
if '!' == newNumber[2]:
# past Z in 3rd digit
letterOrder = order.find(oldNumber[1])
newNumber = newNumber[0:1] + order[letterOrder + 1] + 'A' + newNumber[3]
if '!' == newNumber[1]:
# past Z in 2nd digit
letterOrder = order.find(oldNumber[0])
newNumber = order[letterOrder + 1] + 'A' + newNumber[2:]
return newNumber
print(autoIncrement('A999'))
print(autoIncrement('AA99'))
print(autoIncrement('AAA9'))
print(autoIncrement('AAAA'))
print(autoIncrement('AZZ9'))
This is not quite what you are asking for, but if your requirement is for 4-character "sequential" strings, let me suggest a far more simpler approach. Why not simply used base 36 numbers? That is, have your numbers go from 0, 1, 2, ... A, B, C, ... Z, 10, 11, 12, ... 1Z, ... Then to convert one of the base 36 strings to an int it is simply:
n = int('12AV', 36)
And to convert an int to a base n string:
def baseN(num, base, numerals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
return ((num == 0) and numerals[0]) or (baseN(num // base, base, numerals).lstrip(numerals[0]) + numerals[num % base])
Putting it all together:
n = int('12AV', 36)
s = baseN(n + 1, 36)
print(s)
Prints:
12AW
You can, of course, start with 'A001' if you need to. You will then go to A00Z after 35 iterations. You will end up generating the same numbers as in your original method, just in a different order.
Thank you for the solutions you had provided. But I tried something exactly which I want for my question. Please check it and give your comments on it.
def full_format(i):
# limit of first range is 26 letters (A-Z) times 999 numbers (001-999)
if i < 26 * 999:
c,n = divmod(i,999) # quotient c is index of letter 0-25, remainder n is 0-998
c = chr(ord('A') + c) # compute letter
n += 1
return f'{c}{n:03}'
# After first range, second range is 26 letters times 26 letters * 99 numbers (01-99)
elif i < 26*999 + 26*26*99:
i -= 26*999 # remove first range offset
cc,n = divmod(i,99) # remainder n is 0-98, use quotient cc to compute two letters
c1,c2 = divmod(cc,26) # c1 is index of first letter, c2 is index of second letter
c1 = chr(ord('A') + c1) # compute first letter
c2 = chr(ord('A') + c2) # compute second letter
n += 1
return f'{c1}{c2}{n:02}'
else:
raise OverflowError(f'limit is {26*999+26*26*99}')
for i in range(92880, 92898):
print(full_format(i))
This question already has answers here:
Writing a function that alternates plus and minus signs between list indices
(7 answers)
Closed 2 years ago.
9.Write a program that accepts 9 integers from the user and stores them in a list. Next, compute the alternating sum of all of the elements in the list. For example, if the user enters
1 4 9 16 9 7 4 9 11
then it computes
1 – 4 + 9 – 16 + 9 – 7 + 4 – 9 + 11 = –2
myList = []
value = None
count = 0
while count != 9:
value = int(input("Please enter a number: "))
myList.append(value)
count = count + 1
if count == 9:
break
print(myList)
def newList(mylist):
return myList[0] - myList[1] + myList[2] - myList[3] + myList[4] - myList[5] + myList[6] - myList[7] + myList[8]
x = newList(myList)
print(x)
My code returns the correct answer, but I need it to print out the actual alternating sums as in the example. I have been stuck on this for a while. I am having a mental block on this and havent been able to find anything similar to this online.
I appreciate any help or tips.
Also, this is python 3.
Thank you.
a=[1, 4, 9, 16, 9, 7, 4, 9, 11]
start1=0
start2=1
sum1=0
first_list=[a[i] for i in range(start1,len(a),2)]
second_list=[a[i] for i in range(start2,len(a),2)]
string=''
for i,j in zip(first_list,second_list):
string+=str(i)+'-'+str(j)+'+'
string.rstrip('+')
print('{}={}'.format(string,str(sum(first_list)-sum(second_list))))
Output
1-4+9-16+9-7+4-9+=-2
Try doing this:
positives = myList[::2]
negatives = myList[1::2]
result = sum(positives) - sum(negatives)
print ("%s = %d" % (" + ".join(["%d - %d" % (p, n) for p, n in zip(positives, negatives)]), result))
I'll explain what I'm doing here. The first two lines are taking slices of your list. I take every other number in myList starting from 0 for positives and starting from 1 for negatives. From there, finding the result of the alternating sum is just a matter of taking the sum of positives and subtracting the sum of negatives from it.
The final line is somewhat busy. Here I zip positives and negatives together which produces a list of 2-tuples where of the form (positive, negative) and then I use string formatting to produce the p - n form. From there I use join to join these together with the plus sign, which produces p0 - n0 + p1 - n1 + p2 - n2.... Finally, I use string formatting again to get it in the form of p0 - n0 + p1 - n1 + p2 - n2 ... = result.
You can do as you did but place it in a print statement
print(myList[0] + " - " + myList[1] + " + " + myList[2] + " - " + myList[3] + " + " + myList[4] + " - " + myList[5] + " + " + myList[6] + " - " + myList[7] + " + " + myList[8] + " = " + x)
Its not perfectly clean, but it follows your logic, so your teacher won't know you got your solution from someone else.
Something along the lines of the following would work:
def sumList(theList):
value = 0
count = 0
steps = ""
for i in theList:
if count % 2 == 0:
value += i
steps += " + " + str(i)
else:
value -= i
steps += " - " + str(i)
count += 1
print(steps[3:])
return value
print(sumList(myList))
It alternates between + and - by keeping track of the place in the list and using the modulus operator. Then it calculates the value and appends to a string to show the steps which were taken.
You can also do something like below once your 9 or more numbers list is ready
st = ''
sum = 0
for i, v in enumerate(myList):
if i == 0:
st += str(v)
sum += v
elif i % 2 == 0:
st += "+" + str(v)
sum += v
else:
st += "-" + str(v)
sum -= v
print("%s=%d" % (st, sum))
It prints : 1-4+9-16+9-7+4-9+11=-2
I need to draw the following pattern using Python While Loops.
I have spent quite a lot of time and came up with this code which prints it perfectly but this code is so much long and I feel like it is not one of those good codes.
If anybody here can help me out shrinking this code or suggesting a better way to output?
here is the code:
#Question 10, Alternate Approach
temp = 1
pattern = ""
innerSpace = 7
starCount = 1
while temp <= 5:
st = 1
while st <= starCount:
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
sp = 0
if temp == 5:
innerSpace = 1
while sp < innerSpace:
pattern = pattern + " "
sp = sp + 1
st = 1
while st <= starCount:
if temp == 5:
st = st + 1
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
temp = temp + 1
innerSpace = innerSpace - 2
pattern = pattern + "\n"
if temp % 2 == 0:
pattern = pattern + " "
else:
starCount = starCount + 1
starCount = 2
innerSpace = 1
while temp > 5 and temp <= 9:
st = 1
while st <= starCount:
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
sp = 0
while sp < innerSpace:
pattern = pattern + " "
sp = sp + 1
st = 1
while st <= starCount:
pattern = pattern + "*"
if st != starCount:
pattern = pattern + " "
st = st + 1
temp = temp + 1
innerSpace = innerSpace + 2
pattern = pattern + "\n"
if temp % 2 == 0:
starCount = starCount - 1
pattern = pattern + " "
print pattern
Since this looks like an assignment, I'll give you a hint how I would do it.
Take advantage of the symmetry of the bow. It is symmetrical about the horizontal and vertical axis. Therefore, you really only need to solve 1 corner, then copy/mirror the results to get the rest.
This code gives one way of looking at the problem, which is just shifting a initial string (the middle of the bow) to get the desired shape:
m = '*'
size = 4
n = 5 # must be odd
pad = ' ' * n
middle = (m + pad) * size
half = int(n / 2) + 1
print middle
print middle[half*1:]
print middle[half*2:]
print middle[half*3:]
print middle[half*4:]
print middle[half*5:]
print middle[half*6:]
Which yields this:
* * * *
* * *
* * *
* *
* *
*
*
Good luck!
I would use list comprehensions and strings and would exploit the symmetry of the figure.
Not a complete solution, but could be a part of a loop body
In [2]: a = '*' + ' '*8
In [3]: a
Out[3]: '* '
In [24]: result = ''
In [25]: result += a
In [26]: result
Out[26]: '* '
In [27]: result += a[-1::-1]
In [28]: result
Out[28]: '* *'
In [29]: result += '\n'
In [30]: a = ' '+'*' + ' '*7
In [31]: a
Out[31]: ' * '
In [32]: result += a
In [33]: result += a[-1::-1]
In [34]: result += '\n'
In [36]: print result
* *
* *
IMHO you use while loop much as if they where for loops.
I don't think that's what your teacher wants.
The idea behind while is to run until a certain condition is met, not
necessarily when the number of iterations exceed a certain limit.
The condition does not need to be included in the while statement, you can check it later and use the break command to escape the loop
Try for example this:
start = '*'
while True:
print start
if start[0] == '*':
start = ' ' + start
else:
start = '*' + start
if (start == '* * *'):
break
output is just a part of your assignment, think you should be able to work it out to the final, expected result!
Hopefully by this time HW is done. Since I solved this using dynamic programming, I thought I would list solution here.
Observations:
While looking at pattern its observed that bottom half is palindrome of top half. Hence we need to calculate only the top half.
Next we see that for every row count,we have pattern like,
row 1 = 1 , n
row 2 = 2 , n -1
row 3 = 1,3, n-2, n
row 4 = 2, 4 , n-3, n-1
.. and so on.
With iteration index as row count and n as input value we can dynamically calculate remaining values very efficiently.
Source-Code
def get_list(bound, alist):
tmp_list = []
for i in xrange(1,bound + 1):
tmp_list.append(star if i in alist else dot)
return tmp_list
star = "*"
dot = " "
n = 20 #How large of BowTie do you want?
m = (n * 2) - 1
#get top half list
th = []
for idx,k in enumerate(xrange(1,n+1)): #run through 1 - n
row = idx + 1
tmplst = []
if row % 2 != 0:
tmplst.append(i for i in xrange(1,row + 1) if i % 2 != 0)
tmplst.append(i for i in xrange(m, m-row, -1) if i % 2 != 0)
else:
tmplst.append(i for i in xrange(1,row + 1) if i % 2 == 0)
tmplst.append(i for i in xrange(m, m-row, -1) if i % 2 == 0)
#append each row value to top half list.
th.append(sorted(set([j for i in tmplst for j in i])))
#create palindrome of top half which is our bottom half
th = th + th[len(th) -2::-1]
#create list of * and blanks
final = [get_list(m, i) for i in th]
#Print BowTie
for i in final:
print ' '.join(i)
Using a stars and spacing and counting variable
counting=1
star_amount=1
space_amount=6
loop_var=7
while loop_var>0:
loop_var-=1
if space_amount==0:
counting*=-1
stars=" * "*star_amount
spaces=" "*space_amount
print(stars+spaces+stars)
star_amount+=counting
space_amount-= counting*2
i'm trying to generate a string from characters of ['A','B','C','D','E'] with length of 3900, and every character should have probability of:
{'A':0.1,
'B':0.3,
'C':0.3,
'D':0.1,
'E':0.2 }
in this string
i wrote the following code:
from random import random
from bisect import bisect
def weighted_choice(choices):
values, weights = zip(*choices)
total = 0
cum_weights = []
for w in weights:
total += w
cum_weights.append(total)
x = random() * total
i = bisect(cum_weights, x)
return values[i]
string_ = ''
for i in range(0,3900):
string_ = string_ + weighted_choice([("A",10), ("B",30), ("C",30),("D",10),("E",20)])
with open("rand_file","w") as f:
f.write(string_)
but it doesn't generate the string(file) based on the probabilities. it generates with probabilities like this:
C 0.2500264583
B 0.2499284457
E 0.1666428313
D 0.0833782424
A 0.0833758065
probability cause the for loop runs separately every time, without considering previous results.
any help please to solve this problem ?
If you just use the list ['A','B','B','B','C','C','C','D','E','E'] and choose an item from it at random, you can get rid off all that weighting stuff in your code totally, and the weighting will be built in.
You can see that in the following example (yes, I don't doubt it could be written better but it's only meant to be a proof-of-concept, not production-ready, pure-as-snow-white code):
from random import random, seed
def choice(lst):
return lst[int(random() * len(lst))];
seed()
(a, b, c, d, e, t) = (0, 0, 0, 0, 0, 0)
for i in range(1000):
x = choice('ABBBCCCDEE')
if (x == 'A'): a += 1
if (x == 'B'): b += 1
if (x == 'C'): c += 1
if (x == 'D'): d += 1
if (x == 'E'): e += 1
t += 1
print ("a =", a, "which is", a * 100 / t, "%")
print ("b =", b, "which is", b * 100 / t, "%")
print ("c =", c, "which is", c * 100 / t, "%")
print ("d =", d, "which is", d * 100 / t, "%")
print ("e =", e, "which is", e * 100 / t, "%")
with the output matching (roughly) the desired distribution:
a = 101 which is 10.1 %
b = 297 which is 29.7 %
c = 299 which is 29.9 %
d = 102 which is 10.2 %
e = 201 which is 20.1 %
Now that's obviously going to be annoying if your distribution is 99.9% A and 0.1% B (it'll be a rather long string passed to choice) but this should be adequate for the distribution you have.
You can generate all letters according to the weighting, then randomly shuffle them and finally join them. Something like:
from random import shuffle
N = 3900 # the string length
doc = {'A':0.1, 'B':0.3, 'C':0.3, 'D':0.1, 'E':0.2 } #weights
letters = []
for key in doc.keys():
m = int(doc[key] * N) #generate correct number of letter
letters.append(list(key * m))
letters = [item for sublist in letters for item in sublist] # flatten the list
shuffle(letters) # shuffle all letters randomly
result = ''.join(letters) # join all letter to make one string
print(len(result))
# 3900
this is actually the same as paxdiablo's solution, except a little more general (for your simple example, his solution is better. +1):
import random
choice = [("A",10), ("B",30), ("C",30),("D",10),("E",20)]
choose_from = ''.join(x * letter for letter, x in choice)
print(choose_from)
# AAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDetc...
print(random.choice(choose_from))
This question already has answers here:
How can I use `return` to get back multiple values from a loop? Can I put them in a list?
(2 answers)
Closed 6 months ago.
I've made a simple function to print out a times table chart depending on the number you decide to run with. The problem I'm having due to my basic understanding of the language is why it only returns the first loop and nothing else.
def timestables(number):
for a in range(1, number+1):
b = a*a
c = a
return (str(c) + " * " + str(c) + " = " + str(b))
print(timestables(5))
I get the answer ..
1 * 1 = 1
I've tried to rectify this issue by using print instead of return but this ultimately results with a None appearing as well.
def timestables(number):
for a in range(1, number+1):
b = a*a
c = a
print (str(c) + " * " + str(c) + " = " + str(b))
print(timestables(5))
I get the answer ..
1 * 1 = 1
2 * 2 = 4
3 * 3 = 9
4 * 4 = 16
5 * 5 = 25
None
How can I return all given results from the for loop to avoid a None error?
yield them.
def timestables(number):
for a in range(1, number+1):
yield '%s + %s = %s' % (a, a, a*a )
for x in timestables(5):
print x
This turns your function into a generator function, and you need to iterate over the results, i.e. the result is not a list, but an iterable.
If you need a list, the simplest is to explicitly create one:
res = list(timestables(5))
But again, if you don't, you don't.
IMHO, this is the most pythonic way.
You're returning inside the for loop - and functions stop execution immediately once they hit a return statement.
To work around this, you can use a list to store those values, and then return that list.
def timestables(number):
lst = []
for a in range(1, number+1):
b = a*a
c = a
lst.append(str(c) + " * " + str(c) + " = " + str(b))
return lst
As a side note, you should use string formatting to build the string, like so.
lst.append('{a} * {a} = {b}'.format(a=a, b=a*a))
Now we can get rid of all those intermediate variables (b and c), and we can use a list comprehension instead.
def timestables(number):
return ['{a} * {a} = {b}'.format(a=a, b=a*a) for a in range(1, number+1)]
If you don't want the function to return a list, but a multi-line string, you can use str.join:
def timestables(number):
return '\n'.join('{a} * {a} = {b}'.format(a=a, b=a*a) for a in range(1, number+1))
Now we can test the function:
>>> print(timestables(5))
1 * 1 = 1
2 * 2 = 4
3 * 3 = 9
4 * 4 = 16
5 * 5 = 25
You can return an array:
def timestables(number):
out = []
for a in range(1, number+1):
b = a*a
c = a
out.append( str(c) + " * " + str(c) + " = " + str(b))
return out
print(timestables(5))