Ejemplo n.º 1
0
def clone(compressed, filename):
    contents = None
    with open(filename) as f:
        contents = f.read()

    puzzle, name, reverse_id_map = load(contents)
    board = puzzle.board
    revealed = puzzle.revealed
    constraints = puzzle.og_constraints

    num = len(board)
    board.sort(
        key=lambda c: c[0] in revealed)  # praise be to Python's stable sort

    if not compressed:
        return dict(
            num=num,
            board=board,
            revealed=revealed,
            constraints=constraints,
        )
    else:
        replace_cells(board, revealed, constraints, compressed)
        puzzle = Puzzle(board, revealed, constraints)
        result = puzzle.solve()
        scored = score(result, 'seqnum')
        title = f'Cloned "{name}" with score {scored}'
        tile_text = 'CLO'

        data = extract(contents)
        num_revealed = 0
        for index, node in enumerate(data['nodes']):
            if index in revealed:
                node['revealed'] = True
                num_revealed += 1
            else:
                node['has_mine'] = compressed[index - num_revealed] == '*'
                node['secret'] = compressed[index - num_revealed] == '?'

        return dict(
            title=title,
            tile_text=tile_text,
            scored=scored,
            nodes=data['nodes'],
            columns=data['columns'],
            colors=data['colors'],
        )
Ejemplo n.º 2
0
def cl_corner_bite_render(compressed, size):
    num, board, revealed, constraints, _ = cl_corner_bite(size)

    tile_size = 10
    points = '-{s},-{s},{s},-{s},{s},{s},-{s},{s}'.format(s=0.96 * tile_size /
                                                          2)

    nodes = []
    columns = []

    for i in range(num):
        board[i][1] = compressed[i]
        nodes.append(
            dict(
                id=i,
                neighbors=board[i][2],
                position=((i % size) * tile_size, (i // size) * tile_size),
                has_mine=compressed[i] == '*',
                secret=compressed[i] == '?',
                revealed=i in revealed,
                points=points,
            ))

    for j in range(size):
        # horizontal column hints
        constraints[2 * j][0] = sum(
            [compressed[i] == '*' for i in constraints[2 * j][1]])
        columns.append(
            dict(
                ids=constraints[2 * j][1],
                text_location=(-tile_size, j * tile_size),
            ))

        # vertical column hints
        constraints[2 * j + 1][0] = sum(
            [compressed[i] == '*' for i in constraints[2 * j + 1][1]])
        columns.append(
            dict(
                ids=constraints[2 * j + 1][1],
                text_location=(j * tile_size, -tile_size),
            ))

    constraints[-1][0] = compressed.count('*')

    result = Puzzle(board, revealed, constraints).solve()
    scored = score(result, 'seqnum')
    title = f'CL Corner Bite {size}x{size} with score {scored}'
    tile_text = 'CoB'

    return dict(
        title=title,
        tile_text=tile_text,
        nodes=nodes,
        columns=columns,
        scored=scored,
    )
Ejemplo n.º 3
0
def test_conformsToRuleThreeIsolatedWhiteTile():
	p = Puzzle( ((2, 1, 3),
				 (1, 1, 2),
				 (3, 2, 1)), True)
	p.markBlack(1, 1)
	p.markBlack(2, 0)
	p.markBlack(2, 2)
	assert(not p.conformsToRuleThree())
Ejemplo n.º 4
0
def test_conformsToRuleOneMultipleMarked():
	p = Puzzle( ((2, 1), (1, 1)), False)
	p.markBlack(1, 1)
	assert(p.conformsToRuleOne())
Ejemplo n.º 5
0
def test_conformsToRuleOneNoneMarked():
	p = Puzzle( ((2, 1), (1, 1)), False)
	assert(not p.conformsToRuleOne())
Ejemplo n.º 6
0
def test_getMarkedNum():
	p = Puzzle( ((2, 1), (1, 1)), True)
	assert(p.getNum(0, 0) == 2)
Ejemplo n.º 7
0
def L_shape_grid(compressed, size, depth):
    """
    33
    13
  2114
  2244
  """
    size, depth = int(size), int(depth)
    side_length = 2 * size * 2**depth
    points = '-{s},-{s},{s},-{s},{s},{s},-{s},{s}'.format(s=0.96 / 2)
    cindex = 0

    board = []
    revealed = []
    constraints = []
    nodes = []
    columns = []
    colors = [
        dict(ids=[], color='RED', is_dark=False),
        dict(ids=[], color='ORANGE', is_dark=False),
        dict(ids=[], color='GREEN', is_dark=False),
        dict(ids=[], color='BLUE', is_dark=False),
    ]

    id_map = dict()
    for y in range(side_length):
        for x in range(side_length):
            if x < side_length // 2 - 1 and y < side_length // 2 - 1:
                continue
            else:
                id_map[(x, y)] = len(id_map)

    pos_to_id = lambda x, y: id_map.get((x, y))

    for y in range(side_length):
        for x in range(side_length):
            if x < side_length // 2 - 1 and y < side_length // 2 - 1:
                continue

            cell_id = pos_to_id(x, y)
            neighbors = []

            for dy in range(-1, 2):
                for dx in range(-1, 2):
                    if dx == dy == 0:
                        continue

                    neighbor_id = pos_to_id(x + dx, y + dy)
                    if neighbor_id:
                        neighbors.append(neighbor_id)

            if x < side_length // 2 and y < side_length // 2:
                what = '.'
                revealed.append(cell_id)
            else:
                what = compressed[cindex] if compressed else ''
                cindex += 1

                temp_x, temp_y, threshold = x, y, side_length // 4

                for i in range(depth):
                    if threshold <= temp_x < 3 * threshold and threshold <= temp_y < 3 * threshold:
                        if i == depth - 1:
                            colors[0]['ids'].append(cell_id)
                        else:
                            temp_x -= threshold
                            temp_y -= threshold

                    elif temp_x < threshold * 2:
                        if i == depth - 1:
                            colors[1]['ids'].append(cell_id)
                        else:
                            temp_x, temp_y = temp_y - threshold * 2, threshold * 2 - temp_x - 1

                    elif temp_y < threshold * 2:
                        if i == depth - 1:
                            colors[2]['ids'].append(cell_id)
                        else:
                            temp_x, temp_y = threshold * 2 - temp_y - 1, temp_x - threshold * 2

                    else:
                        if i == depth - 1:
                            colors[3]['ids'].append(cell_id)
                        else:
                            temp_x -= threshold * 2
                            temp_y -= threshold * 2

                    threshold //= 2

            board.append([cell_id, what, neighbors])

            if compressed:
                nodes.append(
                    dict(
                        id=cell_id,
                        neighbors=neighbors,
                        position=(x, y),
                        has_mine=what == '*',
                        secret=what == '?',
                        revealed=cell_id in revealed,
                        points=points,
                    ))

    constraints.append([
        sum([c[1] == '*' for c in board]),
        [c[0] for c in board if c[0] not in revealed]
    ])

    for color in colors:
        constraints.append(
            [sum(board[n][1] == '*' for n in color['ids']), color['ids']])

    num = 3 * side_length**2 // 4
    board.sort(
        key=lambda c: c[0] in revealed)  # praise be to Python's stable sort

    if not compressed:
        return dict(
            num=num,
            board=board,
            revealed=revealed,
            constraints=constraints,
        )
    else:
        result = Puzzle(board, revealed, constraints).solve()
        scored = score(result, 'seqnum')
        title = f'L-shape {size}-{depth} with score {scored}'
        tile_text = 'L'

        return dict(
            title=title,
            tile_text=tile_text,
            nodes=nodes,
            columns=columns,
            colors=colors,
            scored=scored,
        )
#     puzzle = Puzzle(g, t, buffer_size=4)
#
#     print(puzzle)
#
#     print('='*50)
#
#
# for g, t in [(g3, t3), (g4, t4)]:
#     puzzle = Puzzle(g, t, buffer_size=4)
#
#     print(puzzle)
#
#     print('='*50)
#
# for g, t in [(g5, t5)]:
#     puzzle = Puzzle(g, t, buffer_size=6)
#
#     print(puzzle)
#
#     print('='*50)

for g, t in [(g6, t6)]:
    puzzle = Puzzle(g, t, buffer_size=4)

    print(puzzle)

    f = puzzle.plot_solution()

    f.show()

    print('=' * 50)
Ejemplo n.º 9
0
def test_conformsToRuleTwoHorizontallyAdjacentMarks():
	p = Puzzle( ((2, 1), (1, 1)), True)
	p.markBlack(0, 0)
	p.markBlack(0, 1)
	assert(not p.conformsToRuleTwo())
Ejemplo n.º 10
0
def test_conformsToRuleTwoNonAdjacentMarks():
	p = Puzzle( ((2, 1), (1, 1)), True)
	p.markBlack(1, 1)
	p.markBlack(0, 0)
	assert(p.conformsToRuleTwo())
Ejemplo n.º 11
0
def test_conformsToRuleTwoSingleMark():
	p = Puzzle( ((2, 1), (1, 1)), True)
	p.markBlack(1, 1)
	assert(p.conformsToRuleTwo())
Ejemplo n.º 12
0
def test_conformsToRuleTwoUnmarked():
	p = Puzzle( ((2, 1), (1, 1)), False)
	assert(p.conformsToRuleTwo())
Ejemplo n.º 13
0
def test_getUnmarkedNum():
	p = Puzzle( ((2, 1), (1, 1)), True)
	assert(int(p.getNum(0, 1)) == 1)
Ejemplo n.º 14
0
def test_findMostRestrictedCompleted():
	b = (
		(1, 2, 3),
		(1, 1, 3),
		(2, 3, 3)
	)
	p = Puzzle(b , False)
	possibles = [
				[
					[[], [], []],
					[
						[
							[1, 0],
							[1, 1]],
						[],
						[]
					],
					[
						[],
						[],
						[
							[2, 1],
							[2, 2]
						]
					]
				],
				[
					[
						[
							[0, 0],
							[1, 0]
						],
						[],
						[]
					],
					[
						[],
						[],
						[]
					],
					[
						[],
						[],
						[
							[0, 2],
							[1, 2],
							[2, 2]
						]
					]
				]
			]
	findMostRestricted(p, possibles)
	findMostRestricted(p, possibles)

	# These should be Black
	assert(p.isBlack(1, 0))
	assert(p.isBlack(0, 2))

	# These should be now marked White
	assert(p.isWhite(0, 0))
	assert(p.isWhite(1, 2))
	assert(p.isWhite(2, 1))

	# These should still be adjacent
	assert(p.isMarkedAdjacent(1, 1))

	# The other three tiles should have remained marked White
	assert(p.isWhite(0, 1))
	assert(p.isWhite(2, 0))

	# Solve the puzzle fully
	findMostRestricted(p, possibles)

	# This should now be marked White
	assert(p.isWhite(1, 1))

	# Check that the puzzle was solved
	assert(p.isSolved())
Ejemplo n.º 15
0
def test_markBlack():
	p = Puzzle( ((2, 1), (1, 1)), True)
	p.markBlack(1, 1)
	assert(p.isBlack(1, 1))
Ejemplo n.º 16
0
def test_findMostRestricted():
	b = (
		(1, 2, 3),
		(1, 1, 3),
		(2, 3, 3)
	)
	p = Puzzle(b , False)
	possibles = [
				[
					[[], [], []],
					[
						[
							[1, 0],
							[1, 1]],
						[],
						[]
					],
					[
						[],
						[],
						[
							[2, 1],
							[2, 2]
						]
					]
				],
				[
					[
						[
							[0, 0],
							[1, 0]
						],
						[],
						[]
					],
					[
						[],
						[],
						[]
					],
					[
						[],
						[],
						[
							[0, 2],
							[1, 2],
							[2, 2]
						]
					]
				]
			]
	possibles = findMostRestricted(p, possibles)

	# The first iteration should just mark bottom-right element as black
	assert(p.isBlack(2, 2))

	# All other adjacent numbers should be marked as adjacent
	assert(p.isMarkedAdjacent(0, 0))
	assert(p.isMarkedAdjacent(0, 2))
	assert(p.isMarkedAdjacent(1, 0))
	assert(p.isMarkedAdjacent(1, 1))
	assert(p.isMarkedAdjacent(1, 2))
	assert(p.isMarkedAdjacent(2, 1))

	# The other two tiles should remain marked White
	assert(p.isWhite(0, 1))
	assert(p.isWhite(2, 0))
Ejemplo n.º 17
0
def test_conformsToRuleThreeEmpty():
	p = Puzzle( ((2, 1), (1, 1)), False)
	assert(p.conformsToRuleThree())
Ejemplo n.º 18
0
def load(contents, verbose=False):
    id_map = dict()
    nodes = []
    total_mines = 0
    initial_revealed = []

    # Not parsing arbitrary XML here!
    matches = re.finditer('<NODE>.*?</NODE>', contents, re.DOTALL)
    for match in matches:
        node = match.group(0)

        node_id = re.search('<ID>(.*?)</ID>', node).group(1)
        neighbor_ids = re.search('<EDGES>(.*?)</EDGES>',
                                 node).group(1).split(',')
        revealed = bool(re.search('<REVEALED>[Tt]rue</REVEALED>', node))
        has_mine = bool(re.search('<HAS_MINE>[Tt]rue</HAS_MINE>', node))
        secret = bool(re.search('<SECRET>[Tt]rue</SECRET>', node))

        if neighbor_ids == ['']:  # no neighbors
            neighbor_ids = []
        if revealed:
            initial_revealed.append(node_id)
        if has_mine:
            total_mines += 1

        node_info = dict(
            node_id=node_id,
            neighbor_ids=neighbor_ids,
            revealed=revealed,
            has_mine=has_mine,
            secret=secret,
        )
        id_map[node_id] = len(nodes)
        nodes.append(node_info)

    # Hack for 94: Gridlock III (that the dev had to do too)
    if re.search('<ID>(.*?)</ID>', contents).group(1) == '2256502332117638':
        initial_revealed = '0,96,33,66,3,35,99,36,37,69,6,39,9,46,26,90,60,93,30,63'.split(
            ',')

    board = []
    revealed = [id_map[revealed_id] for revealed_id in initial_revealed]
    constraints = []

    for node in nodes:
        cell = [
            id_map[node['node_id']],
            '*' if node['has_mine'] else '?' if node['secret'] else '.',
            [id_map[neighbor_id] for neighbor_id in node['neighbor_ids']],
        ]
        board.append(cell)

    constraints.append([total_mines, list(range(len(nodes)))])
    gray_mines = [total_mines, set(range(len(nodes)))]

    hints = re.finditer('<(COLUMN_)?HINT>.*?</(COLUMN_)?HINT>', contents,
                        re.DOTALL)
    for hint in hints:
        mapped_ids = []
        mine_count = 0

        ids = re.search('<IDS>(.*?)</IDS>', hint.group(0)).group(1).split(',')
        for hint_id in ids:
            hint_id = id_map[hint_id]
            mapped_ids.append(hint_id)
            mine_count += nodes[hint_id]['has_mine']

        constraints.append([mine_count, mapped_ids])

        if 'COLUMN' not in hint.group(0):
            gray_mines[0] -= mine_count
            gray_mines[1].difference_update(set(mapped_ids))

    if total_mines != gray_mines[0]:
        gray_mines[1] = sorted(gray_mines[1])
        constraints.append(gray_mines)

    if verbose:
        print('board:')
        for cell in board:
            print(' ', cell)
        print('revealed:', revealed)
        print('constraints:')
        for constraint in constraints:
            print(' ', constraint)

    name = re.search('<TITLE>(.+?)</TITLE>', contents).group(1)
    reverse_id_map = [node['node_id'] for node in nodes]
    return Puzzle(board, revealed, constraints,
                  verbose=verbose), name, reverse_id_map
Ejemplo n.º 19
0
def test_getRows():
	p = Puzzle( ((2, 1), (1, 1)), True)
	assert(p.getRows() == 2)
Ejemplo n.º 20
0
def holey_render(compressed, size):
    num, board, revealed, constraints, _ = holey(size)
    size = 2 * size + 1

    tile_size = 10
    points = '-{s},-{s},{s},-{s},{s},{s},-{s},{s}'.format(s=0.96 * tile_size /
                                                          2)

    nodes = []
    columns = []
    mapped = dict()

    for i in range(size**2):
        c = compressed[i] if i < len(compressed) else '.'
        board[i][1] = c
        mapped[board[i][0]] = c

        nodes.append(
            dict(
                id=board[i][0],
                neighbors=board[i][2],
                position=((board[i][0] % size) * tile_size,
                          (board[i][0] // size) * tile_size),
                has_mine=c == '*',
                secret=c == '?',
                revealed=board[i][0] in revealed,
                points=points,
            ))

    for j in range(size // 2 + 1):
        # horizontal column hints
        constraints[2 * j][0] = sum(
            [mapped[i] == '*' for i in constraints[2 * j][1]])
        columns.append(
            dict(
                ids=constraints[2 * j][1],
                text_location=(-tile_size, 2 * j * tile_size),
            ))

        # vertical column hints
        constraints[2 * j + 1][0] = sum(
            [mapped[i] == '*' for i in constraints[2 * j + 1][1]])
        columns.append(
            dict(
                ids=constraints[2 * j + 1][1],
                text_location=(2 * j * tile_size, -tile_size),
            ))

    constraints[-1][0] = compressed.count('*')

    result = Puzzle(board, revealed, constraints).solve()
    scored = score(result, 'seqnum')
    title = f'Holey {size}x{size} with score {scored}'
    tile_text = 'HOL'

    return dict(
        title=title,
        tile_text=tile_text,
        nodes=nodes,
        columns=columns,
        scored=scored,
    )
Ejemplo n.º 21
0
def test_conformsToRuleThreeSingleMarked():
	p = Puzzle( ((2, 1), (1, 1)), True)
	p.markBlack(0, 0)
	assert(p.conformsToRuleThree())
Ejemplo n.º 22
0
def test_conformsToRuleThreeDiagonallyDivided():
	p = Puzzle( ((2, 1), (1, 1)), True)
	p.markBlack(0, 0)
	p.markBlack(1, 1)
	assert(not p.conformsToRuleThree())
Ejemplo n.º 23
0

from flask import Flask, render_template, get_template_attribute
from solver import Puzzle, Solver
from detector import get_pattern_img, get_black_thresh
from puzzle import get_board_from_img, add_piece_edges_to_grid

app = Flask(__name__)

pattern_img = get_pattern_img()
# TODO: get only the string of the board from img,
# do everything else via the solver
board = get_board_from_img(pattern_img, get_black_thresh())
raw_board = get_board_from_img(pattern_img, get_black_thresh(), False)

puzzle = Puzzle(board['red_count'], board['black_count'])
app.jinja_env.globals.update(get_piece=puzzle.get_piece)

pieces = list(puzzle.get_pieces())
solver = Solver(board, pieces, puzzle)

# piece_sets = puzzle.get_piece_sets()

pieces_registry = puzzle.get_pieces_registry()

pieces_map = {}
for name, piece in pieces_registry.items():
  size = piece['size']
  name = piece['name']
  dev = piece['deviation']