Indentation Style in Python : Reverse Words Function - python
def is_reverse(word1, word2):
if len(word1) != len(word2):
return False
i = 0
j = len(word2)
while j > 0:
if word1[i] != word2[j]:
return False
i = i+1
j = j-1
return True
is_reverse('pots', 'stop')
I had defined above function to check two given words reversely match to each other.
but when I run it, it keeps reminding me of indentation error.
How to gauge the indentation level in python?
You can look the Indentation Section in PEP8:
In general
Use 4 spaces per indentation level.
(don't mix tabs and spaces).
When you start the body of a new block (e.g., in your if and `while), keep the body indented 4 spaces relative to the line introducing the block.
So when you write
if len(word1) != len(word2):
...
...
Everything that should happen if the condition occurred, should have 4 spaces relative to the if, for example. If there's another if, or while inside, you increase its body's indent 4 spaces further, and so on.
As a side note, note that you can check if two words are reverse matches of each other with
def is_reverse(word1, word2):
return word1 == reversed(word2)
Indentation matters in python, because it defines which code belongs together (which is done e.g. with brackets in other languages).
Because your code is heavily malformed, please have a look at the reformatted code:
def is_reverse(word1, word2):
if len(word1) != len(word2):
return False
i = 0
j = len(word2)-1
while j >= 0:
if word1[i] != word2[j]:
return False
i = i+1
j = j-1
return True
is_reverse('pots', 'stop')
-> True
Notice I also changed j = len(word2)-1 and while j >= 0:, since a word of length x has letters in positions 0..x-1.
Hint: string reversal can be achieved with slicing notation and a step size of -1:
"pots"[::-1] == "stop"
General rule is 4 space indentation.
Below is an example of proper indentation, without changes to the original code:
def is_reverse(word1, word2):
if len(word1) != len(word2):
return False
i = 0
j = len(word2)
while j > 0:
if word1[i] != word2[j]:
return False
i = i+1
j = j-1
return True
The number of spaces used for an indentation level in python is not syntactically important, it can be any arbitrary number (in most cases 2, 4 or 8 spaces are used per level), but it has to be consistent. So after an if block, you have to return to the same indentation level you had before, like this:
def is_reverse(word1, word2):
if len(word1) != len(word2):
return False
i = 0
j = len(word2)
while j > 0:
if word1[i] != word2[j]:
return False
i = i+1
j = j-1
return True
is_reverse('pots', 'stop')
This code won't throw an IndentationError. Of course, for stylistic reasons, it's good to have a constant indentation level, like this:
def is_reverse(word1, word2):
if len(word1) != len(word2):
return False
i = 0
j = len(word2)
while j > 0:
if word1[i] != word2[j]:
return False
i = i+1
j = j-1
return True
is_reverse('pots', 'stop')
Your code also has a logical error, as the starting value of j should be 1 less than the length of the string (due to zero-based indexing), and go down all the way to 0, like this:
i = 0
j = len(word2) - 1
while j >= 0:
if word1[i] != word2[j]:
return False
i = i+1
j = j-1
Related
Why is it not return any sequence within the string?
So for this code I want to input any string and I want it to return true if there's a sequence of 3 same consecutive characters in n. This code works however, it only counts the first three consecutive numbers in n, but I want it to count any sequence in n. def consec(n): for i in range(len(n)): if n[i] == n[i+1] == n[i+2]: return True else: return False eg: if consec("AAABC") it prints true but if consec("ABCCC") it prints false even though there are 3 consecutive characters, they just happen to be later in the string. What should I change about this code ? Thanks,
You can use regex to extract 3 or more consecutive characters: import re def check_string(text): if re.findall(r'(\w)\1\1+', text): return True else: return False
There are two problems in your code. Currently it only checks the first 3 letters because of the range being between 0 and 1. If you do some print debugging with print(n[i], n[i + 1], n[i + 2]) you will see that consec("ABCCC") will only print A B C. The second problem is that if you fix the above mentioned problem it will still only check the first 3 letters. This is because if the "if n[i]....." isn't True, it will not go to another iteration of the for loop. Instead it will return False. This you can fix by making the function only return False if it doesnt find 3 consecutive letters in any iteration. Im assuming this is homework so the I'm not providing working code, good luck!
your for loop only iterates one time that's why you are getting incorrect responses? Try like this: def consec(n): result = False for i in range(len(n)): if result: return result if n[i] == n[i + 1] == n[i + 2]: result = True else: result = False return result By this the loop will only stop if there are consecutive 3 characters or all characters are already iterated.
Move return False to outside of the loop and check reversely from the last index to avoid index error: def consec(n): for i in range(len(n)): if n[i] == n[i-1] == n[i-2]: return True return False Or add -2 in range(len(n): def consec(n): for i in range(len(n)-2): if n[i] == n[i+1] == n[i+2]: return True return False You can also use any(): def consec(n): return any(n[i] == n[i-1] == n[i-2] for i in range(len(n))) Or def consec(n): return any(n[i] == n[i+1] == n[i+2] for i in range(len(n)-2))
If else statements without else
I came across the question -- 916. Word Subsets on LeetCode and I found it confusing on the usage of if-else statements. My code is as below: class Solution: def wordSubsets(self, words1: List[str], words2: List[str]) -> List[str]: Bfreq, ans, cmax = {}, [], 0 for word in words2: for i in word: count = word.count(i) if i in Bfreq: diff = count - Bfreq[i] if diff > 0: cmax += diff if cmax > 10: return ans Bfreq[i] = count else: cmax += count Bfreq[i] = count for word in words1: if len(word) < cmax: continue for i in Bfreq: if word.count(i) < Bfreq[i]: break ans.append(word) return ans However the output was incorrect until I added the else statement on the second last line as belows: else: ans.append(word) return ans I do not understand why the else statement affects the output. How does it actually affect the logic of my code? Thanks
is_reverse "second" error in Think Python
There is an is_reverse program in Think Python as follows: def is_reverse(word1, word2): if len(word1) != len(word2): return False i = 0 j = len(word2) - 1 while j > 0: print(i, j) if word1[i] != word2[j]: return False i = i + 1 j = j - 1 return True The author asks to figure out an error in it which I am unable to after much brainstorming. The program works just fine and returns this: 0 3 1 2 2 1 True The error pertains to this output. Please help me figure it out.
Change the while condition in is_reverse method to - while j >= 0:
The function suppose to check if word1 is reserve of word2 (I think, please post what you expect the function to do next time) The function does not check final word and beginning word. It does not check word1[-1] (last character) and word2[0] (first character) w1 = 'Dogx' w2 = 'ggoD' print (is_reverse(w1, w2)) The problem is here: while j > 0: The loop terminate before checking word2[0]. I suggest add =. THus, change the condition to: while j >= 0:
Maybe the indentation is incorrect? Would not error if it was this: def is_reverse(word1, word2): if len(word1) != len(word2): return False i = 0 j = len(word2) - 1 while j > 0: print(i, j) if word1[i] != word2[j]: return False i = i + 1 j = j - 1 return True I would write this function like this: def is_reverse(word1, word2): return word1[::-1] == word2 But neither of these functions deal with uppercase to lowercase comparisons. I'm not sure how you want to handle that.
def is_reverse(word3, word4): if len(word3) != len(word4): return False iii = 0 j = len(word4)-1 while j >= 0: print(iii, j) print(word3[iii], word4[j]) print("----------------") if word3[iii] != word4[j]: return False iii += 1 print("j printed", j) j -= 1 is_reverse("spot","tops")
Errors trying to find only the number in a string?
Supposed to take in a string for example "Maroon 5" and then return only the number in the statement. In this case it's "5" but I just get no output. Thank you! def findNumbers(str): found1 = False found2 = False i = 0 while not found1 and i<len(str): if str[i] in "0123456789": found1 = True else: i = i + 1 if found1: j = 0 while not found2 and j<len(str): if str[j] in "0123456789": found2 = False else: j = j + 1 else: return 0 istr = str[i:j] n = (istr) return n print (findNumbers("Maroon 5"))
You have two important errors in your code. One is that once you've found a digit, you jump back to the start of the string: j = 0 Instead, you want to continue from there: j = i The other, bigger problem is that you have an infinite loop. The second loop may continue indefinitely if str[j] is a digit, since setting found2 to False does not end the loop. The code should be while not found2 and j<len(str): if str[j] not in "0123456789": found2 = True else: j = j + 1
you can do it like this: def findNumbers(str): for i in range(0,len(str)): if (str[i].isdigit()): print str[i] findNumbers("Maroon 5") It should print the number 5
You can try this way: This will return a list of tuples with the numbers and their indexes def findNumbers(string): num = '1234567890' return ([(string[x], x) for x in range(len(string)) if string[x] in num])
Sudoku Checker in Python
I am trying to create a sudoku checker in python: ill_formed = [[5,3,4,6,7,8,9,1,2], [6,7,2,1,9,5,3,4,8], [1,9,8,3,4,2,5,6,7], [8,5,9,7,6,1,4,2,3], [4,2,6,8,5,3,7,9], # <--- [7,1,3,9,2,4,8,5,6], [9,6,1,5,3,7,2,8,4], [2,8,7,4,1,9,6,3,5], [3,4,5,2,8,6,1,7,9]] easy = [[2,9,0,0,0,0,0,7,0], [3,0,6,0,0,8,4,0,0], [8,0,0,0,4,0,0,0,2], [0,2,0,0,3,1,0,0,7], [0,0,0,0,8,0,0,0,0], [1,0,0,9,5,0,0,6,0], [7,0,0,0,9,0,0,0,1], [0,0,1,2,0,0,3,0,6], [0,3,0,0,0,0,0,5,9]] I am expecting input like that- a list of 9 lists. The zeros represent number that have not been filled in by the user. They can appear multiple times in a row, column or 3x3. def check_sudoku(grid): if len(grid) == 9: numsinrow = 0 for i in range(9): if len(grid[i]) == 9: numsinrow += 1 if numsinrow == 9: for i in range(9): rowoccurence = [0,0,0,0,0,0,0,0,0,0] for j in range(9): rowoccurence[grid[i][j]] += 1 temprow = rowoccurence[1:10] if temprow == [1,1,1,1,1,1,1,1,1]: return True else: return False else: return False else: return False I obviously need to check that there is a 9x9 list of lists (grid), and that there are no duplicates in each row, column and 3x3 small square. In the code, I first check to see if there are a proper number of rows (There should be 9). Then I check that each row has 9 elements in it (with the ill_formed example you see that this is not the case). I then attempt to check duplicates in each row but I am having some trouble doing so. I thought that I could loop over each row and loop over each element in that row, and add 1 to a list of ints (rowoccurence). For example, if the first number is a 2, then rowoccurence[2] should be equal to 1. The zeros are in rowoccurence[0] and are not checked(I have a temporary list which should take everything except that first element- the zeros- because there could be more than 1 zero in a row and the grid could still be legit). I try to check the temp list (basically rowoccurence) against a reference list of correct values but it does not seem to be working. Could you help me check the rows for duplicates in this sudoku checker? Thank you so much in advance!
Remember, you're not searching for duplicates -- merely nonzero duplicates. Summing a set works for this. You can also check the legality of the row/column at the same time: def sudoku_ok(line): return (len(line) == 9 and sum(line) == sum(set(line))) def check_sudoku(grid): bad_rows = [row for row in grid if not sudoku_ok(row)] grid = list(zip(*grid)) bad_cols = [col for col in grid if not sudoku_ok(col)] squares = [] for i in range(9, step=3): for j in range(9, step=3): square = list(itertools.chain(row[j:j+3] for row in grid[i:i+3])) squares.append(square) bad_squares = [square for square in squares if not sudoku_ok(square)] return not (bad_rows or bad_cols or bad_squares)
You return True too early, so you never make it to the test you hope to see fail: if temprow == [1,1,1,1,1,1,1,1,1]: return True # <-- this is the culprit else: return False Misc other notes: one easy way to make sure that all elements of some vector are equal to some constant is: all(i == const for i in vector) Another, even easier: if vec[1:10] are all 1, then sum(vec[1:10]) must be 9. (bad idea, see comment below.)
I am only posting this because most other solutions are hardly readable though they might be really efficient. For someone who is new and just trying to learn I believe that the code below is helpful and very readable. Hope this helps anyone looking to learn how to create a sudoku checker. def check_sudoku(grid): for row in range(len(grid)): for col in range(len(grid)): # check value is an int if grid[row][col] < 1 or type(grid[row][col]) is not type(1): return False # check value is within 1 through n. # for example a 2x2 grid should not have the value 8 in it elif grid[row][col] > len(grid): return False # check the rows for row in grid: if sorted(list(set(row))) != sorted(row): return False # check the cols cols = [] for col in range(len(grid)): for row in grid: cols += [row[col]] # set will get unique values, its converted to list so you can compare # it's sorted so the comparison is done correctly. if sorted(list(set(cols))) != sorted(cols): return False cols = [] # if you get past all the false checks return True return True
Took reference from #llb 's answer, which did not check for missing values or zeros, here's my solution which would work for negative values, zeros and missing values def line_ok(e): if len(set(e)) != 9: return False for i in range(len(e)): if e[i] not in range(1,10): return False return True def checker(grid): bad_rows = [False for row in grid if not line_ok(row)] grid = list(zip(*grid)) bad_cols = [False for col in grid if not line_ok(col)] squares = [] for i in range(0,9,3): for j in range(0,9,3): square = list(itertools.chain.from_iterable(row[j:j+3] for row in grid[i:i+3])) squares.append(square) bad_squares = [False for sq in squares if not line_ok(sq)] return not any([bad_rows, bad_cols, bad_squares]) print(checker(sudoku_correct)) PS: Due to less reps, couldn't comment. Hope whoever needs it, finds it :)
Define a function to verify that there are no duplicates, then you can use it to check rows, columns, and 3x3 grids. You can reduce the nested blocks by returning early if some condition is not met, for example, number of rows are larger than 9. And only return true at the very end of the function if none of the checks fail. from collections import Counter def check_dups(l): counts = Counter() for cell in l: if cell != 0: counts[cell] += 1 if cell > 9 or counts[cell] > 1: return False return True def check_sudoku(grid): if len(grid) != 9: return False if sum(len(row) == 9 for row in grid) != 9: return False for row in grid: if not check_dups(row): return False return True
I think the reason your code collapse is because your indent. You should do: for j in range(9): rowoccurence[grid[i][j]] += 1 temprow = rowoccurence[1:10] if temprow == [1,1,1,1,1,1,1,1,1]: return True else: return False Rather than: for j in range(9): rowoccurence[grid[i][j]] += 1 temprow = rowoccurence[1:10] if temprow == [1,1,1,1,1,1,1,1,1]: return True else: return False Or use Counter: from collections import Counter ... if numsinrow == 9: for i in range(9): count = Counter(grid[i]) return False if max(count.values()) > 1 else True
valid_solution= lambda board: not any([sorted(row)!=list(range(1,10)) for row in board]) and not any([sorted(list(col))!=list(range(1,10)) for col in zip(*board)]) and not any([sorted(board[i][j:j+3]+board[i+1][j:j+3]+board[i+2][j:j+3]) !=list(range(1,10)) for i in range(0,9,3) for j in range(0,9,3)])
import numpy as np def is_valid(row): # checks whether a given set of values forms a valid row in sudoku return len(list(filter(lambda val: type(val) == int and 0 < val < 10, set(row))) == 9 def check_sudoku(grid): """ Check a sudoku board is correctly completed or not. """ # checks whether the grid has 9 rows if len(grid) != 9: return False # checks whether the grid has 9 columns for i in range(9): if len(grid[i]) != 9: return False # turns grid from list to numpy array grid = np.array(grid) # checks whether the grid is filled with integers if grid.dtype != np.int: return False for i in range(9): # checks for repetition in rows if not is_valid(grid[i, :]): return False # checks for repetition in columns if not is_valid(grid[:, i]): return False # checks for repetition in squares if not is_valid(grid[i//3*3:i//3*3+3, j%3*3:j%3*3+3]): return False # returns true if none of the conditions reached return True
How about just checking each row/column with: sorted(row) == range(1,10) or for python 3 sorted(row) == list(range(1,10)) I imagine the running time is dominated by creating a new list (whether you do the histogram approach or the sorting approach) so the extra factor of log(n) shouldn't be noticeable In order to check each row,column, and subsquare, I suggest having extractor methods that get the nth row, column, and subsquare from your matrix (ie don't try and put it all in one method). So for instance: getSubSquare(m, i): subrow = (i // 3) * 3 subcol = (i % 3) * 3 v = [0] * 9 for j in range(9): subrj = j // 3 subcj = j % 3 v[j] = m[subrow + subrj][subcol + subcj] return v getRow(m,i): return m[i] getCol(m,i): return [m[j][i] for j in range(9)]
def check_sudoku(grid): if len(grid) == 9: numsinrow = 0 for i in range(9): if len(grid[i]) == 9: numsinrow += 1 if numsinrow == 9: if checkrow(grid): if checkcol(grid): return True else: return False else: return False else: return False else: return False def checkrow(grid): for i in range(9): rowoccurence = [0,0,0,0,0,0,0,0,0,0] for j in range(9): rowoccurence[grid[i][j]] += 1 temprow = rowoccurence[1:10] for q in range(9): if temprow[q] == 1 or temprow[q] == 0: continue else: return False return True def checkcol(grid): for num in range(9): coloccurence = [0,0,0,0,0,0,0,0,0,0] for i in range(9): coloccurence[grid[i][num]] += 1 tempcol = coloccurence[1:10] for q in range(9): if tempcol[q] == 1 or tempcol[q] == 0: continue else: return False return True Ok guys I am back with a function to check the rows which works. Thank you so much for all the extensive help. I am sort of a noob at this so I did not understand some answers but I realized that I was returning true way too early. I also realized that if there were multiple zeros in a row, then some numbers would not come up in the rowoccurence/temp list. This is why I had to check for both 1's and 0's in the rowoccurence/temp list. I have also written a similar function to check the columns. Thanks again!
If you want to check a row for duplicates, instead of rowoccurence = [0,0,0,0,0,0,0,0,0,0] for j in range(9): rowoccurence[grid[i][j]] += 1 temprow = rowoccurence[1:10] if temprow == [1,1,1,1,1,1,1,1,1]: return True else: return False count: b = True for i in range(9): grid[i].count(grid[i][j]) > 1: b = False return b Your approach does a bit more than just duplicate checking, it also takes care that only one digit number are present otherwise an out of bound exception will be raised
Wrote up a simple class to model a (completed) Sudoku board. Nothing tricky but a simple solution for a 9x9 board. class SudokuBoard(object): DIGITS = set(range(1, 10)) def __init__(self, values): self.values = values def row(self, n): return self.values[n] def rows(self): return self.values def cols(self): return [self.col(i) for i in xrange(9)] def col(self, n): return [self.values[i][n] for i in xrange(len(self.values))] def groups(self): return [self.group(i) for i in xrange(9)] def group(self, n): start_r = (n / 3) * 3 start_c = n * 3 % 9 values = [] for row in xrange(start_r, start_r + 3): for col in xrange(start_c, start_c + 3): values.append(self.values[row][col]) return values def is_correct(self): for row in self.rows(): if self.DIGITS - set(row): return False for col in self.cols(): if self.DIGITS - set(col): return False for group in self.groups(): if self.DIGITS - set(group): return False return True
I wrote the code on https://github.com/loghmanb/daily-coding-problem from collections import defaultdict def solution_valid(board) #check row and column is distict no or not?! rows = defaultdict(int) columns = defaultdict(int) squares = defaultdict(int) for i in range(9): rows.clear() columns.clear() squares.clear() for j in range(9): if board[i][j] is not None: columns[board[i][j]] += 1 if columns[board[i][j]]>1: return False if board[j][i] is not None: rows[board[j][i]] += 1 if rows[board[j][i]]>1: return False new_j = (i*3 + j%3)%9 new_i = (i//3)*3 + j//3 if squares[board[new_i][new_j]] is not None: squares[board[new_i][new_j]] += 1 if squares[board[new_i][new_j]]>1: return False return True
The question is old, but I leave a new contribution for others who come here, like me. Correct me if I'm wrong, but I think the solution is quite simple. No need to check for duplicates in row, column and grid. Just check the row. Because if there are duplicates in the column or in the grid, there will also be duplicates in the row. So I think it's enough to check for 0 and duplicates on the row: from collections import Counter solved = True for row in board: if max(Counter(row).values()) > 1: solved = False elif 0 in row: solved = False