Im kind of confused on how to implement this in python, I need to be able to iterate through 6 total files, but 2 files at a time, and read a line from one file, do what that line does, then switch over to read a line from the other file and do what it says, and then vice versa iterating down both files, here is what the files would look like:
START,T1
READ,y,B3
EXECUTE,y+1
WRITE,y,B3
READ,z,C1
READ,x,A3
EXECUTE,z=z+x
EXECUTE,x+2
EXECUTE,x+2
WRITE,x,A3
WRITE,z,C1
READ,y,B3
EXECUTE,y+8
READ,z,B2
EXECUTE,z+2
WRITE,z,B2
WRITE,y,B3
READ,x,A1
EXECUTE,x+3
WRITE,x,A1
COMMIT
END,T1
and here is my current code which can parse them:
class Database:
def __init__(self):
self.file = self.readFile()
self.temp_db = None
self.y = 0
self.x = 0
self.z = 0
def readFile(self):
df = pd.read_csv('database.txt', sep=',', engine='python')
df = df.iloc[: , 1:]
df.index = df.index + 1
return df
def parseTransaction(self, fileName, num, transaction):
# if(self.temp_db == None):
# self.temp_db = self.file
with open(fileName, 'r') as t1_file:
for line in t1_file:
split_line = line.split(',')
with open('schedule'+num+'.txt', 'a') as the_file:
the_file.write('Transaction ' + transaction + ': ' + split_line[0] + '\n')
if(split_line[0] == "START"):
continue
elif(split_line[0] == "READ"):
self.read(self.temp_db, split_line[1], split_line[2])
elif(split_line[0] == "EXECUTE"):
self.execute(split_line[1])
elif(split_line[0] == "WRITE"):
self.write(self.temp_db, split_line[1], split_line[2])
elif(split_line[0] == "COMMIT"): #Doesnt ever hit true?
continue
elif(split_line[0] == "END"):
break
def t1(self, num):
self.parseTransaction('t1.txt', num, '1')
def t2(self, num):
self.parseTransaction('t2.txt', num, '2')
def t3(self, num):
self.parseTransaction('t3.txt', num, '3')
def t4(self, num):
self.parseTransaction('t4.txt', num, '4')
def t5(self, num):
self.parseTransaction('t5.txt', num, '5')
def t6(self, num):
self.parseTransaction('t6.txt', num, '6')
def serializeTransaction(self):
self.temp_db = self.file
self.t1('1')
self.t2('1')
self.t3('1')
self.t4('1')
self.t5('1')
self.t6('1')
self.temp_db.to_csv(r'C:\Users\laner\Desktop\program 3\database1.txt', sep=',')
self.temp_db = None
def interleave(self):
self.temp_db = self.file
self.temp_db.to_csv(r'C:\Users\laner\Desktop\program 3\database2.txt', sep=',')
def read(self, db, var, indentfier):
row = indentfier[1]
col = indentfier[0]
res = db.at[int(row),col]
if(var == 'y'):
self.y = res
elif(var == 'x'):
self.x = res
elif(var == 'z'):
self.z = res
def execute(self, expression):
varCount = expression.count(expression[0])
var = None
varName = None
if(varCount == 1):
for char in expression:
if(char == 'y'):
var = self.y
varName = 'y'
elif(char == 'x'):
var = self.x
varName = 'x'
elif(char == 'z'):
var = self.z
varName = 'z'
elif(char == '+'):
continue
else:
try:
var += int(char)
except:
pass
if(varName == 'y'):
self.y = int(var)
elif(varName == 'x'):
self.x = int(var)
elif(varName == 'z'):
self.z = int(var)
elif(varCount == 2):
for char in expression:
if(char == 'y' and varName == None):
var = self.y
varName = 'y'
elif(char == 'x' and varName == None):
var = self.x
varName = 'x'
elif(char == 'z' and varName == None):
var = self.z
varName = 'z'
elif(char == varName or char == '+'):
continue
elif(char == 'y' and varName != None):
var += self.y
elif(char == 'x' and varName != None):
var += self.x
elif(char == 'z' and varName != None):
var += self.z
if(varName == 'y'):
self.y = int(var)
elif(varName == 'x'):
self.x = int(var)
elif(varName == 'z'):
self.z = int(var)
def write(self, db, var, identifier):
row = identifier[1]
col = identifier[0]
if(var == 'y'):
db.at[int(row),col] = self.y
self.y = 0
elif(var == 'x'):
db.at[int(row),col] = self.x
self.x = 0
elif(var == 'z'):
db.at[int(row),col] = self.z
self.z = 0
t1-t6 function is for reading the specified files in, so t1 is what i pasted above and t2 looks similar like this:
START,T2
READ,y,A2
EXECUTE,y+2
WRITE,y,A2
READ,z,B2
READ,x,A3
EXECUTE,x+5
WRITE,x,A3
EXECUTE,z+2
WRITE,z,B2
READ,y,C1
EXECUTE,y+4
READ,z,A1
EXECUTE,z+10
WRITE,z,A1
WRITE,y,C1
READ,x,A3
EXECUTE,x=x+y
WRITE,x,A3
COMMIT
END,T2
there are 6 of these files in total, so thats where im at, parsing through 2 files at once one file at a time and cycling between the two?
In general, you can interleave two streams using itertools.chain and zip. (A file-like object can be treated as a stream of str values.)
>>> from itertools import chain
>>> list(chain.from_iterable(zip([1,2,3], "abc")))
[1, 'a', 2, 'b', 3, 'c']
This extends to an arbitrary number of iterables in a straight word manner, by simply passing each iterable as a separate argument to zip. You can define a function to wrap this:
def interleave(*args):
yield from chain.from_iterable(zip(*args))
for x in interleave("abc", "def", "ghi"):
print(x)
outputs
a
d
g
b
e
h
c
f
i
I'm making chess in python. It was all working and I had the moves as a list of indexes but I decided to use a class instead as I thought this would be better. However, now the function to get all the legal moves doesn't seem to work and I've found that this is because for some reason it thinks it can move a pawn from a4 to a5 on the starting board and I think this could be because it doesn't change the position back to the normal position after checking a2 to a4 but does move it on the board which is made up of a list of lists however I cannot find why. The error is caused by the code in lines 379-387 which stops you making a move if it puts you in check because when I comment it out there's no error. I've been searching for hours so if someone could help then it would be much appreciated. Also any other feedback would be helpful.
Exceptions.py
# Base class for other exceptions
pass
class NoPieceThereError(Error):
# When there's no piece on the selected tile
pass
class InvalidFENError(Error):
# When the inputed FEN is invalid
pass
class WrongPieceColour(Error):
# Chose the wrong piece colour
pass
class InvalidMove(Error):
# Not a legal move
pass
class InvalidInput(Error):
pass
class KingNotFound(Error):
pass
Chess.py
import random
alphabet = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z".split()
def IsInt(number):
try:
int(number)
return True
except:
return False #returns True if the input is a number
def AddTuples(tuple1, tuple2):
return tuple([x + y for x, y in zip(tuple1, tuple2)])
def MultiplyTuple(tuple1, multiplyer):
return tuple([int(x * multiplyer) for x in tuple1])
def PositionToIndex(position):
try:
row = int(position[1]) - 1
column = alphabet.index(position[0].upper())
return (row, column) # Converts a position "e2" to an index "(1, 4)"
except:
raise Exceptions.InvalidInput
def IndexToPosition(index):
try:
row = str(index[0] + 1)
column = alphabet[index[1]].lower()
return column + row # Converts an index "(1, 4)" to a position "e2"
except:
raise Exceptions.InvalidInput
class FEN():
def __init__(self, passed_FEN):
passed_FEN = passed_FEN.split()
if len(passed_FEN) != 6:
raise Exceptions.InvalidFENError
self.board_FEN = passed_FEN[0]
self.turn = passed_FEN[1]
self.castling = passed_FEN[2]
self.en_passant = passed_FEN[3]
self.half_move_clock = passed_FEN[4]
self.full_move_clock = passed_FEN[5]
def __repr__(self):
return " ".join([
self.board_FEN,
self.turn,
self.castling,
self.en_passant,
self.half_move_clock,
self.full_move_clock
])
def ChangeTurn(self):
self.turn = "b" if self.turn == "w" else "w"
#property
def board_FEN_split(self):
return self.board_FEN.split("/")
class Move():
def __init__(self, start_row, start_column, end_row, end_column, capturing_piece, capturing_row, capturing_column, FEN_before):
self.start_row = start_row
self.start_column = start_column
self.end_row = end_row
self.end_column = end_column
self.capturing = capturing_piece
self.capturing_row = capturing_row
self.capturing_column = capturing_column
self.FEN_before = FEN_before
#property
def start(self):
return (self.start_row, self.start_column)
#property
def end(self):
return (self.end_row, self.end_column)
#property
def capturing_pos(self):
return (self.capturing_row, self.capturing_column)
def __repr__(self):
if self.capturing != None:
string = f" capturing {self.capturing.__repr__()} at {IndexToPosition(self.capturing_pos)}"
else:
string = ""
return f"Piece moved from {IndexToPosition(self.start)} to {IndexToPosition(self.end)}" + string + f", FEN before: {self.FEN_before}"
def __eq__(self, other):
return True if self.__repr__() == other.__repr__() else False
#property
def taking_equals_moved(self):
return True if None == self.capturing_row == self.capturing_column or self.capturing_row == self.end_row and self.capturing_column == self.end_column else False
"""
class Engine():
piece_values = {
"p": 1,
"n": 3,
"b": 3,
"r": 5,
"q": 9
}
#staticmethod
def EvaluatePosition(board):
total = 0
for row in board.board:
for cell in row:
if cell != None:
if cell.__repr__().lower() in Engine.piece_values:
if cell.__repr__().islower():
total -= Engine.piece_values[cell.__repr__()]
else:
total += Engine.piece_values[cell.__repr__().lower()]
return total
#staticmethod
def ChooseComputerMove(board):
move = random.choice(board.GetAllLegalMoves())
board.MovePiece(*move)
#staticmethod
def Search(board, depth=10, alpha=0, beta=0):
if depth == 0:
return Engine.EvaluatePosition(board)
moves = board.GetAllLegalMoves()
if len(moves) == 0:
if board.IsInCheck(board.FEN.turn):
return -10000
return 0
for move in moves:
board.MovePiece(*move)
evaluation = -Engine.Search(board, depth-1, -beta, -alpha)
board.UnmakeMove()
if evaluation >= beta:
# Move was too good so the opponent will avoid this position
return beta
alpha = max(alpha, evaluation)
return alpha
"""
class Board():
def __init__(self,
passed_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
extra_pieces = [],
board_height = 8,
board_width = 8
):
pieces = [
#default pieces
('p', 'Pawn', Pawn),
('r', 'Rook', Rook),
('n', 'Knight', Knight),
('b', 'Bishop', Bishop),
('q', 'Queen', Queen),
('k', 'King', King),
] + extra_pieces #any extra piece types
self.pieces_letters, self.pieces_names, self.pieces_classes = [tuple([piece[x] for piece in pieces]) for x in range(3)]
self.FEN = FEN(passed_FEN)
self.move_list = []
self.board = []
self.board_height = board_height
self.board_width = board_width
for row_index, row in enumerate(self.FEN.board_FEN_split[::-1]):
self.board.append([])
cell_index = 0
for cell in row:
if IsInt(cell):
[self.board[-1].append(None) for x in range(int(cell))]
cell_index += int(cell)
else:
self.board[-1].append(self.CreatePiece(cell, (row_index, cell_index)))
cell_index += 1
def CreatePiece(self, piece_code, position):
piece_name = self.pieces_classes[self.pieces_letters.index(piece_code.lower())]
colour = "w" if piece_code.upper() == piece_code else "b"
return piece_name(colour, position, self)
def DisplayBoard(self, debug = False):
print()
print()
for index, column in enumerate(self.board[::-1]):
if debug:
print(7 - index, end = " ")
else:
print(8 - index, end = " ")
print(" | ".join(" " if x == None else x.__repr__() for x in column))
print("-" * 4 * self.board_width)
print(" ", end = "")
if debug:
print(" | ".join([str(x) for x in range(self.board_width)]))
else:
print(" | ".join(alphabet[:self.board_width]))
def GetBoardValue(self, row, column):
return self.board[row][column]
def FindKing(self, colour):
for rowi, row in enumerate(self.board):
for celli, cell in enumerate(row):
if cell != None:
if cell.type == "King" and cell.colour == colour:
return (rowi, celli)
raise Exceptions.KingNotFound
def IsInCheck(self, colour):
for row in self.board:
for cell in row:
if cell != None:
if cell.colour != colour:
if cell.IsChecking():
return True
return False
def GetAllLegalMoves(self):
LegalMoves = []
for row in self.board:
for cell in row:
if cell != None:
if cell.colour == self.FEN.turn:
LegalMoves += cell.LegalMoves()
return LegalMoves
def FindMove(self, moves = None, start_row = "*", start_column = "*", end_row = "*", end_column = "*"):
if moves == None:
moves = self.GetAllLegalMoves()
for move in moves:
if (
(start_row == "*" or start_row == move.start_row) and
(start_column == "*" or start_column == move.start_column) and
(end_row == "*" or end_row == move.end_row) and
(end_column == "*" or end_column == move.end_column)
):
return move
raise Exceptions.InvalidInput
def MakeMove(self, move):
self.move_list.append(move)
# Changing en passant FEN
if self.board[move.start_row][move.start_column].__repr__().lower() == "p" and abs(move.start_row - move.end_row) == 2:
self.FEN.en_passant = IndexToPosition(((move.start_row + move.end_row) / 2, move.end_column))
else:
self.FEN.en_passant = "-"
# Move piece
print(move)
self.board[move.start_row][move.start_row].position = move.end
self.board[move.end_row][move.end_column] = self.board[move.start_row][move.start_column]
self.board[move.start_row][move.start_column] = None
# If taking a piece not at the location it moved to i.e. en passant
if not move.taking_equals_moved:
self.board[capturing_row][capturing_column] = None
def UnmakeMove(self, number_to_undo=1):
for x in range(number_to_undo):
if self.move_list == []:
print(f"No more moves to undo. Only undid {x} moves")
return
move = self.move_list.pop()
# Move piece back
self.board[move.end_row][move.end_column].position = move.start
self.board[move.start_row][move.start_column] = self.board[move.end_row][move.end_column]
self.board[move.end_row][move.end_column] = None
# Restore captured piece
if move.capturing != None:
self.board[move.capturing_row][move.capturing_column] = move.capturing
# Restore FEN
self.FEN = move.FEN_before
def OnBoard(self, row, column):
return True if 0 <= row < self.board_height and 0 <= column < self.board_width else False
class Piece():
def __init__(self, colour, position, board):
self.colour = colour
self.position = position
self.board = board
def SimilarMoves(self, directions, *args, **kwargs):
legal_moves = []
for direction in directions:
legal_moves += self.CheckForCollision(direction, *args, **kwargs)
return legal_moves
def CheckForCollision(self, direction, limit, must_capture = False, can_capture = True, can_capture_en_passant = False, current_turn = False):
legal_moves = []
checks = 1
current_pos = self.position
while checks <= limit or limit == 0:
current_pos = AddTuples(current_pos, direction)
#if off the board
if not self.board.OnBoard(*current_pos):
break
current_pos_piece = self.GetBoardValue(*current_pos)
#if moving to an empty square
if current_pos_piece == None:
#capturing en passant
#if there is an en passant somewhere and the piece is allowed to capture en passant
if can_capture_en_passant and self.board.FEN.en_passant != "-":
#if it's capturing the en passant square
if PositionToIndex(self.board.FEN.en_passant) == current_pos:
#if it not capturing it's own piece
en_passant_start = self.board.board_height - 4 if self.colour == "w" else 3
if self.position[0] == en_passant_start:
move = Move(
*self.position,
*current_pos,
self.GetBoardValue(en_passant_start, current_pos[1]),
en_passant_start, current_pos[1],
FEN(self.board.FEN.__repr__()))
legal_moves.append(move)
#moving to empty space
elif not must_capture:
legal_moves.append(Move(
*self.position,
*current_pos,
self.GetBoardValue(*current_pos),
None, None,
FEN(self.board.FEN.__repr__())))
#moving to own piece colour
elif self.colour == current_pos_piece.colour:
break
#moving to opponent piece colour
elif self.colour != current_pos_piece.colour:
if can_capture:
legal_moves.append(Move(
*self.position,
*current_pos,
self.board.GetBoardValue(*current_pos),
*current_pos,
FEN(self.board.FEN.__repr__())
))
break
checks += 1
if current_turn == True:
index = 0
while index < len(legal_moves):
self.board.MakeMove(legal_moves[index])
if self.board.IsInCheck(self.colour):
legal_moves.pop(index)
else:
index += 1
self.board.UnmakeMove()
return legal_moves
#property
def row(self):
return self.position[0]
#property
def column(self):
return self.position[1]
def __repr__(self):
letter = self.board.pieces_letters[self.board.pieces_names.index(self.type)]
return letter.upper() if self.colour == "w" else letter
def IsEmpty(self, row, column):
return True if self.GetBoardValue(row, column) == None else False
def GetBoardValue(self, row, column):
return self.board.GetBoardValue(row, column)
#property
def direction(self):
if self.colour == "w":
return 1
else:
return -1
#property
def enemy_colour(self):
if self.colour == "w":
return "b"
else:
return "w"
def CheckCorrectTurn(self):
return True if self.colour == self.board.FEN.turn else False
def IsChecking(self):
enemy_king_pos = self.board.FindKing(self.enemy_colour)
moves = self.LegalMoves(current_turn = False)
for move in moves:
if move == enemy_king_pos:
return True
return False
class Pawn(Piece):
def __init__(self, colour, position, board):
super().__init__(colour, position, board)
self.type = "Pawn"
def LegalMoves(self, current_turn = True):
legal_moves = []
print(self.position)
on_starting_row = self.row == 1 and self.colour == 'w' or self.row == self.board.board_height - 2 and self.colour == "b"
#forwards
limit = 2 if on_starting_row else 1
legal_moves += self.CheckForCollision((self.direction, 0), limit, can_capture = False, current_turn=current_turn)
#capturing
capturing_directions = ((self.direction, 1), (self.direction, -1))
legal_moves += self.SimilarMoves(capturing_directions, 1, must_capture = True, can_capture_en_passant = True, current_turn=current_turn)
return legal_moves
class Rook(Piece):
directions = ((1, 0), (0, 1), (-1, 0), (0, -1))
def __init__(self, colour, position, board):
super().__init__(colour, position, board)
self.type = "Rook"
def LegalMoves(self, current_turn = True):
legal_moves = self.SimilarMoves(self.directions, 0, current_turn=current_turn)
return legal_moves
class Knight(Piece):
directions = ((2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2), (2, -1))
def __init__(self, colour, position, board):
super().__init__(colour, position, board)
self.type = "Knight"
def LegalMoves(self, current_turn = True):
legal_moves = self.SimilarMoves(self.directions, 1, current_turn=current_turn)
return legal_moves
class Bishop(Piece):
directions = ((1, 1), (-1, 1), (-1, -1), (1, -1))
def __init__(self, colour, position, board):
super().__init__(colour, position, board)
self.type = "Bishop"
def LegalMoves(self, current_turn = True):
legal_moves = self.SimilarMoves(self.directions, 0, current_turn=current_turn)
return legal_moves
class King(Piece):
directions = Rook.directions + Bishop.directions
def __init__(self, colour, position, board):
super().__init__(colour, position, board)
self.type = "King"
def LegalMoves(self, current_turn = True):
legal_moves = self.SimilarMoves(self.directions, 1, current_turn=current_turn)
return legal_moves
class Queen(Piece):
directions = Rook.directions + Bishop.directions
def __init__(self, colour, position, board):
super().__init__(colour, position, board)
self.type = "Queen"
def LegalMoves(self, current_turn = True):
legal_moves = self.SimilarMoves(self.directions, 0, current_turn=current_turn)
return legal_moves
def main():
entered_FEN_valid = False
while not entered_FEN_valid:
try:
player_FEN = input("Would you like to play with a custom FEN. If so put it here, or press enter for a default board: ")
if not player_FEN:
player_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
b = Board(player_FEN)
entered_FEN_valid = True
except Exceptions.InvalidFENError:
print("Invalid FEN")
#no longer needed as I added Smith --> print("Moves are entered in the form \"{row} {column}\" with row and column being numbers from 0-7. Bottom left is 0 0. Example input: \"1 4\"")
debug = False # True if input("Debug Mode? (Y/N): ").lower() == "y" else False
player_colour = "w"
player_won = False
apawn = b.board[1][0]
while not player_won:
#if len(b.GetAllLegalMoves()) == 0:
# player_won = True
# print(b.IsInCheck("b"))
# if b.IsInCheck(b.FEN.turn):
# player_who_won = "w" if b.FEN.turn == "b" else "b"
# else:
# player_who_won = "no one"
# break
try:
if True: #b.FEN.turn == player_colour:
b.DisplayBoard(debug)
#print(Engine.Search(b, depth = 20))
#print("\n".join([x.__repr__() for x in b.move_list]))
#print([[IndexToPosition(position) for position in move] for move in b.GetAllLegalMoves()])
#print(len(b.GetAllLegalMoves()))
start = input("\nEnter start: ")
if start.lower()[:4] == "undo":
b.UnmakeMove(int(start[-1]))
else:
start = PositionToIndex(start)
if b.GetBoardValue(*start) == None:
raise Exceptions.NoPieceThereError
moves = b.GetBoardValue(*start).LegalMoves()
if moves == []:
raise Exceptions.WrongPieceColour
print("Legal moves: \n" + str([IndexToPosition((x.end_row, x.end_column)) for x in moves]))
end = PositionToIndex(input("\nEnter end: "))
print(start, end)
b.MakeMove(b.FindMove(
moves = moves,
start_row = start[0],
start_column = start[1],
end_row = end[0],
end_column = end[1]))
else:
Engine.ChooseComputerMove(b)
except Exceptions.NoPieceThereError:
print("There is no piece there")
except Exceptions.WrongPieceColour:
print("That is not the correct piece colour")
except Exceptions.InvalidMove:
print("That is not a legal move")
#except Exceptions.InvalidInput:
# print("Invalid input")
#except:
# print("Unknown error")
print(player_who_won, "won!")
if __name__ == "__main__":
#main()
b = Board()
print(b.GetAllLegalMoves())
So I found that the positions of the pieces kept changing randomly so I just made it a property of the Piece class that finds it each time
class Piece():
#property
def position(self):
for rowi, row in enumerate(self.board.board):
for celli, cell in enumerate(row):
if cell == self:
return (rowi, celli)
I am trying to make a sudoku solver that solves boards very quickly. At the moment my solver works on easy boards but never terminates on harder boards. I believe it has something to do with my recursion because easy boards do not require recursion and hard boards do. Any help is appreciated.
import sys
def rowno(i):
return i // 9
def colno(i):
return i % 9
def boxno(i):
return (i // 9 // 3 )*3 + (i // 3) % 3
def isNeighbor(i, j):
if rowno(i) == rowno(j) or colno(i) == colno(j) or boxno(i) == boxno(j):
return True
else:
return False
def getFileName():
if sys.platform == "win32":
filename = input("Filename? ")
else:
filename = sys.argv[-1]
return filename
solutionlist = []
class Board(object):
def __init__(self, puzzle):
self.puzzle = puzzle
self.board = [Cell(int(value), idx) for idx, value in enumerate(puzzle)]
self.change = False
def printAll(self):
print [cell.candidates for cell in self.board]
#return str(" ")
def update(self):
self.change = False
l = [cell for cell in self.board if len(cell.candidates) == 1]
for i in l:
for j in xrange(81):
if isNeighbor(i.dex, j) and i.dex != j:
old = self.board[j].candidates
self.board[j].delCandidate(i.value)
if len(old) != len(self.board[j].candidates):
self.change = True
def toString(self):
str1 = ''.join(str(e.value) for e in self.board)
return str1
def solved(self):
for cell in self.board:
if len(cell.candidates) != 1:
return False
return True
def solve(self):
self.change = True
while self.change == True:
self.update()
if self.solved():
solutionlist.append(self.board)
return
l = [cell for cell in self.board if len(cell.candidates) > 1]
for i in l:
for j in i.candidates:
newBoard = Board(self.toString())
curLen = 12
curCell = -1
for u in l:
if len(u.candidates)<curLen:
curLen=len(u.candidates)
curCell = u.dex
for c in newBoard.board[curCell].candidates:
newBoard.board[curCell].candidates = [int(c)]
newBoard.board[curCell].value = int(c)
newBoard.solve()
return
def __repr__(self):
l = [cell.value for cell in self.board]
return str(l)
class Cell(object):
def __init__(self, value, dex):
self.value = value
self.dex = dex
if value == 0:
self.candidates = [1,2,3,4,5,6,7,8,9]
else:
self.candidates = [int(value)]
def __str__(self):
return str(self.value)
def delCandidate(self, value):
# deletes value from candidate list
#return self.candidate.remove(value);
self.candidates = [x for x in self.candidates if x != value]
if len(self.candidates) == 1:
self.value = self.candidates[0]
easy = "700583006006001405052006083300200958500078060648010300060802500003150072215600030"
twosol = "000805200800000401705040009000100702040000000006430000030900000010006080000000000"
hard = "040090008000000070060000120030020000005839060080600700050170600000043000003000200"
#easy solution: 794583216836721495152496783371264958529378164648915327967832541483159672215647839
b = Board(hard)
print b
b.solve()
print "end of the line"
for i in solutionlist:
print [cell.value for cell in i]
print "\n"
One major issue is the line for i in l: in the solve method. Since you're recursing, you only need to fill in one cell - the recursion will take care of the rest. So instead of for i in l:, just recurse on the one cell that is the best candidate (curCell):
l = [cell for cell in self.board if len(cell.candidates) > 1]
if len(l) > 0:
newBoard = Board(self.toString())
curLen = 12
curCell = -1
for u in l:
if len(u.candidates)<curLen:
curLen=len(u.candidates)
curCell = u.dex
for c in newBoard.board[curCell].candidates:
newBoard.board[curCell].candidates = [int(c)]
newBoard.board[curCell].value = int(c)
newBoard.solve()