Thursday, March 10, 2016

Python coding practice: 8 queen's problem

So Sasa challenged me to write a code to find all solutions to 8-queen's problem before he can write the code for the same. This is my try in python. While I took a longer time to code, my code was orders of magnitude faster than his super-elegant 4-line code. Sasa is also irritated by me using brackets for if / while; but then I am coding in SystemVerilog/ VerilogAMS at my day job!!
def try1():
        dict1 = {}
        list1 = []
        j_list = []
        i = 1
        while (i < 9):
            #print(str(i)+str("         ")+str(dict1)+str("          ")+str(list1))
            dict_list = []
            first_match = 0
            match_found = 0
         
            ##if you have come here before: add to list1 the next element in the row's dictionary
            if (i in dict1):
                if len(dict1[i][0])!=0:
                    match_found = 1
                    new_in_list1= dict1[i][0].pop(0)
                    list1.append(new_in_list1)
                    j_list.append(new_in_list1[1])
                    dict_list = dict1[i][0]
                    for k in range(i+1, 9):
                        if k in dict1:
                            dict1.pop(k)
                    ##will be incremented near the end in match_found condition
                ##implied else: ##go to no match
            else:
                for j in range(1, 9):
                    ##is column covered?
                    if (j in j_list):
                        continue
                    if (i in dict1):
                        ##rejected tuple?
                        if ((i,j) in dict1[i][1]):
                            continue
                    flag = 0
                    for x in list1:
                        if (abs(i-x[0])==abs(j-x[1])): flag = 1
                    if flag==1:
                        #print ("("+str(i)+","+str(j)+") is on diagonal to already placed queen")
                        continue
                    else:
                        match_found = 1
                        if first_match:
                            dict_list.append((i,j))
                        else:
                            list1.append((i,j))
                            j_list.append(j)
                            first_match = 1
            ##if no match found go back to prev row
            if match_found==0:
                if i > 1:
                    i = i - 1 ##go to prev row
                    if len(list1)!=0:
                         ##add prev row's val in list1 to reject list
                        dict1[i][1].append(list1.pop())
                        j_list.pop()
                else:
                    break
            else:
                if i not in dict1:
                    dict1[i]=[[], []]
                dict1[i][0]=dict_list
                if i==8:
                    print(list1)
                    tup1 = list1.pop()
                    dict1[8][1].append(tup1) ##add prev row's val in list1 to reject list
                    j_list.pop()

                else:
                    i = i + 1