#tiling #board #tile #counting #math #shapes #l-tile

bin+lib dcc-tiler

一个用于计算/渲染各种形状镶嵌的库和CLI工具

3 个版本

0.1.2 2019年11月2日
0.1.1 2019年8月22日
0.1.0 2019年8月22日

#299 in 图形API

MIT/Apache

56KB
1K SLoC

dcc-tiler

基本镶嵌术语

目前支持两种类型的镶嵌,以下将进行解释。

LTile

一个大小为 nLTile 是由 n + 1 个方块组成的L形泰特拉米诺。例如,大小为3的 LTile

dcc_tiler_cli --single --board_type LBoard --tile_type LTile 3 3

而大小为5的 LTile

dcc_tiler_cli --single --board_type LBoard --tile_type LTile 5 5

TTile

一个大小为 nTTile 是由 2(n + 1) 个方块组成的T形泰特拉米诺。例如,大小为1的 TTile

dcc_tiler_cli --single --board_type TBoard --tile_type TTile 1 1

而大小为2的 TTile

dcc_tiler_cli --single --board_type TBoard --tile_type TTile 2 2

基本棋盘术语

目前支持三种棋盘: RectangleLBoardTBoard

LBoardTBoard

有两个参数影响L/T棋盘的形状/大小: board_sizeboard_scale。使用这些参数,创建一个大小为 board_size 的瓷砖(无论是L还是T),然后在这个瓷砖中的每个方块都被 board_scale * 2 个方块替换。

例如,大小为4且比例为1的 LBoard 看起来像

dcc_tiler_cli --single --scale 1 --board_type LBoard --tile_type BoxTile 4 0

而将比例提高到2的结果是

dcc_tiler_cli --single --scale 2 --board_type LBoard --tile_type BoxTile 4 0

大小为1且比例为1的 TBoard 看起来像

dcc_tiler_cli --single --scale 1 --board_type TBoard --tile_type BoxTile 1 0

而将比例提高到2的结果是

dcc_tiler_cli --single --scale 2 --board_type TBoard --tile_type BoxTile 1 0

矩形

有两个参数影响矩形棋盘的形状/大小: board_size(高度)和 width

例如,大小为3且宽度为5的 Rectangle 看起来像

dcc_tiler_cli --single --board_type Rectangle --width 5 --tile_type BoxTile 3 0

Rectangleboard_size = 6width = 4 时,它看起来是这样的

dcc_tiler_cli --single --board_type Rectangle --width 4 --tile_type BoxTile 6 0

注意:对于 Rectangle,比例参数被忽略。

使用 LTiles 计算 LBoard 的镶嵌数

以下命令计算了 2x2 大小的 LBoard 使用 2x2 大小的 LTile 镶嵌的数量,比例参数为 x

dcc_tiler_cli--count--scale x--board_type LBoard--tile_type LTile2 2

随着 x 的变化,得到以下镶嵌数

x 镶嵌
1 1
2 1
3 4
4 409
5 108388
6 104574902
7 608850350072
8 19464993703121249

这个整数序列(1, 1, 4, 409, ...)不在 OEIS 中。

使用 TTiles 计算 TBoard 的镶嵌数

这里的命令是

dcc_tiler_cli--count--scale x--board_type TBoard--tile_type TTile1 1

练习: 证明如果 x > 1x % 4 != 0,则不存在这样的镶嵌!

随着 x 的变化,得到以下镶嵌数

x 镶嵌
1 1
4 54
8 655302180
12 ?

另一种方法

您可以使用 --scaling 选项代替每次修改比例参数,如下所示

dcc_tiler_cli--scaling--board_type TBoard--tile_type TTile1 1

这将得到以下输出

scale(1), 1 tilings
scale(2), 0 tilings
scale(3), 0 tilings
scale(4), 54 tilings
scale(5), 0 tilings
scale(6), 0 tilings
scale(7), 0 tilings
scale(8), 655302180 tilings
...

计算 LBoard 的 TTiles 镶嵌数

可能的组合很多。一个例子是

dcc_tiler_cli--count--scale4 --board_type LBoard--tile_type TTile3 1

这计算了 54 种镶嵌。以下是一个这样的镶嵌的例子

dcc_tiler_cli --single --scale 4 --board_type LBoard --tile_type TTile 3 1

使用 TTiles 计算矩形镶嵌数

假设我们想要计算使用 1x1 大小的 T-tetronimos 镶嵌 n x n 矩形的数量。这里的命令是

dcc_tiler_cli--count--board_type Rectangle--width n--tile_type TTile n1

这将得到以下输出

n 镶嵌
4 2
8 84
12 78696
16 1668091536
20 804175873700640
24 8840889502844537044800

这与 C. Merino 在 2008 年发表在 C. Merino, 2008 中的表格相一致。

生成单个镶嵌图像

在计算镶嵌数之后,生成这样的镶嵌图像以供视觉检查通常很有用。从上一节我们知道,有 54 种 3x3 大小、比例为 4 的 LBoard 使用 1x1 大小的 TTile 的镶嵌。要生成这样的镶嵌,我们使用 --single 选项并将输出重定向到 output.svg

dcc_tiler_cli--single--scale4 --board_type LBoard--tile_type TTile3 1 >output.svg

注意: CLI 生成最多 1000 个镶嵌,然后从其中选择一个进行渲染,因此不能保证重复运行此命令会生成所有可能的镶嵌。

生成所有镶嵌图像

除了生成单个图像之外,您还可以使用 --all <filename> 命令生成包含所有镶嵌的 ZIP 文件。例如

dcc_tiler_cli--all tilings.zip--scale4 --board_type LBoard--tile_type TTile3 1

镶嵌图

可以将所有镶嵌数据作为 JSON 表示的图输出。一个 4x8 的矩形板由以下 JSON 对象表示

{ "board" : [ [false, false, false, false], 
              [false, false, false, false], 
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false], ] }

如果我们把一个 1x1 大小的 T-tetronimo 放在板的左上角,我们的新板将是

{ "board" : [ [true,  true,  true,  false], 
              [false, true,  false, false], 
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false],
              [false, false, false, false], ] }

镶嵌图由以下组成

  • 一个由板对象(如上所示)组成的数组 nodes_arena
  • 一个形式为的 edges 对象,
{
   "0":  [ 1, 2 ],
   "1" : [ 3 ],
   "2" : [ 4 ],
   "3" : [ 5, 7, 8, 6 ],
}
  • 一个形式为的 rev_edges 对象,
{
    "1":  [ 0 ],
    "2" : [ 0 ],
    "3" : [ 1 ],
    "4" : [ 2 ],
    "5" : [ 3 ],
    "6" : [ 3 ],
    "7" : [ 3 ],
    "8" : [ 3 ],
}
  • 一个形式为的数组 complete_indices
[ 36 ]

我们图中的节点对应于 node_arena 中的拼图板,因此 nodes_arena 的第一个条目是节点 0,第二个条目是节点 1,依此类推。节点 0 总是空拼图板(没有拼图)。两个节点之间的边 s -> t 表示您可以通过放置拼图从拼图板 s 到拼图板 t。这样的边被记录在两个地方:在 edges 对象中(因此 tedges[s] 中),和在 rev_edges 对象中(因此 srev_edges[t] 中)。最后,如果可以完成完整的铺装,其节点将存储在 complete_indices 数组中。

关于铺装图的一些注意事项

  • 如果有许多铺装,生成图可能需要 很长时间,生成的图通常很大,难以在内存中处理。这个问题促使产生了 --count--single 命令,这些命令避免了生成整个拼图图。

  • 给定边 s -> t,我们不会存储任何关于放置哪个拼图才能从拼图板 s 到拼图板 t 的数据;这可以通过查看从 st 时哪些条目从 false 切换到 true 来恢复。

  • 假设您想计算铺装拼图的可能方式的数量。使用图,一种方法如下

    • 初始化一个哈希表 count,其中 count[0] = 1(即空拼图板的铺装方式有一种)。
    • 初始化一个哈希集 current_layer,其中包含节点 0
    • current_layer 非空时
      • 初始化一个空的哈希集 next_layer
      • 对于 current_layer 中的每个节点 s
        • 对于 edges[s] 中的每个节点 t
          • 如果 t 不在 count 中,则设置 count[t] = 0
          • count[t] 的值增加 count[s]
          • t 添加到 next_layer
      • current_layer 设置为 next_layer
    • 总的铺装数量将是 count[final],其中 final 是出现在 complete_indices 中的节点。

许可证

根据您的要求,许可如下

任选其一。

贡献

除非您明确声明,否则您根据Apache-2.0许可证定义的任何有意提交以包含在工作中的贡献,均应按上述方式双许可,不附加任何额外条款或条件。

依赖项

~5-7MB
~119K SLoC