Difficulty with solving sudoku puzzle - python-2.7

I was stuck solving a sudoku puzzle with python.I am solving it using the method of backtracking error.My Code is implementing this method correctly upto some number of elements.But after some element it is not moving to the next empty cell to implement this,but it is staing at that particular cell.I think my function to check whether a value is valid at a position is working correctly.I was not able to figure out the mistake I was doing. Can someone help me regarding this.
code:
from numpy import *
def isValid(matrix,row,col):
element = matrix[row][col]
#print element
#print where(matrix[row,:] == element)
if len(where(matrix[row,:] == element)[0]) == 1 and len(where(matrix[:,col] == element)[0]) == 1:
#print 'entered'
row_type = row%3;col_type =col%3
row_index = row-row_type;col_index = col-col_type
if len(where(matrix[row_index:row_index+3,col_index:col_index+3])[0] == 1):
return 1
else:
return 0
else :
return 0
sudoku = loadtxt('1')
sudoku = array(sudoku,dtype = int)
blankRow,blankCol = where(sudoku == 0)
i=0
while i< len(blankRow):
print 'i:',i
#print 'entered'
while sudoku[blankRow[i],blankCol[i]] < 9:
#print 'entered',sudoku[blankRow[i],blankCol[i]]
sudoku[blankRow[i],blankCol[i]] += 1
#j = sudoku[blankRow[i],blankCol[i]]
valid = isValid(sudoku,blankRow[i],blankCol[i])
if valid == 1:
break
if sudoku[blankRow[i],blankCol[i]] == 9 and valid != 1:
print 'entered' #invalid,i:',i,'j',j,'row:',blankRow[i],'col:',blankCol[i]
sudoku[blankRow[i],blankCol[i]] = 0
i-= 1
i+=1

Your backtracking never works, because you unconditionally add 1 to i at the end of the outer loop. I think you want to put that increment in an else block, attached to the if just above it:
if sudoku[blankRow[i],blankCol[i]] == 9 and valid != 1:
print 'entered' #invalid,i:',i,'j',j,'row:',blankRow[i],'col:',blankCol[i]
sudoku[blankRow[i],blankCol[i]] = 0
i-= 1
else: # add this!
i+=1 # indent this!
Note that you might need to add some additional checking to make your code behave properly if it is given an unsolvable puzzle. In that situation, i will become negative, as it backtracks past the first position. This won't actually lead to an immediate error, as you can index a list or array with a negative value, but it will eventually raise an exception after trying (and failing) to solve the puzzle again several times.

Related

For-loop error: list index out of range

So I am rather new to programming and just recently started with Classes and we are supposed to make a phonebook that can be loaded in seperate text files.
I however keep running into the problem in this section that when I get into the for-loop. It hits a brick wall on
if storage[2] == permaStorage[i].number:
And tells me "IndexError: list index out of range". I am almost certain it is due to permaStorage starts out empty, but even when I attempt to fill it with temporary instances of Phonebook it tells me it out of range. The main reason it is there is to check if a phone number already exists within the permaStorage.
Anyone got a good tip on how to solve this or work around it?
(Sorry if the text is badly written. Just joined this site and not sure on the style)
class Phonebook():
def __init__(self):
self.name = ''
self.number = ''
def Add(name1, number1):
y = Phonebook()
y.name = name1
y.number = number1
return y
def Main():
permaStorage = []
while True:
print " add name number\n lookup name\n alias name newname\n change name number\n save filename\n load filename\n quit\n"
choices = raw_input ("What would you like to do?: ")
storage = choices.split(" ")
if storage[0] == "add":
for i in range(0, len(permaStorage)+1):
if storage[2] == permaStorage[i].number:
print "This number already exists. No two people can have the same phonenumber!\n"
break
if i == len(permaStorage):
print "hej"
try:
tempbox = Add(storage[1], storage[2])
permaStorage.append(tempbox)
except:
raw_input ("Remember to write name and phonenumber! Press any key to continue \n")
I think problem is that permaStorage is empty list and then u try to:
for i in range(0, len(permaStorage)+1):
if storage[2] == permaStorage[i].number:
will cause an error because permaStorage has 0 items but u trying to get first (i=0, permaStorage[0]) item.
I think you should replace second if clause with first one:
for i in range(0, len(permaStorage)+1):
if i == len(permaStorage):
print "hej"
try:
tempbox = Add(storage[1], storage[2])
permaStorage.append(tempbox)
if storage[2] == permaStorage[i].number:
print "This number already exists. No two people can have the same phonenumber!\n"
break
So in this case if perStorage is blank you will append some value and next if clause will be ok.
Indexing starts at zero in python. Hence, a list of length 5 has the last element index as 4 starting from 0. Change range to range(0, len(permastorage))
You should iterate upto the last element of the list, not beyond.
Try -
for i in range(0, len(permaStorage)):
The list of numbers produced in range() is from the start, but not including the end, so range(3) == [0, 1, 2].
So if your list x has length 10, range(0, len(x)) will give you 0 through 9, which is the correct indices of the elements of your list.
Adding 1 to len(x) will produce the range 0 through 10, and when you try to access x[10], it will fail.

Using Bubble sort and encountering out of range list index

doc = "unsorted.txt"
out_fil = "H:\Grade 11\Intro to Computer Science\sorted.txt" # Used in the Windows variation of the program
out_file = "/Applications/Banter" # Used in the Mac variation of the program
import time
def main():
order = False
blank = []
passcount = 0
starttime = time.time()
numlist = CreateList(doc)
while not order:
passcount = passcount + 1
switch = False
switchcount = 0
print "1" # These are test prints to I used to find problems
for x in range (len(numlist)):
print "2" # These are test prints to I used to find problems
if numlist[x] > numlist[x+1]:
temp = numlist[x+1]
numlist[x+1] = numlist[x]
numlist[x] = temp
switchcount = switchcount + 1
switch = True
print "9" # These are test prints to I used to find problems
elif switch == 0:
order = True
CreateFile(numlist)
endtime = time.time()
print "This list required",endtime-starttime,"seconds to sort."
print "This list required",switchcount,"switches to sort."
print "This list required",passcount,"passes to sort."
def CreateList(doc):
sort = open(doc,"r")
numlist = sort.readlines()
sort.close()
for x in range (len(numlist)):
numlist[x] = int(numlist[x].strip())
return numlist
def CreateFile(numlist):
sort = open(doc,"w")
sort.write(str(numlist)+"\n")
sort.close()
return numlist
def List(numlist):
print numlist
main()
The main purpose of my program is to sort a list of integers from a file in order using the bubble sort method, and then put that list into a new file. I'm also detailing the amount of time it takes to perform this as well as the number of passes and switches within the program that it took to sort it completely.
Now, the problem I'm having is that the list index falls out of range because it's comparing x and x+1 of my numlist. But, I need to compare x+1 in order to sort the two integers beside each others within the list. Is there any way I can fix the program so that it'll compare all the integers in the list and not try to compare the space that isn't in the list because of the x+1?
You could make your loop in this way:
for x in range ( len(numlist) -1 ):
Though stackoverflow is a great resource for answers, giving them up for homework assignments feels like cheating. I'll meet you half way: Make your loop run for one less iteration.

Why won't my csv list replace my blank values with "N"?

I'm attempting to create a function which reads a specific column of a csv file which currently alternates between empty values and "1", pops them into a list and then replaces them with an "N" for the empty value and "B" for the "1"'s. I'm pretty new to python, as well as programming in general, so any tips and all help is welcome. This is what I have so far, and it does process, but only replaces my "1"'s with "B"'s. I've double checked my csv and the position is definitely empty and does not contain spaces. I've also looked at other responses and tried to emulate some similar logic that appeared to be behind them, but something still doesn't seem to work. If someone could point me in the right direction it would be very much appreciated.
#sample data (for 195 entries):
["Header0,"Header1","Foundation","Header3"],
["abc1","a12n","","123"],
["def2","d13b","1","456"],
["ghi3","g12n","","789"],
def Foundation( csv_file_path, Remove_Header = False, Remove_SubHeader = False ):
delineator = ','
raw_file = file(csv_file_path, 'r')
return_List = []
n = 0
#Process lines in file
for line in raw_file.readlines():
#Check if to include or remove header
if (n == 0 ) and (Remove_Header == True):
n = n + 1
continue
#Check if to include or remove sub header
if (n == 1) and (Remove_SubHeader == True):
n = n + 1
continue
sList2 = line.replace("\n","").strip().split( delineator )
col_2 = str(sList2.pop(2))
for n in col_2:
if n == "1":
col_2 = col_2.replace("1", "B")
elif n == "":
col_2 = col_2.replace("", "N")
print col_2
return_List.append(sList2) #add my secondary list back to my main List? right?
sList2.insert(0, col_2)# insert back to my secondary list where it went
n = n + 1 #add to counter and move down the line
raw_file.close()
#Return the list
return return_List

How do I improve the performance of the following code in python

I have a dataset with a column of the form:
'< 1 year'
'10+ years'
'6 years'
etc
I needed it to convert to integer format, that is, '< 1 year' --> 0, '10+ years' --> 10 and entries like '6 years' --> 6 etc. There are 500,000 entries. I wrote the following script to clean it:
temp = data.X11
for i in range(len(temp)):
if ~is_nan(temp[i]):
if isinstance(temp[i], six.string_types):
b= temp[i].split(" ")
if len(b) == 3 and (b[0])=='<':
temp[i] = 0
elif len(b) == 2:
if b[0] == '10+':
temp[i] = 10
else:
temp[i] = int(b[0])
else:
if isinstance(temp[i], float):
temp[i] = math.floor(temp[i])
if isinstance(temp[i], int):
if temp[i] >= 10:
temp[i] = 10
elif temp[i] < 1 and temp[i] >= 0:
temp[i] = 0
elif temp[i] < 0:
temp[i] = -10
else:
pass
else:
temp[i] = -10
It works. But the downside is, it is awfully slow (took hours to complete). My question is how to improve the performance of this code.
Any advice or help with code snippet would be greatly appreciated.
Thanks
I am not sure you can do much here.
You can try to avoid the temp[i] accesses by iterating the temp values instead. You can also append the new values at the end of another list (fast) instead of modifying a value in the middle (not that fast).
new_temp = list()
for temp_i in data.X11:
if ~is_nan(temp_i):
if isinstance(temp_i, six.string_types):
b = temp_i.split(" ")
if len(b) == 3 and (b[0])=='<':
new_temp.append(0)
elif len(b) == 2:
if b[0] == '10+':
new_temp.append(10)
else:
new_temp.append(int(b[0]))
else:
if isinstance(temp_i, float):
new_temp.append(math.floor(temp_i))
if isinstance(temp_i, int):
if temp_i >= 10:
new_temp.append(10)
elif temp_i < 1 and temp_i >= 0:
new_temp.append(0)
elif temp_i < 0:
new_temp.append(-10)
else:
new_temp.append(-10)
string.split is likely to be very slow.
If it is possible, you can also try to execute your code using pypy or rewrite it to be compatible with cython.
I think the culprit is this line:
math.floor(temp[i])
It returns a float which uses quite a few more bits than a standard integer. Casting the result of that operation to an integer could increase performance.
Another solution would be upgrading to Python 3.x.x as in those versions round, floor, and ceil all return integers.
With Pandas
You can create a dictionnary , and then map your dataframe with it
dico = {'< 1 year' :1,'10+ years' :10,'6 years' :6 }
df['New_var'] = df.var1.map(dico)
should only take a couple of seconds

runtime error(nzec) in python

It works fin in my pc and in an online compiler+debugger. However, when I submit it in codechef, it gives me a runtime error(nzec). When do you get a runtime error and how to you resolve it. What is the problem in this code? I keep getting runtime error very frequently. How do I avoid it? Any kind of help will be deeply appreciated!
t = int(raw_input())
for i in range(t):
a = map(int, raw_input())
if a.index(min(a)) != 0:
if min(a) == 0:
print a.index(min(a))
else:
print str(str(a.index(min(a))) * (min(a)+1))
elif a.index(min(a)) == 0:
k = min(a)
a[0] = 99
l = min(a)
if l == k:
print str(str(a.index(min(a))) * min(a))
elif l > k:
print '1'+ ('0' * (k+1))
You have to split the raw_input()
raw_input() receives the input as just a string. Use raw_input().split() to convert the string to a list. Else you will have indexing problems, since the spaces given in the input are taken for mapping. So you get the nzec (non-zero exit code) error
a=map(int,raw_input().split())
will do
Many times it is due to some white places left.
Try this:
raw_input().strip().split(" ")
if the data is separated by " ".