Gere inclinações válidas de Fibonacci

9

fundo

O mosaico de Fibonacci é um mosaico da linha (1D) usando dois segmentos: um curto, S e um longo, L (a razão de comprimento é a proporção áurea, mas isso não é relevante para esse desafio). Para que um ladrilho usando esses dois protótipos seja realmente um ladrilho de Fibonacci, as seguintes condições devem ser cumpridas:

  • A lado a lado não deve conter a subsequência SS .
  • A lado a lado não deve conter a LLL subsequente .
  • Se um novo mosaico for composto executando todas as seguintes substituições, o resultado ainda deverá ser um mosaico de Fibonacci:
    1. LLS
    2. SL
    3. L(string vazia)

Vejamos alguns exemplos:

SLLSLLSLLSLS

Parece um bloco válido, porque não contém dois * S * s ou três * L * s, mas vamos executar a composição:

LSLSLSLL

Ainda parece bom, mas se compormos isso de novo, obtemos

LLLS

que não é um mosaico válido de Fibonacci. Portanto, as duas seqüências anteriores também não eram válidas.

Por outro lado, se começarmos com

LSLLSLSLLSLSLL

e componha isso repetidamente para seqüências mais curtas

LSLLSLLS
LSLSL
LL
S

todos os resultados são inclinações válidas de Fibonacci, porque nunca obtemos SS ou LLL em lugar algum nessas cadeias.

Para uma leitura mais aprofundada, há uma tese que usa esse ladrilho como uma simples analogia 1D às inclinações de Penrose.

O desafio

Escreva um programa ou função que, dado um número inteiro não negativo N , retorne todos os blocos de Fibonacci válidos na forma de cadeias contendo N caracteres (sendo Sou L).

Você pode receber informações via argumento de função, STDIN ou ARGV e retornar ou imprimir o resultado.

Isso é código de golfe, a resposta mais curta (em bytes) vence.

Exemplos

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
Martin Ender
fonte
Isso deveria ser LSLSL-> LL?
@tolos Ah sim, boa captura. Eu consertei isso. Para sua informação, isso aconteceu porque na verdade eu gerei a string ao contrário, começando de baixo usando regras de decomposição semelhantes, e essas não são exatamente reversíveis quando se trata dos limites do fragmento.
Martin Ender

Respostas:

4

CJam, 70 62 59 bytes

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

Lê de STDIN. Experimente online.

Exemplo de execução

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

Como funciona

A idéia é empurrar todas as strings de L e S do comprimento adequado, aplicar sucessivamente a transformação a cada uma até o resultado ser uma string vazia, concatenar as seqüências de strings e procurar as substrings proibidas.

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.                                          ";
Dennis
fonte
3

GolfScript (86 bytes)

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

Esta é uma abordagem inflacionária: ele começa com Le Se expande-los usando as regras LL -> SLS, L -> S, S -> LL, e esquerda ou à direita Spode ter um Ladicionado no limite de palavra.

Demonstração online

Peter Taylor
fonte
@ MartinBüttner, normalmente eu vincularia a uma demonstração online com golfscript.apphb.com, mas está executando uma versão antiga com um bug em torno de loops aninhados (corrigido na versão de 3 de dezembro de 2012 ) e não pode executar corretamente este programa.
Peter Taylor
3
@ MartinBüttner Opa. Obrigado pessoal por me informar sobre o bug. Atualizei o site com a nova versão GS. Clique neste link para a demonstração.
Cristian Lupascu
@ w0lf, obrigado pela atualização (e pela recente alteração para aumentar o limite de tempo também).
Peter Taylor
1

Haskell, 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

Explicação:

Eu defino 4 funções:

  • f pega um número inteiro e retorna o resultado

    replicateM n [L,S]cria todas as permutações possíveis de [L,S]com o comprimento n filter s ...filtrará esta lista (de listas) com a funçãos

  • r reduz uma lista dada em 1 nível.

    Isso é feito simplesmente pela correspondência de padrões. Uma lista começando com 2 Lse tornará uma lista começando com So restante reduzido

  • v valida uma lista dada pelas regras dadas (no 3 L contínuo, no 2 S contínuo)

    se a lista começar com uma das 2 seqüências ilegais (L, L, L ou S, S), o resultado é False: uma lista vazia é válida e uma lista não-vazia é verificada novamente com o primeiro elemento removido

  • s verifica se uma lista e todas as listas reduzidas são válidas.

    Novamente: uma lista vazia é válida (e não pode ser reduzida mais).
    Se a lista fornecida como argumento for válida, a lista será reduzida e o anúncio verificado snovamente.
    Caso contrário, o resultado éFalse

Johannes Kuhn
fonte