Check indexes in 3D numpy array - python

I'm trying to write code that will play a dice game called Pig through the command line with a person against the computer
For the computer's player, I am using a 3D numpy array to store a game strategy based on the information current score AI_1_current, banked score AI_1_bank and opponent's banked score human_bank.
The idea is, each turn, the computer will check the strategy array, if the value at the index [AI_1_current, AI_1_bank, human_bank] is equal to 0, it will keep rolling, if it's equal to 1, it will bank it's current score.
Now, the problem I'm having, is the function that takes the computer's turn is not reading the array properly, and not banking when it should.
I have this code to set up the array:
AI_1_strategy = numpy.zeroes((100,100,100))
for i in range(10, 100):
for j in range(10, 100):
for k in range(10, 100):
AI_1_strategy[i, j, k] = 1
Which ideally should mean, if i, j or k are greater than or equal to 10, the computer will bank every turn
Then later I have this code to check the array:
if AI_1_strategy[AI_1_bank, AI_1_current, human_bank] == 1:
AI_1_bank += AI_1_current # add current points to the bank
AI_1_current = 0
time.sleep(3) # 3 second delay
if AI_1_bank >= 100: # win condition
print "AI_1 WINS!"
else:
AI_current = 0 # sets current points to 0
print "AI has banked"
pig_human() # moves to the player's turn
else:
time.sleep(3) # 3 second delay
print "AI_1 chose to keep rolling"
pig_AI_1() # AI takes another roll
Despite this code, the computer will fail to bank consistently.
The problem also occurs if I instead do:
AI_1_strategy = numpy.ones((100,100,100))
for i in range(10, 100):
for j in range(10, 100):
for k in range(10, 100):
AI_1_strategy[i, j, k] = 0
Except in that case, it will bank every turn regardless of the scores, when it should really stop banking once i, j or k reaches 10.
If anybody could help me out I'd greatly appreciated, I have no idea what I'm doing wrong.
Thanks.

It looks like you're making a small logic error.
I have this code to set up the array:
AI_1_strategy = numpy.zeroes((100,100,100))
for i in range(10, 100):
for j in range(10, 100):
for k in range(10, 100):
AI_1_strategy[i, j, k] = 1
Which ideally should mean, if i, j or k are greater than or equal to 10, the computer will bank every turn
This is incorrect: Each of i, j AND k must be >=10 to read a 1 from this array.

Related

Unable to code for non-squares integers in Python

How do I create a code that prints out all the integers less than 100 that are not a square of any integer?
For instance, 3^2=9 to not be printed, but 30 should.
I’ve managed to print out the squared values but not sure how to print out the values that are not a square.
Here is my code:
for i in range(1,100):
square = i**2
print(square)
There can be multiple ways you can write this code. I think you can use two for loops here to make it easier for you. I'm using comments so for you being a newbie to understand better. You can choose from these two whichever you find easier to understand:
list_of_squares = [] #list to store the squares
for i in range(1, 11): #since we know 10's square is 100 and we only need numbers less than that
square = i ** 2
list_of_squares.append(square) #'append' keeps adding each number's square to this list
for i in range(1, 100):
if i not in list_of_squares: #'not in' selects only those numbers that are not in the squares' list
print(i)
Or
list_of_squares = []
for i in range(1, 100):
square = i ** 2
list_of_squares.append(square)
if square >= 100: #since we only need numbers less than 100
break #'break' breaks the loop when square reaches a value greater than or equal to 100
for i in range(1, 100):
if i not in list_of_squares:
print(i)
You can store the nums that is square of integers into a array.
squares =[]
for i in range(1,100):
squares.append(i**2)
j = 0
for k in range(1,100):
if k==squares[j]:
j=j+1
elif k>squares[j]:
print(k)
j=j+1
else:
print(k)

How do I print the two elements of an array and the subsequent sum of these elements? (Goldbachs Primes Question)

I am trying to solve this problem: Goldbach Conjecture
Show with a program "goldbach.py" ​​that all even numbers up to 1000 can indeed be written as the sum of two primes. Specifically: for each even number, also show explicitly (on the screen) that it can be written as the sum of two primes, as in the example below
Even more important is of course if you find a number that does not meet Goldbach's suspicion. Make sure your program clearly displays such a discovery on the screen. Bingo!
python goldbach.py
16 = ...
18 = 5 + 13
20 = 3 + 17
22 = 5 + 17
24 = ...
Progress
So far, I have created a list where all the primes until 1000 are stored, and then I have created a list in which all the combination of primes of which the sum is an even number until 1000. I knew the format to have it print 3 + 17, but I am stuck in trying to have it say sum(pairs) = prime1 "+" prime2. Should be 3 + 17 = 20 for example. Also, I don't know how to have only 1 example of a pair of primes who's sum is of an even number until 1000. I need to break the loop some how.
Because the sum function was not working I found I could convert it to a "numpy array" and then use "accumulate". I just can't get it to work and know I'm getting the error message 'DeprecationWarning: elementwise == comparison failed; this will raise an error in the future.'
Could someone help me with the code?
from itertools import accumulate, islice
from numpy import array
import numpy as np
primes = []
pairs = []
numpy_pairs = np.asarray(pairs)
for num in range (4, 1000):
for j in range (2, num):
if (num % j) == 0:
break
else:
primes.append(num)
#for x in range(2,1000):
# if x in primes:
# print ("Ja, het getal {} komt voor in mijn primes".format(x))
for x in range(2,1000):
if x % 2 == 0:
for prime1 in primes:
for prime2 in primes:
if prime1 + prime2 == x and [prime1, prime2] not in numpy_pairs and [prime2, prime1] not in numpy_pairs:
np.append(numpy_pairs,[prime1,prime2])
results = ("{}+{}={}".format(i, j, k) for i, j in zip(numpy_pairs[0::2],
numpy_pairs[1::2]) for k in accumulate(islice(numpy_pairs,numpy_pairs.stop)))
print('\n'.join(results))
First things first, there are a lot of optimizations you can do to make the code logic better. the way you find primes can be improved, you only need to check numbers upto square root n to verify if n is a prime. Also, the actual verification of Goldbachs conjecture can be improved as well.
However, just focusing on the current code, You should stick to using lists if you want to append values, and to stop the code you need to use a sort of hack to stop the nested looping using the for-else syntax. Also, you can use f-strings to format strings nicely from python 3.6 onwards.
primes = []
pairs = []
for num in range (2, 1000): #modified. you forgot 2 and 3!
for j in range (2, num):
if (num % j) == 0:
break
else:
primes.append(num)
result = []
for x in range(2,1000):
if x % 2 == 0:
for prime1 in primes:
for prime2 in primes:
if prime1 + prime2 == x:
print(f"{x} = {prime1} + {prime2}")
result.append((prime1, prime2))
break
else: #this is a for-else syntax. enter this block if the for loop did not encounter a break
continue #go to next iteration of the mid-level loop. This prevents the line afterwards from being executed in cases where the inner loop did not "break"
break #break the mid level loop if you reach this line.
else:
print("You have done it! Bingo!!")

How does one calculate the number of multiples in a set or list using Python?

I have been generating random sets and lists and was curious about how one would calculate the number of multiples in that given set or list. The code I have written gives me the wrong number, so I am assuming I have allocated something incorrectly. The code is
b= random.sample(range(1, 56), 6)
print(b)
numbers = (b)
count_multiples = 0
for y in (b):
for x in (b):
if y % x ==0:
count_multiples+=1
print("MPS:", count_multiples)
I am brand new to coding and this exchange, so any help would be appreciated.
This depends on what exactly you mean by number of multiples in the list.
1). Do you want to count every number at least once, since every number is a multiple of itself?
2). Do you want to count an element more than once if it is a multiple of more than one element in the list?
If you answer yes to both of these questions your code looks fine (although not the most efficient). If no try something like the following:
min, max = 1, 56
n = 6
count = 0
random_list_with_no_duplicates = random.sample(range(min, max), n)
# If no to 1) but yes to 2)
random_list_with_no_duplicates.sort()
for i in range(n):
for j in range(i + 1, n):
if random_list_with_no_duplicates[j] % random_list_with_no_duplicates[i] == 0:
count += 1
# If no both
random_list_with_no_duplicates.sort(reverse=True)
for i in range(n):
for j in range(i + 1, n): # change to just 'i' if yes to 1), no to 2)
if random_list_with_no_duplicates[i] % random_list_with_no_duplicates[j] == 0:
count += 1
break
In Python, True and False are equal to 1 and 0, respectively. You can take advantage of this and use sum to add the booleans together. The result will be the number of elements, e, where bool(e) evaluates as True.
count_multiples = sum(y % x == 0 for y in b for x in b)

Calculating Polygonal Numbers Taking A While To Calculate

I've created a function which, hopefully, creates a list of numbers that are both pentagonal and square.
Here is what i've got so far:
def sqpent(n):
i = 0
list = []
while n >= 0:
if n == 0:
list.append(0)
elif n == 1:
list.append(1)
elif (i*i == (i*(3*i-1)//2)):
list.append(i)
n -= 1
i += 1
But when it gets past the first two numbers it seems to be taking a while to do so...
You have two issues: the first is that the special-casing for n==0 and n==1 doesn't decrease n, so it goes into an infinite loop. The special-casing isn't really needed and can be dropped.
The second, and more significant one, is that in the test i*i == (i*(3*i-1)//2) you are assuming that the index i will be the same for the square and pentagonal number. But this will only happen for i==0 and i==1, so you won't find values past that.
I suggest:
Iterate over i instead of n to make things simpler.
Take the ith pentagonal number and check if it is a square number (e.g. int(sqrt(x))**2 == x).
Stop when you've reached n numbers.
Thanks to #interjay's advice, I came up with this answer which works perfectly:
import math
def sqpent(n):
counter = 0
i = 0
l = []
while counter < n:
x = (i*(3*i-1)//2)
#print(x)
if(int(math.sqrt(x))**2 == x):
#print("APPENDED: " + str(x))
l.append(x)
counter += 1
i += 1
return l
For an explanation:
It iterates through a value i, and gets the ith pentagonal number. Then it checks if it is a square and if so it appends it to a list which i ultimately return.
It does this until a final point when the counter reaches the number of items in the list you want.

Python Monte Carlo Simulation Loop

I am working on a simple Monte-Carlo simulation script, which I will later on extend for a larger project. The script is a basic crawler trying to get from point A to point B in a grid. The coordinates of point A is (1,1) (this is top left corner), and the coordinates of point B is (n,n) (this is bottom right corner, n is the size of the grid).
Once the crawler starts moving, there are four options, it can go left, right, up or down (no diagonal movement allowed). If any of these four options satisfy the following:
The new point should still be within the boundries of the n x n grid
The new point should not be visited previously
the new point will be selected randomly among the remaining valid options (as far as I know Python uses the Mersenne Twister algorithm for picking random numbers).
I would like to run the simulation for 1,000,000 times (the code below runs for 100 only), and each iteration should be terminated either:
The crawler gets stuck (no valid options for movement)
The crawler gets to the final destination (n,n) on the grid.
I thought I implemented the algorithm correctly, but obviously something is wrong. No matter how many times I run the simulations (100 or 1,000,000), I only get 1 successful event wehere the crawler manages to get to the end, and rest of the attempts (99, or 999,999) is unsuccessful.
I bet there is something simple I am missing out, but cannot see it for some reason. Any ideas?
Thanks a bunch!
EDIT: Some typos in the text were corrected.
import random
i = 1 # initial coordinate top left corner
j = 1 # initial coordinate top left corner
k = 0 # counter for number of simulations
n = 3 # Grid size
foundRoute = 0 # counter for number of cases where the final point is reached
gotStuck = 0 # counter for number of cases where no valid options found
coordList = [[i, j]]
while k < 100:
while True:
validOptions = []
opt1 = [i - 1, j]
opt2 = [i, j + 1]
opt3 = [i + 1, j]
opt4 = [i, j - 1]
# Check 4 possible options out of bound and re-visited coordinates are
# discarded:
if opt1[0] != 0 and opt1[0] <= n and opt1[1] != 0 and opt1[1] <= n:
if not opt1 in coordList:
validOptions.append(opt1)
if opt2[0] != 0 and opt2[0] <= n and opt2[1] != 0 and opt2[1] <= n:
if not opt2 in coordList:
validOptions.append(opt2)
if opt3[0] != 0 and opt3[0] <= n and opt3[1] != 0 and opt3[1] <= n:
if not opt3 in coordList:
validOptions.append(opt3)
if opt4[0] != 0 and opt4[0] <= n and opt4[1] != 0 and opt4[1] <= n:
if not opt4 in coordList:
validOptions.append(opt4)
# Break loop if there are no valid options
if len(validOptions) == 0:
gotStuck = gotStuck + 1
break
# Get random coordinate among current valid options
newCoord = random.choice(validOptions)
# Append new coordinate to the list of grid points visited (to be used
# for checks)
coordList.append(newCoord)
# Break loop if lower right corner of the grid is reached
if newCoord == [n, n]:
foundRoute = foundRoute + 1
break
# If the loop is not broken, assign new coordinates
i = newCoord[0]
j = newCoord[1]
k = k + 1
print 'Route found %i times' % foundRoute
print 'Route not found %i times' % gotStuck
Your problem is that you're never clearing out your visited locations. Change your block that breaks out of the the inner while loop to look something like this:
if len(validOptions) == 0:
gotStuck = gotStuck + 1
coordList = [[1,1]]
i,j = (1,1)
break
You'll also need to change your block where you succeed:
if newCoord == [n, n]:
foundRoute = foundRoute + 1
coordList = [[1,1]]
i,j = (1,1)
break
Alternatively, you could simply place this code right before your inner while loop. The start of your code would then look like:
k = 0 # counter for number of simulations
n = 3 # Grid size
foundRoute = 0 # counter for number of cases where the final point is reached
gotStuck = 0 # counter for number of cases where no valid options found
while k < 100:
i,j = (1,1)
coordList = [[i,j]]
while True:
#Everything else

Categories

Resources