how to check for square condition in sudoku - python

I am a beginner and wrote a small script for playing sudoku
I was able to check for the row and column conditions but i need little help to check for square condition i.e there should be only one unique digit in a 3x3 square
Also i would be grateful if anyone would help me to reduce the size of the conditions and can please explain me how to create a random sudoku board generating random numbers as i have taken a static board in
tf()
Also i want to make GUI version for it so please recommend me a way to do it.
Thanks in advance
following is the code link is available here https://drive.google.com/file/d/0B0mzB3WBm-8-VzJua1BLakExajQ/view?usp=sharing
board=[[5,7,3,6,9,4,2,1,8],[9,2,4,7,8,1,3,5,'X'],['X',1,6,3,5,'X',7,9,4],[3,8,5,4,2,7,9,6,1],[1,9,2,5,3,6,8,4,7],[4,6,7,9,1,8,5,2,3],[7,3,1,'X',4,5,6,8,'X'],
['X',5,8,1,7,9,4,3,2],[2,4,9,8,6,3,'X',7,5]]#simple sudoku board for testing
def initiator():#print the board and start redirect to the funtion
for i in range(0,9):
print str(board[i])+"\n"
rc_checker()
def find_xs():#find whether there are any remaining spaces to fill
count = 0
for i in range(0,9):
for j in range(0,9):
if board[i][j] == 'X':
count+=1
if count>0:
return 1
else:
for i in range(0,9):
print str(board[i])+"\n"
print "Thanks for playing"
def rc_checker():#checks whether inputted row and column are valid
if find_xs()==1:
for i in range(0,9):
print str(board[i])+"\n"
print "Give the row and column"
r = int(input())
c = int(input())
if r<10 and c<10:
r=r-1
c-=1
validator(r,c)
def validator(r,c):#validate whether the field is empty and redirects accordingly
if board[r][c]=='X':
print "Enter the value"
val = int(input())
if val>0 and val <10:
tf(r,c,val)
rc_checker()
else:
print "The feild is not empty please try again"
rc_checker()
def tf(r,c,val):#checking if the inputted value is repeated in corresponding row or column
i = 0
r1 = 0
c1 = 0
if val!=board[r][i] and val!=board[r][i+1] and val!=board[r][i+2] and val!=board[r][i+3] and val!=board[r][i+4] and val!=board[r][i+5] and val!=board[r][i+6] and val!=board[r][i+7] and val!=board[r][i+8] and val!=board[r1][c] and val!=board[r1+1][c] and val!=board[r1+2][c] and val!=board[r1+3][c] and val!=board[r1+4][c] and val!=board[r1+5][c] and val!=board[r1+6][c] and val!=board[r1+7][c] and val!=board[r1+8][c]:
print "Value entered is correct"
board[r][c]=val#value is set
else:
print "Invalid value Retry"
board[r][c]='X'
def main():#welcome message
print "Welcome to sudoku game"
print "Fill all 'X' with valid input"
initiator()
main()

Questions you asked:
1. How to check for squares?
2. How to reduce the size of the conditions?
3. How to generate random numbers?
4. How to make a GUI version?
Answers.
1. and 2.
First, one simple way to check these kind of conditions is:
val = 6
my_list = [2, 4, 3, 1, 'X', 7, 8, 9, 5] # this might be your row for example
if val in my_list:
print 'Invalid value Retry'
else:
print 'Value entered is correct'
Depending on the case you have to construct my_list differently:
get the list for the row
r = 3
my_list = board[r]
get the list for the column
c = 4
my_list = [row[4] for row in board]
get the list for the square
# where the squares are numbered as follows:
# 0 1 2
# 3 4 5
# 6 7 8
s = 3 # second row, first column
r = int(s/3) # r = 1
c = s%3 # c = 0
my_list = [element for row in board[r*3:r*3+3]
for element in row[c*3:c*3+3]]
Here I used 2 important features:
list comprehension
list slicing
Make sure to understand them as they are really useful.
3.
You may use the function randint
import random
random.randint(0,8) # random integer in range [0, 8], including both end points.
4.
There are many ways to do it and I don't have enough experience to tell you about. Personally I liked a lot this tutorial. It might be useful, if you want to program a simple game with GUI. Before starting a project with GUI, my advice is to learn classes.

Related

Python code not displaying the list values each in a new line no matter how hard I try

I've written a code which works pretty well, no errors, no problems. But no matter how hard I try to print the list values each in a new line, it still wouldn't work. I've tried sep='\n', and even tried to put the list in a loop to print each value one by one. I still get the result printed all in a row, in one line. This sounds too annoying and I can't figure out why my code is having this strange behavior. Here's my code:
length = int(input())
input_string = [int(y) for y in input().split()]
def lowest(string):
return(min(x for x in string if x is not None))
def none_set(string):
for k in range(length):
if string[k] != None:
if string[k] <=0:
string[k] = None
def counter(string):
nums = 0
for h in range(length):
if string[h] != None:
nums += 1
return nums
cnt = []
for i in range(length):
minimum = lowest(input_string)
none_set(input_string)
cnt.append(counter(input_string))
for j in range(length):
if input_string[j] != None:
input_string[j] -= minimum
result = list(set(cnt))[::-1]
print(result, sep='\n') #Doesn't print the values in new line :/
Sample Input:
6
5 4 4 2 2 8
Expected Output:
6
4
2
1
The Output I Get:
[6, 4, 2, 1]
In case you want to know what exactly my code does, check this link here (No login/signup needed), however, the issue is not really relative to what the goal of my code is, I'd say.
I appreciate in advance, for any tip, solution, or help.
It's because you're printing the whole list.
lst = ['a','b','c']
If I print this list I get ['a','b','c']. To print each item you can use a for loop like so:
lst = ['a','b','c']
for item in lst:
print(item)
#output:
a
b
c
Try this.
for i in result:
print(i)
Try to print like that:
for i in result:
print(i)
Use join() instead of multiple calls to print(). Some will consider it more difficult to read, but it's definitely more efficient even for small lists, and orders of magnitude faster for lists greater than 100 elements.
print("\n".join(map(str, result)))

Trying create a matrix for sudoku with random numbers in Python

I need to create a sudoku template, with it all filled. I need to do with random numbers, so I check if the number already exists in the row and in the column. The problem is that when a number is repeated in the column, it does not try another one, getting an infinite loop. Can Someone help me? Remembering that I am required to do with random numbers.
import random
matrix = [[None for i in range(9)] for j in range(9)]
def criarSdk():
for l in range(9):
for c in range(9):
if matrix[l][c] is None:
tmp3 = False
print("linha l={}, coluna c={}".format(l,c))
while tmp3 is False:
ale = random.randint(1, 9)
tmp1 = veriLine(matrix,ale, l)
tmp2 = veriCol(matrix,ale, c)
tmp3 = tmp1 and tmp2
if tmp3 is True:
matrix[l][c] = ale
def veriLine(vetor, value, line):
tmp = True
for c in range(9):
if value == vetor[line][c]:
tmp = False
return tmp
def veriCol(vetor, value, col):
tmp = True
for l in range(9):
if value == vetor[l][col]:
tmp = False
return tmp
criarSdk()
for i in range(9):
print(matrix[i])
Your problem is not with the code, but with your algorithm.
If you fill up a sudoku like this, you can end up in a situation where no digit can be filled in for some space.
Consider this:
1 2 3 4 5 6 7 8 9
2 1 5 3 4 7 8 6 x
You can imagine the first line getting filled with random values (which happen to be in order) and then the values on the second line also getting filled in with random values, but what value to put in x? You can't put in 9, because it would conflict on the column. But you can't put in anything else either, since everything else is already on the line.
In this case, your code will loop endlessly, trying random numbers, but none of them will ever work.
You need to look into backtracking and come up with a better solution. Note that your requirement for randomly picking a number doesn't have to mean you keep calling random.randint() for a new option, you could also randomly pick from a set of numbers you haven't tried yet.

How to find elements in one arbitrary list that occur in another list (preserving their order)?

I need to create an algorithm which would read user input of lists A and B and determine whether elements from list B occur in list A (if they occur, program needs to print 'Yes', and 'No' otherwise').
I have come up with the following code which should can be a starting point:
n=int(input('Enter the length of list A '))
A=[]
for i in range (0,n):
InpEl=int(input('Enter the elements '))
A.append(InpEl)
print(A)
n=int(input('Enter the length of list B '))
B=[]
for i in range (0,n):
InpEl2=int(input('Enter the elements '))
B.append(InpEl2)
print(B)
checklist=B
for each in A:
if each in checklist:
print('YES')
else:
print('NO')
Although in any case, I get 'No'. What is the mistake here?
Also, later I may need to modify the list so the program could determine if elements of B occur in A in the order they appear in B, but not necessarily consecutively.
For example, let M be the length of B and N be the length of A.
Then the program should return yes if there are indices i0, i1...im+1 such that 0<= i0 < i1...< im-1 < N such that A[i0] = B[0];A[i1] = B[1]...A[im-1] =
B[m-1].
Is there a simpler way to build the loop which would satisfy this kind of request?
P.S.: is it possible to make user input read not only integers, but strings? I am not sure if raw_input would be useful in Python 3.5.
P.S.S:
sorry, I made a minor mistake inputting the code here, I fixed it now.
Another question: I get the output of multiple yes' and no's for each element:
Enter the length of list A 3
Enter the elements 1
Enter the elements 2
Enter the elements 3
[1, 2, 3]
Enter the length of list B 3
Enter the elements 5
Enter the elements 4
Enter the elements 3
[5, 4, 3]
NO
NO
YES
How can I modify the code so it would print only one yes and no only once in case of any occurencies happen?
Here's one solution. Keep in mind there are many that have asked this type of question before and that best practice is to search around before asking.
a = input('enter list A with comma between each element: ')
b = input('enter list B with comma between each element: ')
a = a.split(',')
b = b.split(',')
contained_in_b = [element in b for element in a]
for i, in_b in enumerate(contained_in_b):
print('element {} contained in list B: {}'.format(a[i], in_b))
Better to take the raw input all together and use Python to split it into lists. This way, no need for the user to give the length of the list beforehand. Also, no need to convert to int - string comparisons work fine.
contained_in_b uses a list comprehension - a handy feature of Python that applies the boolean element in b to each element in a. Now you have a list of True/False values that you can enumerate through to print out the desired output.
One weapon you get is the all operator, which just checks that all of the items in the iterable are True:
A = [1, 4, 6, 8, 13]
B = [4, 6, 13, 8]
C = [3, 8, 25]
master = [i for i in range(20)]
print all(i in master for i in A)
print all(i in master for i in B)
print all(i in master for i in C)
Output:
True
True
False
To get the order as well, you'll need to drop back to an iterative method, stepping through the first list with a loop, while you maintain an index to know where you are in the second. For each value in the first list, go through the rest of the second list, until you either find the item (temporary success) or hit the end (failure).
Reading in number names and converting them to integers is a separate problem, and longer code.

find triangular numbers between any given two numbers

My code is showing bellow
import math,sys
#create a list with numbers
def create_list():
num_list=[]
for num in range(int(input("insert start point: ")),int(input("Insert end point: "))):
num_list.append(num)
return num_list
#function to find triangular numbers
def get_triangles(numlist):
triangles = []
for i in numlist:
if (check_triangle(i)):
triangles.append(i)
return triangles
#function to check number is triangular or not
def check_triangle(n):
return math.sqrt((8*n)+1).is_integer()
#function main to run the process
def main():
numlist = create_list()
print(get_triangles(numlist))
Even though it seems like the task is completed it was not. I tried it with the range of 0 - 100000000(1*10^8) numbers . it is cause to stuck my laptop any method that can complete this task ?
DO NOT PRINT A LIST THAT LARGE. Instead write it to a file, that way you can open the file afterward. The program can't efficiently write that much information into the console. I find that printing stuff to the console makes a programs a ton less efficient.
Additionally, I read some of the comments on your code and they state it isn't efficient and I would have to concur.
Here is piece of code I wrote up. It takes a bit of interpretation, but I was in a hurry. Just reply if you need help understanding it.
def getTriangles(input1,input2): #input1 is the min value and input2 is the max value
li = [] #the list where all of the numbers will go
i = 0 #an integer that acts how much another layer of the triangle would have
j = 0 #the most current number that it is on
while True: #I whipped up this algorithm in a couple minutes, so there is probably a more efficient way than just looping through all of them, but it is faster than the current one being used
i += 1 #i has to increment to act as the increase of a side
if j > input2: #if the value that could be added is greater than the max number, than just end the function and return the list
return li
if j >= input1: #if the number qualifies the minimum number requirements, then the program will add it to the list, otherwise it will ignore it and continue on with the function
li.append(j)
j += i #this simulates adding in another layer of the triangle to the bottom
This would be a way to use it:
print(getTriangles(1,45))
I trust you can look up how to write content to a file.
It appears that you are just trying to generate all triangle numbers within a range. If this is so, computing them directly is substantially quicker than checking via square root.
Note that you can generate triangular numbers by simply adding consecutive numbers.
T_0 = 0
T_1 = T_0 + 1 = 1
T_2 = T_1 + 2 = 3
T_3 = T_2 + 3 = 6
...
If you want to keep it simple, you can create a function to keep generating these numbers from n = 0, keeping them when they enter the desired range, and continue until it exceeds the upper bound.
def generate_triangular_numbers(a, b):
"""Generates the triangular numbers in [a, b] (inclusive)"""
n, t = 0, 0
triangles = []
while t < a:
n += 1
t += n
while t <= b:
triangles.append(t)
n += 1
t += n
return triangles

How to determine the sum of a group of integers without using recursion

This is my first post on Stack Overflow, and I'm hoping that it'll be a good one.
This is a problem that I thought up myself, and now I'm a bit embarrassed to say, but it's beating the living daylights out of me. Please note that this is not a homework exercise, scout's honor.
Basically, the program takes (as input) a string made up of integers from 0 to 9.
strInput = '2415043'
Then you need to break up that string of numbers into smaller groups of numbers, until eventually, the sum of those groups give you a pre-defined total.
In the case of the above string, the target is 289.
iTarget = 289
For this example, there are two correct answers (but most likely only one will be displayed, since the program stops once the target has been reached):
Answer 1 = 241, 5, 043 (241 + 5 + 043 = 289)
Answer 2 = 241, 5, 0, 43 (241 + 5 + 0 + 43 = 289)
Note that the integers do not change position. They are still in the same order that they were in the original string.
Now, I know how to solve this problem using recursion. But the frustrating part is that I'm NOT ALLOWED to use recursion.
This needs to be solved using only 'while' and 'for' loops. And obviously lists and functions are okay as well.
Below is some of the code that I have so far:
My Code:
#Pre-defined input values, for the sake of simplicity
lstInput = ['2','4','1','5','0','4','3'] #This is the kind of list the user will input
sJoinedList = "".join(lstInput) #sJoinedList = '2415043'
lstWorkingList = [] #All further calculuations are performed on lstWorkingList
lstWorkingList.append(sJoinedList) #lstWorkingList = ['2415043']
iTarget = 289 #Target is pre-defined
-
def SumAll(_lst): #Adds up all the elements in a list
iAnswer = 0 #E.g. lstEg = [2,41,82]
for r in _lst: # SumAll(lstEg) = 125
iAnswer += int(r)
return(iAnswer)
-
def AddComma(_lst):
#Adds 1 more comma to a list and resets all commas to start of list
#E.g. lstEg = [5,1001,300] (Note only 3 groups / 2 commas)
# AddComma(lstEg)
# [5,1,0,001300] (Now 4 groups / 3 commas)
iNoOfCommas = len(_lst) - 1 #Current number of commas in list
sResetString = "".join(_lst) #Make a string with all the elements in the list
lstTemporaryList = []
sTemp = ""
i = 0
while i < iNoOfCommas +1:
sTemp += sResetString[i]+',' #Add a comma after every element
i += 1
sTemp += sResetString[i:]
lstTemporaryList = sTemp.split(',') #Split sTemp into a list, using ',' as a separator
#Returns list in format ['2', '415043'] or ['2', '4', '15043']
return(lstTemporaryList)
return(iAnswer)
So basically, the Pseudo-code will look something like this:
Pseudo-Code:
while SumAll(lstWorkingList) != iTarget: #While Sum != 289
if(len(lstWorkingList[0]) == iMaxLength): #If max possible length of first element is reached
AddComma(lstWorkingList) #then add a new comma / group and
Reset(lstWorkingList) #reset all the commas to the beginning of the list to start again
else:
ShiftGroups() #Keep shifting the comma's until all possible combinations
#for this number of comma's have been tried
#Otherwise, Add another comma and repeat the whole process
Phew! That was quite a mouthfull .
I have worked through the process that the program will follow on a piece of paper, so below is the expected output:
OUTPUT:
[2415043] #Element 0 has reached maximum size, so add another group
#AddComma()
#Reset()
[2, 415043] #ShiftGroups()
[24, 15043] #ShiftGroups()
[241, 5043] #ShiftGroups()
#...etc...etc...
[241504, 3] #Element 0 has reached maximum size, so add another group
#AddComma()
#Reset()
[2, 4, 15043] #ShiftGroups()
[2, 41, 5043] #ShiftGroups()
#etc...etc...
[2, 41504, 3] #Tricky part
Now here is the tricky part.
In the next step, the first element must become 24, and the other two must reset.
#Increase Element 0
#All other elements Reset()
[24, 1, 5043] #ShiftGroups()
[24, 15, 043] #ShiftGroups()
#...etc...etc
[24, 1504, 3]
#Increase Element 0
#All other elements Reset()
[241, 5, 043] #BINGO!!!!
Okay. That is the basic flow of the program logic. Now the only thing I need to figure out, is how to get it to work without recursion.
For those of you that have been reading up to this point, I sincerely thank you and hope that you still have the energy left to help me solve this problem.
If anything is unclear, please ask and I'll clarify (probably in excruciating detail X-D).
Thanks again!
Edit: 1 Sept 2011
Thank you everyone for responding and for your answers. They are all very good, and definitely more elegant than the route I was following.
However, my students have never worked with 'import' or any data-structures more advanced than lists. They do, however, know quite a few list functions.
I should also point out that the students are quite gifted mathematically, many of them have competed and placed in international math olympiads. So this assignment is not beyond the scope of
their intelligence, perhaps only beyond the scope of their python knowledge.
Last night I had a Eureka! moment. I have not implemented it yet, but will do so over the course of the weekend and then post my results here. It may be somewhat crude, but I think it will get the job done.
Sorry it took me this long to respond, my internet cap was reached and I had to wait until the 1st for it to reset. Which reminds me, happy Spring everyone (for those of you in the Southern Hempisphere).
Thanks again for your contributions. I will choose the top answer after the weekend.
Regards!
A program that finds all solutions can be expressed elegantly in functional style.
Partitions
First, write a function that partitions your string in every possible way. (The following implementation is based on http://code.activestate.com/recipes/576795/.) Example:
def partitions(iterable):
'Returns a list of all partitions of the parameter.'
from itertools import chain, combinations
s = iterable if hasattr(iterable, '__getslice__') else tuple(iterable)
n = len(s)
first, middle, last = [0], range(1, n), [n]
return [map(s.__getslice__, chain(first, div), chain(div, last))
for i in range(n) for div in combinations(middle, i)]
Predicate
Now, you'll need to filter the list to find those partitions that add to the desired value. So write a little function to test whether a partition satisfies this criterion:
def pred(target):
'Returns a function that returns True iff the numbers in the partition sum to iTarget.'
return lambda partition: target == sum(map(int, partition))
Main program
Finally, write your main program:
strInput = '2415043'
iTarget = 289
# Run through the list of partitions and find partitions that satisfy pred
print filter(pred(iTarget), partitions(strInput))
Note that the result is calculated in a single line of code.
Result: [['241', '5', '043'], ['241', '5', '0', '43']]
Recursion isn't the best tool for the job anyways. itertools.product is.
Here's how I search it:
Imagine the search space as all the binary strings of length l, where l is the length of your string minus one.
Take one of these binary strings
Write the numbers in the binary string in between the numbers of your search string.
2 4 1 5 0 4 3
1 0 1 0 1 0
Turn the 1's into commas and the 0's into nothing.
2,4 1,5 0,4 3
Add it all up.
2,4 1,5 0,4 3 = 136
Is it 289? Nope. Try again with a different binary string.
2 4 1 5 0 4 3
1 0 1 0 1 1
You get the idea.
Onto the code!
import itertools
strInput = '2415043'
intInput = map(int,strInput)
correctOutput = 289
# Somewhat inelegant, but what the heck
JOIN = 0
COMMA = 1
for combo in itertools.product((JOIN, COMMA), repeat = len(strInput) - 1):
solution = []
# The first element is ALWAYS a new one.
for command, character in zip((COMMA,) + combo, intInput):
if command == JOIN:
# Append the new digit to the end of the most recent entry
newValue = (solution[-1] * 10) + character
solution[-1] = newValue
elif command == COMMA:
# Create a new entry
solution.append(character)
else:
# Should never happen
raise Exception("Invalid command code: " + command)
if sum(solution) == correctOutput:
print solution
EDIT:
agf posted another version of the code. It concatenates the string instead of my somewhat hacky multiply by 10 and add approach. Also, it uses true and false instead of my JOIN and COMMA constants. I'd say the two approaches are equally good, but of course I am biased. :)
import itertools
strInput = '2415043'
correctOutput = 289
for combo in itertools.product((True, False), repeat = len(strInput) - 1):
solution = []
for command, character in zip((False,) + combo, strInput):
if command:
solution[-1] += character
else:
solution.append(character)
solution = [int(x) for x in solution]
if sum(solution) == correctOutput:
print solution
To expand on pst's hint, instead of just using the call stack as recursion does, you can create an explicit stack and use it to implement a recursive algorithm without actually calling anything recursively. The details are left as an exercise for the student ;)

Categories