Hi is it possible to run a for loop over my Matrix list?
I tried Matrix [o + for i in range 4], but it didn't work.
for i in range(col):
for o in range(row):
if Matrix[o][i] == "X" and Matrix[o + for i in range 4][i] == "X":
return True
Matrix[o + for i in range 4] is nonsensical. If your goal is to check that at least five symbols in a given "column" are equal to X, the solution is to count them up and compare:
for i in range(col):
# booleans have numeric value of 1/0 for True/False, so sum works on them
if sum(r[i] == 'X' for r in Matrix) >= 5:
return True
If there must be five such symbols in a row, the code is a little more complex (because iterating over slices of a list is annoying):
for i in range(col):
for o in range(row):
rows = Matrix[o:o+5] # Slice out five consecutive rows
# Check if given column in all five is X
if all(r[i] == 'X' for r in rows):
return True
This is slightly inefficient (in that it repeatedly slices and rechecks five elements at a time, even if we could know with certainty that such a run could not occur), but likely acceptable unless the code is in a hot loop and absolutely critical to performance. The only way you could get improved performance without complicating things would be if the matrix was guaranteed to contain exactly one character in each cell, in which case the code could simplify to:
for i in range(col):
# Get characters from each cell in column, join to single string
colstr = ''.join([r[i] for r in Matrix])
if 'XXXXX' in colstr: # Scan string once (pushes all work to C, should be fast)
return True
Related
The goal of my Python program is printing out a user-specified N^N board surrounded with +'s using a 2D array. To do that I first created a 2D list with N+2 lines and rows of +'s. Then using a nested for loop, I tried to replace the +'s with " " on indices 1 to N+1(not including) on each row except the first and the last rows, so that my code would print out a N^N board on the inside, surrounded with +'s. However I could not get my program to skip the first and last lines when erasing the +'s, despite excluding their indices in the 2D List in the nested for loop.
Thank you for your help in beforehand!
Here is my code.
This is the desired output (for N=5)
And this is the output of my code.
In your code, you do:
board =[['+'] * (N+2)] * (N+2)
This makes a list with N+2 references to the same list.
So everytime you change a 'middle square' to a white space inside your code(board[x][y] = " ") for a particular row x, you're infact actually changing all the tiles in the column y in your board to the white space simultaneously, since all the rows refer to but one list.
Instead, you should use something like this which actually creates (N+2) separate lists:
board =[['+'] * (N+2) for _ in range(N+2)]
This has also been explained in greater detail in this stackoverflow answer
Making the above change in the code results in the output you desire.
Although, it is a good practice to think of your own approaches & code it out when you're learning, but reading other people's code along with that will give you some hints towards multiple better approaches that you should eventually try to come up with. Here, are my two cents. Keeping it simple!
# board dimension
N = 5
# print board
def print_board(board):
for i in range(N):
for j in range(N):
print(board[i][j], end='')
print()
# declare & populate the board
board = []
for i in range(N):
row = []
for j in range(N):
row.append('+')
board.append(row)
# state of board initially
print_board(board)
print()
# Your logic of removing the plus sign, simply don't include the first & last
# row and column for converting into space
for i in range(1,N-1):
for j in range(1,N-1):
board[i][j] = ' '
print_board(board)
to make this pattern you can simply use for loops.
N = int(input())
for i in range(N+2):
for j in range(N+2):
if(i == 0 or i == N+1 or j == 0 or j == N+1):
print('+', end = '')
else:
print(' ', end = '')
print()
I wrote the following solution for the Leetcode question copied below:
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
Each of the digits 1-9 must occur exactly once in each row. Each of
the digits 1-9 must occur exactly once in each column. Each of the the
digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of
the grid. Empty cells are indicated by the character '.'.
Note:
The given board contain only digits 1-9 and the character '.'. You may
assume that the given Sudoku puzzle will have a single unique
solution. The given board size is always 9x9.
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
EMPTY_CELL = '.'
target = set(str(n) for n in range(1, 10))
def _validate():
cols = [[board[r][c] for r in range(9)] for c in range(9)]
boxes = []
for i in (0, 3, 6):
for j in (0, 3, 6):
boxes.append([board[a][b] for a in range(i, i + 3) for b in range(j, j + 3)])
valid_rows = all(set(row) == target for row in board)
valid_cols = valid_rows and all(set(col) == target for col in cols)
valid_boxes = valid_cols and all(set(box) == target for box in boxes)
return valid_boxes
def helper(r, c):
if c == len(board[0]):
return helper(r + 1, 0)
if r == len(board):
return _validate()
if not board[r][c] == EMPTY_CELL:
return helper(r, c + 1)
for n in range(1, 10):
board[r][c] = str(n)
if helper(r, c + 1):
return True
return False
helper(0, 0)
Here's my strategy in plain English. For every cell that is empty, I try placing a number in that cell, and recursing on the remainder of the board. If that doesn't lead to a valid solution, I backtrack, increment the number, and recurse having placed that number in the empty cell instead.
My validate function is returning False for everything, and I'm ending up with a board with 9's in the empty spaces. The problem guarantees that there IS a correct solution for every test case. I've walked through this code dozens of times and am unable to see what the issue is.
(I understand that I could use constraint propagation to speed up the solution, but the current problem isn't that my solution is too slow - it is that its incorrect).
Anyone see why? Also, in case this is unclear from the problem statement, each digit is supposed to be a string.
Your validate function will return true if you feed it a correct solution. You can verify this yourself by feeding it a solved sudoku board:
solved_text = '''435269781
682571493
197834562
826195347
374682915
951743628
519326874
248957136
763418259'''
solved_board = [ list(line) for line in solved_text.split('\n') ]
There are two problems. First, you do not actually search the complete space of solutions. If you print each complete board passed into _validate(), you will notice something odd: the whole board is always in lexical order! This is not the 10^81 set of possible boards. This can be fixed by simply omitting these two lines of code:
if not board[r][c] == EMPTY_CELL:
return helper(r, c + 1)
These are causing a problem because you mutate board state as a side affect as you go but do not clean-up (put back empty cells) while backtracking. You can simply omit those two lines (so that the algorithm in helper() never cares about what is to the right in the (r,c) lexical ordering) or by adding code to set board[r][c] = EMPTY_CELL when back-tracking.
The other problem is that because you only run validation on complete boards, and because your validation function can only check complete boards for correctness, your algorithm really will have to plow through all 10^81 possible boards before it finds a solution. This isn't just slow, it's completely intractable! Instead, you should rewrite your validation function so that it can validate a partial board. For example, if the first row is ['1', '1', '.', ..., '.'], it should return False, but if the first row is ['1', '2', '.', ..., '.'] it should return True because there are no problems so far. Obviously, you will also have to call _validate() at every step now, not just when the board is complete... but this is worth it because otherwise you will spend enormous amounts of time exploring boards which are obviously never going to work.
You will need to fix both problems before your algorithm will work.
You are not having a right validation! Your validation only works for the final solution. Unless you are trying to general all possible fill-outs for your sudoku, this validation do not give you any check (and always false).
The pseudo-code of what a backtracking algorithm in my mind is the following:
Scan from cell (0,0) up to cell (8,8), find an empty one
Test out options "1" to "9"
call validation on each option, if valid, recur to the scan line above
if failed validation, try other option
if exhaused all options "1" to "9", previous level of recursion is invalid, try another one
So the validation is not to check if all rows, columns, boxes have 1 to 9, but to check if they have no duplicate! In python code, it means len(x) == len(set(x)) for x the row, column, or box, which takes only "1" to "9" but not ".".
This is a practice problem I am solving:
Given a set S of distinct integers, print the size of a maximal subset S' of S where the sum of any 2 numbers in S' are not evenly divisible by k.
My approach was to limit the problem to the subset S[0...i] where 0 < i <= n-1 and determine the length of the maximal subset for that subproblem, then extend the subproblem by 1. I know there is a different approach to this problem but I am confused why my solution does not work.
ex) for n = 10, k = 5, and S = [770528134, 663501748, 384261537, 800309024, 103668401, 538539662, 385488901, 101262949, 557792122, 46058493]
dp = [0 for _ in range(n)]
dp[0] = 1
for i in range(1, n):
flag = 0
for j in range(i):
if s[j] == "#":
pass
elif (not s[j] == "#") and (s[j] + s[i])%k==0:
dp[i] = dp[i-1]
flag = 1
s[i] = "#"
break
if not flag == 1:
dp[i] = dp[i-1] + 1
print dp[-1]
The output should be 6 but my function prints 5. What I try to do is iterate from j=0 to i and check if for any j < i if (s[j] + s[i])%k==0. If so, then considering s[i] in S' would be erroneous so instead mark s[i] with a # to indicate it is not in S'.
Your lack of comments and explanatory names makes your code very hard to follow, so I do not understand it. (Your example using a list when you talk of sets, and the use of both s and S for your "set", do not help.) However, the basic idea of your algorithm is flawed: this problem for a given set cannot be solved by extending the solution for a proper subset.
For example, take k=3, set S=[1,4,2,5,8]. For the first three elements [1,4,2], the solution is [1,4]. For the first four elements [1,4,2,5], the solution is either [1,4] or [2,5]. For the entire set, the solution is [2,5,8]. You see there is no "path" from the solution from the first three elements through the first five: you need to "restart" at either the first four or the entire set.
A solution that does work partitions the entire set S into equivalence classes where the elements in each class have the same remainder when divided by k. Examining these equivalence classes gives the final result. Let me know if you need more details. Note that you will need to decide clearly if any 2 numbers in S' means any 2 distinct numbers in S': this changes what you do at one or two of the equivalence classes.
I have a list of numbers that represent the number of 1s in a row and I have an integer that represents the length of the entire sequence. So for example, if I get list [1, 2, 3] and length 8, then the only possible bit sequence is 10110111. But if the length was 9, I should get
010110111, 100110111, 101100111 and 101101110. I wonder if there is a simply pythonic way of doing this. My current method is
def genSeq(seq, length):
strSeq = [str(i) for i in seq]
strRep = strSeq + ["x" for i in xrange(length-sum(seq))]
perm = list(set(permutations(strRep)))
legalSeq = [seq for seq in perm if isLegal(seq) and [char for char in seq if char.isdigit()] == strSeq]
return [''.join(["1"*int(i) if i.isdigit() else "0" for i in seq]) for seq in legalSeq]
def isLegal(seq):
for i in xrange(len(seq)-1):
if seq[i].isdigit() and seq[i+1].isdigit(): return False
return True
print genSeq([1, 2, 3], 9)
My approach is as follows:
Figure out how many zeros will appear in the result sequences, by doing the appropriate arithmetic. We'll call this value n, and call the length of the input list k.
Now, imagine that we write out the n zeros for a given result sequence in a row. To create a valid sequence, we need to choose k places where we'll insert the appropriate number of ones, and we have n + 1 choices of where to do so - in between any two digits, or at the beginning or end. So we can use itertools.combinations to give us all the possible position-groups, asking it to choose k values from 0 up to n, inclusive.
Given a combination of ones-positions, in ascending order, we can figure out how many zeroes appear before the first group of ones (it's the first value from the combination), the second (it's the difference between the first two values from the combination), etc. As we iterate, we need to alternate between groups of zeros (the first and/or last of these might be empty) and groups of ones; so there is one more group of zeros than of ones, in general - but we can clean that up by adding a "dummy" zero-length group of ones to the end. We also need to get "overlapping" differences from the ones-positions; fortunately there's a trick for this.
This part is tricky when put all together; I'll write a helper function for it, first:
def make_sequence(one_positions, zero_count, one_group_sizes):
zero_group_sizes = [
end - begin
for begin, end in zip((0,) + one_positions, one_positions + (zero_count,))
]
return ''.join(
'0' * z + '1' * o
for z, o in zip(zero_group_sizes, one_group_sizes + [0])
)
Now we can get back to the iteration over all possible sequences:
def generate_sequences(one_group_sizes, length):
zero_count = length - sum(one_group_sizes)
for one_positions in itertools.combinations(
range(zero_count + 1), len(one_group_sizes)
):
yield make_sequence(one_positions, zero_count, one_group_sizes)
Which we could of course then fold back into a single function, but maybe you'll agree with me that it's better to keep something this clever in more manageable pieces :)
This is more fragile than I'd like - the one_positions and one_group_sizes sequences need to be "padded" to make things work, which in turn requires assuming their type. one_positions will be a tuple because that's what itertools.combinations produces, but I've hard-coded the assumption that the user-supplied one_group_sizes will be a list. There are ways around that but I'm a little exhausted at the moment :)
Anyway, the test:
>>> list(generate_sequences([1,2,3], 9))
['101101110', '101100111', '100110111', '010110111']
>>> list(generate_sequences([1,1,1], 9))
['101010000', '101001000', '101000100', '101000010', '101000001', '100101000', '
100100100', '100100010', '100100001', '100010100', '100010010', '100010001', '10
0001010', '100001001', '100000101', '010101000', '010100100', '010100010', '0101
00001', '010010100', '010010010', '010010001', '010001010', '010001001', '010000
101', '001010100', '001010010', '001010001', '001001010', '001001001', '00100010
1', '000101010', '000101001', '000100101', '000010101']
I'm trying to make a Sudoku solver, and at the moment I'm making the part which checks if it has been solved, but I've got abit stuck. The grid is made of a list of 81 numbers (9*9), and then I have dictionaries which group them into rows, columns and boxes, eg:
self.rows = {'toptop':self.board[0:9],'topmid':self.board[9:18],'topbottom':self.board[18:27],
'midtop':self.board[27:36],'midmid':self.board[36:45],'midbottom':self.board[45:54]
,
The bit that I'm stuck with is checking whether each row, or column or box have numbers 1-9 in them. I've experimented abit and tried
self.winning = [1,2,3,4,5,6,7,8,9]
[x for x in self.rows.values() if (x == y for y in self.winning)]
But that just returned every value grouped into rows. I also tried variations to this, and some would return the lists which had numbers 1-9 in, but they often had duplicates; they would never show the lists with 1-9 exclusively. How could I achieve this? Thanks
It is hard to tell from what little code you have posted exactly where your problem lies, or what to change in order to make it work, but based on your question title and the information that you provided (that you are solving Sudoku) I can say that the following will help you.
In order to compare that items in a list are or aren't in another list, we have to determine the scope.
Let us say we have two lists, A and B.
A == B
# lists are in the same order with the same items.
all(a in B for a in A)
# all items in A are in B. (order not checked)
all(b in A for b in B)
# all items in B are in A. (order not checked)
all(A[i] == B[i] for i in range(len(A)))
# all items in A are in B. (order checked) (len(A) <= len(B))
all(B[i] == A[i] for i in range(len(B)))
# all items in B are in A. (order checked) (len(B) <= len(A))
This is a generator you can use on lists of equal length to check on what indices they are True/False
def gen_diff(A, B):
if len(A) != len(B):
raise IndexError('lists not of same length')
for i in range(len(A)):
if A[i] == B[i]:
yield (True, i)
else:
yield (False, i)
I don't think you can compare lists with ==, but something like this should work:
len(x)==len(y) and all(x[i] == y[i] for i in range(len(x)-1))