How to use nested while loops - python-3.x

I'm trying to make a function that uses a nested while loop that prints something like this.
ranges(5,2)
5
0 1 2 3 4
4
0 1 2 3
3
0 1 2
2
0 1
my code that i have so far looks like this
def ranges(high,low):
while high >= low:
print(high)
high = high - 1
y = 0
x = high
while x > y:
print (y, end = " ")
y = y + 1
The output is like this
5
0 1 2 3 4
0 1 2 3
0 1 2
0
I'm pretty sure I missed up in calling the nested while loop because when i split up the code to just print 5,...,2 in a column it works and so does the code for printing the numbers in a row. Any help would be cool

Add print("") right after the while loop, and modify the condition of the while loop to >=:
def ranges(high,low):
while high >= low: # <-- change the condition otherwise you'll miss the last number in every line
print(high)
high = high - 1
y = 0
x = high
while x >= y:
print (y, end = " ")
y = y + 1
print("") # <-- this
ranges(5, 2)
OUTPUT
5
0 1 2 3 4
4
0 1 2 3
3
0 1 2
2
0 1

Related

How to recognize [1,X,X,X,1] repeating pattern in panda serie

I have a boolean column in a csv file for example:
1 1
2 0
3 0
4 0
5 1
6 1
7 1
8 0
9 0
10 1
11 0
12 0
13 1
14 0
15 1
You can see here 1 is reapting every 5 lines.
I want to recognize this repeating pattern [1,0,0,0] as soon as the repetition is above 10 in python (I have ~20.000 rows/file).
The pattern can start at any position
How could I manage this in python avoiding if .....
# Generate 20000 of 0s and 1s
data = pd.Series(np.random.randint(0, 2, 20000))
# Keep indices of 1s
idx = df[df > 0].index
# Check distance of current index with next index whether is 4 or not,
# Say if position 2 and position 6 is found as 1, so 6 - 2 = 4
found = []
for i, v in enumerate(idx):
if i == len(idx) - 1:
break
next_value = idx[i + 1]
if (next_value - v) == 4:
found.append(v)
print(found)

Python recursive index changing

I am trying to arrange matrix in way that it will dynamically change the indexes.
I have tried to do it by means of for loop, however it only does once for each index.
def arrangeMatrix(progMatrix):
for l in range(len(progMatrix)):
for item in range(len(progMatrix[l])):
if indexExists(progMatrix,l + 1,item) and progMatrix[l + 1][item] == " ":
progMatrix[l + 1][item] = progMatrix[l][item]
progMatrix[l][item] = " "
The original list is:
1 0 7 6 8
0 5 5 5
2 1 6
4 1 3 7
1 1 1 7 5
And my code should fill all gapped indexes from up to bottom, however my result is:
1 0 6 8
0 5 5
2 1 7
4 1 3 7 6
1 1 1 7 5 5
The actual result should be:
1 0
0 5 8
2 1 7 5
4 1 3 7 6 6
1 1 1 7 5 5
Any help or hint is appreciated.Thanks in advance
It is probably easier if you first iterate the columns, since the change that happens in one column is independent on what happens in other columns. Then, per column, you could iterate the cells from the bottom to the top and keep track of the y-coordinate where the next non-space should "drop down" to.
No recursion is needed.
Here is how that could be coded:
def arrangeMatrix(progMatrix):
for x in range(len(progMatrix[0])):
targetY = len(progMatrix)-1
for y in range(len(progMatrix)-1,-1,-1):
row = progMatrix[y]
if row[x] != " ": # Something to drop down
if y < targetY: # Is it really to drop any lower?
progMatrix[targetY][x] = row[x] # copy it down
row[x] = " " # ...and clear the cell where it dropped from
targetY -= 1 # since we filled the target cell, the next drop would be higher

connect 4 check for win by using lists and matrix

I am currently writing a code that takes a connect 4 board from a text file and transfers it into a list. I split each row into a separate list and then added it to a matrix. My goal here is to check if there is a winner. I only need to check for horizontal and vertical wins. I am thinking of checking each element of the matrix to see if there is a winner for four in a row. I know that this is tedious and there is probably a more efficient way. This is what the text file contains:
0 0 0 0 0 0 2
0 0 0 0 0 2 1
2 1 0 2 2 1 2
2 1 0 1 1 2 2
1 1 2 2 2 1 2
1 1 1 2 1 2 1
I see the win in the second column but how would I check for everything to see if there is a win?
This is the code I have so far:
file1=open("file1.txt","r")
matrix=[]
for line in file1:
connect=line.split(" ")
matrix.append(connect)
print(matrix)
if matrix[0][0]==matrix[0][1]==matrix[0][2]==matrix[0][3]: #this is only temporary, supposed to check for every element
if matrix[0][0]==1:
print("player 1 wins!")
elif matrix[0][0]==2:
print("player 2 wins!")
else:
print("no winner")
if matrix[0][0]==matrix[1][0]==matrix[2][0]==matrix[0][0]: #check for vertical matches
if matrix[0][0]==1:
print("player 1 wins!")
elif matrix[0][0]==2:
print("player 2 wins!")
else:
print("no winner")
You can rely on the builtin substing match to do all of the heavy lifting.
# read data
board = list(
map(
str.split,
"""0 0 0 0 0 0 2
0 0 0 0 0 2 1
2 1 0 2 2 1 2
2 1 0 1 1 2 2
1 1 2 2 2 1 2
1 1 1 2 1 2 1""".split(
"\n"
),
)
)
# contains ['1111', '2222']
winning_strings = [c * 4 for c in "12"]
def has_winner(board):
# get rows, e.g. rows[0] == '0000002'
rows = map("".join, board)
# get cols, e.g. cols[0] == '002211'
# zip(*...) is a common idiom for a transpose
cols = map("".join, zip(*board))
# check if a winning sequence occurs as a substring
# of any row or column
return any(
seq in row or seq in col
for seq in winning_strings
for row, col in zip(rows, cols)
)
assert has_winner(board)

How to apply function to data frame column to created iterated column

I have IDs with system event times, and I have grouped the event times by id (individual systems) and made a new column where the value is 1 if the eventtimes.diff() is greater than 1 day, else 0 . Now that I have the flag I am trying to make a function that will be applied to groupby('ID') so the new column starts with 1 and keeps returning 1 for each row in the new column until the flag shows 1 then the new column will go up 1, to 2 and keep returning 2 until the flag shows 1 again.
I will apply this along with groupby('ID') since I need the new column to start over again at 1 for each ID.
I have tried to the following:
def try(x):
y = 1
if row['flag']==0:
y = y
else:
y += y+1
df['NewCol'] = df.groupby('ID')['flag'].apply(try)
I have tried differing variations of the above to no avail. Thanks in advance for any help you may provide.
Also, feel free to let me know if I messed up posting the question. Not sure if my title is great either.
Use boolean indexing for filtering + cumcount + reindex what is much faster solution as loopy apply :
I think you need for count only 1 per group and if no 1 then 1 is added to output:
df = pd.DataFrame({
'ID': ['a','a','a','a','b','b','b','b','b'],
'flag': [0,0,1,1,0,0,1,1,1]
})
df['new'] = (df[df['flag'] == 1].groupby('ID')['flag']
.cumcount()
.add(1)
.reindex(df.index, fill_value=1))
print (df)
ID flag new
0 a 0 1
1 a 0 1
2 a 1 1
3 a 1 2
4 b 0 1
5 b 0 1
6 b 1 1
7 b 1 2
8 b 1 3
Detail:
#filter by condition
print (df[df['flag'] == 1])
ID flag
2 a 1
3 a 1
6 b 1
7 b 1
8 b 1
#count per group
print (df[df['flag'] == 1].groupby('ID')['flag'].cumcount())
2 0
3 1
6 0
7 1
8 2
dtype: int64
#add 1 for count from 1
print (df[df['flag'] == 1].groupby('ID')['flag'].cumcount().add(1))
2 1
3 2
6 1
7 2
8 3
dtype: int64
If need count 0 and if no 0 is added -1:
df['new'] = (df[df['flag'] == 0].groupby('ID')['flag']
.cumcount()
.add(1)
.reindex(df.index, fill_value=-1))
print (df)
ID flag new
0 a 0 1
1 a 0 2
2 a 1 -1
3 a 1 -1
4 b 0 1
5 b 0 2
6 b 1 -1
7 b 1 -1
8 b 1 -1
Another 2 step solution:
df['new'] = df[df['flag'] == 1].groupby('ID')['flag'].cumcount().add(1)
df['new'] = df['new'].fillna(1).astype(int)
print (df)
ID flag new
0 a 0 1
1 a 0 1
2 a 1 1
3 a 1 2
4 b 0 1
5 b 0 1
6 b 1 1
7 b 1 2
8 b 1 3

Python Modulo Function

I understand that the Modulo function returns the remainder of a division problem.
Ex: 16 % 5 = 3 with a remainder of 1. So 1 would be returned.
>>> 1 % 3 Three goes into 1 zero times remainder 1
1
>>> 2 % 3 Three goes into 2 zero times remainder 2
2
>>> 0 % 3 What happens here? 3 goes into zero, zero times remainder 3
if we follow the logic of the previous two illustrations, that is not what was returned, zero was. Why?
>>> 0 % 3
0
The Python % operator is defined so that x % y == x - (x // y) * y, where x // y = ⌊x / y⌋. For positive integers, this corresponds to the usual notion of the “remainder” of a division. So, for any y ≠ 0,
0 % y
= 0 - ⌊0 / y⌋ * y by definition of %
= 0 - ⌊0⌋ * y because 0 divided by anything is 0
= 0 - 0 * y because 0 is an integer, so floor leaves it unchanged
= 0 - 0 because 0 times anything is 0
= 0
Look at it again:
1 % 3 is 0 remainder 1 => 1 = 3*0 + 1
2 % 3 is 0 remainder 2 => 2 = 3*0 + 2
0 % 3 is 0 remainder 0 [not 3] because 0 = 3*0 + 0
why are you taking what remains after the division in the first two cases but not the last?

Resources