Cadena generadora más corta, lexicográficamente más pequeña

16

Una cadena x genera una cadena ysi yes una subcadena de una repetición infinita de x. Por ejemplo abcgenera bcabcab.

Escriba un programa para encontrar la cadena más corta, lexicográficamente más pequeña que generará la entrada. Se le da en la entrada estándar una sola línea de texto. Debe imprimir la cadena generadora a la salida estándar. Por ejemplo:

entrada

bcabcabca

salida

abc

El código más corto gana. Puede suponer que la entrada contiene solo los caracteres az (y una nueva línea final si lo desea).

Keith Randall
fuente
La salida debe estar en cualquier orden? Decir salida puede estar bacen su ejemplo en lugar de abc?
Ant's
@GroovyUser: no, la entrada no es una subcadena de un patrón repetido de bacs.
Keith Randall
Pero la entrada podría consistir en una subcadena de (bca)^n, lo que significa que bcaes tan válido para el ejemplo dado como abc.
JAB
1
@JAB: bcano es el más pequeño lexicográficamente.
Keith Randall
Ah, de alguna manera me perdí esa parte.
JAB

Respuestas:

9

Ruby 1.9, 40 caracteres

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

Asume que la entrada no es terminada por una nueva línea. También es probablemente ridículamente lento para obtener resultados más grandes.

$ echo -n "bcabcabca" | ruby genlex.rb 
abc
$ echo -n "barfoobarfoobarfoo" | ruby1.9 genlex.rb 
arfoob
Ventero
fuente
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])

Salida:

bcabcabca
abc

aaa
a

abc
abc

cccbbcccbbcccbb
bbccc

barfoofoobarfoofoo
arfoofoob

bacabac
abacbac
Vader
fuente
No le da la cadena lexicográficamente más pequeña para algunas entradas, por ejemplo, "bacabac"
Howard
@Howard Tienes razón. He actualizado mi código, ahora es mucho más largo, pero maneja cadenas como bacabaccorrectamente.
Vader
"abac" sería correcto, vea la respuesta de @ yogsototh: un bababac 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)

Gracias a jloy! Ahora la versión es mucho más corta y creo que es correcta.

yogotototh
fuente
1
Entonces, la buena noticia es que es posible reducir esta solución a aproximadamente 91 caracteres si acepta la entrada en stdin como en la solución Ruby de Ventero. Desafortunadamente, la entrada cabcabcabcproduce abcabc, por lo que esta solución no está ahí. Creo que tendrá que modificar q++q++qpara obtener el resultado deseado. Sin embargo, mi intento rápido de arreglar las cosas volvieron a tener 145 caracteres. (Spoilers están aquí: gist.github.com/1035161 )
¡Gracias! No sabía sobre interactuar ni nunca sobre inits << = tails para obtener todas las subcadenas. Modifiqué ligeramente tu versión para ganar un poco de caracteres. Eliminé la ordenación y cambié el filtro (not.null) por filtro ((/ =) ""). ¡Gracias de nuevo!
yogsototh
¿Por qué necesitas (/=)""condición? No parece hacer nada. Además, deshacerse de lambdas ayuda: puede deshacerse de w por completo utilizando el .operador y cambiar la función principal main=interact spara guardar un par de caracteres.
Rotsor
Creo que la respuesta para "bca" es incorrecta. Debería ser "abc", pero ahora es "bca".
Rotsor
Una posible solución es usar en permutationslugar de tails.
Rotsor
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)

EDITAR: se corrigió el error detectado por JiminP

Jules Olléon
fuente
¡Wow es genial! Desafortunadamente, imprime aababpara cadena ababa... :(
JiminP
Ok, arreglado ... se está alargando :(
Jules Olléon
2

Ruby 1.9, 36

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

Utiliza el mismo enfoque que la solución de Ventero.

Lowjacker
fuente
2

Pitón, 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

EDITAR : Golfed el código después de leer el comentario de Jules Olléon. Se eliminó un 'error' que bcdabcdabda como resultado abbc.

EDIT2 : Se corrigió el error ( abaaresultados aaa) detectado por Jules Olléon.

No conozco bien Python, por lo que este código probablemente no sea "golf".

Amo esta regla:

Puede suponer que la entrada contiene solo los caracteres az ...

Salidas, entradas

bcdabcd
abcd

bcabcabca
abc


abcdabcd
abcd

bcdabcdab
abcd

barfoofoobarfoofoobar
arfoofoob

cccbbcccbbcccbb
bbccc

aaaaaaaaaaaaaaaa
a

thequickbrownfox
brownfoxthequick

ababa
ab

abaa
aab
JiminP
fuente
1
Zorro marrón, el rápido! Perro, el vago!
JiminP
¡Buena solución, bastante corta y probablemente la mejor complejidad aquí! Podrías jugar un poco al golf; por ejemplo, no necesitas "int" para comparar cadenas; y reemplace "while i> 0" por "while i" y "y = y + y" por "y * = 2".
Jules Olléon el
En realidad hay un problema: para abaa imprime aaa ...
Jules Olléon
@Jules Gracias por el comentario! No pensé en eso ...
JiminP
Puedes hacer en i-=1lugar de i=i-1. Igualmente para el 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]

Los espacios en blanco y las nuevas líneas (en presencia de punto y coma en los extremos de las líneas) no tienen significado en Mathematica y se incluyen aquí para facilitar la lectura.

La entrada va entre comillas en la primera línea. Si se relanza como una función, eso toma la entrada de cadena de la siguiente manera:

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" *)

entonces son 128 bytes.

El Forbucle toma los primeros icaracteres de la entrada y los repite al menos hasta la longitud de la entrada, luego verifica si la entrada es una subcadena del resultado. Habiendo encontrado la longitud del período de la cadena, el StringPartitioncomando concatena dos copias de ese período y toma todas las subcadenas de esa longitud (básicamente obtiene todas las permutaciones cíclicas), luego First@Sortencuentra la primera de ellas cuando se ordena lexicográficamente.

LLlAMnYP
fuente
0

javascript 96 Chars.

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

Plunkr de trabajo

ngLover
fuente
1
¡Bienvenido a la comunidad! Sin embargo, no pude probar su código, ¿podría proporcionar lectura de código de GET / POST y escribir con alert o console.log o una función que tome la entrada como parámetro y devuelva la salida?
Aaron
@AaronGOUZIT agregó pluckr
ngLover
Gracias, eso ayuda. Aún así, el código que publicó no se puede usar solo, por lo que engaña al recuento de bytes. Más importante aún, me temo que su código no respeta las especificaciones: creo que devuelve un conjunto de letras únicas utilizadas en lugar de una "cadena generadora", que deberíamos poder repetir (como un todo) con truncamiento opcional para obtener la entrada ¡Espero ver tu código actualizado!
Aaron