#!/usr/bin/env python # -*- coding: utf-8 -*- # $Id: polyominoes45.py 452 2012-03-31 12:25:25Z goodger $ # Author: David Goodger <goodger@python.org> # Copyright: (C) 1998-2015 by David J. Goodger # License: GPL 2 (see __init__.py) """ Concrete miscellaneous polyomino puzzles. """ import copy from pprint import pprint, pformat from puzzler.puzzles.polyominoes import Polyominoes class PolyominoesPuzzleArt(Polyominoes): """ Specify a puzzle graphically. Whitespace in `self.puzzle_art` defines the puzzle space (via `self.coordinates`, which sets `self.height` and `self.width`). The `self.piece_art` dictionary defines pieces graphically. """ implied_0 = False puzzle_art = None """A multi-line string where '#' is a border square (not part of the puzzle space), and spaces form the puzzle space.""" piece_art = None """A mapping of piece name to 2-tuple: puzzle piece art multi-line string ('#' is a filled square), and a dictionary of piece-specific aspect restrictions.""" base_aspect_restrictions = {} def customize_piece_data(self): total_squares = 0 for name, art_data in self.piece_art.iteritems(): art, piece_aspect_restrictions = art_data aspect_restrictions = copy.deepcopy(self.base_aspect_restrictions) aspect_restrictions.update(piece_aspect_restrictions) coordinates, width, height, squares = self.coordinates_from_art(art) total_squares += len(coordinates) self.piece_data[name] = (tuple(coordinates), aspect_restrictions) def coordinates_from_art(self, art, include='#'): lines = art.splitlines() squares = 0 height = len(lines) width = 0 coordinates = [] for y, line in enumerate(reversed(lines)): width = max(width, len(line)) for x, char in enumerate(line): if char == include: coordinates.append((x, y)) squares += 1 return coordinates, width, height, squares def coordinates(self): coordinates, width, height, squares = self.coordinates_from_art( self.puzzle_art, include=' ') self.height = height self.width = width coordinates.sort() assert len(coordinates) == squares for coord in coordinates: yield coord class PolyominoesPuzzleArtFixed(PolyominoesPuzzleArt): """ Pieces each have a single fixed aspect, no rotation or flipping alowed. """ base_aspect_restrictions = {'flips': None, 'rotations': None} class PuzzleBits56(PolyominoesPuzzleArtFixed): puzzle_art = """\ ########### ### ##### ### ##### ## # #### ## #### # # ### # ### # # ### ## #### ###########""" piece_art = { 'I': ( """\ ### """, {}), 'D1': ( """\ # # """, {}), 'L4': ( """\ # # ## """, {}), 'I3': ( """\ # # # """, {}), 'Z': ( """\ ## # ## """, {}), 'P': ( """\ ### ## """, {}), 'T ': ( """\ # # ### """, {}), 'V3': ( """\ # ## """, {}), 'Y': ( """\ # # ## # """, {}), 'L2': ( """\ ## # # """, {}), } class PuzzleBitsA(PolyominoesPuzzleArtFixed): puzzle_art = """\ ########### # # # # # # # # # # ##### ##### #### #### ###########""" piece_art = { 'T6': ( """\ # # # ### """, {}), 'I3': ( """\ # # # """, {}), 'L4': ( """\ # # ## """, {}), 'D1': ( """\ # # """, {}), 'N': ( """\ ### ## """, {}), 'T': ( """\ #### # # """, {}), 'T4': ( """\ # ### """, {}), 'Q': ( """\ # # #### ## # """, {}), 'Z4': ( """\ # ## # """, {}), 'V3': ( """\ ## # """, {}), 'I': ( """\ ### """, {}), } class PuzzleBits25(PolyominoesPuzzleArtFixed): puzzle_art = """\ ############### ### ###### ## ##### ## ##### ## ##### # #### ###############""" piece_art = { 'T4': ( """\ # ### """, {}), 'T5': ( """\ ### # # """, {}), 'L1': ( """\ # # # ## """, {}), 'L2': ( """\ # #### """, {}), 'Y': ( """\ # ## # # """, {}), 'D1': ( """\ # # """, {}), 'I4': ( """\ #### """, {}), 'S4': ( """\ ## ## """, {}), 'C6': ( """\ ## # # ## """, {}), } class PuzzleBits9(PolyominoesPuzzleArtFixed): puzzle_art = """\ ############### ##### ####### ##### ####### ##### ####### ###### ######## ### # # ##### ## #### ### # # ##### ##### ####### ##### # ####### ##### # ####### #### # ###### ############### ###############""" piece_art = { 'X': ( """\ # ### # """, {}), 'T1': ( """\ # ## # """, {}), 'T2': ( """\ # ### """, {}), 'L5': ( """\ # # # ## """, {}), 'L4': ( """\ # # ## """, {}), 'Y': ( """\ # ## # # """, {}), 'V1': ( """\ # ## """, {}), 'V2': ( """\ ## # """, {}), 'D1': ( """\ # # """, {}), 'D2': ( """\ ## """, {}), 'I3': ( """\ # # # """, {}), }