MemoryError in the Nim Sum game on Leetcode - python

I'm trying to solve the following problem from https://leetcode.com/problems/nim-game/description/:
You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.
Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.
For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.
I came up with the following solution, using a bottom-up dynamic programming approach:
class Solution(object):
def canWinNim(self, n):
"""
:type n: int
:rtype: bool
"""
if n <= 3:
return True
win = [None for _ in range(n+1)]
win[1] = win[2] = win[3] = True
for n in range(4, n+1):
win[n] = not all([win[n-i] for i in [1, 2 ,3]])
return win[n]
However, when I try to submit this, I get a MemoryError:
Since the exact test case for which this MemoryError arises is not given, I'm struggling to see what is causing the problem. Any ideas?

Indeed as pointed out by Kenny Ostrom, probably the test cases are for such large n that there is insufficient memory to store the answers generated in the 'bottom up' dynamic programming approach. By running it on a smaller example, I noticed that the answer is simply
bool(x % 4)

Related

RecursionError in Project Euler #5

I'm receiving a "maximum recursion depth exceeded" error when executing my program to solve this problem. Project Euler's question #5 asks to find:
The smallest positive number that is evenly divisible by all of the numbers from 1 to 10.
I've tried to write a program that recursively checks if x is divisible by each integer 1-10, and if it doesn't then we call it again with x incremented by 1 and repeat until x is found. (In this case the answer is 2520, which is why I added the if statement.)
def euler5(x):
if x < 2521:
for i in range(1, 11):
if x % i == 0:
print(x)
else:
euler5(x+1)
else:
print(x)
x = 2
print(euler5(x))
The reason for this is that Python (or CPython, at least) has a limited stack size and no tail call optimization. So you cannot use unbounded recursion in Python, unlike Scheme (for example).
The solution is to use a regular loop:
x = 0
while True:
x += 1
# Put loop body here
In you defined function, you could you a loop even if you do not know math functions. However, your code is not efficient as program has to keep checking the values to see if it matches the condition. Recursion is not recommended as it should be flexible to be used with other values not just for this question. Euler questions are meant to train your coding practices.
A better method can be used to simplify your code:
from functools import reduce
from fractions import gcd
def lcm(a,b):
return a*b//gcd(a,b) #gcd is greatest common divisor AKA HCF
print (reduce(lcm, range(1, 20+1)))

Checkers algorithm: how to reduce nested for loops

I’m trying to build a program that plays draughts/checkers. At the moment I’m trying to make the function, that allows the computer to make and evaluate moves. My idea is to have the computer look at all it’s own possible moves and for each of these moves, look at the possible opponents moves and then for each of these moves, again look at it’s own possible moves.
With each ply it will evaluate if the move is good or bad for the player and assign points, at the end it picks the moves with the highest points.
So far I have managed to get a version of this working, but involves a lot of nested for loops. The code is a mess and not very readable at the moment, but this is a simple model of the same concept. Instead of evaluating and producing more lists, it just multiplies by two for the new list.
counter = 0
for x in list:
counter += 1
list_2 = [x * 2 for x in list]
print 'list_2', list_2, counter
for x in list_2:
counter += 1
list_3 = [x * 2 for x in list_2]
print 'list_3',list_3, counter
for x in list_3:
counter += 1
list_4 = [x * 2 for x in list_3]
print 'list_4', list_4, counter
If I run this code, I get what I want, except that I can't easily control the depth of the search without copying in more for loops. I thought recursion might be a way of doing this, but I can’t figure out how to stop the recursion after x levels of search depth.
Is there a better way of getting the same output form the code above, while getting rid of all the for loops? If I can get that to work, I think I can do the rest myself.
Here's an equivalent function that uses recursion. It controls the recursion with two parameters which track the current depth and maximum depth. If current depth exceeds the maximum depth it will return immediately thus stopping the recursion:
def evaluate(l, max_depth, cur_depth=0, counter=0):
if cur_depth > max_depth:
return counter
for x in l:
counter += 1
l2 = [x * 2 for x in l]
print cur_depth, l2, counter
counter = evaluate(l2, max_depth, cur_depth + 1, counter)
return counter
If called with max_depth=2 it will produce the same output except that instead of variable name the current depth is printed.
I thought recursion might be a way of doing this, but I can’t figure out how to stop the recursion after x levels of search depth.
Your intuition is correct, and a simple a way of doing this would be to have an incrementing number passed to each level. When the recursion gets the maximum value then the recursion is completed. A trivial example is below to demonstrate.
def countup(i=0):
print(i)
if i==MAX_COUNT: return
countup(i+1)
For your algorithm, you need a value to represent the board evaluation. For instance in the range [-1,1]. Player A could be said to be winning if the evaluation is -1 and Player B is winning if the evaluation is 1 for example. A recursive algorithm could be as follows.
def evaulate(board, player, depth=0):
if depth==MAX_DEPTH: return hueristicEvaluation(board)
bestMove = None
if player==PLAYER_A:
val=999 # some large value
for move in get_moves():
newboard = board.makeMove(move)
eval, _ = evaluate(newboard, PLAYER_B, depth+1)
if eval < val:
bestMove = move
val = eval
elif player==PLAYER_B:
val=-999 # some large negative value
for move in get_moves():
newboard = board.makeMove(move)
eval, _ = evaluate(newboard, PLAYER_A, depth+1)
if eval > val:
bestMove = move
val = eval
return val, bestMove
This is abstract, but the idea is there. Adjust depending on how your are representing the board or the players. The function hueristicEvaluation could be something as simple as counting the pieces on the board for each player and how close they are to the other side. Remember that this function needs to return a number between [-1,1]
Edge cases to consider, which I didn't take into account:
If all moves are winning and/or losing
If the are NO moves in the position, for example if your pieces are all blocked by your opponent's pieces
Many improvements exist to a simple search like this. Read if you're interested :)
For checkers, perhaps Memoization would speed things up a lot. I'm not sure, but I'd think it would be especially in the beginning. See python's way of doing this.
Pruning
Alpha-beta pruning
Branch and bound

Prime numbers using generators in Python? [duplicate]

This question already has answers here:
Simple prime number generator in Python
(27 answers)
Closed 6 years ago.
I wrote this simple python function to calc:
def isPrime(number):
if number == 2:
return True
elif number > 1 and number % 2 != 0:
for current in range(3, number):
if number % current == 0:
return False
return True
And I'm calling it to print out the sum of all prime numbers from 1 to 2 million, as in project euler #10
However it's terribly slow, and I was wondering if I could tackle the same problem using generators? But I don't really understand generators in python completely..
Any help on how to solve this problem more efficiently would be appreciated! Thanks :)
Firstly, I suggest you use a better function to check whether a number is prime or not.
Here's a better modification, from https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/ which is an excellent
explanation on generators in Python.
import math
def is_prime(number):
while True:
if number == 2:
return True
elif number > 1 and number % 2 != 0:
for current in range(3, int(math.sqrt(number) + 1), 2):
if number % current == 0:
return False
return True
return False
Secondly, you need to understand what a Generator actually does. Again Jeff Knupp explains it perfectly.
In short a generator is a function that does not "return" it simply "yields" and takes back control when the next() method is called on it.
So no variables that are created during the function are lost, and memory is saved by not creating the variables defined in the function again and again.
Then you can go on solving Euler 10, which is also explained in the link. :)
Good luck with the rest of the Eulers!
Another angle of attack on this problem is to try a different algorithm rather than attempting to optimize your current method. Learning more about generators is great, but you could also try solving this using a sieve, which can be quite efficient.
The general idea would be to "mark" all composite numbers (not prime), leaving behind the primes. It's pretty efficient, as my python implementation runs in ~3.5s

Python: determining if a number is prime [duplicate]

This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 7 years ago.
I am new to Python and I'm attempting to write a code that checks to see whether or not a number is prime. So far, I've written this:
def main():
n = input("Enter number:")
isprime(n)
def isprime():
x = Prime
for m in range (1,n+1,1)
result = n % m
print result
main()
I'm not sure how to proceed after this. I know I have to define isprime. Any help would be greatly appreciated. Thank you!
Your first and biggest problem is that you need to list n as a parameter to isprime before you can use it within isprime, and before you can pass an argument in main. See the tutorial on Defining Functions for more details. But basically, it's like this:
def isprime(n):
Also, that x = Prime is going to raise a NameError, because there's nothing named Prime. Given that it doesn't actually do anything at all, you should just delete it.
Of course that won't make this a complete working prime testing function, but it is how to proceed from where you are.
The next step is to consider what to return from the function. If you find a value that divides n, then obviously n isn't prime, and therefore isprime is false. If you go through all possibilities and don't find anything that divides n, then isprime is true. So, with two return statements in the right places, you can finish the function.
Once it's at least always returning True or False, you have bugs to fix.*
Look at what numbers you get from range(1, n+1, 1). Two of those numbers are guaranteed to divide any n. How do you avoid that problem?
After you've got it working, then you can work on optimizing it. If you look up primality test on Wikipedia, you can see a really simple way to improve the naive trial division test. A bit of research will show the pros and cons of different algorithms. But if what you've got is fast enough for your purposes, it's usually not worth putting more effort into optimizing.
* You might want to consider writing a test program that calls isprime on a bunch of numbers and compares the results with the right answers (for answers you already know off the top of your head—1 is not prime, 2 is prime, 17 is prime, etc.). This is called Test Driven Development, and it's a great way to make sure you've covered all the possible cases—including outliers like 0, 1, 2, -3, etc.
Your isprime is quite close. The first line x = Prime is unnecessary, so let's get rid of that.
Now, let's take a look at what you're doing next:
You seem to want to check if there are any numbers that divide n perfectly. While this is the correct approach, you are including n and 1 in the numbers that you are testing. This is wrong for obvious reasons.
There is another error: you use n without ever defining it (I think you want it to be a parameter to your function). So let's put all this together:
def isprime(n):
for m in range(2, n):
if not n%m: # m divides n perfectly
return False
return True # if n were not prime, the function would have already returned
But going a step further, you don't really have to check every number between 2 and n-1. You just need to check the numbers between 2 and the square-root of n:
def isprime(n):
for m in range(2, int(n**0.5)+1):
if not n%m:
return False
return True

Permuting Magic Squares

I'm having a little bit of trouble writing a recursive permutation function for solving Magic Squares. For this function, I'm not allowed to use two-dimensional arrays, only lists. Below is what I have currently:
def permute(size):
magicSquare = []
for value in permute(size**2):
for pos in range(size**2 + 1):
magicSquare.append(value)
return magicSquare
size is defined by the user through command-line argument.
I'm slightly confused if the function written above accomplishes the task of permuting the values.
It wouldn't appear to and in fact should basically never terminate the way it is currently written.
An easy way to start thinking about this problem is that a magic square can be represented by a list of size n**2, so a 3x3 magic square can be represented by a 9-length list. Since it is a magic square, you then need to permute over the values range(1,n+1), e.g., for a 3x3:
1 2 3
4 5 6
7 8 9
Check to see if this is a magic square (it isn't since the rows don't sum to the same value) and if it is, add it to your magic squares list. Either way, try the next permutation:
1 2 3
4 5 6
7 9 8
…until you are out of permutations. This is, of course, a non-optimal route because the trouble row (1, 2, 3) still won't sum to 15, so there is clear room for optimization and easily discarding possibilities that won't work.
An easy tool to either check your work or do the permutation piece for you is itertools.permutations. Which will create a generator that will yield each additional permutation until there aren't any more.
Note that for anything beyond a trivial square size you are going to exceed the maximum recursion limit if you try to make another recursive call each time using this method. You'll need to find a way to manage that situation once size=3. There are a couple of ways to handle that of varying degrees of complexity, depending on what exactly you are trying to do.
Here is a simple method for checking magic square or not.
Note: please try by using 3*3 grid.
def magic():
print "maximam 9 values"
a=[]
for i in range(3):
a.append([])
for j in range(3):
a[i].append(input('Enter the values'))
print a
l1= a[0][0]+a[1][0]+a[2][0]
l2=a[0][1]+a[1][1]+a[2][1]
l3=a[0][2]+a[1][2]+a[2][2]
r1=sum(a[0])
r2=sum(a[1])
r3=sum(a[2])
if l1 == l2 == l3 == r1 == r2 == r3:
print a,"Its magic square"
else:
print a,"not magic square"
magic()

Categories

Resources