Print recursion steps - python

I would like to print the steps my program made and put these steps in a list. But i can't figure out why my code prints the wrong output. I am new to programming and i hope somoene could help. This is my code:
r=[]
listOfsteps = []
j = 0
class Main(object):
def __init__(self):
i=0
while i != 1:
self.method(r, j)
i+=1
def method(self, r, j):
r.append(j)
listOfsteps.append(r)
j+=1
if j ==5:
return "stop"
print r
print "ListOfSteps", listOfsteps
return self.method(r, j)
Main()
Output now:
[0]
ListOfSteps [[0]]
[0, 1]
ListOfSteps [[0, 1], [0, 1]]
[0, 1, 2]
ListOfSteps [[0, 1, 2], [0, 1, 2], [0, 1, 2]]
[0, 1, 2, 3]
ListOfSteps [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
Output that I want:
[0]
ListOfSteps [[0]]
[0, 1]
ListOfSteps [[0], [0, 1]]
[0, 1, 2]
ListOfSteps [[0], [0, 1], [0, 1, 2]]
[0, 1, 2, 3]
ListOfSteps [[0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]

Use:
listOfsteps.append(list(r))
Instead of:
listOfsteps.append(r)
in your version you append a reference to r and in the next iteration you change r so the reference you have stored is affected. You need to copy a list you want to append.
You could also use copy for doing this.

r=[]
listOfsteps = []
j = 0
class Main(object):
def __init__(self):
#you don't need loop while for your example
self.method(r, j)
def method(self, r, j):
r.append(j)
# append only the steps index
#you don't need to add whole list for every step
listOfsteps.append(j)
j+=1
if j == 5:
return "stop"
print r
#to print your step with your output that you want use this loop
l = [listOfsteps[:i+1] for i in range(len(listOfsteps))]
print "ListOfSteps", l
return self.method(r, j)
Main()

Related

How to find all the permutations of a variable amount of 0's and 1's recursively (without using itertools or random)?

I'm trying to produce all permutations of a certain number of numbers (for example, 0s and 1s) for a variable number of positions. I will call the number of numbers ord (e.g. ord=2 for only 0s and 1s; ord=3 for 0s, 1s, and 2s) and the number of positions Num. Hence the number of permutations is ord**Num.
Note: I don't want to use itertools or any other types of built-in functions. I'm asking this out of curiosity, not just trying to find a solution.
For ord=2 and Num=3, the output, in any order, should be:
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
This can be accomplished by:
ord = 2
mylist = []
for a in range(ord):
for b in range(ord):
for c in range(ord):
mylist.append([a,b,c])
For ord = 2 and Num = 4, the output should be:
[[0,0,0,0],[0,0,0,1],[0,0,1,0],[0,0,1,1],[0,1,0,0],[0,1,0,1],[0,1,1,0],[0,1,1,1],[1,0,0,0],[1,0,0,1],[1,0,1,0],[1,0,1,1],[1,1,0,0],[1,1,0,1],[1,1,1,0],[1,1,1,1]]
But then I would have to add another nested for loop:
ord = 2
mylist = []
for a in range(ord):
for b in range(ord):
for c in range(ord):
for d in range(ord):
mylist.append([a,b,c,d])
An obvious solution is to add 0s and 1s randomly to a list of length Num and then to accept that list if it hasn't already been added to mylist, but I want a solution that isn't quite so ridiculous.
This is the closest I've gotten so far to a real solution:
def myperms(elem, mylist):
for i in range(len(elem)-1,-1,-1):
while (elem[i] + 1) < ord:
elem = list(elem)
elem[i] += 1
if elem not in mylist:
mylist.append(elem)
if (elem[i] + 1) >= ord:
elem = list(elem)
elem[i] = 0
return mylist
Num = 3
ord = 2
TotsNum = ord**Num
mylist = []
elem = [0,]*Num
mylist.append(elem)
print(myperms(elem, mylist))
But this only gives:
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0]]
I've tried calling the function within itself (recursion), but I haven't been able to figure out how to do it properly. Does anyone have any ideas about how to solve it recursively? Thank you!
Let's use a recursive solution:
def get_seq(ord, num):
val = [0]*num
N = num
def recurse(ord, num):
for i in range(ord):
val[N - num] = i
if num > 1:
yield from recurse(ord, num-1)
else:
yield val[:]
return recurse(ord, num)
print(list(get_seq(2, 4)))
Output:
[[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 1, 0, 0],
[0, 1, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 1],
[1, 0, 1, 0],
[1, 0, 1, 1],
[1, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 0],
[1, 1, 1, 1]]
For other inputs:
>>> list(get_seq(3, 2))
[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
Use binary, which consists of 0s and 1s.
n = 4
all_permutations = []
for i in range(2**n):
permutation = []
string = bin(i)
string = string.split("0b")[1]
while len(string) != n:
string = f"0{string}"
for i in string:
permutation.append(int(i))
all_permutations.append(permutation)
print(all_permutations)

Copies and bindings between python objects

Given a matrix, A of size M x N of 0s and 1s. If an element is 0, set its entire row and column to 0.
Input 1:
[ [1, 0, 1],
[1, 1, 1],
[1, 1, 1] ]
Output 1:
[ [0, 0, 0],
[1, 0, 1],
[1, 0, 1] ]
My Code:
def setZeroes(self, A):
B=A
for i in range(len(A)):
for j in range(len(A[i])):
if(A[i][j]==0):
for x in range(len(A[i])):
B[i][x]=0
for y in range(len(A)):
B[y][j]=0
A=B
return A
Is creating a zero matrix. What do I miss ?
You can do it by masking rows and columns with a zero
mask = A==0
A[:, mask.any(0)] = 0
A[mask.any(1)] = 0
print(A)
array([[0, 0, 0],
[1, 0, 1],
[1, 0, 1]])
import copy
def setZeroes(A):
B=copy.deepcopy(A)
for i in range(len(A)):
for j in range(len(A[i])):
if(A[i][j]==0):
for x in range(len(A[i])):
B[i][x]=0
for y in range(len(A)):
B[y][j]=0
return B
A = [ [1, 0, 1],
[1, 1, 1],
[1, 1, 1] ]
print(setZeroes(A))
since, array is pass by reference, you have to deepcopy it.
def func(l):
r = []
c = []
# storing the index value of coloum and row where there is 0 everywhere
for i,v1 in enumerate(l):
for j,v2 in enumerate(v1):
if v2 ==0:
c.append(j)
r.append(i)
r = list(set(r))
c = list(set(c))
# making all element of row 0
for i in r:
for j in range(len(l[i])):
l[i][j] = 0
# making lal element of coloumn 0
for i in c:
for j in range(len(l)):
l[j][i] = 0
return l
l = [ [1, 0, 1],
[1, 1, 1],
[1, 1, 1] ]
res = func(l)
print(res,sep='\n')
output:
[
[0, 0, 0],
[1, 0, 1],
[1, 0, 1]
]
Your problem is right here:
B=A
This doesn't create three new arrays for the rows of B: it makes B point to the same arrays as A. So as soon as you set the first row and column to zeros, there are additional zeroes which your loop discovers. Copy each row (or deep copy) to avoid the problem.
This is a simple answer which does not modify A but create another matrix which is returned:
from more_itertools import locate
def setZeroes(A):
indexPosList = [] # will contains all the zeroable indices
result = [] # the result matrix
for i in A:
indexPosList.extend(list(locate(i, lambda a: a == 0)))
if 0 in i:
result.append([0]*len(i))
else:
for idx in indexPosList:
i[idx] = 0
result.append(i)
return result
Sample test:
>>> A = [[1, 0, 1], [1, 1, 1], [1, 1, 1]]
>>> setZeroes(A)
[[0, 0, 0], [1, 0, 1], [1, 0, 1]]
This is a full python implementation that correctly changes A in place including changing columns
def set_zero(A):
columns = set()
for row_nr, row in enumerate(A):
if 0 in row:
columns |= {i for i, c in enumerate(row) if c == 0}
A[row_nr] = [0] * len(row)
for row_nr, row in enumerate(A):
A[row_nr] = [0 if i in columns else c for i, c in enumerate(row)]

Calculating The sum of SandPiles

I am a noob in python
Well i watched a video from numberphile (https://youtu.be/1MtEUErz7Gg)
that was about sandpiles (adding them) so i decided to write my own python program to add 2 sandpiles.
but for some reason it does not work
The program gives me the wrong sum like 2+2=7 type wrong
it should give me:
[ [2, 2, 0], [2, 1, 1], [0, 1, 3] ] + [ [2, 1, 0], [1, 0, 1], [3, 1, 0] ] =
[[2, 1, 0],[0, 3, 3],[1, 2, 3] ]
but instead gives:
[ [2, 2, 0], [2, 1, 1], [0, 1, 3] ] + [ [2, 1, 0], [1, 0, 1], [3, 1, 0] ] =
[[1, 3, 3], [0, 1, 2], [2, 2, 3]]
This is my code
X = [ [2, 2, 0], [2, 1, 1], [0, 1, 3] ]
Y = [ [2, 1, 0], [1, 0, 1], [3, 1, 0] ]
xy = [ [0, 0, 0], [0, 0, 0], [0, 0, 0] ]
i = j = 0
while (i < 3):
while(j < 3):
xy[i][j] = X[i][j] + Y[i][j]
j = j + 1
i = i + 1
j = 0
def get_above(pile):
found = False
while not found:
i, j = 0,0
while (i < 3):
while (j < 3):
if(pile[i][j] > 3):
return i, j
j = j + 1
i = i + 1
j = 0
found = True
return True
def tupple_pile():
while get_above(xy):
i, j = get_above(xy)
neg = [ [i, j+1], [i+1, j], [i, j-1], [i-1,j] ]
neg = [n for n in neg if n[0] in [0, 1, 2] and n [1] in [0, 1, 2]]
k = 0
while k < len(neg):
p = neg[k][0]
q = neg[k][1]
xy[p][q] = xy[p][q] + 1
k = k + 1
xy[i][j] = xy[i][j] - 4
return xy
tupple_pile()
You really should be more specific in your question. Running your code as it is results in Errors.
Anyhow, one thing that looks strange is the check function. Is it supposed to filter out indices that are outside the sandpile? In that case I think you will see something missing here:
if (neg[i][j] < 0) or (neg[i][j]):
Try with this instead:
if (neg[i][j] < 0) or (neg[i][j] > 2):
The second problem with this loop is that you are deleting elements from neg del(neg[i]) while iterating over it. This is error prone. And as you may have noticed, as soon as you delete an item, the i will go out of range.
A better way to filter a list is to use a list comprehension, something like this:
neighbors = [ [i, j+1], [i+1, j], [i, j-1], [i-1,j] ]
neighbors = [n for n in neighbours if n[0] in [0, 1, 2] and n[1] in [0, 1, 2]]

How to remove an specific item from a list - Python

I´m a begginer in Python and I want to remove a specific item from a list, the removal criterion is that when an item contains the three firsts elements null it must be removed from the main list. This is what I´m trying to do:
a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
temp = []
for i in range(len(a)):
for j in range(len(a[i])):
if a[j][0] + a[j][1] + a[j][2] == 0:
temp = a.pop(j)
print temp
else:
print a
j += 1
i += 1
And I´m getting the following error:
if a[j][0] + a[j][1] + a[j][2] == 0:
IndexError: list index out of range
I have no idea what I´m doing wrong...
Thanks!
You could use a list comprehension to filter out sublists
>>> a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
>>> a = [i for i in a if any(i[:3])]
>>> a
[[0, 0, 1, 1], [1, 1, 1, 1]]
This basically works by using slicing to get elements [0] through [2], then uses any to check whether there are non-zero values.
All you need is this (range in this case is unnecessary):
a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
newList = []
for i in a:
if i[0] + i[1] + i[2] != 0:
newList.append(i)
print newList
if you want to avoid the any() method call you can just use a conditional check with the in operator.
a = [[0, 0, 0, 1],[0, 0, 1, 1],[1, 1, 1, 1]]
b = [i for i in a if 1 in i[:3]]
# [[0, 0, 1, 1], [1, 1, 1, 1]]

How can I get step jump in for loop when it has a while conditioned on the for loop's variable

My matrix is a 8x8 having binary values. I want to filter out patterns of consecutive three 1's i.e.(111) in the diagonals of upper triangular matrix of M. I have written a piece of python code with for and while loop but it did not work and I am unable to figure out whats happening there. Please help..
rf =([1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0],
[1,0,1,0,1,0,0,0])
for i in range(1):
for j in range(len (rf)-3):
while (i<len(rf)-3 and j<len(rf)-3):
count =0
if rf[i,j]==True:
for w in range(3):
if rf[i+w,j+w]==True:
count +=1
print count
if count==3:
i=i+3
j=j+3
else:
rf[i,j]=False
i=i+1
j=j+1
You might simplify your code using numpy to access diagonals:
>>> import numpy as np
>>> rf = [[1,0,1,0,1,0,0,0]] * 8
>>> m = np.array(rf)
>>> m.diagonal(0)
array([1, 0, 1, 0, 1, 0, 0, 0])
>>> m.diagonal(1)
array([0, 1, 0, 1, 0, 0, 0])
a simply routine to find positions of consecutive ones:
def consecutive_values(arr, val=1, cnt=3):
def comparator(pos):
return arr[pos] == val
if len < cnt:
return []
else:
return [p for p, x in enumerate(arr[:1-cnt])
if all(map(comparator, xrange(p, p+cnt, 1)))]
and usage:
>>> consecutive_values([1]*5)
[0, 1, 2]
>>> consecutive_values([1]*5 + [0]*4 + [1]*3)
[0, 1, 2, 9]
>>> m = np.array([[1]*8]*8)
>>> diagonals = map(m.diagonal, range(len(m)))
>>> map(consecutive_values, diagonals)
[[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4], [0, 1, 2, 3], [0, 1, 2], [0, 1], [0], [], []]

Categories

Resources