This question already has answers here:
Making a shift function in 2048
(3 answers)
Closed 4 years ago.
So I have some code to shift up a board of numbers in a 2048 game:
data = [0, 2, 4, 8, 0, 2, 8, 0, 0, 0, 0, 2, 4, 2, 2, 0]
def drawBoard(): # Making the board into a 2d array
count = 0
for i in range(16):
print(data[i], end = ' ')
count += 1
if count == 4:
print("")
count = 0
print(drawBoard())
for col in range(4): #Loop to shift numbers up
count = 0
for row in range(4): # read loop
if data[row*4+col] != 0:
data[count*4+col] = data[row*4+col]
count += 1
for row in range(count, 4):
data[row*4+col] = 0
print(drawBoard())
This basically takes data, makes it into a 4 x 4 board and shifts all the non zero numbers up.
Non Shifted Board:
2 2 4 8
0 2 8 0
0 0 0 2
4 2 2 0
Shifted Board:
2 2 4 8
4 2 8 2
0 2 2 0
0 0 0 0
Is there a way using the same format as what I commented "loop to shift numbers up" and make this shift up function into a shift left function?
So the board shifted left looks like:
2 2 4 8
2 8 0 0
2 0 0 0
4 2 2 0
I suggest you to rotate the row/col reference, and the code will be the same. Immagine that you turn the grid counter clockwise so your first column is the last row and your first row is the first column
Related
I have a large dataframe with a price column that stays at the same value as the time increases and then will change values, and then stay at that value new value for a while before going up or down. I want to write a function that looks at the price column and creates a new column called next movement that indicates wheather or not the next movement of the price column will be up or down.
For example if the price column looked like [1,1,1,2,2,2,4,4,4,3,3,3,4,4,4,2,1] then the next movement column should be [1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,-1] with 1 representing the next movement being up 0 representing the next movement being down, and -1 representing unknown.
def make_next_movement_column(DataFrame, column):
DataFrame["next movement"] = -1
for i in range (DataFrame.shape[0]):
for j in range(i + 1, DataFrame.shape[0]):
if(DataFrame[column][j] > DataFrame[column][i]):
DataFrame["next movement"][i:j] = 1
break;
if(DataFrame[column][j] < DataFrame[column][i]):
DataFrame["next movement"][i:j] = 0
break;
i = j - 1
return DataFrame
I wrote this function and it does work, but the problem is it is horribly ineffcient. I was wondering if there was a more effcient way to write this function.
This answer doesn't seem to work because the diff method only looks at the next column but I want to find the next movement no matter how far away it is.
Annotated code
# Calculate the diff between rows
s = df['column'].diff(-1)
# Broadcast the last diff value per group
s = s.mask(s == 0).bfill()
# Select from [1, 0] depending upon the value of diff
df['next_movement'] = np.select([s <= -1, s >= 1], [1, 0], -1)
Result
column next_movement
0 1 1
1 1 1
2 1 1
3 2 1
4 2 1
5 2 1
6 4 0
7 4 0
8 4 0
9 3 1
10 3 1
11 3 1
12 4 0
13 4 0
14 4 0
15 2 0
16 1 -1
There are three columns in df: mins, maxs, and col. I would like to generate a binary list according to the following rule: if col[i] is smaller than or equal to mins[i], add a "1" to the list and keep adding "1" for each row until col[i+n] is greater than or equal maxs[i+n]. After reaching maxs[i+n], add "0" to the list for each row until finding the next row where col[i] is smaller than or equal to mins[i]. Repeat this entire process till going over all rows.
For example,
col mins maxs
2 1 6 (0)
4 2 6 (0)
2 3 7 (1)
5 5 6 (1)
4 3 8 (1)
4 2 5 (1)
5 3 5 (0)
4 0 5 (0)
3 3 8 (1)
......
So the list would be [0,0,1,1,1,1,0,0,1]. Does this make sense?
I gave it a shot and wrote the following, which unfortunately did not achieve what I wanted.
def get_list(col, mins, maxs):
l = []
i = 0
while i <= len(col):
if col[i] <= mins[i]:
l.append(1)
while col[i+1] <= maxs[i+1]:
l.append(1)
i += 1
break
break
return l
Thank you so much folks!
My answer may not be elegant but should work according to your expectation.
Import the pandas library.
import pandas as pd
Create dataframe according to data provided.
input_data = {
'col': [2, 4, 2, 5, 4, 4, 5, 4, 3],
'mins': [1, 2, 3, 5, 3, 2 , 3, 0, 3],
'maxs': [6, 6, 7, 6, 8, 5, 5, 5, 8]
}
dataframe_ = pd.DataFrame(data=input_data)
Using a for loop iterate over the rows. The switch variable will change accordingly depending on the conditions was provided which results in the binary column being populated.
binary_switch = False
for index, row in dataframe_.iterrows():
if row['col'] <= row['mins']:
binary_switch = True
elif row['col'] >= row['maxs']:
binary_switch = False
binary_output = 1 if binary_switch else 0
dataframe_.at[index, 'binary'] = binary_output
dataframe_['binary'] = dataframe_['binary'].astype('int')
print(dataframe_)
Output from code.
col mins maxs binary
0 2 1 6 0
1 4 2 6 0
2 2 3 7 1
3 5 5 6 1
4 4 3 8 1
5 4 2 5 1
6 5 3 5 0
7 4 0 5 0
8 3 3 8 1
Your rules give the following decision tree:
1: is col <= mins?
True: l.append(1)
False: next question
2: was col <= mins before?
False: l.append(0)
True: next question:
3: is col >= maxs?
True: l.append(0)
False: l.append(1)
Making this into a function with an if/else tree, you get this:
def make_binary_list(df):
l = []
col_lte_mins = False
for index, row in df.iterrows():
col = row["col"]
mins = row["mins"]
maxs = row["maxs"]
if col <= mins:
col_lte_mins = True
l.append(1)
else:
if col_lte_mins:
if col >= maxs:
col_lte_mins = False
l.append(0)
else:
l.append(1)
else:
l.append(0)
return l
make_binary_list(df) gives [0, 0, 1, 1, 1, 1, 0, 0, 1]
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
I did an Algorithm to print a triangle in the upper half of the matrix (without recursive function) but now i want to do it recursively can anyone Help?
Thanks
CLICK HERE TO SEE AN EXAMPLE
My python code:
def T(row,column):
print("Row: ",row)
print("Column", column)
if row != column and row%2 == 0:
print("Please enter valid number")
else:
matrix = []
start = 1
cteRow = row
cteColumn = column
for i in range(0,column):
matrix.append(list(range(start,row + 1)))
start = start + cteRow
row = row + cteColumn
print("The Matrix: \n")
for i in range(len(matrix)):
for j in range(len(matrix)):
print(matrix[i][j], end= " ")
print()
print()
length = len(matrix)
middle = int(length/2)
for i in range(length):
for j in range(length):
matrix[i][j] = 0
if (middle + i)<= length and (middle - i)>= 0:
matrix[i][middle] = 1
myRangeList=list(range(middle-i,middle+i+1))
for n in myRangeList:
matrix[i][n] = 1
print(matrix[i][j], end = " ")
print()
T(5,5)
To make it recursive, you have to come up with a method to convert the result of a smaller matrix into a larger one.
for example:
From T(3,5) --> T(4,7)
0 0 1 0 0 0 0 0 1 0 0 0
0 1 1 1 0 0 0 1 1 1 0 0
1 1 1 1 1 0 1 1 1 1 1 0
1 1 1 1 1 1 1
The transformation could be adding zeros on each side and a line of 1s at the bottom:
0 0 1 0 0 0 x x x x x 0 0 0 0 1 0 0 0
0 1 1 1 0 0 x x x x x 0 0 0 1 1 1 0 0
1 1 1 1 1 0 x x x x x 0 0 1 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1
This will be easy if the parameters provided fit the triangle size exactly: rows = (columns+1)/2. You can handle the disproportionate dimensions by padding the result from an appropriate size ratio with zeros so that the function only needs to handle proper proportions:
def R(rows,cols):
if not cols%2: # must have odd number of columns (pad trailing zero)
return [ row+[0] for row in R(rows,cols-1)]
height = (cols+1)//2
if rows>height: # too high, pad with lines of zeros
return R(height,cols)+[[0]*cols for _ in range(rows-height)]
if rows<height: # not high enough
return R(height,cols)[:rows] # truncate bottom
if cols == 1: # base case (1,1)
return [[1]]
result = R(rows-1,cols-2) # Smaller solution
result = [[0]+row+[0] for row in result] # pad with zeros
result += [[1]*cols] # add line of 1s
return result
The function only generates the matrix. User input and printing should always be separate from data manipulation (especially for recursion)
output:
for row in R(5,5): print(*row)
0 0 1 0 0
0 1 1 1 0
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
Note that this will work for any combination of row & column sizes but, if you always provide the function with a square matrix, only the "upper half" will contain the triangle because triangle height = (columns+1)/2. It would also be unnecessary to ask the user for both a number of rows and a number of columns if the two are required to be equal.
For only square matrices with an odd number of columns, the process can be separated in a recursive part and a padding function that uses it:
def R(cols):
if cols == 1: return [[1]] # base case (1,1)
result = R(cols-2) # Smaller solution
result = [[0]+row+[0] for row in result] # pad with zeros
result += [[1]*cols] # add line of 1s
return result
def T(n):
return R(n)+[[0]*n]*((n-1)//2) # square matrix with padding
for row in T(7): print(*row)
0 0 0 1 0 0 0
0 0 1 1 1 0 0
0 1 1 1 1 1 0
1 1 1 1 1 1 1
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
I have a list of zeros and ones, I want to print them in two different columns with headings and index numbers. Something like this.
list = [1,0,1,1,1,0,1,0,1,0,0]
ones zeros
1 1 2 0
3 1 6 0
4 1 8 0
5 1 10 0
7 1 11 0
9 1
This is the desired output.
I tried this:
list = [1,0,1,1,1,0,1,0,1,0,0]
print('ones',end='\t')
print('zeros')
for index,ele in enumerate(list,start=1):
if ele==1:
print(index,ele,end=" ")
elif ele==0:
print(" ")
print(index,ele,end=" ")
else:
print()
But this gives output like this:
ones zeros
1 1
2 0 3 1 4 1 5 1
6 0 7 1
8 0 9 1
10 0
11 0
How do get the desired output?
Any help is appreciated.
You can use itertools.zip_longest, str.ljust, f-strings (for formatting), and some calculations for the printing part, and use two lists to hold the indices of both zeros and ones:
l = [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0]
ones, zeros = [], []
max_len_zeros = max_len_ones = 0
for index, num in enumerate(l, 1):
if num == 0:
zeros.append(index)
max_len_zeros = max(max_len_zeros, len(str(index)))
else:
ones.append(index)
max_len_ones = max(max_len_ones, len(str(index)))
from itertools import zip_longest
print('ones' + ' ' * (max_len_ones + 2) + 'zeros')
for ones_index, zeros_index in zip_longest(ones, zeros, fillvalue = ''):
one = '1' if ones_index else ' '
this_one_index = str(ones_index).ljust(max_len_ones)
zero = '0' if zeros_index else ''
this_zero_index = str(zeros_index).ljust(max_len_zeros)
print(f'{this_one_index} {one} {this_zero_index} {zero}')
Output:
ones zeros
1 1 2 0
3 1 6 0
4 1 8 0
5 1 10 0
7 1 11 0
9 1
List with more zeros than ones:
In: l = [1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0]
Out:
ones zeros
1 1 2 0
4 1 3 0
7 1 5 0
9 1 6 0
10 1 8 0
14 1 11 0
12 0
13 0
15 0
List with equal number of zeros and ones:
In: l = [1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1]
Out:
ones zeros
1 1 2 0
3 1 4 0
5 1 6 0
8 1 7 0
9 1 10 0
11 1 13 0
12 1 14 0
15 1 16 0
18 1 17 0
20 1 19 0
It's hard to do what you need in an iterative way. I have kind of a "broken" solution that both shows how you could better do what you are trying to do and why an iterative approach is limited in this case.
I updated your code as following:
list = [1,0,1,1,1,0,1,0,1,0,0]
print('ones',end='\t')
print('zeros')
for index,ele in enumerate(list,start=1):
# First check if extra space OR new lines OR both are needed
if index > 1:
if ele==1:
print()
elif ele==0:
if list[index-2]==1:
print('', end=' \t')
else:
print('', end='\n\t\t')
# THEN, write your desired output without any end
if ele==1:
print(index,ele,end="")
elif ele==0:
print(index,ele,end="")
# Finally an empty line
print()
It gives the following ouput:
ones zeros
1 1 2 0
3 1
4 1
5 1 6 0
7 1 8 0
9 1 10 0
11 0
As you can see, its limitation is that you can't go "up" and rewrite in old lines.
However, if you need to display EXACTLY as you've shown, you need to construct an intermediate data structure (for example a dict) and then display it using zip
Imagine a simple 3x3 matrix upon which I impose the following "boundary conditions". Here are an array showing the corresponding indexes if flattened, and the boundary value.
I = B =
0 3 6 3 0 1
1 4 7 3 0 1
2 5 8 3 0 1
It is easy to see that the flattened boundary value array would be
b =
3 3 3 0 0 0 1 1 1
I also have a connectivity structure C, given as a set of pairs,
C =
0 0 1 1 2 3 3 4 4 5 6 7
1 3 2 4 5 4 6 5 7 8 6 8
I wanna construct a matrix A that represents this linear system, to use spsolve(A, b) and get
A =
1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
1 0 0 -3 1 0 1 0 0
0 1 0 1 -4 1 0 1 0
0 0 1 0 1 -3 0 0 1
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1
x =
3 3 3 2 2 2 1 1 1
This was very simple to do using numpy and manipulating dense matrices, zeroing out columns, and so on. However as the matrices grow large, I start running out of memory and the solvers are incredibly slow.
I thought I'd build my sparse matrix with this logic:
Initialize a matrix using the connectivity array and np.ones_like one of the vectors
Add the matrix and its transpose to fill out the LD region
where b is nonzero: Wipe out the rows and place a 1 in the diagonal (this represents an initial condition)
where b is zero: Sum the matrices along axis=1, and place the negative value of the sum into each diagonal (this balances out sinks and sources)
This works perfectly in numpy, but I find it absolutely impossible to do anything useful with the sparse matrices after initializing them. They don't handle item deletion, transpose, etc. Can I get a walk through on these operations?
I guess I'm going with this so far
Seems a little obscure, like I'm doing something wrong
b = np.array([3, 3, 3, 0, 0, 0, 1, 1, 1])
i = (0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 7)
j = (1, 3, 2, 4, 5, 4, 6, 5, 7, 8, 7, 8)
f = b!=0
A = sparse.lil_matrix((b.size, b.size))
A[f,f] = 1
C = sparse.coo_matrix((np.ones_like(i+j), (i+j,j+i)), shape=(b.size, b.size)).tolil()
D = sparse.diags(np.asarray(C.sum(axis=1).T)[0], 0).tocsr()
A[~f,:] = C[~f, :] - D[~f]
print A.toarray()