Find diagonals in a Python matrix using lists
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I'm trying to code the game connect-4, and there is a part of my code in which i try to find in a 7x6 matrix, diagonals of 4 ones in a row or 4 2s in a row.
This part of my code does not work i tried everything I was able to. And sometimes it detects that there is a 4 1s or 4 2s diagonal where is not. I created the matrix puting a 7 zero list in each position of a 6 zeros lists. I'm trying to do it using only lists functions, i cant use the numpy library or similar.
Okay, in this part of the code I'm trying to find if in each possible diagonal of the matrice there are 4 zeros in a row. PD: I'm only trying to find the diagonals that go from left to right ATM. Thanks for your help, I tried to explain my problem as good as I can because english is not my main tongue.
This is my code:
import random
llista = [0]*6 #when i say llista y mean matrix
for i in range(6):
llista[i]=[0]*7
#Here i fill the 7*6 matrix of 0s 1s and 2s randomly so i can see if it works.
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=1
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=2
#This 2 loops here are too see if it is possible to have a diagonal in the matrece because if you want a diagonal u need at least a one or 2 in the center, the problem is not here.
for i in range(-1,-7,-1):
possible = False
if llista[i][3]==1:
possible = True
break
for i in range(7):
possible2 = False
if llista[-4][i]==1 or llista[-4][i]==1:
possible2=True
break
if possible==True and possible2==True:
#The problem starts here. This first loop i use it too find the diagonals that go from left to right. I want to find diagonals of 4 1s or 4 2s.
for i in range(len(llista)-3):
for j in range(len(llista[i])-3):
#This if is too see if we have four 1 or 2 togheter in the list, if we have them it prints the sentence below.
if (llista[i][j]==1 and llista[i+1][j+1]==1 and llista[i+2][j+2]==1 and llista[i+3][j+3]==1) or (llista[i][j]==2 and llista[i+1][j+1]==2 and llista[i+2][j+2]==2 and llista[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
#This loop is the same than the last one but to find diagonals from right to left (a 4 diagonal made of 1s or 2s)
for i in range(len(llista)):
for j in range(len(llista[i])):
if i-3<0 and j-3<0:
if (llista[i][j]==1 and llista[i-1][j-1]==1 and llista[i-2][j-2]==1 and llista[i-3][j-3]==1) or (llista[i][j]==2 and llista[i-1][j-1]==2 and llista[i-2][j-2]==2 and llista[i-3][j-3]==2 ):
print("There is at least one right to left diagonal")
#Here i print the matrix
for i in range(6):
print(llista[i])
#So this program should say if there is at least one left to right diagonal
or right to left diagonal.
#I dont want to use functions that are not being used already, and i dont wanna do it another way because i must understand this way. thanks
python
add a comment |
I'm trying to code the game connect-4, and there is a part of my code in which i try to find in a 7x6 matrix, diagonals of 4 ones in a row or 4 2s in a row.
This part of my code does not work i tried everything I was able to. And sometimes it detects that there is a 4 1s or 4 2s diagonal where is not. I created the matrix puting a 7 zero list in each position of a 6 zeros lists. I'm trying to do it using only lists functions, i cant use the numpy library or similar.
Okay, in this part of the code I'm trying to find if in each possible diagonal of the matrice there are 4 zeros in a row. PD: I'm only trying to find the diagonals that go from left to right ATM. Thanks for your help, I tried to explain my problem as good as I can because english is not my main tongue.
This is my code:
import random
llista = [0]*6 #when i say llista y mean matrix
for i in range(6):
llista[i]=[0]*7
#Here i fill the 7*6 matrix of 0s 1s and 2s randomly so i can see if it works.
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=1
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=2
#This 2 loops here are too see if it is possible to have a diagonal in the matrece because if you want a diagonal u need at least a one or 2 in the center, the problem is not here.
for i in range(-1,-7,-1):
possible = False
if llista[i][3]==1:
possible = True
break
for i in range(7):
possible2 = False
if llista[-4][i]==1 or llista[-4][i]==1:
possible2=True
break
if possible==True and possible2==True:
#The problem starts here. This first loop i use it too find the diagonals that go from left to right. I want to find diagonals of 4 1s or 4 2s.
for i in range(len(llista)-3):
for j in range(len(llista[i])-3):
#This if is too see if we have four 1 or 2 togheter in the list, if we have them it prints the sentence below.
if (llista[i][j]==1 and llista[i+1][j+1]==1 and llista[i+2][j+2]==1 and llista[i+3][j+3]==1) or (llista[i][j]==2 and llista[i+1][j+1]==2 and llista[i+2][j+2]==2 and llista[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
#This loop is the same than the last one but to find diagonals from right to left (a 4 diagonal made of 1s or 2s)
for i in range(len(llista)):
for j in range(len(llista[i])):
if i-3<0 and j-3<0:
if (llista[i][j]==1 and llista[i-1][j-1]==1 and llista[i-2][j-2]==1 and llista[i-3][j-3]==1) or (llista[i][j]==2 and llista[i-1][j-1]==2 and llista[i-2][j-2]==2 and llista[i-3][j-3]==2 ):
print("There is at least one right to left diagonal")
#Here i print the matrix
for i in range(6):
print(llista[i])
#So this program should say if there is at least one left to right diagonal
or right to left diagonal.
#I dont want to use functions that are not being used already, and i dont wanna do it another way because i must understand this way. thanks
python
1
Are you getting an error message? What is it?
– berkelem
Nov 21 '18 at 21:55
I'm not getting any error message, it says that there is a diagonal even if there is not a 4 ones or 2s diagonal.
– RiesenChicken
Nov 21 '18 at 22:10
add a comment |
I'm trying to code the game connect-4, and there is a part of my code in which i try to find in a 7x6 matrix, diagonals of 4 ones in a row or 4 2s in a row.
This part of my code does not work i tried everything I was able to. And sometimes it detects that there is a 4 1s or 4 2s diagonal where is not. I created the matrix puting a 7 zero list in each position of a 6 zeros lists. I'm trying to do it using only lists functions, i cant use the numpy library or similar.
Okay, in this part of the code I'm trying to find if in each possible diagonal of the matrice there are 4 zeros in a row. PD: I'm only trying to find the diagonals that go from left to right ATM. Thanks for your help, I tried to explain my problem as good as I can because english is not my main tongue.
This is my code:
import random
llista = [0]*6 #when i say llista y mean matrix
for i in range(6):
llista[i]=[0]*7
#Here i fill the 7*6 matrix of 0s 1s and 2s randomly so i can see if it works.
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=1
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=2
#This 2 loops here are too see if it is possible to have a diagonal in the matrece because if you want a diagonal u need at least a one or 2 in the center, the problem is not here.
for i in range(-1,-7,-1):
possible = False
if llista[i][3]==1:
possible = True
break
for i in range(7):
possible2 = False
if llista[-4][i]==1 or llista[-4][i]==1:
possible2=True
break
if possible==True and possible2==True:
#The problem starts here. This first loop i use it too find the diagonals that go from left to right. I want to find diagonals of 4 1s or 4 2s.
for i in range(len(llista)-3):
for j in range(len(llista[i])-3):
#This if is too see if we have four 1 or 2 togheter in the list, if we have them it prints the sentence below.
if (llista[i][j]==1 and llista[i+1][j+1]==1 and llista[i+2][j+2]==1 and llista[i+3][j+3]==1) or (llista[i][j]==2 and llista[i+1][j+1]==2 and llista[i+2][j+2]==2 and llista[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
#This loop is the same than the last one but to find diagonals from right to left (a 4 diagonal made of 1s or 2s)
for i in range(len(llista)):
for j in range(len(llista[i])):
if i-3<0 and j-3<0:
if (llista[i][j]==1 and llista[i-1][j-1]==1 and llista[i-2][j-2]==1 and llista[i-3][j-3]==1) or (llista[i][j]==2 and llista[i-1][j-1]==2 and llista[i-2][j-2]==2 and llista[i-3][j-3]==2 ):
print("There is at least one right to left diagonal")
#Here i print the matrix
for i in range(6):
print(llista[i])
#So this program should say if there is at least one left to right diagonal
or right to left diagonal.
#I dont want to use functions that are not being used already, and i dont wanna do it another way because i must understand this way. thanks
python
I'm trying to code the game connect-4, and there is a part of my code in which i try to find in a 7x6 matrix, diagonals of 4 ones in a row or 4 2s in a row.
This part of my code does not work i tried everything I was able to. And sometimes it detects that there is a 4 1s or 4 2s diagonal where is not. I created the matrix puting a 7 zero list in each position of a 6 zeros lists. I'm trying to do it using only lists functions, i cant use the numpy library or similar.
Okay, in this part of the code I'm trying to find if in each possible diagonal of the matrice there are 4 zeros in a row. PD: I'm only trying to find the diagonals that go from left to right ATM. Thanks for your help, I tried to explain my problem as good as I can because english is not my main tongue.
This is my code:
import random
llista = [0]*6 #when i say llista y mean matrix
for i in range(6):
llista[i]=[0]*7
#Here i fill the 7*6 matrix of 0s 1s and 2s randomly so i can see if it works.
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=1
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=2
#This 2 loops here are too see if it is possible to have a diagonal in the matrece because if you want a diagonal u need at least a one or 2 in the center, the problem is not here.
for i in range(-1,-7,-1):
possible = False
if llista[i][3]==1:
possible = True
break
for i in range(7):
possible2 = False
if llista[-4][i]==1 or llista[-4][i]==1:
possible2=True
break
if possible==True and possible2==True:
#The problem starts here. This first loop i use it too find the diagonals that go from left to right. I want to find diagonals of 4 1s or 4 2s.
for i in range(len(llista)-3):
for j in range(len(llista[i])-3):
#This if is too see if we have four 1 or 2 togheter in the list, if we have them it prints the sentence below.
if (llista[i][j]==1 and llista[i+1][j+1]==1 and llista[i+2][j+2]==1 and llista[i+3][j+3]==1) or (llista[i][j]==2 and llista[i+1][j+1]==2 and llista[i+2][j+2]==2 and llista[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
#This loop is the same than the last one but to find diagonals from right to left (a 4 diagonal made of 1s or 2s)
for i in range(len(llista)):
for j in range(len(llista[i])):
if i-3<0 and j-3<0:
if (llista[i][j]==1 and llista[i-1][j-1]==1 and llista[i-2][j-2]==1 and llista[i-3][j-3]==1) or (llista[i][j]==2 and llista[i-1][j-1]==2 and llista[i-2][j-2]==2 and llista[i-3][j-3]==2 ):
print("There is at least one right to left diagonal")
#Here i print the matrix
for i in range(6):
print(llista[i])
#So this program should say if there is at least one left to right diagonal
or right to left diagonal.
#I dont want to use functions that are not being used already, and i dont wanna do it another way because i must understand this way. thanks
python
python
edited Nov 22 '18 at 5:39
RiesenChicken
asked Nov 21 '18 at 21:48
RiesenChickenRiesenChicken
52
52
1
Are you getting an error message? What is it?
– berkelem
Nov 21 '18 at 21:55
I'm not getting any error message, it says that there is a diagonal even if there is not a 4 ones or 2s diagonal.
– RiesenChicken
Nov 21 '18 at 22:10
add a comment |
1
Are you getting an error message? What is it?
– berkelem
Nov 21 '18 at 21:55
I'm not getting any error message, it says that there is a diagonal even if there is not a 4 ones or 2s diagonal.
– RiesenChicken
Nov 21 '18 at 22:10
1
1
Are you getting an error message? What is it?
– berkelem
Nov 21 '18 at 21:55
Are you getting an error message? What is it?
– berkelem
Nov 21 '18 at 21:55
I'm not getting any error message, it says that there is a diagonal even if there is not a 4 ones or 2s diagonal.
– RiesenChicken
Nov 21 '18 at 22:10
I'm not getting any error message, it says that there is a diagonal even if there is not a 4 ones or 2s diagonal.
– RiesenChicken
Nov 21 '18 at 22:10
add a comment |
3 Answers
3
active
oldest
votes
If you consider the logic of your 'right-to-left' loop, you are actually just doing the same as your 'left-to-right' loop in reverse order. To really get the 'right-to-left' pass right you have to have your i and j indices moving in different directions.
So your conditional statement in this section should look like:
if i-3>=0 and j+3<7:
if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1) or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):
print("There is at least one right to left diagonal")
There are a ton of optimizations you could use by importing libraries like numpy or itertools as AResem showed. That answer is not entirely correct though for the following reason.
When you say return True, k you are not exercising any control over the value of k because it was used in the list comprehension just above and will just have the value of the last item it iterated over. So when your function finds a diagonal it reports the wrong number about two thirds of the time.
Here is an edited function that gives the correct results:
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
# Here you can create a tuple of numbers with the number of times they are repeated.
# This allows you to keep your k and g values associated.
repeat_groups = [(k, sum(1 for _ in g)) for k, g in groupby(diag)]
# By using the built-in max function with the 'key' keyword, you can find
# the maximum number of repeats and return the number associated with that.
num, max_repeats = max(repeat_groups, key=lambda item: item[1])
if max_repeats >= 4:
return True, num
return False, None
If you run this function with print statements added you can get output like the following:
Matrix:
[[1 0 2 2 1 0 1]
[0 2 0 2 1 1 1]
[2 2 0 0 0 0 1]
[0 0 2 2 0 2 2]
[2 1 1 1 1 1 0]
[2 2 0 2 1 0 2]]
offset -2
diag [2 0 1 2]
repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]
num, max_repeats 2 1
offset -1
diag [0 2 2 1 1]
repeat_groups [(0, 1), (2, 2), (1, 2)]
num, max_repeats 2 2
offset 0
diag [1 2 0 2 1 0]
repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]
num, max_repeats 1 1
offset 1
diag [0 0 0 0 1 2]
repeat_groups [(0, 4), (1, 1), (2, 1)]
num, max_repeats 0 4
(True, 0)
There is at least one left to right diagonal: 0's' # Correct!
If you want to ignore diagonals of zeros, you can easily add an extra condition, e.g.
if max_repeats >= 4 and num != 0:
return True, num
You could try and recreate this without using numpy if you wanted.
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
add a comment |
Perhaps you are not getting the right answer because of the way you parsed your conditional statements.
You should have
if cond1 or cond2:
# do something
with the conditions contained in parentheses (). At the moment only your second condition is contained in parentheses.
Try the following:
if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1) or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
1
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
add a comment |
You may consider using numpy for this problem. Here goes some code to get you started.
import numpy as np
from itertools import groupby
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
if max([sum(1 for _ in g) for k, g in groupby(diag)]) >= 4:
return True, k
return False, None
# random test matrix
matrix = np.random.randint(0, 3, 6 * 7)
matrix = matrix.reshape(6,7)
# left to right check
resp_tuple = check_diagonals(matrix)
if resp_tuple[0]:
print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))
else:
# right to left
resp_tuple = check_diagonals(np.fliplr(matrix))
if resp_tuple[0]:
print("There is at least one right to left diagonal: {}'s'".format(resp_tuple[1]))
else:
# No diagonals
print('No diagonals')
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420933%2ffind-diagonals-in-a-python-matrix-using-lists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you consider the logic of your 'right-to-left' loop, you are actually just doing the same as your 'left-to-right' loop in reverse order. To really get the 'right-to-left' pass right you have to have your i and j indices moving in different directions.
So your conditional statement in this section should look like:
if i-3>=0 and j+3<7:
if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1) or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):
print("There is at least one right to left diagonal")
There are a ton of optimizations you could use by importing libraries like numpy or itertools as AResem showed. That answer is not entirely correct though for the following reason.
When you say return True, k you are not exercising any control over the value of k because it was used in the list comprehension just above and will just have the value of the last item it iterated over. So when your function finds a diagonal it reports the wrong number about two thirds of the time.
Here is an edited function that gives the correct results:
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
# Here you can create a tuple of numbers with the number of times they are repeated.
# This allows you to keep your k and g values associated.
repeat_groups = [(k, sum(1 for _ in g)) for k, g in groupby(diag)]
# By using the built-in max function with the 'key' keyword, you can find
# the maximum number of repeats and return the number associated with that.
num, max_repeats = max(repeat_groups, key=lambda item: item[1])
if max_repeats >= 4:
return True, num
return False, None
If you run this function with print statements added you can get output like the following:
Matrix:
[[1 0 2 2 1 0 1]
[0 2 0 2 1 1 1]
[2 2 0 0 0 0 1]
[0 0 2 2 0 2 2]
[2 1 1 1 1 1 0]
[2 2 0 2 1 0 2]]
offset -2
diag [2 0 1 2]
repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]
num, max_repeats 2 1
offset -1
diag [0 2 2 1 1]
repeat_groups [(0, 1), (2, 2), (1, 2)]
num, max_repeats 2 2
offset 0
diag [1 2 0 2 1 0]
repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]
num, max_repeats 1 1
offset 1
diag [0 0 0 0 1 2]
repeat_groups [(0, 4), (1, 1), (2, 1)]
num, max_repeats 0 4
(True, 0)
There is at least one left to right diagonal: 0's' # Correct!
If you want to ignore diagonals of zeros, you can easily add an extra condition, e.g.
if max_repeats >= 4 and num != 0:
return True, num
You could try and recreate this without using numpy if you wanted.
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
add a comment |
If you consider the logic of your 'right-to-left' loop, you are actually just doing the same as your 'left-to-right' loop in reverse order. To really get the 'right-to-left' pass right you have to have your i and j indices moving in different directions.
So your conditional statement in this section should look like:
if i-3>=0 and j+3<7:
if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1) or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):
print("There is at least one right to left diagonal")
There are a ton of optimizations you could use by importing libraries like numpy or itertools as AResem showed. That answer is not entirely correct though for the following reason.
When you say return True, k you are not exercising any control over the value of k because it was used in the list comprehension just above and will just have the value of the last item it iterated over. So when your function finds a diagonal it reports the wrong number about two thirds of the time.
Here is an edited function that gives the correct results:
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
# Here you can create a tuple of numbers with the number of times they are repeated.
# This allows you to keep your k and g values associated.
repeat_groups = [(k, sum(1 for _ in g)) for k, g in groupby(diag)]
# By using the built-in max function with the 'key' keyword, you can find
# the maximum number of repeats and return the number associated with that.
num, max_repeats = max(repeat_groups, key=lambda item: item[1])
if max_repeats >= 4:
return True, num
return False, None
If you run this function with print statements added you can get output like the following:
Matrix:
[[1 0 2 2 1 0 1]
[0 2 0 2 1 1 1]
[2 2 0 0 0 0 1]
[0 0 2 2 0 2 2]
[2 1 1 1 1 1 0]
[2 2 0 2 1 0 2]]
offset -2
diag [2 0 1 2]
repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]
num, max_repeats 2 1
offset -1
diag [0 2 2 1 1]
repeat_groups [(0, 1), (2, 2), (1, 2)]
num, max_repeats 2 2
offset 0
diag [1 2 0 2 1 0]
repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]
num, max_repeats 1 1
offset 1
diag [0 0 0 0 1 2]
repeat_groups [(0, 4), (1, 1), (2, 1)]
num, max_repeats 0 4
(True, 0)
There is at least one left to right diagonal: 0's' # Correct!
If you want to ignore diagonals of zeros, you can easily add an extra condition, e.g.
if max_repeats >= 4 and num != 0:
return True, num
You could try and recreate this without using numpy if you wanted.
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
add a comment |
If you consider the logic of your 'right-to-left' loop, you are actually just doing the same as your 'left-to-right' loop in reverse order. To really get the 'right-to-left' pass right you have to have your i and j indices moving in different directions.
So your conditional statement in this section should look like:
if i-3>=0 and j+3<7:
if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1) or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):
print("There is at least one right to left diagonal")
There are a ton of optimizations you could use by importing libraries like numpy or itertools as AResem showed. That answer is not entirely correct though for the following reason.
When you say return True, k you are not exercising any control over the value of k because it was used in the list comprehension just above and will just have the value of the last item it iterated over. So when your function finds a diagonal it reports the wrong number about two thirds of the time.
Here is an edited function that gives the correct results:
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
# Here you can create a tuple of numbers with the number of times they are repeated.
# This allows you to keep your k and g values associated.
repeat_groups = [(k, sum(1 for _ in g)) for k, g in groupby(diag)]
# By using the built-in max function with the 'key' keyword, you can find
# the maximum number of repeats and return the number associated with that.
num, max_repeats = max(repeat_groups, key=lambda item: item[1])
if max_repeats >= 4:
return True, num
return False, None
If you run this function with print statements added you can get output like the following:
Matrix:
[[1 0 2 2 1 0 1]
[0 2 0 2 1 1 1]
[2 2 0 0 0 0 1]
[0 0 2 2 0 2 2]
[2 1 1 1 1 1 0]
[2 2 0 2 1 0 2]]
offset -2
diag [2 0 1 2]
repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]
num, max_repeats 2 1
offset -1
diag [0 2 2 1 1]
repeat_groups [(0, 1), (2, 2), (1, 2)]
num, max_repeats 2 2
offset 0
diag [1 2 0 2 1 0]
repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]
num, max_repeats 1 1
offset 1
diag [0 0 0 0 1 2]
repeat_groups [(0, 4), (1, 1), (2, 1)]
num, max_repeats 0 4
(True, 0)
There is at least one left to right diagonal: 0's' # Correct!
If you want to ignore diagonals of zeros, you can easily add an extra condition, e.g.
if max_repeats >= 4 and num != 0:
return True, num
You could try and recreate this without using numpy if you wanted.
If you consider the logic of your 'right-to-left' loop, you are actually just doing the same as your 'left-to-right' loop in reverse order. To really get the 'right-to-left' pass right you have to have your i and j indices moving in different directions.
So your conditional statement in this section should look like:
if i-3>=0 and j+3<7:
if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1) or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):
print("There is at least one right to left diagonal")
There are a ton of optimizations you could use by importing libraries like numpy or itertools as AResem showed. That answer is not entirely correct though for the following reason.
When you say return True, k you are not exercising any control over the value of k because it was used in the list comprehension just above and will just have the value of the last item it iterated over. So when your function finds a diagonal it reports the wrong number about two thirds of the time.
Here is an edited function that gives the correct results:
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
# Here you can create a tuple of numbers with the number of times they are repeated.
# This allows you to keep your k and g values associated.
repeat_groups = [(k, sum(1 for _ in g)) for k, g in groupby(diag)]
# By using the built-in max function with the 'key' keyword, you can find
# the maximum number of repeats and return the number associated with that.
num, max_repeats = max(repeat_groups, key=lambda item: item[1])
if max_repeats >= 4:
return True, num
return False, None
If you run this function with print statements added you can get output like the following:
Matrix:
[[1 0 2 2 1 0 1]
[0 2 0 2 1 1 1]
[2 2 0 0 0 0 1]
[0 0 2 2 0 2 2]
[2 1 1 1 1 1 0]
[2 2 0 2 1 0 2]]
offset -2
diag [2 0 1 2]
repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]
num, max_repeats 2 1
offset -1
diag [0 2 2 1 1]
repeat_groups [(0, 1), (2, 2), (1, 2)]
num, max_repeats 2 2
offset 0
diag [1 2 0 2 1 0]
repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]
num, max_repeats 1 1
offset 1
diag [0 0 0 0 1 2]
repeat_groups [(0, 4), (1, 1), (2, 1)]
num, max_repeats 0 4
(True, 0)
There is at least one left to right diagonal: 0's' # Correct!
If you want to ignore diagonals of zeros, you can easily add an extra condition, e.g.
if max_repeats >= 4 and num != 0:
return True, num
You could try and recreate this without using numpy if you wanted.
edited Nov 22 '18 at 12:55
answered Nov 22 '18 at 10:09
berkelemberkelem
9632721
9632721
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
add a comment |
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
Thanks for ur help berkelem I really appreciate the time u spend helping me :)
– RiesenChicken
Nov 22 '18 at 14:37
add a comment |
Perhaps you are not getting the right answer because of the way you parsed your conditional statements.
You should have
if cond1 or cond2:
# do something
with the conditions contained in parentheses (). At the moment only your second condition is contained in parentheses.
Try the following:
if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1) or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
1
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
add a comment |
Perhaps you are not getting the right answer because of the way you parsed your conditional statements.
You should have
if cond1 or cond2:
# do something
with the conditions contained in parentheses (). At the moment only your second condition is contained in parentheses.
Try the following:
if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1) or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
1
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
add a comment |
Perhaps you are not getting the right answer because of the way you parsed your conditional statements.
You should have
if cond1 or cond2:
# do something
with the conditions contained in parentheses (). At the moment only your second condition is contained in parentheses.
Try the following:
if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1) or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
Perhaps you are not getting the right answer because of the way you parsed your conditional statements.
You should have
if cond1 or cond2:
# do something
with the conditions contained in parentheses (). At the moment only your second condition is contained in parentheses.
Try the following:
if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1) or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
answered Nov 21 '18 at 21:59
berkelemberkelem
9632721
9632721
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
1
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
add a comment |
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
1
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
I changed that and sometimes it says that there is a diagonal even if is not there.
– RiesenChicken
Nov 21 '18 at 22:08
1
1
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
Could you post more of your code? It should help pinpoint where the problem is. Otherwise we're just guessing where the problem might be.
– berkelem
Nov 21 '18 at 22:20
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
done, i really apreciate ur help
– RiesenChicken
Nov 22 '18 at 5:39
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
I posted another answer below. I initially copied the wrong code so you have a corrected version of AResem's answer as well as a correction for your own code.
– berkelem
Nov 22 '18 at 12:56
add a comment |
You may consider using numpy for this problem. Here goes some code to get you started.
import numpy as np
from itertools import groupby
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
if max([sum(1 for _ in g) for k, g in groupby(diag)]) >= 4:
return True, k
return False, None
# random test matrix
matrix = np.random.randint(0, 3, 6 * 7)
matrix = matrix.reshape(6,7)
# left to right check
resp_tuple = check_diagonals(matrix)
if resp_tuple[0]:
print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))
else:
# right to left
resp_tuple = check_diagonals(np.fliplr(matrix))
if resp_tuple[0]:
print("There is at least one right to left diagonal: {}'s'".format(resp_tuple[1]))
else:
# No diagonals
print('No diagonals')
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
add a comment |
You may consider using numpy for this problem. Here goes some code to get you started.
import numpy as np
from itertools import groupby
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
if max([sum(1 for _ in g) for k, g in groupby(diag)]) >= 4:
return True, k
return False, None
# random test matrix
matrix = np.random.randint(0, 3, 6 * 7)
matrix = matrix.reshape(6,7)
# left to right check
resp_tuple = check_diagonals(matrix)
if resp_tuple[0]:
print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))
else:
# right to left
resp_tuple = check_diagonals(np.fliplr(matrix))
if resp_tuple[0]:
print("There is at least one right to left diagonal: {}'s'".format(resp_tuple[1]))
else:
# No diagonals
print('No diagonals')
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
add a comment |
You may consider using numpy for this problem. Here goes some code to get you started.
import numpy as np
from itertools import groupby
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
if max([sum(1 for _ in g) for k, g in groupby(diag)]) >= 4:
return True, k
return False, None
# random test matrix
matrix = np.random.randint(0, 3, 6 * 7)
matrix = matrix.reshape(6,7)
# left to right check
resp_tuple = check_diagonals(matrix)
if resp_tuple[0]:
print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))
else:
# right to left
resp_tuple = check_diagonals(np.fliplr(matrix))
if resp_tuple[0]:
print("There is at least one right to left diagonal: {}'s'".format(resp_tuple[1]))
else:
# No diagonals
print('No diagonals')
You may consider using numpy for this problem. Here goes some code to get you started.
import numpy as np
from itertools import groupby
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
if max([sum(1 for _ in g) for k, g in groupby(diag)]) >= 4:
return True, k
return False, None
# random test matrix
matrix = np.random.randint(0, 3, 6 * 7)
matrix = matrix.reshape(6,7)
# left to right check
resp_tuple = check_diagonals(matrix)
if resp_tuple[0]:
print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))
else:
# right to left
resp_tuple = check_diagonals(np.fliplr(matrix))
if resp_tuple[0]:
print("There is at least one right to left diagonal: {}'s'".format(resp_tuple[1]))
else:
# No diagonals
print('No diagonals')
answered Nov 22 '18 at 0:19
AResemAResem
1114
1114
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
add a comment |
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
Thnak you, but, like I said using numpy is not an option because I'm new at coding and i must understand how to find it without the numpy function, only using lists. Thanks
– RiesenChicken
Nov 22 '18 at 5:27
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420933%2ffind-diagonals-in-a-python-matrix-using-lists%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Are you getting an error message? What is it?
– berkelem
Nov 21 '18 at 21:55
I'm not getting any error message, it says that there is a diagonal even if there is not a 4 ones or 2s diagonal.
– RiesenChicken
Nov 21 '18 at 22:10