Beispiel #1
0
 def test_add_black_cell(self):
     grid = Grid(9)
     grid.add_black_cell(1, 5)
     grid.add_black_cell(4, 9)
     expected = [(1, 5), (4, 9), (6, 1), (9, 5)]
     actual = grid.get_black_cells()
     self.assertEqual(expected, actual)
Beispiel #2
0
    def test_add_black(self):
        n = 5
        grid = Grid(n)
        black_cells = [
            (1, 1),
            (1, 3),
            (2, 3),
            (2, 4),
            (3, 1),
            (3, 2),
        ]
        for (r, c) in black_cells:
            grid.add_black_cell(r, c)

        puzzle = Puzzle(grid)

        expected_cells = [
            ["*", " ", "*", " ", " "],
            [" ", " ", "*", "*", " "],
            ["*", "*", " ", "*", "*"],
            [" ", "*", "*", " ", " "],
            [" ", " ", "*", " ", "*"],
        ]
        for r in range(1, n + 1):
            for c in range(1, n + 1):
                expected = expected_cells[r - 1][c - 1]
                actual = puzzle.get_cell(r, c)
                self.assertEqual(expected, actual, f'Mismatch at ({r},{c})')
Beispiel #3
0
 def create_atlantic_puzzle():
     """ Creates a puzzle from the Atlantic puzzle of May 15, 2020
     +-----------------+
     |D|A|B|*|*|E|F|T|S|
     |S|L|I|M|*|R|I|O|T|
     |L|O|C|A|V|O|R|E|S|
     |R|E|U|N|I|T|E|D|*|
     |*|*|R|A|P|I|D|*|*|
     |*|R|I|C|E|C|A|K|E|
     |C|O|O|L|R|A|N|C|H|
     |C|L|U|E|*|C|A|L|X|
     |R|O|S|S|*|*|E|R|E|
     +-----------------+
     """
     n = 9
     grid = Grid(n)
     for (r, c) in [
         (1, 4),
         (1, 5),
         (2, 5),
         (4, 9),
         (5, 8),
         (5, 9),
     ]:
         grid.add_black_cell(r, c)
     puzzle = Puzzle(grid)
     puzzle.title = 'My Atlantic Theme'
     return puzzle
Beispiel #4
0
def grid_new():
    """ Creates a new grid and redirects to grid screen """

    # Get the grid size from the form
    n = int(request.args.get('n'))

    # Remove any leftover grid name in the session
    session.pop('gridname', None)

    # Create the grid
    grid = Grid(n)
    jsonstr = grid.to_json()
    session['grid'] = jsonstr
    session['grid.initial.sha'] = sha256(jsonstr)

    return redirect(url_for('uigrid.grid_screen'))
Beispiel #5
0
def puzzle_new():
    """ Creates a new puzzle and redirects to puzzle screen """

    # Get the chosen grid name from the query parameters
    gridname = request.args.get('gridname')

    # Open the corresponding file and read its contents as json
    # and recreate the grid from it
    userid = 1  # TODO replace hard-coded user ID
    query = DBGrid.query.filter_by(userid=userid, gridname=gridname)
    jsonstr = query.first().jsonstr
    grid = Grid.from_json(jsonstr)

    # Now pass this grid to the Puzzle() constructor
    puzzle = Puzzle(grid)

    # Save puzzle in the session
    jsonstr = puzzle.to_json()
    session['puzzle'] = jsonstr
    session['puzzle.initial.sha'] = sha256(jsonstr)

    # Remove any leftover puzzle name in the session
    session.pop('puzzlename', None)

    return redirect(url_for('uipuzzle.puzzle_screen'))
Beispiel #6
0
 def get_bad_grid():
     jsonstr = """
 {
 "n": 7,
 "black_cells": [
 [ 1, 3 ], [ 2, 3 ], [ 3, 3 ], [ 3, 4 ], [ 3, 5 ], [ 4, 2 ],
 [ 4, 6 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ], [ 6, 5 ], [ 7, 5 ]
 ],
 "numbered_cells": [
 { "seq": 1, "r": 1, "c": 1, "a": 2, "d": 7 },
 { "seq": 2, "r": 1, "c": 2, "a": 0, "d": 3 },
 { "seq": 3, "r": 1, "c": 4, "a": 4, "d": 2 },
 { "seq": 4, "r": 1, "c": 5, "a": 0, "d": 2 },
 { "seq": 5, "r": 1, "c": 6, "a": 0, "d": 3 },
 { "seq": 6, "r": 1, "c": 7, "a": 0, "d": 7 },
 { "seq": 7, "r": 2, "c": 1, "a": 2, "d": 0 },
 { "seq": 8, "r": 2, "c": 4, "a": 4, "d": 0 },
 { "seq": 9, "r": 3, "c": 1, "a": 2, "d": 0 },
 { "seq": 10, "r": 3, "c": 6, "a": 2, "d": 0 },
 { "seq": 11, "r": 4, "c": 3, "a": 3, "d": 0 },
 { "seq": 12, "r": 5, "c": 1, "a": 2, "d": 0 },
 { "seq": 13, "r": 5, "c": 2, "a": 0, "d": 3 },
 { "seq": 14, "r": 5, "c": 6, "a": 2, "d": 3 },
 { "seq": 15, "r": 6, "c": 1, "a": 4, "d": 0 },
 { "seq": 16, "r": 6, "c": 3, "a": 0, "d": 2 },
 { "seq": 17, "r": 6, "c": 4, "a": 0, "d": 2 },
 { "seq": 18, "r": 6, "c": 6, "a": 2, "d": 0 },
 { "seq": 19, "r": 7, "c": 1, "a": 4, "d": 0 },
 { "seq": 20, "r": 7, "c": 6, "a": 2, "d": 0 }
 ]
 }        
 """
     grid = Grid.from_json(jsonstr)
     return grid
Beispiel #7
0
def grid_screen():
    """ Renders the grid screen """

    # Get the existing grid from the session
    grid = Grid.from_json(session['grid'])
    gridname = session.get('gridname', None)

    # Create the SVG
    svg = GridToSVG(grid)
    boxsize = svg.boxsize
    svgstr = svg.generate_xml()

    # Set the state to editing grid
    session['uistate'] = UIState.EDITING_GRID
    enabled = session['uistate'].get_enabled()
    enabled["grid_undo"] = len(grid.undo_stack) > 0
    enabled["grid_redo"] = len(grid.redo_stack) > 0
    enabled["grid_delete"] = gridname is not None

    # Show the grid.html screen
    return render_template('grid.html',
                           enabled=enabled,
                           n=grid.n,
                           gridname=gridname,
                           boxsize=boxsize,
                           svgstr=svgstr)
Beispiel #8
0
def grid_redo():
    """ Redoes the last grid action then redirects to grid screen """

    jsonstr = session.get('grid', None)
    grid = Grid.from_json(jsonstr)
    grid.redo()
    jsonstr = grid.to_json()
    session['grid'] = jsonstr
    return redirect(url_for('uigrid.grid_screen'))
Beispiel #9
0
    def from_json(jsonstr):
        image = json.loads(jsonstr)

        # Create a puzzle of the specified size
        n = image['n']
        grid = Grid(n)

        # Initialize the black cells
        black_cells = image['black_cells']
        for black_cell in black_cells:
            grid.add_black_cell(*black_cell)

        # Create the puzzle
        puzzle = Puzzle(grid)
        title = image.get('title', None)
        puzzle._title = title  # Can't use the undo/redo here yet

        # Reload the "ACROSS" words
        awlist = image['across_words']
        for aw in awlist:
            seq = aw['seq']
            text = aw['text']
            clue = aw['clue']
            word = puzzle.get_across_word(seq)
            word.set_text(text)  # TODO: Can't do this - undo/redo
            word.set_clue(clue)  # TODO: Can't do this - undo/redo

        # Reload the "DOWN" words
        dwlist = image['down_words']
        for dw in dwlist:
            seq = dw['seq']
            text = dw['text']
            clue = dw['clue']
            word = puzzle.get_down_word(seq)
            word.set_text(text)  # TODO: Can't do this - undo/redo
            word.set_clue(clue)  # TODO: Can't do this - undo/redo

        # Reload the undo/redo stacks
        puzzle.undo_stack = image.get('undo_stack', [])
        puzzle.redo_stack = image.get('redo_stack', [])

        # Done
        return puzzle
Beispiel #10
0
 def test_add_undo(self):
     grid = Grid(5)
     grid.add_black_cell(1, 2)
     self.assertEqual(True, grid.is_black_cell(1, 2))
     self.assertEqual(True, grid.is_black_cell(5, 4))
     self.assertEqual([(1, 2)], grid.undo_stack)
     self.assertEqual([], grid.redo_stack)
     grid.undo()
     self.assertEqual(False, grid.is_black_cell(1, 2))
     self.assertEqual(False, grid.is_black_cell(5, 4))
     self.assertEqual([], grid.undo_stack)
     self.assertEqual([(1, 2)], grid.redo_stack)
    def __init__(self, data):

        self.data = data
        self.offset = 0

        # Get the size
        self.offset = self.OFFSET_WIDTH
        self.n = n = self.read_byte()
        self.grid = grid = Grid(n)

        # Read the solution to get the black cell locations
        self.offset = self.OFFSET_WORDS
        for r in range(1, n+1):
            line = self.read_chunk(n)
            for c in range(1, n+1):
                letter = chr(line[c-1])
                if letter == self.BLACK_CELL:
                    grid.add_black_cell(r, c)

        # Create the puzzle, then go back and read the words
        self.puzzle = puzzle = Puzzle(grid)

        self.offset = self.OFFSET_WORDS
        for r in range(1, n+1):
            line = self.read_chunk(n)
            for c in range(1, n + 1):
                letter = chr(line[c-1])
                if not grid.is_black_cell(r, c):
                    puzzle.set_cell(r, c, letter)

        # Skip over the solution work area
        self.offset += n*n

        # Read the title and set it in the puzzle

        title = self.read_string()
        if title != "":
            puzzle.title = title

        # Skip the author and copyright lines
        s = self.read_string()     # author
        s = self.read_string()     # copyright

        # Read the clues
        for nc in puzzle.numbered_cells:
            if nc.a:        # Across word
                clue = self.read_string()
                puzzle.set_clue(nc.seq, Word.ACROSS, clue)
            if nc.d:        # Down word
                clue = self.read_string()
                puzzle.set_clue(nc.seq, Word.DOWN, clue)

        # Done
        self.jsonstr = puzzle.to_json()
Beispiel #12
0
 def create_puzzle():
     """
     Creates sample puzzle as:
     +---------+
     | | |*| | |
     | | |*|*| |
     |*|*| |*|*|
     | |*|*| | |
     | | |*| | |
     +---------+
     """
     n = 5
     grid = Grid(n)
     for (r, c) in [
         (1, 3),
         (2, 3),
         (2, 4),
         (3, 1),
         (3, 2),
     ]:
         grid.add_black_cell(r, c)
     return Puzzle(grid)
Beispiel #13
0
 def create_nyt_puzzle():
     """
     Creates a puzzle from a real New York Times crossword of March 15, 2020
     +-----------------------------------------+
     |A|B|B|A|*| | | |*| | | | | |*| | | | | | |
     | | | | |*| | | |*| | | | | |*| | | | | | |
     | | | | | | | | | | | | | | |*| | | | | | |
     | | | | | |*| | | | | |*| | | |*| | | | | |
     | | | |*| | | | | |*|*| | | | | |*|*| | | |
     |*|*|*| | | | | | | | | | | | | | | | | | |
     | | | | | | |*|*| | | | | | |*| | | | | | |
     | | | | |*| | | |*| | | |*|*| | | | | | | |
     | | | | | | | | | | | | | | | | | | |*|*|*|
     | | | |*| | | | | |*| | | | | | |*| | | | |
     | | | | | |*| | | | |*| | | | |*| | | | | |
     | | | | |*| | | | | | |*| | | | | |*| | | |
     |*|*|*| | | | | | | | | | | | | | | | | | |
     | | | | | | | |*|*| | | |*| | | |*| | | | |
     | | | | | | |*| | | | | | |*|*| | | | | | |
     | | | | | | | | | | | | | | | | | | |*|*|*|
     | | | |*|*| | | | | |*|*| | | | | |*| | | |
     | | | | | |*| | | |*| | | | | |*| | | | | |
     | | | | | | |*| | | | | | | | | | | | | | |
     | | | | | | |*| | | | | |*| | | |*| | | | |
     | | | | | | |*| | | | | |*| | | |*| | | | |
     +-----------------------------------------+
     """
     n = 21
     grid = Grid(n)
     for (r, c) in [(1, 5), (1, 9), (1, 15), (2, 5),
                    (2, 9), (2, 15), (3, 15), (4, 6), (4, 12), (4, 16),
                    (5, 4), (5, 10), (5, 11), (5, 17), (5, 18), (6, 1),
                    (6, 2), (6, 3), (7, 7), (7, 8), (7, 15), (8, 5), (8, 9),
                    (8, 13), (8, 14), (9, 19), (9, 20), (9, 21), (10, 4),
                    (10, 10), (11, 6), (11, 11), (12, 5), (13, 1), (13, 2),
                    (13, 3), (14, 8), (15, 7), (17, 4), (17, 5)]:
         grid.add_black_cell(r, c)
     return Puzzle(grid)
Beispiel #14
0
 def test_set_cell(self):
     n = 5
     puzzle = Puzzle(Grid(n))
     puzzle.set_cell(2, 3, 'D')
     cell = puzzle.get_cell(2, 3)
     self.assertEqual('D', cell)
     for r in range(1, n + 1):
         if r == 2:
             continue
         for c in range(1, n + 1):
             if c == 3:
                 continue
             cell = puzzle.get_cell(r, c)
             self.assertEqual(Puzzle.WHITE, cell, f'Mismatch at ({r}, {c})')
Beispiel #15
0
def grid_save_common(gridname):
    """ Common method used by both grid_save and grid_save_as """

    # Recreate the grid from the JSON in the session
    # and validate it
    jsonstr = session.get('grid', None)
    grid = Grid.from_json(jsonstr)
    ok, messages = grid.validate()
    if not ok:
        flash("Grid not saved")
        for message_type in messages:
            message_list = messages[message_type]
            if len(message_list) > 0:
                flash(f"*** {message_type} ***")
                for message in message_list:
                    flash("   " + message)
    else:
        # Save the file
        userid = 1  # TODO Replace hard coded user id
        query = DBGrid.query.filter_by(userid=userid, gridname=gridname)
        if not query.all():
            # No grid in the database. This is an insert
            logging.debug(f"Inserting grid '{gridname}' into grids table")
            created = modified = datetime.now().isoformat()
            newgrid = DBGrid(userid=userid,
                             gridname=gridname,
                             created=created,
                             modified=modified,
                             jsonstr=jsonstr)
            db.session.add(newgrid)
            db.session.commit()
        else:
            # There is a grid. This is an update
            logging.debug(f"Updating grid '{gridname}' in grids table")
            oldgrid = query.first()
            oldgrid.modified = datetime.now().isoformat()
            oldgrid.jsonstr = jsonstr
            db.session.commit()

        # Send message about save
        flash(f"Grid saved as {gridname}")

        # Store the sha256 of the saved version of the grid
        # in the session as 'grid.initial.sha' so that we can detect
        # whether it has been changed since it was last saved
        session['grid.initial.sha'] = sha256(jsonstr)

    # Show the grid screen
    return redirect(url_for('uigrid.grid_screen'))
Beispiel #16
0
def grid_rotate():
    """ Rotates the grid 90 degrees left then returns the new SVG """

    # Rotate the grid
    jsonstr = session.get('grid', None)
    grid = Grid.from_json(jsonstr)
    grid.rotate()

    # Save the updated grid in the session
    session['grid'] = grid.to_json()

    # Send the new SVG data to the client
    svg = GridToSVG(grid)
    svgstr = svg.generate_xml()
    response = make_response(svgstr, HTTPStatus.OK)
    return response
Beispiel #17
0
def grid_statistics():
    """ Return the grid statistics in a JSON string """

    # Get the grid from the session
    grid = Grid.from_json(session['grid'])
    gridname = session.get('gridname', None)
    stats = grid.get_statistics()
    enabled = {}

    svgstr = GridToSVG(grid).generate_xml()

    # Render with grid statistics template
    return render_template("grid-statistics.html",
                           enabled=enabled,
                           gridname=gridname,
                           svgstr=svgstr,
                           stats=stats)
Beispiel #18
0
def grid_new_from_puzzle():
    """ Creates a new grid from the specified puzzle """

    puzzlename = request.args.get('puzzlename')
    userid = 1  # TODO replace hard-coded user ID
    query = DBPuzzle.query.filter_by(userid=userid, puzzlename=puzzlename)
    jsonstr = query.first().jsonstr
    grid = Grid.from_json(jsonstr)
    grid.undo_stack = []
    grid.redo_stack = []
    jsonstr = grid.to_json()

    # Save grid in the session
    session['grid'] = jsonstr
    session['grid.initial.sha'] = sha256(jsonstr)

    # Remove any leftover grid name in the session
    session.pop('gridname', None)

    return redirect(url_for('uigrid.grid_screen'))
Beispiel #19
0
def grid_preview():
    """ Creates a grid preview and returns it to ??? """
    userid = 1  # TODO Replace hard coded user id

    # Get the chosen grid name from the query parameters
    gridname = request.args.get('gridname')

    # Open the corresponding file and read its contents as json
    # and recreate the grid from it
    jsonstr = grid_load_common(userid, gridname)
    grid = Grid.from_json(jsonstr)

    # Get the top two word lengths
    heading_list = [f"{grid.get_word_count()} words"]
    wlens = grid.get_word_lengths()
    wlenkeys = sorted(wlens.keys(), reverse=True)
    wlenkeys = wlenkeys[:min(2, len(wlenkeys))]
    for wlen in wlenkeys:
        entry = wlens[wlen]
        total = 0
        if entry["alist"]:
            total += len(entry["alist"])
        if entry["dlist"]:
            total += len(entry["dlist"])
        heading_list.append(f"{wlen}-letter: {total}")
    heading = f'Grid {gridname}({", ".join(heading_list)})'

    scale = 0.75
    svgobj = GridToSVG(grid, scale=scale)
    width = (svgobj.boxsize * grid.n + 32) * scale
    svgstr = svgobj.generate_xml()

    obj = {
        "gridname": gridname,
        "heading": heading,
        "width": width,
        "svgstr": svgstr
    }
    resp = make_response(json.dumps(obj), HTTPStatus.OK)
    resp.headers['Content-Type'] = "application/json"
    return resp
Beispiel #20
0
def grid_click():
    """ Adds or removes a black cell then returns the new SVG """

    # Get the row and column clicked from the query parms
    r = int(request.args.get('r'))
    c = int(request.args.get('c'))

    # Get the existing grid from the session
    jsonstr = session['grid']
    grid = Grid.from_json(jsonstr)

    # Toggle the black cell status
    if grid.is_black_cell(r, c):
        grid.remove_black_cell(r, c)
    else:
        grid.add_black_cell(r, c)

    # Save the updated grid in the session
    session['grid'] = grid.to_json()

    return redirect(url_for('uigrid.grid_screen'))
Beispiel #21
0
def puzzle_replace_grid():

    # Get the chosen grid name from the query parameters
    gridname = request.args.get('gridname')
    if not gridname:
        return redirect(url_for('uipuzzle.puzzle_screen'))

    # Create the grid
    userid = 1  # TODO replace hard-coded user ID
    query = DBGrid.query.filter_by(userid=userid, gridname=gridname)
    jsonstr = query.first().jsonstr
    grid = Grid.from_json(jsonstr)

    # Get the current puzzle
    puzzle = Puzzle.from_json(session['puzzle'])

    # and replace its grid
    puzzle.replace_grid(grid)

    # Save in the session
    session['puzzle'] = puzzle.to_json()

    return redirect(url_for('uipuzzle.puzzle_screen'))
Beispiel #22
0
 def __init__(self, grid: Grid, *args, **kwargs):
     super().__init__(grid.n, *args, **kwargs)
     self.grid = grid
     self.black_cells = grid.get_black_cells()
     self.numbered_cells = grid.get_numbered_cells()
Beispiel #23
0
 def test_symmetric_point_on_edge(self):
     grid = Grid(9)
     expected = (9, 1)
     actual = grid.symmetric_point(1, 9)
     self.assertEqual(expected, actual)
Beispiel #24
0
 def test_symmetric_point(self):
     grid = Grid(9)
     expected = (8, 5)
     actual = grid.symmetric_point(2, 5)
     self.assertEqual(expected, actual)
Beispiel #25
0
 def test_str(self):
     grid = Grid(3)
     grid_string = str(grid)
     self.assertTrue("+-----+" in grid_string)
     self.assertTrue("| | | |" in grid_string)
Beispiel #26
0
 def test_bad_symmetric_point(self):
     grid = Grid(9)
     actual = grid.symmetric_point(-3, 45)
     self.assertIsNone(actual)
Beispiel #27
0
 def test_to_json(self):
     grid = Grid(9)
     grid.add_black_cell(1, 5)
     grid.add_black_cell(4, 9)
     jsonstr = grid.to_json()
     self.assertIsNotNone(jsonstr)
 def test_same_grid(self):
     oldpuzzle = TestPuzzle.create_solved_atlantic_puzzle()
     grid = Grid.from_json(oldpuzzle.to_json())
     newpuzzle = Puzzle.from_json(oldpuzzle.to_json())
     newpuzzle.replace_grid(grid)
     self.assertEqual(oldpuzzle, newpuzzle)
    def test_new_grid(self):
        puzzle = TestPuzzle.create_solved_atlantic_puzzle()
        oldjson = puzzle.to_json()
        grid = Grid.from_json(puzzle.to_json())
        grid.add_black_cell(4, 4)
        puzzle.replace_grid(grid)
        newjson = puzzle.to_json()

        import json
        old = json.loads(oldjson)
        new = json.loads(newjson)

        # Compare black cells
        self.assertIn([4, 4], new['black_cells'])
        self.assertIn([6, 6], new['black_cells'])
        new['black_cells'].remove([4, 4])
        new['black_cells'].remove([6, 6])
        self.assertListEqual(old['black_cells'], new['black_cells'])

        # Compare numbered cells
        expected = [
            NumberedCell(seq=1, r=1, c=1, a=3, d=4),
            NumberedCell(seq=2, r=1, c=2, a=0, d=4),
            NumberedCell(seq=3, r=1, c=3, a=0, d=9),
            NumberedCell(seq=4, r=1, c=6, a=4, d=5),
            NumberedCell(seq=5, r=1, c=7, a=0, d=9),
            NumberedCell(seq=6, r=1, c=8, a=0, d=4),
            NumberedCell(seq=7, r=1, c=9, a=0, d=3),
            NumberedCell(seq=8, r=2, c=1, a=4, d=0),
            NumberedCell(seq=9, r=2, c=4, a=0, d=2),
            NumberedCell(seq=10, r=2, c=6, a=4, d=0),
            NumberedCell(seq=11, r=3, c=1, a=9, d=0),
            NumberedCell(seq=12, r=3, c=5, a=0, d=5),
            NumberedCell(seq=13, r=4, c=1, a=3, d=0),
            NumberedCell(seq=14, r=4, c=5, a=4, d=0),
            NumberedCell(seq=15, r=5, c=3, a=5, d=0),
            NumberedCell(seq=16, r=5, c=4, a=0, d=5),
            NumberedCell(seq=17, r=6, c=2, a=4, d=4),
            NumberedCell(seq=18, r=6, c=7, a=3, d=0),
            NumberedCell(seq=19, r=6, c=8, a=0, d=4),
            NumberedCell(seq=20, r=6, c=9, a=0, d=4),
            NumberedCell(seq=21, r=7, c=1, a=9, d=3),
            NumberedCell(seq=22, r=7, c=6, a=0, d=2),
            NumberedCell(seq=23, r=8, c=1, a=4, d=0),
            NumberedCell(seq=24, r=8, c=6, a=4, d=0),
            NumberedCell(seq=25, r=9, c=1, a=4, d=0),
            NumberedCell(seq=26, r=9, c=7, a=3, d=0),
        ]
        actual = []
        for x in new['numbered_cells']:
            jsonstr = json.dumps(x)
            nc = NumberedCell.from_json(jsonstr)
            actual.append(nc)
        self.assertListEqual(expected, actual)

        # Compare clues

        oldclues = {
            x['text']: x['clue']
            for x in old['across_words'] + old['down_words']
        }
        newclues = {
            x['text']: x['clue']
            for x in new['across_words'] + new['down_words']
        }
        for k, v in newclues.items():
            if k in oldclues:
                oldclue = oldclues[k]
                self.assertEqual(oldclue, newclues[k])
 def test_wrong_size(self):
     puzzle = TestPuzzle.create_solved_atlantic_puzzle()
     grid = Grid(5)
     with self.assertRaises(ValueError):
         puzzle.replace_grid(grid)
Beispiel #31
0
    def _get_minion_string(self, grid, wordlist):
        across, down = grid.get_words()
        nums = grid.get_numbered_cells(across, down)
        formed_across = Grid.format_words(across, nums)
        formed_down = Grid.format_words(down, nums)
        outfile = cStringIO.StringIO()
        outfile.write("MINION 3\n")
        outfile.write("**VARIABLES**\n")
        allwords = []

        for word in formed_across:
            key = "across%d" % word[0]
            allwords.append((key, word[1]))
            outfile.write("DISCRETE %s[%d] {97..122}\n" % (key, len(word[1])))
            

        for word in formed_down:
            key = "down%d" % word[0]
            allwords.append((key, word[1]))
            outfile.write("DISCRETE %s[%d] {97..122}\n" % (key, len(word[1])))

        for word in formed_across:
            key = "h%d" % word[0]
            words = wordlist.words_matching(word[1])
            outfile.write("**TUPLELIST**\n%s %s %s\n" % (key, len(words), len(words[0])))
            outfile.write("\n".join([" ".join([str(ord(c)) for c in word]) for word in words]))
            outfile.write("\n")

        for word in formed_down:
            key = "v%d" % word[0]
            words = wordlist.words_matching(word[1])
            outfile.write("**TUPLELIST**\n%s %s %s\n" % (key, len(words), len(words[0])))
            outfile.write("\n".join([" ".join([str(ord(c)) for c in word]) for word in words]))
            outfile.write("\n")

        outfile.write("**CONSTRAINTS**\n")
        for word, itword in allwords:
            if len(itword) > 1:
                outfile.write("\n".join([
                    ("watchvecneq(%s,%s)" % (w, word))
                    for w, wcon in allwords
                    if w != word and len(wcon) == len(itword)]))
                outfile.write("\n")

        for start, word in across.items():
            rownum = nums[word[0]]
            for hidx, cell in enumerate(word):
                column = grid.col_at(cell.x, cell.y)
                colnum = nums[column[0]]
                vidx = column.index(cell)
                outfile.write("eq(across%d[%d],down%d[%d])" % (rownum, hidx, colnum, vidx))
                outfile.write("\n")
        self.diffs = []

        for word in Grid.format_words(across, nums):
            key = "across%d" % word[0]
            self.diffs.append("h%d" % word[0])
            outfile.write("table(across%d, h%d)\n" % (word[0], word[0]))

        for word in Grid.format_words(down, nums):
            key = "down%d" % word[0]
            self.diffs.append("v%d" % word[0])
            outfile.write("table(down%d, v%d)\n" % (word[0], word[0]))

        outfile.write("**EOF**")
        return outfile.getvalue()