生成有效的斐波那契平铺


9

背景

斐波那契平铺是(1D)线的平铺,使用两段:短段S和长段L(它们的长宽比是黄金比例,但这与这项挑战无关)。要将使用这两个原生动物的拼贴实际上是斐波那契拼贴,必须满足以下条件:

  • 拼贴中不得包含子序列SS
  • 平铺中不得包含子序列LLL
  • 如果通过执行以下所有替换操作组成新的平铺,则结果仍必须是斐波那契平铺:
    1. LLS
    2. SL
    3. L(空字符串)

让我们看一些例子:

SLLSLLSLLSLS

这看起来像是一个有效的平铺,因为它不包含两个* S *或三个* L * s,但让我们执行合成:

LSLSLSLL

看起来仍然不错,但是如果我们再次进行组合,我们会得到

LLLS

这不是有效的斐波那契平铺。因此,前两个序列也不是有效的平铺。

另一方面,如果我们从

LSLLSLSLLSLSLL

并反复将其组合成较短的序列

LSLLSLLS
LSLSL
LL
S

所有结果都是有效的斐波那契平铺,因为我们从未在这些字符串内的任何位置获得SSLLL

为了进一步阅读,有一篇论文将这种平铺作为与Penrose平铺的简单一维类比。

挑战

编写一个程序或函数,给定一个非负整数N,该程序或函数以包含N个字符(be SL)的字符串形式返回所有有效的斐波那契平铺。

您可以通过函数参数STDIN或ARGV接受输入,然后返回或打印结果。

这是代码高尔夫球,最短的答案(以字节为单位)获胜。

例子

N      Output
0      (an empty string)
1      S, L
2      SL, LS, LL
3      LSL, SLS, LLS, SLL
4      SLSL, SLLS, LSLS, LSLL, LLSL
5      LLSLL, LLSLS, LSLLS, LSLSL, SLLSL, SLSLL
...
8      LLSLLSLS, LLSLSLLS, LSLLSLLS, LSLLSLSL, LSLSLLSL, SLLSLLSL, SLLSLSLL, SLSLLSLL, SLSLLSLS

应该是LSLSL-> LL吗?

@tolos嗯,很好。我修好了 仅供参考,发生这种情况是因为实际上我是使用类似的分解规则从底部开始以相反的方式生成字符串的,当涉及到片段的边界时,它们并不是完全可逆的。
Martin Ender 2014年

Answers:


4

CJam,70 62 59字节

Qali{_'L:Xf+\'S:Yf++}*{{_X2*/Xf-Yf/Xf*Y*}h]N*_X3*#\Y2*#=},p

从STDIN读取。在线尝试。

运行示例

$ cjam tilings.cjam <<< 5
["LLSLL" "SLSLL" "SLLSL" "LSLSL" "LSLLS" "LLSLS"]

怎么运行的

想法是推入所有适当长度的L和S的字符串,依次对每个字符串应用转换,直到结果为空字符串,连接字符串序列并搜索禁止的子字符串。

Qa         " Push R := [ '' ].                                                            ";
li{        " Do the following int(input()) times:                                         ";
  _'L:Xf+  " Append (X := 'L') to a copy of all strings in R.                             ";
  \'S:Yf+  " Append (Y := 'S') to all original strings in R.                              ";
  +        " Concatenate the arrays into R.                                               ";
}*         " R now contains all strings of L's and S's of length int(input()).            ";
{          " For each S ∊ R:                                                              ";
  {        "                                                                              ";
    _      " Push a copy of S.                                                            ";
    X2*/   " Split S at 'LL'.                                                             ";
    Xf-    " Remove 'L' from the chunks.                                                  ";
    Yf/    " Split the chunks at 'S'.                                                     ";
    Xf*    " Join the chunks, separating by 'L'.                                          ";
    Y*     " Join, separating by 'S'.                                                     ";
  }h       " If the resulting string is non-empty, repeat.                                ";
  ]N*      " Join the array of resulting strings from S to '', separating by linefeeds.   ";
  _X3*#    " Push the index of 'LLL' a copy in the resulting string (-1 if not present).  ";
  \Y2*#    " Push the index of 'SS' in the original string (-1 if not present).           ";
  =        " Check if the indexes are equal; this happens if and only if both are -1.     ";
},         " Filter: Keep S in R if and only if = pushed 1.                               ";
p          " Print a string representation of R.                                          ";

3

GolfScript(86字节)

~:|'LS'1/\{{.{1&!'LLS'2/=}%'SS'/'SLS'*[.(1&{'LS'\+}*]{.)1&{'SL'+}*}/}%.&}*['']+{,|=},p

这是一个通货膨胀的方法:它开始与LS使用规则扩大他们LL -> SLSL -> SS -> LL,和开头或结尾S可以有一个L在字边界补充说。

在线演示


@MartinBüttner,我通常会使用golfscript.apphb.com链接到在线演示,但是它运行的是旧版本,并且带有嵌套循环(已在2012年12月3日发布的版本中修复)中的错误并且无法正确执行此程序。
彼得·泰勒

3
@MartinBüttner糟糕。谢谢你们让我知道这个错误。我用新的GS版本更新了网站。单击此链接进行演示。
Cristian Lupascu 2014年

@ w0lf,感谢您的更新(以及最近的更改也增加了时间限制)。
彼得·泰勒

1

哈斯克尔217

import Control.Monad
data F=L|S deriving (Eq)
f n=filter s$replicateM n [L,S]
r (L:L:m)=S:r m
r (S:m)=L:r m
r (L:m)=r m
r []=[]
s []=True
s m|v m=s$r m
s _=False
v (L:L:L:_)=False
v (S:S:_)=False
v (_:m)=v m
v []=True

说明:

我定义了4个功能:

  • f 接受一个整数并返回结果

    replicateM n [L,S]创建[L,S]长度为的所有可能排列,n filter s ...将使用函数过滤此列表(列表)s

  • r 将给定列表减少1级。

    只需通过模式匹配即可完成。以2开头L的列表将成为以开头的列表,S剩余的减少

  • v 根据给定的规则验证给定列表(无3个连续L,无2个连续S)

    如果列表以2个非法序列(L,L,L或S,S)之一开头,则结果为False,一个空列表有效,并且在删除第一个元素的情况下再次检查非空列表

  • s 检查列表和所有简化列表是否有效。

    再次:空列表是有效的(并且不能进一步减少)。
    如果作为参数给出的列表有效,则将对列表进行缩减并s再次检查。
    否则结果是False

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.