python solves Sudoku

Sudoku problem explanation
1, The basic rules of Sudoku
Rule 1: different numbers in the same line
Rule 2: different numbers in the same column
Rule 3: different numbers in the same house

2, Strategies to solve Sudoku
1. Simple method
The first step, in each cell, is to Please add link description for basic rules Write possible results
Step 2: determine the number of results in each cell. If the result is unique, write the number.
Step 3, return to step 1, loop
Stop flag: fill all cells, or the minimum possible result in the cell is greater than 1.

2. Intermediate method
The first step is to use a simple method
Step 2: in each palace, there is only one occurrence of a certain number. Fill in the number directly
Step 3, return to step 1, loop
Stop flag: no number filled in

3. Ultimate approach
The first step is to use the intermediate method
The second step is to assume every possible answer of each position, and deduce the contradiction and eliminate it.
(1) In the first place, fill in the first possible answer
(2) Using the intermediate method, derive and fill in numbers
(3) If contradiction A appears, if the assumption is not true, return to this position and fill in the second answer.
If contradiction B appears, assume that it is temporary. Go to the next position and fill in the answer.
End of loop flag: fill in numbers and follow basic rules

Three codes are as follows
import pandas as pd
import numpy as np
shudu_data=pd.read_csv('data/shudu.csv')
data=shudu_data.copy()

def block(i,data):
ru3_1=data.iloc[0:3,0:3]
ru3_2=data.iloc[0:3,3:6]
ru3_3=data.iloc[0:3,6:]
ru3_4=data.iloc[3:6,0:3]
ru3_5=data.iloc[3:6,3:6]
ru3_6=data.iloc[3:6,6:]
ru3_7=data.iloc[6:,0:3]
ru3_8=data.iloc[6:,3:6]
ru3_9=data.iloc[6:,6:]

ru3_list=[ru3_1,ru3_2,ru3_3,ru3_4,ru3_5,ru3_6,ru3_7,ru3_8,ru3_9]

ru3=ru3_list[i]
ru3=ru3.values.tolist()
lis=[]
for l in ru3:
    lis+=l
ru3=set(lis)-{0}
return ru3

def Block_dataframe(i,data):

ru3_1=pd.DataFrame(data=data.iloc[0:3,0:3],index=[0,1,2],columns=['0','1','2'])
ru3_2=pd.DataFrame(data=data.iloc[0:3,3:6],index=[0,1,2],columns=['3','4','5'])
ru3_3=pd.DataFrame(data=data.iloc[0:3,6:],index=[0,1,2],columns=['6','7','8'])
ru3_4=pd.DataFrame(data=data.iloc[3:6,0:3],index=[3,4,5],columns=['0','1','2'])
ru3_5=pd.DataFrame(data=data.iloc[3:6,3:6],index=[3,4,5],columns=['3','4','5'])
ru3_6=pd.DataFrame(data=data.iloc[3:6,6:],index=[3,4,5],columns=['6','7','8'])
ru3_7=pd.DataFrame(data=data.iloc[6:,0:3],index=[6,7,8],columns=['0','1','2'])
ru3_8=pd.DataFrame(data=data.iloc[6:,3:6],index=[6,7,8],columns=['3','4','5'])
ru3_9=pd.DataFrame(data=data.iloc[6:,6:],index=[6,7,8],columns=['6','7','8'])

ru3_list=[ru3_1,ru3_2,ru3_3,ru3_4,ru3_5,ru3_6,ru3_7,ru3_8,ru3_9]

return ru3_list[i]

def jianyan(data):

flag=True
for ind in range(9):
    li_1=list(data.iloc[ind].values)
    li_=[]
    for li in li_1:
        if li!=0:
            li_.append(li)
    flag=(len(set(li_))==len(li_))
    if flag==False:
        return flag

for col in ['0','1','2','3','4','5','6','7','8']:
    li_2=list(data.iloc[:][col].values)
    li_=[]
    for li in li_2:
        if li!=0:
            li_.append(li)
    #print(set(li_))
    #print(li_)
    flag=(len(set(li_))==len(li_))
    if flag==False:
        return flag

for i in range(9):
    block_dataframe=Block_dataframe(i,data)
    li_3=block_dataframe.values.tolist()
    li_q=[]
    for li_ in li_3:
        li_q=li_q+li_  
    li_=[]
    for li in li_q:
        if li!=0:
            li_.append(li) 

    flag=(len(set(li_))==len(li_))
    if flag==False:
        return flag
return flag

def full(data):
for i in range(9):
for j in ['0','1','2','3','4','5','6','7','8']:
if data[j][i]==0:
return False
return True

def Block_num(index,colums,data):
if index in [0,1,2]:
if colums in ['0','1','2']:
block_num=0
elif colums in ['3','4','5']:
block_num=1
else:
block_num=2
if index in [3,4,5]:
if colums in ['0','1','2']:
block_num=3
elif colums in ['3','4','5']:
block_num=4
else:
block_num=5
if index in [6,7,8]:
if colums in ['0','1','2']:
block_num=6
elif colums in ['3','4','5']:
block_num=7
else:
block_num=8
return block_num

def len_re(index,colums,data):
result={1,2,3,4,5,6,7,8,9}
ru1=set(data.iloc[index])
ru2=set(data[colums])
if index in [0,1,2]:
if colums in ['0','1','2']:
ru3=block(0,data)
elif colums in ['3','4','5']:
ru3=block(1,data)
else:
ru3=block(2,data)
if index in [3,4,5]:
if colums in ['0','1','2']:
ru3=block(3,data)
elif colums in ['3','4','5']:
ru3=block(4,data)
else:
ru3=block(5,data)
if index in [6,7,8]:
if colums in ['0','1','2']:
ru3=block(6,data)
elif colums in ['3','4','5']:
ru3=block(7,data)
else:
ru3=block(8,data)
re=result-ru1-ru2-ru3-{0}

return re

class result():

def result(self,data):

    #Calculate the possible results at each location, return pos, ans
    index=[0,1,2,3,4,5,6,7,8]
    colums=['0','1','2','3','4','5','6','7','8']
    pos=[]
    ans=[]
    for ind in index:
        for col in colums:
            if data[col][ind] ==0:
                re=len_re(ind,col,data)
                ans.append(list(re))
                pos.append((ind,col)) 
    return zip(pos,ans)

def result_min_len(data):
R=result()
c=R.result(data)
reslut_len=[]
reslut_list=[]
try:
for pos,ans in c:
reslut_list.append(ans)
reslut_len.append(len(ans))
return min(reslut_len)
except:

    return False   

class paichu():

def result(self,data):
    data_copy=data.copy()
    #If there are multiple results in one location, try to correct them in sequence
    i=0
    j=0
    if result_min_len(data_copy)==0:
        print('Incoming data error, calculation aborted')
    else:
        result_=result()
        result_1=result_.result(data_copy)
        pos_=[]
        ans_1_b=[]
        for pos,ans_list in result_1:
            ind=pos[0]
            col=pos[1]
            ans_1_a=[]
            for ans in ans_list:
                j+=1
                data_copy[col][ind]=ans
                f=result_min_len(data_copy)
                if f:
                    i+=1
                    ans_1_a.append(ans)
                data_copy[col][ind]=0
            ans_1_b.append(ans_1_a)
            pos_.append((ind,col))
        print('Eliminated{}Number'.format(j-i))
        return zip(pos_,ans_1_b)

class rule_1():

def result(self,data):
    #If ind=0, press row, ind=1, exclude by column
    ind=0
    result_000=result()
    answer_zip=result_000.result(data)

    #rule1 if n identical lists are in the same row / column, and the number of elements is equal to the number of list, all elements in the list can be excluded by other pending cell s in the row
    index_0=[]
    index_1=[]
    index_2=[]
    index_3=[]
    index_4=[]
    index_5=[]
    index_6=[]
    index_7=[]
    index_8=[] 

    ans_0=[]
    ans_1=[]
    ans_2=[]
    ans_3=[]
    ans_4=[]
    ans_5=[]
    ans_6=[]
    ans_7=[]
    ans_8=[]

    for pos,ans in answer_zip:
        if pos[ind]==0:
            index_0.append(pos)
            ans_0.append(ans)
        elif pos[ind]==1:
            index_1.append(pos)
            ans_1.append(ans)
        elif pos[ind]==2:
            index_2.append(pos)
            ans_2.append(ans)
        elif pos[ind]==3:
            index_3.append(pos)
            ans_3.append(ans)
        elif pos[ind]==4:
            index_4.append(pos)
            ans_4.append(ans)
        elif pos[ind]==5:
            index_5.append(pos)
            ans_5.append(ans)
        elif pos[ind]==6:
            index_6.append(pos)
            ans_6.append(ans)
        elif pos[ind]==7:
            index_7.append(pos)
            ans_7.append(ans)
        elif pos[ind]==8:
            index_8.append(pos)
            ans_8.append(ans)

    index=[index_0,index_1,index_2,index_3,index_4,index_5,index_6,index_7,index_8]
    ans=[ans_0,ans_1,ans_2,ans_3,ans_4,ans_5,ans_6,ans_7,ans_8]

    ans_=[]
    for ans_array in ans:
        l2=[]
        for i in ans_array:
            l2.append(set(i))

        for i in np.unique(l2):
            if l2.count(i)==len(i):
                for k,j in enumerate(l2):
                    if i!=j:
                        j=j-i
                        l2[k]=j

        ans_.append(list(l2))

    pos_=[]
    for i in index:
        pos_=pos_+i

    ans_list=[]
    for i in ans_:
        ans_list=ans_list+i
    ans_listn=[]
    for i in ans_list:
        ans_listn.append(list(i))
    return zip(pos_,ans_listn)

class rule_2():

def result(self,data):
    #If ind=0, press row, ind=1, exclude by column
    ind=1
    result_000=result()
    answer_zip=result_000.result(data)

    #rule1 if n identical lists are in the same row / column, and the number of elements is equal to the number of list, all elements in the list can be excluded by other pending cell s in the row
    index_0=[]
    index_1=[]
    index_2=[]
    index_3=[]
    index_4=[]
    index_5=[]
    index_6=[]
    index_7=[]
    index_8=[] 

    ans_0=[]
    ans_1=[]
    ans_2=[]
    ans_3=[]
    ans_4=[]
    ans_5=[]
    ans_6=[]
    ans_7=[]
    ans_8=[]

    for pos,ans in answer_zip:
        if pos[ind]=='0':
            index_0.append(pos)
            ans_0.append(ans)
        elif pos[ind]=='1':
            index_1.append(pos)
            ans_1.append(ans)
        elif pos[ind]=='2':
            index_2.append(pos)
            ans_2.append(ans)
        elif pos[ind]=='3':
            index_3.append(pos)
            ans_3.append(ans)
        elif pos[ind]=='4':
            index_4.append(pos)
            ans_4.append(ans)
        elif pos[ind]=='5':
            index_5.append(pos)
            ans_5.append(ans)
        elif pos[ind]=='6':
            index_6.append(pos)
            ans_6.append(ans)
        elif pos[ind]=='7':
            index_7.append(pos)
            ans_7.append(ans)
        elif pos[ind]=='8':
            index_8.append(pos)
            ans_8.append(ans)

    index=[index_0,index_1,index_2,index_3,index_4,index_5,index_6,index_7,index_8]
    ans=[ans_0,ans_1,ans_2,ans_3,ans_4,ans_5,ans_6,ans_7,ans_8]

    ans_=[]
    for ans_array in ans:
        l2=[]
        for i in ans_array:
            l2.append(set(i))

        for i in np.unique(l2):
            if l2.count(i)==len(i):
                for k,j in enumerate(l2):
                    if i!=j:
                        j=j-i
                        l2[k]=j
        ans_.append(list(l2))

    pos_=[]
    for i in index:
        pos_=pos_+i

    ans_list=[]
    for i in ans_:
        ans_list=ans_list+i
    ans_listn=[]
    for i in ans_list:
        ans_listn.append(list(i))
    return zip(pos_,ans_listn)

class rule_3():

def result(self,data):

    result_000=result()
    answer_zip=result_000.result(data)

    #rule3 if n identical lists are in the same 9-house lattice and the number of elements is equal to the number of lists, all elements in the list can be excluded by other pending cell s in the row
    block_0=[]
    block_1=[]
    block_2=[]
    block_3=[]
    block_4=[]
    block_5=[]
    block_6=[]
    block_7=[]
    block_8=[] 

    index_0=[]
    index_1=[]
    index_2=[]
    index_3=[]
    index_4=[]
    index_5=[]
    index_6=[]
    index_7=[]
    index_8=[] 

    for pos,ans in answer_zip:
        index=pos[0]
        colums=pos[1]

        if index in [0,1,2]:
            if colums in ['0','1','2']:
                block_0.append(ans)
                index_0.append(pos)
            elif colums in ['3','4','5']:
                block_1.append(ans)
                index_1.append(pos)
            else:
                block_2.append(ans)
                index_2.append(pos)
        if index in [3,4,5]:
            if colums in ['0','1','2']:
                block_3.append(ans)
                index_3.append(pos)
            elif colums in ['3','4','5']:
                block_4.append(ans)
                index_4.append(pos)
            else:
                block_5.append(ans)
                index_5.append(pos)
        if index in [6,7,8]:
            if colums in ['0','1','2']:
                block_6.append(ans)
                index_6.append(pos)
            elif colums in ['3','4','5']:
                block_7.append(ans)
                index_7.append(pos)
            else:
                block_8.append(ans)
                index_8.append(pos)

    index=[index_0,index_1,index_2,index_3,index_4,index_5,index_6,index_7,index_8]       
    block=[block_0,block_1,block_2,block_3,block_4,block_5,block_6,block_7,block_8]

    ans_=[]   
    for index_array in block:
        l2=[]
        for i in index_array:
            l2.append(set(i))

        for i in np.unique(l2):
            if l2.count(i)==len(i):
                for k,j in enumerate(l2):
                    if i!=j:
                        j=j-i
                        l2[k]=j    
        ans_.append(list(l2))

    pos_=[]
    for i in index:
        pos_=pos_+i

    ans_list=[]
    for i in ans_:
        ans_list=ans_list+i
    ans_listn=[]
    for i in ans_list:
        ans_listn.append(list(i))
    return zip(pos_,ans_listn)

class rule_():

def result(self,data):
    Rule_1=rule_1()
    Rule_2=rule_2()
    Rule_3=rule_3()

    result_dict_1={}
    for pos,ans in Rule_1.result(data):
        result_dict_1[pos]=set(ans)
    result_dict_2={}
    for pos,ans in Rule_2.result(data):
        result_dict_2[pos]=set(ans)  
    result_dict_3={}
    for pos,ans in Rule_3.result(data):
        result_dict_3[pos]=set(ans)

    #Three dictionaries take the intersection of key values and merge them into the final result
    key_list=result_dict_1.keys()
    result_dict={}
    for key in key_list:
        result_dict[key]=(result_dict_1[key])&(result_dict_2[key])&(result_dict_3[key])

    ans=[]
    pos=[]
    for key,value in result_dict.items():
        k=list(value)
        k.sort()
        ans.append(k)
        pos.append(key)

    return zip(pos,ans)

def fill_pinlv(result_zip,data):

#Input data type is zip
result_zip=result_zip
result_list=list(result_zip)
#print(result_zip)

block_num_list=[]
for tup in result_list:
    pos=tup[0]
    ans=tup[1]
    block_num=Block_num(pos[0],pos[1],data)
    block_num_list.append(block_num)
#print(block_num_list)

ind_list_0=[]
ind_list_1=[]
ind_list_2=[]
ind_list_3=[]
ind_list_4=[]
ind_list_5=[]
ind_list_6=[]
ind_list_7=[]
ind_list_8=[]
ind_block_array=[]
for ind,num in enumerate(block_num_list):

    if num==0:
        ind_list_0.append(ind)
    if num==1:
        ind_list_1.append(ind)            
    if num==2:
        ind_list_2.append(ind)            
    if num==3:
        ind_list_3.append(ind)
    if num==4:
        ind_list_4.append(ind)            
    if num==5:
        ind_list_5.append(ind)    
    if num==6:
        ind_list_6.append(ind)
    if num==7:
        ind_list_7.append(ind)            
    if num==8:
        ind_list_8.append(ind)    
ind_block_array=[ind_list_0,ind_list_1,ind_list_2,ind_list_3,ind_list_4,ind_list_5,ind_list_6,ind_list_7,ind_list_8]
#print(ind_block_array)

result_block_array=[]
for ind_list in ind_block_array:
    result_block_list=[]
    for ind in ind_list:
        result_block_list.append(result_list[ind])
    result_block_array.append(result_block_list)  
#print(result_block_array)

#Generate block counter array
block_counter_array=[]
for block_list in result_block_array:
    counter_list=[]
    for i in range(1,10):
        counter=0
        for pos,ans in block_list:
            if i in ans:
                counter+=1
        counter_list.append(counter)
    block_counter_array.append(counter_list) 
#print(block_counter_array)

#Update data
jishuqi=0
for block_index,block in enumerate(block_counter_array):
    processing_num=0
    processing_num_pos=False
    for num,count in enumerate(block):
        if count==1:
            processing_num=num+1
            for tup in result_list:
                pos=tup[0]
                ans=tup[1]

                if block_index==Block_num(pos[0],pos[1],data):
                    #print(block_index)
                    if processing_num in ans:
                        #print(pos)
                        processing_num_pos=pos
                        jishuqi+=1
                        data[processing_num_pos[1]][processing_num_pos[0]]=processing_num
                        if jianyan(data)==False:
                            data[processing_num_pos[1]][processing_num_pos[0]]=0
                            return jishuqi

return jishuqi   

def fill_jilian(data):
jishuqi=0
for i in range(1,10):
index_list=[]
col_list=[]
block_dataframe=pd.DataFrame()
for block_num in range(9):
#print(block_num)
block_dataframe=Block_dataframe(block_num,data)
index_list=list(block_dataframe.index)
col_list=list(block_dataframe.columns)
if i not in block_dataframe.values:
#Exclude line index
for ind in index_list:
for col in range(9):
if i==data.iloc[ind][col]:
index_list.remove(ind)
#Exclusion col
for col in col_list:
for ind in range(9):
if i ==data[col][ind]:
col_list.remove(col)

        #Exclude several cell s
        pos_list=[]
        for ind in index_list:
            for col in col_list:
                pos=(ind,col)
                pos_list.append(pos)
        for pos in pos_list:
            if data[pos[1]][pos[0]]!=0:
                pos_list.remove(pos)
        #print(pos_list)
        #Fill in figures
        if len(pos_list)==1:
            pos=pos_list[0]
            data[pos[1]][pos[0]]=i  
            jishuqi+=1
#print('already filled with {} numbers'. format(jishuqi))
return jishuqi

def fill(data,classname):
#print('executing... )
data=data
if classname =='result':
cla=result()
elif classname=='paichu':
cla=paichu()
elif classname=='rule':
cla=rule()

#If there is only one possible location, fill in the data directly
i=0
m=0
flag_1=True
while(flag_1):

    if result_min_len(data)==0:
        #print('wrong data entered in the last round ')
        flag_1=False  
    m=i
    for pos,ans in cla.result(data):
        #print(len(ans))
        if len(ans)==1:
            i+=1
            ind=pos[0]
            col=pos[1]
            data[col][ind]=ans[0]
            if jianyan(data)==False:
                #print('error filling data, filling stopped ')
                flag_1=False
                break           
    if m == i:
        break             

#If there are only many possible locations, fill in the data with fill
j=0
m=0
flag_2=True
while(flag_2):

    if result_min_len(data)==0:
        #print('wrong data entered in the last round ')
        flag_2=False
    if jianyan(data)==False:
        #print('error filling data, filling stopped ')
        flag_2=False
    m=j
    j=j+fill_pinlv(cla.result(data),data)
    if m == j:
        break

def labelinit(data):
R=rule()
label_list=[]
for pos,ans in R.result(data):
label_list.append([pos,ans,[None]*len(ans)])
return label_list

def label_change_B(pos,ans,label_list):
#label_list_copy=label_list.copy()
for l in label_list:
if l[0]==pos:
for a in range(len(l[2])):
l[2][a]=False
if ans == l[1][a]:
l[2][a]=True
return

def label_change_A(pos,ans,label_list):
#label_list_copy=label_list.copy()
for l in label_list:
if l[0]==pos:
for a in range(len(l[2])):
l[2][a]=False
if ans == l[1][a]:
l[2][a]=False
return

def label_rechange(data,label_list):
try:
#Update label? List
for ind,l in enumerate(label_list):
if (None not in l[2]) and (True not in l[2]):
#Empty last line
process_1=[None]*len(l[1])
#Move previous line True one unit back
process_2=label_list[ind-1][2]
index=process_2.index(True)+1
process_2.pop()
process_2.insert(0,False)
label_list[ind][2]=process_1
label_list[ind-1][2]=process_2
return True
except:
Print ('label_exchange error ')
print('Please confirm the input data is correct!!! )
return False

def data_change(data,label_list):
#Update the data according to the label? List
try:
for l in label_list:
if True in l[2]:
pos=l[0]
ans=l[1]
marker=l[2]
data[pos[1]][pos[0]]=ans[marker.index(True)]
else:
print('data is completed according to the label assumption ')
break
except:
Print ('data change error ')

def AB_test(data_copy):

flag=None
#AB judgment (3 directions, 1 succeeded, 2 returned, 3 continued,)
flag_1=jianyan(data_copy)
flag_2=full(data_copy)
flag_3=result_min_len(data)
if flag_1==True:
    if flag_2==True:
        #1 success
        print('C:Results found successfully')
        print(data_copy)
        flag='C'
    if flag_2==False:
        if flag_3==0:
            #2 return
            print('A:Traverse next ans')
            flag='A'
            #label_change(pos,ans,result_label_list)
        if flag_3>0:
            #3 continue
            print('B:Go to the next position')
            flag='B'
            #label_change(pos,ans,result_label_list) 
if flag_1==False:
    #2 return
    print('A:Traverse next ans')
    flag='A'
    #label_change(pos,ans,result_label_list)
return flag

def jiashe(data,label_list_array,lunci):

data_copy=data.copy()
R=result()
ans_list=label_list_array[lunci][1]
pos=label_list_array[lunci][0]

for ans in ans_list:
    #hypothesis
    data_copy[pos[1]][pos[0]]=ans 
    #Deduction
    fill(data_copy,'result')
    fill(data_copy,'rule_')
    fill(data_copy,'rule_')
    label=AB_test(data_copy)

    if label=='B':
        #Assume next location restart assumed function
        label_change_B(pos,ans,label_list_array)
        return 'B'
    elif label=='A':
        #Suppose the next ans traverses the next ans
        label_change_A(pos,ans,label_list_array) 
    elif label=='C':
        #print('success')
        return data_copy

def jie(data,label_list_array):
ind=0
for i in range(10):

    f_1=jiashe(data,label_list_array,ind)
    if type(f_1)==pd.core.frame.DataFrame:
        return f_1

    f_2=label_rechange(data,label_list_array)
    data_change(data,label_list_array)
    ind+=1
    if f_2:
        ind-=1
        print('B: Back to previous position')
    if f_2==False:
        return False
    #print(label_list_array[0:5])   

def main(data):
datacopy=data.copy()
fill(data,'result')
fill(data,'rule')
label_list_array=label_init(data)
shudu_jie=jie(data,label_list_array)
print('original data ')
print(data_copy)
print('result is')
print(shudu_jie)

main(data)

Tags: Python

Posted on Tue, 14 Jan 2020 22:28:31 -0500 by thegame261