def trim_and_report(pboard, things_to_trim, real_corners, x_length, key): x_length_lookup = {3: "triplicate", 4: "quadruplicate"} #log(0, things_to_trim) display = [] #log(0, real_corners) for coord in real_corners: if coord != key: for poss in pboard[coord[0]][coord[1]]: display.append((coord, poss, "set1")) for poss in pboard[key[0]][key[1]]: display.append((key, poss, "set2")) first_entry = True for number_info in things_to_trim: for coord in number_info[1]: y, x = coord[0], coord[1] pboard[y][x].remove(number_info[0]) if first_entry: first_entry = False GAMESTEPS[0] += 1 display.append((coord, number_info[0], "remove")) else: display = [(coord, number_info[0], "remove")] msg = " because its seen by all members of the hinged " + x_length_lookup[ x_length] display_msg = "Removed " + str(number_info[0]) + msg support.update_gamestepslog('pboard', 'remove', coord, number_info[0], display_msg, False, display)
def trim_and_report(pboard, things_to_trim, real_corners, x_length, key): x_length_lookup = {3:"triplicate", 4:"quadruplicate"} #log(0, things_to_trim) display = [] #log(0, real_corners) for coord in real_corners: if coord != key: for poss in pboard[coord[0]][coord[1]]: display.append((coord, poss, "set1")) for poss in pboard[key[0]][key[1]]: display.append((key, poss, "set2")) first_entry = True for number_info in things_to_trim: for coord in number_info[1]: y, x = coord[0], coord[1] pboard[y][x].remove(number_info[0]) if first_entry: first_entry = False GAMESTEPS[0] += 1 display.append((coord, number_info[0], "remove")) else: display = [(coord, number_info[0], "remove")] msg = " because its seen by all members of the hinged " + x_length_lookup[x_length] display_msg = "Removed " + str(number_info[0]) + msg support.update_gamestepslog('pboard', 'remove', coord, number_info[0], display_msg, False, display)
def locked_pairs(board, pboard): for number in NUMBERS: for xtype in range(2): # look for 2 binary pairs pairs = [] for line in LINES[xtype]: pair = find_binary_pair(pboard, line, xtype, number) if pair: pairs.append(pair) # enumerate every possible combination of 2 pairs (if you find 3 binary pairs there are 3 possible squares) combopairs = return_pair_combos(pairs) if combopairs: for combo in combopairs: #log(0, "checking combo" + str(combo)) altpairs, alt_xtype = rotate(combo, xtype) if check_if_square(pboard, altpairs, alt_xtype): trimmed = [] for altpair in altpairs: trimmed += trim_alt_line_in_square(pboard, altpair, alt_xtype, number) if trimmed: GAMESTEPS[0] += 1 locked_pairs = [cflip(combo[0][0]), cflip(combo[0][1]), cflip(combo[1][0]), cflip(combo[1][1]),] msg = "Removed " + str(number) + " because of the locked pairs at " + str(locked_pairs)[1:-1] display = [(combo[0][0], number, "set1"), (combo[0][1], number, "set1"), (combo[1][0], number, "set1"), (combo[1][1], number, "set1")] # fill in the rest of the reporting details laters for coord in trimmed: otl = list(display) otl.append((coord, number, "remove")) support.update_gamestepslog('pboard', 'remove', coord, number, msg, False, otl) return True return False
def solve_singles(board, pboard): lone = look_for_lone_ptable_entries(pboard) if lone[0]: for value in lone[1]: msg = "possibility table at " + str(cflip(value[0])) + " has only a single entry which is the number " + str(value[1]) support.update_gamestepslog("board", "add", value[0], value[1], msg, True) support.oo_update_actions(value[0], value[1], board, pboard) return True return False
def report(pboard, key, corner1, corner2, trimmed_list, alt): msg = "Removed " + str(alt) + " due to corner intersection at the corners " + str(cflip(corner1)) + ", " + str(cflip(corner2)) + " and the key " + str(cflip(key)) GAMESTEPS[0] += 1 y, x = key[0], key[1] num1, num2 = pboard[y][x][0], pboard[y][x][1] display = [(key, num1, 'set1'), (key, num2, 'set1'), (corner1, num1, 'set1'), (corner2, num2, 'set1'), (corner1, alt, 'set2'), (corner2, alt, 'set2'),] for coord in trimmed_list: otl = list(display) otl.append((coord, alt, "remove")) support.update_gamestepslog('pboard', 'remove', coord, alt, msg, False, otl)
def trim_cleanup(list_of_trims, chain_display, msg, any_trim, y, x): if not any_trim: GAMESTEPS[0] += 1 any_trim = True for removed_number in list_of_trims: trimme_msg = "trimmed " + str(removed_number) + msg onetimelist = chain_display[:] onetimelist.append(((y, x), removed_number, 'remove')) support.update_gamestepslog('pboard', 'remove', (y, x), removed_number, trimme_msg, False, onetimelist) return any_trim
def trim_naked_matches(pboard, trim_type, x_length): trim_type_lookup = { 0: "row", 1: "column", 2: "square", } x_lenth_lookup = {2: "pair", 3: "triplicate"} any_trim = False results = naked_matches(pboard, trim_type, x_length) if results[0]: for result in results[1]: dedup = False matched, line = result[0], result[1] matched_nums = [] m_c = matched[0] for num in pboard[m_c[0]][m_c[1]]: matched_nums.append(num) coordinates = get_coord_list(line, trim_type) # replace with my extra check set of coords coordinates = extra_check( coordinates, matched, trim_type, ) for number in matched_nums: for c in coordinates: if c not in matched: if number in pboard[c[0]][c[1]]: any_trim = True pboard[c[0]][c[1]].remove(number) #print "removed", number, "from", c c_list = '' for e in matched: c_list += str(cflip(e)) + ' ' msg = "Trimmed " + str( number) + " due to naked " + x_lenth_lookup[ x_length] + " at " + c_list displaystuff = [] for numbers in matched_nums: displaystuff.append( (matched[0], numbers, "set1")) displaystuff.append( (matched[1], numbers, "set1")) displaystuff.append((c, number, "remove")) if dedup: support.update_gamestepslog( 'pboard', 'remove', c, number, msg, False, displaystuff) else: support.update_gamestepslog( 'pboard', 'remove', c, number, msg, True, displaystuff) dedup = True return any_trim
def solve_single_possible(board, pboard): placed = False type_x_lookup = {0:"row", 1:"column", 2:"square"} possible = look_for_single_poss_numbers(pboard) if possible[0]: for value in possible[1]: msg = "the number " + str(value[1]) + " showed up only once in the possibility table for its " + str(type_x_lookup[value[2]]) support.update_gamestepslog(b_type="board", func="add", coord=value[0], num=value[1], msg=msg, step_up=True) support.oo_update_actions(value[0], value[1], board, pboard) placed = True return placed
def solve_singles(board, pboard): lone = look_for_lone_ptable_entries(pboard) if lone[0]: for value in lone[1]: msg = "possibility table at " + str( cflip(value[0]) ) + " has only a single entry which is the number " + str(value[1]) support.update_gamestepslog("board", "add", value[0], value[1], msg, True) support.oo_update_actions(value[0], value[1], board, pboard) return True return False
def trim_ptable_from_chains(pboard, number, type): any_trim = False if type == "simple": chained = find_all_simple_chain(pboard, number) if type == "complex": chained = find_chain_board(pboard, number) if chained[0]: for chain in chained[1]: alist, blist = chain[0], chain[1] display = [] for coord in alist: display.append((coord, number, 'set1')) for coord in blist: display.append((coord, number, 'set2')) invalid = invalid_chain_board(alist, blist) displayed = False if invalid[0]: any_trim = True GAMESTEPS[0] += 1 msg = "Invalid binary chain" for c in invalid[1]: onetimelist = [(c, number, 'remove')] display.extend(onetimelist) pboard[c[0]][c[1]].remove(number) support.update_gamestepslog('pboard', 'remove', c, number, msg, False, display) excess = find_excess_chain_board(pboard, alist, blist, number) excess_trimmed = False if len(excess) > 0: for c in excess: pboard[c[0]][c[1]].remove(number) excess_trimmed = True if excess_trimmed: any_trim = True msg = "Trimmed excess " + str( number) + " that isnt in the binary chains" GAMESTEPS[0] += 1 for coord in excess: onetimelist = display[:] onetimelist.append((coord, number, 'remove')) support.update_gamestepslog('pboard', 'remove', coord, number, msg, False, onetimelist) # If a trime was done stop looping and return true if any_trim: return any_trim # No chain found, no trim is possible else: return False
def trim_cleanup(pboard, matched_coords, trimmed_list): first_entry = True display = [] for coord in matched_coords: y, x = coord[0], coord[1] for num in pboard[y][x]: display.append((coord, num, "set1")) for entry in trimmed_list: if first_entry: first_entry = False GAMESTEPS[0] += 1 display.append((entry[0], entry[1], "remove")) else: display = [(entry[0], entry[1], "remove")] msg = "Removed " + str(entry[1]) + " because its sees a naked triplicate" support.update_gamestepslog('pboard', 'remove', entry[0], entry[1], msg, False, display)
def gridtacular(pboard, x_length): ''' Solves for variable size grids returns a boolean indicating work done ''' for number in NUMBERS: for x_type in range(2): data_array = [] # Each line should contain between 1 and x_length of my number to be considered for line in LINES[x_type]: potential_line = [] coords = get_coord_list(line, x_type) for coord in coords: y, x = coord[0], coord[1] if number in pboard[y][x]: potential_line.append(coord) if len(potential_line) > 0: if len(potential_line) <= x_length: data_array.append(list(potential_line)) # I need at least my x_length worth of lines to attempt to make a grid if len(data_array) >= x_length: possible_combinations = create_set_iterable( x_length, len(data_array)) for combination in possible_combinations: grid_info = is_a_grid(data_array, combination, x_type) if grid_info: trimmed = trim_grid(pboard, number, grid_info, x_type) if trimmed: GAMESTEPS[0] += 1 msg = "Removed " + str( number ) + " as its seen by the " + trim_type_lookup[ x_type] + " based grid" display = [] for grid_coord in grid_info[0]: display.append((grid_coord, number, "set1")) for coord in trimmed: otl = list(display) otl.append((coord, number, "remove")) support.update_gamestepslog( 'pboard', 'remove', coord, number, msg, False, otl) # Stop looping completely, because there was something to trim return True else: continue # Nothing at all found, im done return False
def trim_ptable_from_chains(pboard, number, type): any_trim = False if type == "simple": chained = find_all_simple_chain(pboard, number) if type == "complex": chained = find_chain_board(pboard, number) if chained[0]: for chain in chained[1]: alist, blist = chain[0], chain[1] display = [] for coord in alist: display.append((coord, number, 'set1')) for coord in blist: display.append((coord, number, 'set2')) invalid = invalid_chain_board(alist, blist) displayed = False if invalid[0]: any_trim = True GAMESTEPS[0] += 1 msg = "Invalid binary chain" for c in invalid[1]: onetimelist = [(c, number, 'remove')] display.extend(onetimelist) pboard[c[0]][c[1]].remove(number) support.update_gamestepslog('pboard', 'remove', c, number, msg, False, display) excess = find_excess_chain_board(pboard, alist, blist, number) excess_trimmed = False if len(excess) > 0: for c in excess: pboard[c[0]][c[1]].remove(number) excess_trimmed = True if excess_trimmed: any_trim = True msg = "Trimmed excess " + str(number) + " that isnt in the binary chains" GAMESTEPS[0] += 1 for coord in excess: onetimelist = display[:] onetimelist.append((coord, number, 'remove')) support.update_gamestepslog('pboard', 'remove', coord, number, msg, False, onetimelist) # If a trime was done stop looping and return true if any_trim: return any_trim # No chain found, no trim is possible else: return False
def locked_pairs(board, pboard): for number in NUMBERS: for xtype in range(2): # look for 2 binary pairs pairs = [] for line in LINES[xtype]: pair = find_binary_pair(pboard, line, xtype, number) if pair: pairs.append(pair) # enumerate every possible combination of 2 pairs (if you find 3 binary pairs there are 3 possible squares) combopairs = return_pair_combos(pairs) if combopairs: for combo in combopairs: #log(0, "checking combo" + str(combo)) altpairs, alt_xtype = rotate(combo, xtype) if check_if_square(pboard, altpairs, alt_xtype): trimmed = [] for altpair in altpairs: trimmed += trim_alt_line_in_square( pboard, altpair, alt_xtype, number) if trimmed: GAMESTEPS[0] += 1 locked_pairs = [ cflip(combo[0][0]), cflip(combo[0][1]), cflip(combo[1][0]), cflip(combo[1][1]), ] msg = "Removed " + str( number ) + " because of the locked pairs at " + str( locked_pairs)[1:-1] display = [(combo[0][0], number, "set1"), (combo[0][1], number, "set1"), (combo[1][0], number, "set1"), (combo[1][1], number, "set1")] # fill in the rest of the reporting details laters for coord in trimmed: otl = list(display) otl.append((coord, number, "remove")) support.update_gamestepslog( 'pboard', 'remove', coord, number, msg, False, otl) return True return False
def trim_cleanup(pboard, matched_coords, match_nums, trimmed_list, msg): first_entry = True display = [] for coord in matched_coords: y, x = coord[0], coord[1] for num in pboard[y][x]: if num in match_nums: display.append((coord, num, "set1")) for entry in trimmed_list: if first_entry: first_entry = False GAMESTEPS[0] += 1 display.append((entry[0], entry[1], "remove")) else: display = [(entry[0], entry[1], "remove")] display_msg = "Removed " + str(entry[1]) + msg support.update_gamestepslog('pboard', 'remove', entry[0], entry[1], display_msg, False, display)
def trim_cleanup(pboard, key, corners, match_nums, trimmed_list, msg): first_entry = True display = [] for num in match_nums: display.append((key, num, "set1")) for corner in corners: y, x = corner[0], corner[1] for num in pboard[y][x]: if num in match_nums: display.append((corner, num, "set1")) for entry in trimmed_list: if first_entry: first_entry = False GAMESTEPS[0] += 1 display.append((entry[0], entry[1], "remove")) else: display = [(entry[0], entry[1], "remove")] display_msg = "Removed " + str(entry[1]) + msg support.update_gamestepslog('pboard', 'remove', entry[0], entry[1], display_msg, False, display)
def report(pboard, key, corner1, corner2, trimmed_list, alt): msg = "Removed " + str( alt) + " due to corner intersection at the corners " + str( cflip(corner1)) + ", " + str( cflip(corner2)) + " and the key " + str(cflip(key)) GAMESTEPS[0] += 1 y, x = key[0], key[1] num1, num2 = pboard[y][x][0], pboard[y][x][1] display = [ (key, num1, 'set1'), (key, num2, 'set1'), (corner1, num1, 'set1'), (corner2, num2, 'set1'), (corner1, alt, 'set2'), (corner2, alt, 'set2'), ] for coord in trimmed_list: otl = list(display) otl.append((coord, alt, "remove")) support.update_gamestepslog('pboard', 'remove', coord, alt, msg, False, otl)
def gridtacular(pboard, x_length): ''' Solves for variable size grids returns a boolean indicating work done ''' for number in NUMBERS: for x_type in range(2): data_array = [] # Each line should contain between 1 and x_length of my number to be considered for line in LINES[x_type]: potential_line = [] coords = get_coord_list(line, x_type) for coord in coords: y, x = coord[0], coord[1] if number in pboard[y][x]: potential_line.append(coord) if len(potential_line) > 0: if len(potential_line) <= x_length: data_array.append(list(potential_line)) # I need at least my x_length worth of lines to attempt to make a grid if len(data_array) >= x_length: possible_combinations = create_set_iterable(x_length, len(data_array)) for combination in possible_combinations: grid_info = is_a_grid(data_array, combination, x_type) if grid_info: trimmed = trim_grid(pboard, number, grid_info, x_type) if trimmed: GAMESTEPS[0] += 1 msg = "Removed " + str(number) + " as its seen by the " + trim_type_lookup[x_type] + " based grid" display = [] for grid_coord in grid_info[0]: display.append((grid_coord, number, "set1")) for coord in trimmed: otl = list(display) otl.append((coord, number, "remove")) support.update_gamestepslog('pboard', 'remove', coord, number, msg, False, otl) # Stop looping completely, because there was something to trim return True else: continue # Nothing at all found, im done return False
def trim_naked_matches(pboard, trim_type, x_length): trim_type_lookup = {0:"row", 1:"column", 2:"square",} x_lenth_lookup = { 2:"pair", 3:"triplicate"} any_trim = False results = naked_matches(pboard, trim_type, x_length) if results[0]: for result in results[1]: dedup = False matched, line = result[0], result[1] matched_nums = [] m_c = matched[0] for num in pboard[m_c[0]][m_c[1]]: matched_nums.append(num) coordinates = get_coord_list(line, trim_type) # replace with my extra check set of coords coordinates = extra_check(coordinates, matched, trim_type,) for number in matched_nums: for c in coordinates: if c not in matched: if number in pboard[c[0]][c[1]]: any_trim = True pboard[c[0]][c[1]].remove(number) #print "removed", number, "from", c c_list = '' for e in matched: c_list += str(cflip(e)) + ' ' msg = "Trimmed " + str(number) + " due to naked " + x_lenth_lookup[x_length] + " at " + c_list displaystuff = [] for numbers in matched_nums: displaystuff.append((matched[0], numbers, "set1")) displaystuff.append((matched[1], numbers, "set1")) displaystuff.append((c, number, "remove")) if dedup: support.update_gamestepslog('pboard', 'remove', c, number, msg, False, displaystuff) else: support.update_gamestepslog('pboard', 'remove', c, number, msg, True, displaystuff) dedup = True return any_trim
def trim_ptable_for_num_in_line(pboard, trim_type): ''' Looks for a number appearing only in a line in a single square ''' trim_type_lookup = { 0:"row", 1:"column"} any_trim = False for square in SQUARES: coords = get_coord_list(square, 2) if trim_type == 0: # take first (upper left cell) coord and iterate off Y iterate_base = coords[0][0] if trim_type == 1: # take first (upper left cell) coord and iterate off X iterate_base = coords[0][1] # look through all three rows/columns, no more no less for i in range(3): # iterate_base is the current row/column number iterate_now = i + iterate_base current_set = set() rest_of_line_set = set() rest_of_square_set = set() current_line = [] rest_of_line = [] rest_of_square = [] for coord in coords: if trim_type == 0: comparison = coord[0] if trim_type == 1: comparison = coord[1] if comparison == iterate_now: # can update whole line except if in my square... ie current_line current_line.append(coord) for element in pboard[coord[0]][coord[1]]: current_set.add(element) else: rest_of_square.append(coord) for element in pboard[coord[0]][coord[1]]: rest_of_square_set.add(element) # check for a number existing only in the currentset uniqueset = current_set - rest_of_square_set # get row/column coord list line_list = get_coord_list(current_line[0], trim_type) for coord in line_list: if coord not in current_line: rest_of_line.append(coord) for element in pboard[coord[0]][coord[1]]: rest_of_line_set.add(element) if len(uniqueset) >= 1: for u_num in uniqueset: #log(0,uniqueset) #log(0, str(square) + " square") # clear the number from the rest of the line uniquenum = u_num # clean the rest of the line first_trim = True for coord in line_list: if coord not in current_line: if uniquenum in pboard[coord[0]][coord[1]]: msg = "trimmed " + str(uniquenum) + " because it has to be in " + trim_type_lookup[trim_type] + " " + str(iterate_now + 1) + " in square " + str(square + 1) display = [(coord, uniquenum, 'remove'), ] for entry in current_line: display.append((entry, uniquenum, 'set1')) if first_trim: any_trim = True support.update_gamestepslog('pboard', 'remove', coord, uniquenum, msg, True, display) first_trim = False else: support.update_gamestepslog('pboard', 'remove', coord, uniquenum, msg, False, display) pboard[coord[0]][coord[1]].remove(uniquenum) # only update 1 number if any_trim: return True # checking for requirement to "only" be in a certain row/column for i in range(len(current_set)): numtoeval = current_set.pop() if numtoeval not in rest_of_line_set: if numtoeval in rest_of_square_set: first_trim = True for coord in rest_of_square: if numtoeval in pboard[coord[0]][coord[1]]: msg = "trimmed " + str(numtoeval) + " because in square " + str(square + 1) + " the number can only be in " + trim_type_lookup[trim_type] + " " + str(iterate_now + 1) display = [(coord, numtoeval, 'remove')] for entry in current_line: display.append((entry, numtoeval, 'set1')) if first_trim: any_trim = True support.update_gamestepslog('pboard', 'remove', coord, numtoeval, msg, True, display) first_trim = False else: support.update_gamestepslog('pboard', 'remove', coord, numtoeval, msg, False, display) pboard[coord[0]][coord[1]].remove(numtoeval) return any_trim