Pythonで「四角に切れ」を解く>パズルの盤面
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import csv
from factor import FList
class Square: # 長方形の定義
def __init__(self, x, y, w, h): # コンストラクタ
self.x1 = x
self.y1 = y
self.x2 = x + w - 1
self.y2 = y + h - 1
def getw(self): return self.x2 - self.x1 + 1
def geth(self): return self.y2 - self.y1 + 1
def isInsideOf(self, other): # 範囲判定
if self.x1 < other.x1: return False
if self.y1 < other.y1: return False
if self.x2 > other.x2: return False
if self.y2 > other.y2: return False
return True
def product(self, other): # 共通範囲
x1 = max(self.x1, other.x1)
y1 = max(self.y1, other.y1)
x2 = min(self.x2, other.x2)
y2 = min(self.y2, other.y2)
if x2 < x1: return None
if y2 < y1: return None
return Square(x1, y1, x2 - x1 + 1, y2 - y1 + 1)
class SquareID: # 長方形のID
def __init__(self, board, x, y, id): # コンストラクタ
self.board = board
self.x = x
self.y = y
self.id = id
self.squares = []
self.n = board.quest[y][x]
for sz in FList[self.n]: # 初期長方形リスト作成
h = sz[0]
w = sz[1]
for ix in range(w):
for iy in range(h):
sq = Square(x - ix, y - iy, w, h)
if not sq.isInsideOf(board):
continue # 盤面外の長方形は無視
self.squares.append(sq)
class QuestBoard(Square): # 問題の盤面定義
def __init__(self, quest): # コンストラクタ
super().__init__(0, 0, len(quest[0]), len(quest))
self.quest = quest
self.territory = [[None for i in range(self.getw())] for j in range(self.geth())]
self.squareIDs = []
id = 10
for ix in range(self.getw()):
for iy in range(self.geth()):
if quest[iy][ix] > 0:
self.squareIDs.append( SquareID( self, ix, iy, id) )
id += 1
パズルを解くのに使用するクラスを定義します。
Square
は長方形のクラスです。
長方形に関するいくつかのメソッドも定義しています。
長方形の幅や高さの計算、2つの長方形の包含関係の判定、2つの長方形の共通部分の計算です。
SquareID
は長方形のIDのクラスです。
数字のマスの位置やIDの番号を持っています。
QuestBoard
はパズルの盤面です。
長方形の演算を使えるように、長方形のクラスを継承しています。
コンストラクタで与えられた問題にある数字にIDを振っていますが、IDを10から始めているのは桁数をそろえてCSV出力を見やすくするためです。
QuestBoard
の途中にある、[... for ... in ...]
の書き方は、リスト内包表記というものです。
規則に従ってリストを作るのに便利です。
慣れないと読みずらいですが、for と in で区切られた3つの要素を見分けるのが理解のポイントです。
ここでは要素がNoneの2次元配列を生成しています。
戻る |