Cadeia geradora mais curta e lexicograficamente menor

16

Uma string x gera uma string yse yfor uma substring de uma repetição infinita de x. Por exemplo abcgera bcabcab.

Escreva um programa para encontrar a string mais curta e lexicograficamente menor que irá gerar a entrada. Você recebe na entrada padrão uma única linha de texto. Você deve imprimir a sequência geradora na saída padrão. Por exemplo:

entrada

bcabcabca

resultado

abc

O menor código vence. Você pode assumir que a entrada contém apenas os caracteres az (e uma nova linha à direita, se desejar).

Keith Randall
fonte
A saída deve estar em qualquer ordem? Digamos que a saída possa estar bacno seu exemplo, e não abc?
Ant
@GroovyUser: não, a entrada não é uma substring de um padrão repetido de bacs.
Keith Randall
Mas a entrada pode consistir em uma substring de (bca)^n, o que significa que bcaé tão válido para o exemplo dado quanto abc.
21912 JAB
11
@ JAB: bcanão é o menor lexicograficamente.
Keith Randall
Ah, de alguma forma eu perdi essa parte.
JAB

Respostas:

9

Ruby 1.9, 40 caracteres

gets;a=?a;a.next!until(a*~/$/)[$_];$><<a

Supõe que a entrada não seja finalizada por uma nova linha. Também é provavelmente ridiculamente lento para obter resultados maiores.

$ echo -n "bcabcabca" | ruby genlex.rb 
abc
$ echo -n "barfoobarfoobarfoo" | ruby1.9 genlex.rb 
arfoob
Ventero
fonte
2

Python 88 185 caracteres

import re
s=raw_input()
m=s.index(min(s))
s=s[m:]+s[:m]
i=0
while s.replace(s[:i],''):i+=1
m=min(s[:i])
s=re.findall('%s[\w]*?(?=%s|$)'%(m,m),s[:i])
m=s.index(min(s))
print ''.join(s[m:]+s[:m])

Resultado:

bcabcabca
abc

aaa
a

abc
abc

cccbbcccbbcccbb
bbccc

barfoofoobarfoofoo
arfoofoob

bacabac
abacbac
Vader
fonte
Não lhe dá o lexicographically menor string para alguns insumos, por exemplo, "bacabac"
Howard
@ Howard Você está certo. Atualizei meu código, agora está muito mais longo, mas lida com as strings bacabaccorretamente.
Vader
"abac" estaria correto, veja a resposta de @ yogsototh: um bacabac abac.
Howard
2

Haskell, 299 128 caracteres

import Data.List
main=interact(\z->minimum$filter(\w->isInfixOf z$concat$replicate(length z)w) $filter((/=)"")$inits=<<tails z)

Graças a jloy! Agora a versão é muito mais curta e acredito correta.

yogsototh
fonte
11
Portanto, a boa notícia é que é possível reduzir essa solução para cerca de 91 caracteres se você aceitar a entrada no stdin como na solução Ruby da Ventero. Infelizmente, a entrada cabcabcabcproduz abcabc, então essa solução não está lá. Eu acho que você precisará modificar q++q++qpara obter o resultado desejado. Minha rápida tentativa de consertar as coisas aumentou para 145 caracteres. (Spoilers estão aqui: gist.github.com/1035161 )
Obrigado! Eu não sabia sobre interação nem nunca sobre inits << = tails para obter todas as substrings. Modifiquei levemente sua versão para ganhar um pouco de caracteres. Eu removi a classificação e troquei o filtro (not.null) pelo filtro ((/ =) ""). Obrigado novamente!
yogsototh
Por que você precisa de (/=)""condição? Parece não fazer nada. Além disso, livrar-se de lambdas ajuda: você pode se livrar de w usando o .operador e altere a função principal main=interact spara salvar alguns caracteres.
Rotsor
Eu acho que a resposta para "bca" está errada. Deve ser "abc", mas é "bca" agora.
Rotsor
Uma solução possível é usar em permutationsvez de tails.
precisa saber é o seguinte
2

Python, 121 137 129 caracteres

s=raw_input()
n=len(s)
l=[(s+s)[i/n:i/n+i%n+1]for i in range(n*n)]
print min(filter(lambda x:(x*len(s)).find(s)+1,sorted(l)),key=len)

EDIT: corrigido o erro detectado pelo JiminP

Jules Olléon
fonte
Uau é ótimo! Infelizmente, ele imprime aababpara seqüência de caracteres ababa... :(
JiminP 23/06
Ok, corrigido ... está ficando mais longo :(
Jules Olléon
2

Ruby 1.9, 36

$><<(?a..gets).find{|s|(s*~/$/)[$_]}

Usa a mesma abordagem que a solução da Ventero.

Lowjacker
fonte
2

Pitão, 161 159 166 140 141 134 132 caracteres

y=raw_input();i=n=l=len(y)
while i:
 if (y[:i]*l)[:l]==y:n=i
 i-=1
x=y[:n];y=x*2
while i<n:
 x=min(x,y[i:i+n])
 i+=1
print x

Edição : Golfed o código depois de ler o comentário de Jules Olléon. Foi removido um 'bug' que bcdabcdabresulta em abbc.

EDIT2 : Corrigido o erro ( abaaresulta em aaa) detectado por Jules Olléon.

Eu não conheço bem o Python, portanto esse código provavelmente não é 'jogado'.

Eu amo essa regra:

Você pode assumir que a entrada contém apenas os caracteres az ...

Entradas saídas

bcdabcd
abcd

bcabcabca
abc


abcdabcd
abcd

bcdabcdab
abcd

barfoofoobarfoofoobar
arfoofoob

cccbbcccbbcccbb
bbccc

aaaaaaaaaaaaaaaa
a

thequickbrownfox
brownfoxthequick

ababa
ab

abaa
aab
JiminP
fonte
11
Raposa marrom, o rápido! Cão, o preguiçoso!
JiminP
Ótima solução, muito curta e provavelmente a melhor complexidade aqui! Você poderia jogar um pouco - por exemplo, você não precisa de "int" para comparar strings; e substitua "while i> 0" por "while i" e "y = y + y" por "y * = 2".
Jules Olléon
Na verdade, há um problema: para ABAA imprime aaa ...
Jules Olléon
@Jules Obrigado pelo comentário! Eu não pensei nisso ...
JiminP 23/06
Você pode fazer em i-=1vez de i=i-1. Da mesma forma para o incremento.
Lowjacker
1

Mathematica 124 bytes

x = StringLength@(y = "");
For[i = 1, ! (s = y~StringTake~i)~StringRepeat~x~StringContainsQ~y,i++];
First@Sort@StringPartition[s <> s, i, 1]

Espaço em branco e novas linhas (na presença de ponto e vírgula no final das linhas) não têm significado no Mathematica e estão incluídos aqui para facilitar a leitura.

A entrada entra entre aspas na primeira linha. Se reformulado como uma função, isso leva a entrada de string da seguinte maneira:

f=(x=StringLength@(y=#);For[i=1,!(s=y~StringTake~i)~StringRepeat~x~StringContainsQ~y,i++];First@Sort@StringPartition[s<>s,i,1])&

f@"bca"

(* "abc" *)

f@"abaa"

(* "aab" *)

então são 128 bytes.

O Forloop pega os primeiros icaracteres da entrada e os repete pelo menos até o comprimento da entrada, depois verifica se a entrada é uma substring do resultado. Tendo encontrado a duração do período da string, o StringPartitioncomando concatena duas cópias desse período e tira todas as subseqüências desse comprimento (basicamente obtém todas as permutações cíclicas) e, em seguida, First@Sortencontra a primeira delas quando ordenada lexicograficamente.

LLlAMnYP
fonte
0

javascript 96 caracteres.

var temp = {},len = str.length;
for(i in str) 
temp[str[i]] = true;
Object.keys(temp).join(""); 

Plunkr de trabalho

ngLover
fonte
11
Bem-vindo à comunidade! Porém, não pude testar seu código, você poderia fornecer a leitura de código de GET / POST e escrever com alert ou console.log ou uma função que aceite a entrada como parâmetro e retorne a saída?
Aaron
@AaronGOUZIT adicionou pluckr
ngLover
Obrigado, isso ajuda. Ainda assim, o código que você postou não pode ser usado sozinho, de modo a enganar a contagem de bytes. Mais importante, receio que seu código não respeite as especificações: acredito que você retorne um conjunto de letras únicas usadas em vez de uma "sequência geradora", que poderemos repetir (como um todo) com truncamento opcional para obtenha a entrada. Estou ansioso para ver seu código atualizado!
Aaron