Fannkuch alfabético

14

Fannkuch é um programa de benchmark clássico. O nome vem do alemão "Pfannkuchen" - panquecas - pela semelhança do algoritmo com as pilhas de panquecas. Uma sequência de números Fannkuch é formada da seguinte forma:

Tome uma permutação de {1 ..... n}, por exemplo: {4,2,1,5,3}. Pegue o primeiro elemento, aqui 4, e inverta a ordem dos 4 primeiros elementos: {5,1,2,4,3}. Repita isso até que o primeiro elemento seja 1, para que o lançamento não mude mais: {3,4,2,1,5}, {2,4,3,1,5}, {4,2,3, 1,5}, {1,3,2,4,5}

Você deve escrever um programa ou função que calcule uma sequência do tipo Fannkuch para seqüências de caracteres alfabéticos. Em vez de usar números para indicar quantos elementos da lista devem ser invertidos a cada vez, a posição de uma letra no alfabeto deve ser usada. Por exemplo, um líder cindica que você deve reverter a ordem dos 3 primeiros elementos, enquanto um líder aindica que a sequência está completa.

Entrada

A entrada será fornecida como uma string via stdin ou como um argumento de função. A cadeia conterá entre 1 e 26 letras minúsculas distintas. Strings não conterão letras cujo índice equivalente faria com que o algoritmo Fannkuch invertesse mais elementos do que existem.

Resultado

Programas ou funções devem retornar ou imprimir para evitar a sequência de termos produzidos aplicando o algoritmo Fannkuch até que um líder aseja encontrado, incluindo a sequência inicial. Por exemplo, se a entrada for bca, você pode imprimir:

bca
cba
abc

Os resultados impressos podem usar qualquer separador - vírgulas, novas linhas etc. Qualquer escolha de espaço em branco é aceitável.

Como outro exemplo, se sua entrada for, eabdcvocê poderá retornar:

("eabdc"
 "cdbae"
 "bdcae"
 "dbcae"
 "acbde")

Regras e Pontuação

Este é o - o programa mais curto vence. As brechas padrão não são permitidas.

JohnE
fonte

Respostas:

11

Pitão, 16 bytes

.u+_<NJhxGhN>NJz

Demonstração.

O recurso "repetir até parar de mudar" das funções de redução do Pyth é realmente útil aqui. Isso é usado com .ua função de redução cumulativa para gerar todos os resultados. O corpo da redução é o mais ingênuo possível, mas não consegui encontrar nada melhor.

isaacg
fonte
5

T-SQL, 213 bytes

Claro que sendo SQL é muito grande, mas era interessante de fazer. Criado como uma função de tabela embutida usando uma consulta CTE recursiva.

CREATE FUNCTION F(@ CHAR(26))RETURNS TABLE RETURN WITH R AS(SELECT @ S UNION ALL SELECT CAST(STUFF(S,1,ASCII(LEFT(S,1))-96,REVERSE(LEFT(S,ASCII(LEFT(S,1))-96)))AS CHAR(26))FROM R WHERE LEFT(S,1)<>'a')SELECT*FROM R

Expandido

CREATE FUNCTION F(@ CHAR(26))
RETURNS TABLE 
RETURN WITH R AS(
    SELECT @ S            -- Initial string as an anchor for the recursion
    UNION ALL 
    SELECT CAST(
        STUFF(                                    -- Stuff into 
            S,                                    -- string S
            1,                                    -- from position 1
            ASCII(LEFT(S,1))-96,                  -- to index value of first char
            REVERSE(LEFT(S,ASCII(LEFT(S,1))-96))  -- the reverse of the index first chars
            )
        AS CHAR(26))
    FROM R 
    WHERE LEFT(S,1)<>'a'  -- recurse until first char is a
)SELECT*FROM R

Utilizado da seguinte forma

SELECT * FROM F('eabdc')
S
--------------------------
eabdc                     
cdbae                     
bdcae                     
dbcae                     
acbde                     

(5 row(s) affected)
MickyT
fonte
4

CJam, 22 bytes

Esta é uma função anônima que pega uma string na pilha e retorna uma lista de strings na pilha.

{_,{_0='`-/(W%\+s_}*]}

Experimente online aqui

Optimizer
fonte
3

Python 2, 59 bytes

def p(l):
 print l;o=ord(l[0])-97
 if o:p(l[o::-1]+l[o+1:])

Eu acho que essa é uma resposta bastante direta. Usa recursão e sintaxe de fatia do Python. Chame como: p('eabdc').

mathmandan
fonte
3

SAS, 131 bytes

sub a(s$);outargs s;put s;do while(b ne 1);b=rank(char(s,1))-96;substr(s,1,b)=reverse(substr(s,1,b));if b>1 then put s;end;endsub;

Uma rotina de chamadas do FCMP. Não incluído abaixo (com uma verificação extra, eu recomendo o SAS travar se uma rotina FCMP entrar em um loop infinito).


options cmplib=work.funcs;
proc fcmp outlib=work.funcs.funcs;
  sub a(s$);
    outargs s;
    put s=;
    do while (b ne 1 and z<1e5);
        b=rank(char(s,1))-96;
        substr(s,1,b) = reverse(substr(s,1,b));
        if b>1 then put s=;
        z+1;
    end;
  endsub;
quit;
Joe
fonte
Bom trabalho. Não temos muito proc fcmppor aqui.
27515 Alex A.
2

Haskell, 78 bytes

f l@(h:_)|h=='a'=[l]|1<2=l:f(reverse(take d l)++drop d l)where d=fromEnum h-96

Uso: f "eabdc"-> ["eabdc","cdbae","bdcae","dbcae","acbde"].

nimi
fonte
considere usar splitAt- você pode reduzi-lo a 71 bytes!
MtnViewMark
@MtnViewMark bem i parecem ter o mesmo algoritmo exato, até 68 bytes
haskeller orgulhoso
2

K5, 21 bytes

{(|v#x),(v:*x-96)_x}\

Economizou 5 bytes graças a @JohnE e outro byte, reorganizando uma expressão.

Pela primeira vez na terra, acho que o K venceu o CJam!

Versão de 27 bytes

(~97=*){(|v#x),(v:-96+*x)_x}\
kirbyfan64sos
fonte
Você pode tornar isso um pouco mais curto se você usar a forma de ponto fixo de "varredura".
Johne
@JohnE Thanks! Não percebi que, quando a primeira letra é uma a, a string não muda.
kirbyfan64sos
0

Haskell, 68

f l@(x:_)|x<'b'=[l]|(x,y)<-splitAt(fromEnum x-96)l=l:f(reverse x++y)

Qualquer tática mais complicada em que pensei ocupava mais bytes.

orgulhoso haskeller
fonte