def fill( puzzle_name ):
	"""
	**********************************************************************************************************************

	"""
	# puzzle_structure.read_raw_puzzle( puzzle_name )
	puzzle = puzzle_structure.create_puzzle( puzzle_name, 'skeleton' )
	# clue_scraper.lookup_all_clues( puzzle_name )

	puzzle_structure.sort_answers( puzzle_name )
	f = open( 'puzzles/' + puzzle_name + '/' + puzzle_name + '-answers.txt', 'r' )
	answers = f.read().splitlines()[3:]
	for i in range( len( answers ) ):
		answers[i] = answers[i].strip().split( '\t' )
		answers[i] = [ int( answers[i][0] ), int( answers[i][1] ), answers[i][2], ast.literal_eval( answers[i][3] ), ast.literal_eval( answers[i][4] ) ]

	recursive_solver( puzzle, answers, 0 )
	puzzle_structure.print_puzzle( puzzle )
def recursive_solver( puzzle, answers, answer_index ):
	"""
	**********************************************************************************************************************

	"""
	time.sleep( .25 )
	puzzle_structure.print_puzzle( puzzle )
	## exit condition ##
	if ( answer_index == len( answers ) ):
		return 1

	cur_info = answers[ answer_index ]
	candidates = cur_info[4]
	print( answer_index, candidates )

	for candidate in candidates:
		if ( is_valid( candidate, puzzle, cur_info[0], cur_info[1], cur_info[2] ) ):
			puzzle = fill_answer( candidate, puzzle, cur_info[0], cur_info[1], cur_info[2] )
			if recursive_solver( puzzle, answers, answer_index + 1 ):
				return 1
			puzzle = fill_answer( ' ' * len( candidate ), puzzle, cur_info[0], cur_info[1], cur_info[2] )
Beispiel #3
0
def fill_all_singletons(answers, puzzle, ignore_longs):
    """
	**********************************************************************************************************************
	Fills the grid with all singleton answers, i.e. answers that are the only
	candidate. Remove filled answers once filled

	@param: {string[][]} answers The list of information about each clue
	@param: {string[][]} puzzle The current grid representation
	@param: {boolean} ignore_longs When true, ignore long answers, as they are
								   more likely to have generated a false positive
	@return: {string[][], string[][]} The updated answers and puzzle state
	"""
    to_remove = []
    for info in answers:

        ## clear console using escape sequence ##
        print(chr(27) + '[2J')
        ## print the puzzle to stdout ##
        puzzle_structure.print_puzzle(puzzle)
        time.sleep(TIME_DELAY)

        candidates = info[4]
        if len(candidates) != 1:
            break
        answer = candidates[0]
        ## ignore long answers ##
        if len(answer) > 6 and ignore_longs:
            continue
        row = info[0]
        col = info[1]
        direction = info[2]
        ## fill the answer ##
        fill_answer(answer, puzzle, row, col, direction)
        to_remove.append(info)

    ## remove all filled answers ##
    for info in to_remove:
        answers.remove(info)

    return answers, puzzle
def fill_all_singletons( answers, puzzle, ignore_longs ):
	"""
	**********************************************************************************************************************
	Fills the grid with all singleton answers, i.e. answers that are the only
	candidate. Remove filled answers once filled

	@param: {string[][]} answers The list of information about each clue
	@param: {string[][]} puzzle The current grid representation
	@param: {boolean} ignore_longs When true, ignore long answers, as they are
								   more likely to have generated a false positive
	@return: {string[][], string[][]} The updated answers and puzzle state
	"""
	to_remove = []
	for info in answers:

		## clear console using escape sequence ##
		print( chr( 27 ) + '[2J' )
		## print the puzzle to stdout ##
		puzzle_structure.print_puzzle( puzzle )
		time.sleep( TIME_DELAY )

		candidates = info[4]
		if len( candidates ) != 1:
			break
		answer = candidates[0]
		## ignore long answers ##
		if len( answer ) > 6 and ignore_longs:
			continue
		row = info[0]
		col = info[1]
		direction = info[2]
		## fill the answer ##
		fill_answer( answer, puzzle, row, col, direction )
		to_remove.append( info )

	## remove all filled answers ##
	for info in to_remove:
		answers.remove( info )

	return answers, puzzle
Beispiel #5
0
def fill_empty_squares(puzzle):
    """
	**********************************************************************************************************************
	Fill any remaining squares with 'E' since it's the most common letter

	@param: {string[][]} puzzle The current puzzle
	@param: {string[][]} The updated puzzle
	"""
    height = len(puzzle)
    width = len(puzzle[0])

    ## find empty squares ##
    for i in range(height):
        for j in range(width):
            if puzzle[i][j] == ' ':
                puzzle[i][j] = 'E'
                ## clear console using escape sequence ##
                print(chr(27) + '[2J')
                ## print the puzzle to stdout ##
                puzzle_structure.print_puzzle(puzzle)
                time.sleep(TIME_DELAY)

    return puzzle
def fill_empty_squares( puzzle ):
	"""
	**********************************************************************************************************************
	Fill any remaining squares with 'E' since it's the most common letter

	@param: {string[][]} puzzle The current puzzle
	@param: {string[][]} The updated puzzle
	"""
	height = len( puzzle )
	width = len( puzzle[0] )

	## find empty squares ##
	for i in range ( height ):
		for j in range ( width ):
			if puzzle[i][j] == ' ':
				puzzle[i][j] = 'E'
				## clear console using escape sequence ##
				print( chr( 27 ) + '[2J' )
				## print the puzzle to stdout ##
				puzzle_structure.print_puzzle( puzzle )
				time.sleep( TIME_DELAY )

	return puzzle
Beispiel #7
0
def score_puzzle(diff_arr):
    """
	Evaluate the puzzle based on the differences between our solution and the correct solution.
	One point for each correct letter, plus 10 points for each fully correct word.

	@param: {string[][]} diff_arr The puzzle with differences highlighted
	@return: {float, float} Percent of squares correct, percent of words correct
	"""
    ## count the wrong letters ##
    height = len(diff_arr)
    width = len(diff_arr[0])
    total_letters = 0
    wrong_letters = 0
    total_answers = 0
    correct_answers = 0

    for i in range(height):
        for j in range(width):
            if (diff_arr[i][j]) != '0':
                total_letters += 1

            ## see if word is correct ##
            k, l = i, j
            if (k == 0 and diff_arr[k][l] != '0') or (
                    diff_arr[k - 1][l] == '0'
                    and diff_arr[k][l] != '0'):  # start of a 'down' clue
                total_answers += 1
                while (True):
                    if diff_arr[k][l].islower():
                        break
                    if (k + 1) == height or diff_arr[k][
                            l] == '0':  # whole answer is correct
                        correct_answers += 1
                        break
                    k += 1

            k, l = i, j
            if (l == 0 and diff_arr[k][l] != '0') or (
                    diff_arr[k][l - 1] == '0'
                    and diff_arr[k][l] != '0'):  # start of an 'across' clue
                total_answers += 1
                while (True):
                    if diff_arr[k][l].islower():
                        break
                    if (l + 1) == width or diff_arr[k][
                            l] == '0':  # whole answer is correct
                        correct_answers += 1
                        break
                    l += 1

            ## see if letter is correct ##
            if diff_arr[i][j].islower():
                wrong_letters += 1

    ## print puzzle with wrong letters highlighted ##
    print(chr(27))
    puzzle_structure.print_puzzle(diff_arr)

    ## print some statistics ##
    print(
        str(total_letters - wrong_letters) + ' squares correct out of ' +
        str(total_letters))
    print(
        str(correct_answers) + ' answers correct out of ' + str(total_answers))
    print('score: ' +
          str((total_letters - wrong_letters) + 10 * total_answers))

    letters_correct = 100 * (float(total_letters - wrong_letters) /
                             total_letters)
    words_correct = 100 * (float(correct_answers) / total_answers)
    return letters_correct, words_correct
Beispiel #8
0
def score_puzzle( diff_arr ):
	"""
	**********************************************************************************************************************
	Evaluate the puzzle based on the differences between our solution and the correct solution.
	One point for each correct letter, plus 10 points for each fully correct word.

	@param: {string[][]} diff_arr The puzzle with differences highlighted
	@return: {float, float} Percent of squares correct, percent of words correct
	"""
	## count the wrong letters ##
	height = len( diff_arr )
	width = len( diff_arr[0] )
	total_letters = 0
	wrong_letters = 0
	total_answers = 0
	correct_answers = 0

	for i in range( height ):
		for j in range( width ):
			if ( diff_arr[i][j] ) != '0':
				total_letters += 1

			## see if word is correct ##
			k, l = i, j
			if ( k == 0 and diff_arr[k][l] != '0' ) or ( diff_arr[k-1][l] == '0' and diff_arr[k][l] != '0' ): # start of a 'down' clue
				total_answers += 1
				while ( True ):
					if diff_arr[k][l].islower():
						break
					if ( k + 1 ) == height or diff_arr[k][l] == '0': # whole answer is correct
						correct_answers += 1
						break
					k += 1

			k, l = i, j
			if ( l == 0 and diff_arr[k][l] != '0' ) or ( diff_arr[k][l-1] == '0' and diff_arr[k][l] != '0' ): # start of an 'across' clue
				total_answers += 1
				while ( True ):
					if diff_arr[k][l].islower():
						break
					if ( l + 1 ) == width or diff_arr[k][l] == '0': # whole answer is correct
						correct_answers += 1
						break
					l += 1

			## see if letter is correct ##
			if diff_arr[i][j].islower():
				wrong_letters += 1

	## print puzzle with wrong letters highlighted ##
	print( chr(27) + "[2J" )
	puzzle_structure.print_puzzle( diff_arr )

	## print some statistics ##
	print( str( total_letters - wrong_letters ) + ' squares correct out of ' + str( total_letters ) )
	print( str( correct_answers ) + ' answers correct out of ' + str( total_answers ) )
	print( 'score: ' +  str( ( total_letters - wrong_letters ) + 10 * total_answers ) )

	letters_correct = 100 * ( float ( total_letters - wrong_letters ) / total_letters )
	words_correct = 100 * ( float( correct_answers ) / total_answers )
	return letters_correct, words_correct
Beispiel #9
0
def fill(puzzle_name):
    """
	**********************************************************************************************************************
	This does all the work solving the puzzle, starting with reading the raw
	input, then generating all candidate answers and filling the grid

	@param: {string} puzzle_name
	"""
    ## read the raw puzzle input ##
    puzzle_structure.read_raw_puzzle(puzzle_name)
    ## create a blank skeleton ##
    puzzle = puzzle_structure.create_puzzle(puzzle_name, 'skeleton')
    ## scrape all the clues ##
    clue_scraper.lookup_all_clues(puzzle_name)

    ## ask for input to keep solving ##
    # print( 'Answers computed. Proceed with solving? ' )
    # cont = sys.stdin.readline()

    ## keep track of the puzzle at the previous iteration to control ##
    ## how long to solve at each step ##
    previous_puzzle_state = []

    puzzle_structure.sort_answers(puzzle_name)
    f = open('puzzles/' + puzzle_name + '/' + puzzle_name + '-answers.txt',
             'r')
    answers = f.read().splitlines()[3:]

    ## extract answer data into list ##
    for i in range(len(answers)):
        answers[i] = answers[i].strip().split('\t')
        answers[i][0] = int(answers[i][0])
        answers[i][1] = int(answers[i][1])
        answers[i][3] = ast.literal_eval(answers[i][3])
        answers[i][4] = ast.literal_eval(answers[i][4])

    ## fill singleton answers and update the candidates until this no longer ##
    ## yields any change in the puzzle ##
    while puzzle != previous_puzzle_state:
        ## update previous state ##
        previous_puzzle_state = [row[:] for row in puzzle]
        ## fill all singletons, update possibilites, and resort ##
        answers, puzzle = fill_all_singletons(answers, puzzle, True)
        answers = update_candidates(answers, puzzle)
        answers = sorted(answers, cmp=puzzle_structure.compare_answers)
        answers = refactor_answers(answers)

    previous_puzzle_state = []
    ## update answers with single word and wikipedia title searches ##
    ## then fill singletons until this no longer yields any change ##
    while puzzle != previous_puzzle_state:
        ## update previous state ##
        previous_puzzle_state = [row[:] for row in puzzle]
        answers = search_dictionaries(answers)
        answers = sorted(answers, cmp=puzzle_structure.compare_answers)
        answers = refactor_answers(answers)
        ## fill the singletons ##
        answers, puzzle = fill_all_singletons(answers, puzzle, False)
        answers = update_candidates(answers, puzzle)

    ## fill based on the first candidate. this is pretty arbitrary ##
    for answer in answers:
        if len(answer[4]) > 0:
            puzzle = fill_answer(answer[4][0], puzzle, answer[0], answer[1],
                                 answer[2])
        ## clear console using escape sequence ##
        print(chr(27) + '[2J')
        ## print the puzzle to stdout ##
        puzzle_structure.print_puzzle(puzzle)
        time.sleep(TIME_DELAY)

    ## fill the rest of the squares with 'E'. this is extremely arbitrary ##
    puzzle = fill_empty_squares(puzzle)

    ## write the final output for evaluation ##
    puzzle_structure.write_puzzle(puzzle_name, puzzle)
Beispiel #10
0
def fill( puzzle_name ):
	"""
	**********************************************************************************************************************
	This does all the work solving the puzzle, starting with reading the raw
	input, then generating all candidate answers and filling the grid

	@param: {string} puzzle_name
	"""
	## read the raw puzzle input ##
	puzzle_structure.read_raw_puzzle( puzzle_name )
	## create a blank skeleton ##
	puzzle = puzzle_structure.create_puzzle( puzzle_name, 'skeleton' )
	## scrape all the clues ##
	clue_scraper.lookup_all_clues( puzzle_name )

	## ask for input to keep solving ##
	# print( 'Answers computed. Proceed with solving? ' )
	# cont = sys.stdin.readline()

	## keep track of the puzzle at the previous iteration to control ##
	## how long to solve at each step ##
	previous_puzzle_state = []

	puzzle_structure.sort_answers( puzzle_name )
	f = open( 'puzzles/' + puzzle_name + '/' + puzzle_name + '-answers.txt', 'r' )
	answers = f.read().splitlines()[3:]

	## extract answer data into list ##
	for i in range( len( answers ) ):
		answers[i] = answers[i].strip().split( '\t' )
		answers[i][0] = int( answers[i][0] )
		answers[i][1] = int( answers[i][1] )
		answers[i][3] = ast.literal_eval( answers[i][3] )
		answers[i][4] = ast.literal_eval( answers[i][4] )

	## fill singleton answers and update the candidates until this no longer ##
	## yields any change in the puzzle ##
	while puzzle != previous_puzzle_state:
		## update previous state ##
		previous_puzzle_state = [ row[:] for row in puzzle ]
		## fill all singletons, update possibilites, and resort ##
		answers, puzzle = fill_all_singletons( answers, puzzle, True )
		answers = update_candidates( answers, puzzle )
		answers = sorted( answers, cmp=puzzle_structure.compare_answers )
		answers = refactor_answers( answers )


	previous_puzzle_state = []
	## update answers with single word and wikipedia title searches ##
	## then fill singletons until this no longer yields any change ##
	while puzzle != previous_puzzle_state:
		## update previous state ##
		previous_puzzle_state = [ row[:] for row in puzzle ]
		answers = search_dictionaries( answers )
		answers = sorted( answers, cmp=puzzle_structure.compare_answers )
		answers = refactor_answers( answers )
		## fill the singletons ##
		answers, puzzle = fill_all_singletons( answers, puzzle, False )
		answers = update_candidates( answers, puzzle )


	## fill based on the first candidate. this is pretty arbitrary ##
	for answer in answers:
		if len( answer[4] ) > 0:
			puzzle = fill_answer( answer[4][0], puzzle, answer[0], answer[1], answer[2] )
		## clear console using escape sequence ##
		print( chr( 27 ) + '[2J' )
		## print the puzzle to stdout ##
		puzzle_structure.print_puzzle( puzzle )
		time.sleep( TIME_DELAY )

	## fill the rest of the squares with 'E'. this is extremely arbitrary ##
	puzzle = fill_empty_squares( puzzle )

	## write the final output for evaluation ##
	puzzle_structure.write_puzzle( puzzle_name, puzzle )