Um "esquema de rima" é uma sequência de letras a
para z
, de modo que as primeiras ocorrências dos caracteres estejam em ordem crescente (sem lacunas), a partir de a
. Por exemplo (com as primeiras ocorrências marcadas):
abccdbebdcfa
^^^ ^ ^ ^
O número de esquemas de rima de comprimento N
é dado pelos números de Bell B(N)
. ( OEIS A000110 )
O desafio
Sua tarefa é implementar uma enumeração desses esquemas de rima, ou seja, um mapeamento bijetivo de números inteiros para esquemas de rima. Você recebe um número inteiro positivo e um número inteiro N <= 26
não negativo 0 <= i < B(N)
. Como alternativa, você pode usar o intervalo 1 <= i <= B(N)
. Você deve produzir um esquema de rima de comprimento N
, de modo que cada i
um produza uma sequência diferente.
Você pode escrever um programa ou função, recebendo entrada via STDIN (ou alternativa mais próxima), argumento da linha de comando ou argumento da função e emitindo o resultado via STDOUT (ou alternativa mais próxima), valor de retorno da função ou parâmetro da função (saída).
Você pode usar letras maiúsculas ou minúsculas (de forma consistente).
Seu código deve ser capaz de lidar com qualquer entrada válida em quantidade razoável de tempo (por exemplo, não mais do que algumas horas para N = 26
, pior caso i
). Isso deve permitir soluções que escalam exponencialmente com N
(para pequenas bases), mesmo em linguagens lentas, mas proíbem soluções que escalam linearmente com i
(ie B(N)
). Em particular, isso significa que você não pode simplesmente repetir todos os esquemas de rima válidos N
até ter descartado os i
esquemas.
Aplicam-se as regras de código-golfe padrão .
Exemplos
A atribuição exata dos i
esquemas a (isto é, a ordem dos esquemas para um determinado N
) depende de você. Mas digamos que você escolheu a ordem lexicográfica, sua solução deve corresponder à seguinte tabela (com a -
indicação de entrada inválida):
N\i 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 a - - - - - - - - - - - - - -
2 aa ab - - - - - - - - - - - - -
3 aaa aab aba abb abc - - - - - - - - - -
4 aaaa aaab aaba aabb aabc abaa abab abac abba abbb abbc abca abcb abcc abcd
Aqui está um pequeno script CJam que gera todos os esquemas de rima válidos para um determinado comprimento (mas não tente mais de 10 ou você esperará um pouco).
Desafios relacionados
fonte
N
), desde que isso não seja razoavelmente trivial e eu seja estúpido demais para encontrá-la.Respostas:
CJam,
6866 bytesExperimente online.
Este é o meu primeiro programa CJam. Começou a vida como uma porta da minha solução Perl e tinha inicialmente mais de 130 bytes de comprimento. Mais sugestões de golfe são bem-vindas.
Como no meu programa Perl, ele é dividido em duas partes.
Para depurar as matrizes criadas pela Parte 1 add
]_`o~
entre Parts 1 & 2. Se n é5
, as matrizes será parecido com este:[[1 1 1 1 1 1] [1 2 3 4 5] [2 5 10 17] [5 15 37] [15 52]]
. Os índices 0 de cada matriz não são usados, apenas facilitam o cálculo de compensações. As matrizes são calculadas assim:Ele mantém uma cópia da matriz antiga enquanto calcula a próxima. As matrizes são lidas e descartadas na ordem inversa pela Parte 2.
fonte
Python 2, 153
Ele usa ordem alfabética e indexação baseada em 0.
Vamos
l
denotar o comprimento de um sufixo das letras ea
o número de letras distintas que foram usadas na parte anterior. Em seguida, uma funçãop(l,a)
que calcula o número de maneiras de selecionar as letras restantes pode ter 40 bytes:No entanto, isso é muito lento para o desafio; portanto, os valores necessários são pré-calculados e armazenados na
u
matriz. Em cada estágio do cálculo, se a próxima letra for aa
já usada, n = k * p (l - 1, a) + n ' onde k é a letra do alfabeto indexada em 0 e n' é o valor den
para a próxima chamada de função, que contém as informações sobre as letras restantes. Se uma nova letra for usada, então n = a * p (l - 1, a) + n ' .fonte
Haskell (GHC 7.10), 150 bytes
O operador
n # i
calcula oi
th esquema de rima (indexado a zero) de comprimenton
. É executado em operações O (n²) (número inteiro grande), aproveitando as listas infinitas e preguiçosas de Haskell para memorização automática. Amostras de execuções:(Se o N máximo fosse 25 em vez de 26,
.fromEnum
poderia ser removido, porque B (25) se encaixa em um de 64 bitsInt
.)fonte
Perl 257 + 1 (-p sinalizador) = 258Perl 182 + 10 (sinalizadores -pMbignum) = 192
Obrigado ao dev-nul por salvar muitos bytes! Eu o reescrevi com base no que aprendi com a versão do CJam.
Calcula a rima em ordem alfabética crescente, 0 indexada.
Duas partes: a Parte 1 tem
12890 bytes e calcula uma matriz para a Parte 2. A Parte 2 tem12992 bytes e faz algumas contas simples para calcular cada letra.Se eu conseguisse me livrar da matriz e substituí-la por dois números simples, poderia calcular um único caminho através da matriz para cada número e economizar muitos bytes!Aparentemente, essa ideia não funciona!Infelizmente, não produz as rimas certas para valoresi
superiores a 9007199254740992, mas funciona lindamente para valores baixos!Eu adicionei a biblioteca Bignum a um custo de 11 bytes.É executado a partir da linha de comando comperl -pMbignum bell-rhyme.pl
.-pMbignum
= 10 bytes. Também é muito rápido para qualquer valor de entrada.fonte
Oracle SQL 11.2,
412284283 bytesInfelizmente, ele só executa até um comprimento de 8. Qualquer valor maior resulta em: ORA-01489: o resultado da concatenação de strings é muito longo
Sem golfe
A visualização a gera as letras: i na coluna a e seu valor em b.
A visualização recursiva v assume a cadeia que está sendo construída como parâmetro v, o valor da última letra usada em ce o valor da maior letra usada em n. O parâmetro n é igual ao comprimento da string sem nenhuma letra duplicada, é para isso que serve a regex.
Uma letra é válida se seu valor for <= o valor da maior letra já usada ou se for a próxima letra a ser usada.
De alguma forma, a consulta precisa da parte LENGTH (s) <: n para ser executada. Devo estar faltando alguma coisa em como a consulta funciona.
O SELECT principal cuida da filtragem das entradas inválidas e das seqüências mais curtas construídas antes que o comprimento desejado seja atingido.
Versão de 412 bytes
Não tente a consulta de 412 bytes com 26. Ele coloca o banco de dados no modo restrito, pelo menos na minha versão xe em execução em um contêiner de docker em um macbook. Eu poderia experimentar os exadados no trabalho, mas, infelizmente, ainda preciso trabalhar para viver.
fonte
Mathematica, 136 bytes
Para completar, aqui está a minha implementação de referência de golfe. Ao contrário das respostas existentes, isso não é executado no tempo polinomial (é exponencial na
N
base 2), mas atende à restrição de tempo (o pior caso ainda seria executado em menos de meia hora).A ideia é esta:
Para cada esquema de rima, podemos identificar as posições em que o caractere máximo até agora aumenta:
Podemos tratar essas marcações como um número binário, o que facilita a iteração em todas essas estruturas. Precisamos iterar de 2 n-1 a 2 n (ou vice-versa), que é a origem da complexidade exponencial do tempo.
i
, subtraímos dei
. Caso contrário, encontramos a estrutura do esquema de rima solicitado.i
(ou o que resta dela) como um número de base mista, onde os pesos dos dígitos são determinados pelo número de caracteres permitidos nas posições restantes.Eu me pergunto se isso permitiria uma solução mais curta em alguns dos outros idiomas que foram submetidos, uma vez que não requer nenhuma memória ou pré-computação.
fonte