Chaîne de génération la plus courte et lexicographiquement la plus petite


16

Une chaîne x génère une chaîne ysi yest une sous-chaîne d'une répétition infinie de x. Par exemple abcgénère bcabcab.

Écrivez un programme pour trouver la chaîne la plus courte et lexicographiquement la plus petite qui générera l'entrée. On vous donne en entrée standard une seule ligne de texte. Vous devez imprimer la chaîne de génération sur la sortie standard. Par exemple:

contribution

bcabcabca

production

abc

Le code le plus court gagne. Vous pouvez supposer que l'entrée ne contient que les caractères az (et un retour à la ligne si vous le souhaitez).


La sortie doit être dans n'importe quel ordre? Disons que la sortie peut être bacdans votre exemple plutôt que abc?
Ant's

@GroovyUser: non, l'entrée n'est pas une sous-chaîne d'un motif répété de bacs.
Keith Randall

Mais l'entrée pourrait consister en une sous-chaîne de (bca)^n, ce qui signifie bcaest tout aussi valable pour l'exemple donné que abc.
JAB

1
@JAB: bcan'est pas le plus petit lexicographiquement.
Keith Randall

Ah, j'ai en quelque sorte raté cette partie.
JAB

Réponses:


9

Ruby 1.9, 40 caractères

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

Suppose que l'entrée n'est pas terminée par une nouvelle ligne. De plus, c'est probablement ridiculement lent pour des résultats plus importants.

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

2

Python 88 185 caractères

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])

Production:

bcabcabca
abc

aaa
a

abc
abc

cccbbcccbbcccbb
bbccc

barfoofoobarfoofoo
arfoofoob

bacabac
abacbac

Ne vous donne pas la plus petite chaîne lexicographiquement pour certaines entrées, par exemple "bacabac"
Howard

@Howard Vous avez raison. J'ai mis à jour mon code, il est beaucoup plus long maintenant, mais gère bacabaccorrectement les chaînes .
Vader

"abac" serait correct, voir la réponse de @ yogsototh: un bacabac abac.
Howard

2

Haskell, 299 128 caractères

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

Merci à jloy! Maintenant, la version est à la fois beaucoup plus courte et je crois correcte.


1
Donc, la bonne nouvelle est qu'il est possible de faire jouer cette solution à environ 91 caractères si vous acceptez l'entrée sur stdin comme dans la solution Ruby de Ventero. Malheureusement, l'entrée cabcabcabcproduit abcabc, donc cette solution n'est pas tout à fait là. Je pense que vous devrez modifier q++q++qpour obtenir le résultat souhaité. Ma tentative rapide de réparer les choses a remonté à 145 caractères cependant. (Les spoilers sont ici: gist.github.com/1035161 )

Merci! Je ne connaissais pas les interactions ni jamais les inits << = tails pour obtenir toutes les sous-chaînes. J'ai légèrement modifié votre version pour gagner un peu de personnages. J'ai supprimé le tri et changé le filtre (not.null) par filter ((/ =) ""). Merci encore!
yogsototh

Pourquoi avez-vous besoin de (/=)""condition? Cela ne semble rien faire. De plus, se débarrasser de lambdas aide: vous pouvez vous débarrasser complètement de w en utilisant l' .opérateur et changer la fonction principale main=interact spour enregistrer quelques caractères.
Rotsor

Je pense que la réponse pour "bca" est fausse. Ce devrait être "abc", mais c'est "bca" maintenant.
Rotsor

Une solution possible consiste à utiliser permutationsau lieu de tails.
Rotsor

2

Python, 121 137 129 129 caractères

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: correction du bug repéré par JiminP


Wow c'est génial! Malheureusement, il imprime aababpour la chaîne ababa... :(
JiminP

Ok, fixe ... ça s'allonge :(
Jules Olléon

2

Rubis 1.9, 36

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

Utilise la même approche que la solution de Ventero.


2

Python, 161 159 166 140 141 134 132 caractères

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

EDIT : Golfé le code après avoir lu le commentaire de Jules Olléon. Suppression d'un «bug» qui se bcdabcdabtraduit par abbc.

EDIT2 : Correction du bug ( abaarésultats dans aaa) repéré par Jules Olléon.

Je ne connais pas bien Python, donc ce code n'est probablement pas «joué au golf».

J'adore cette règle:

Vous pouvez supposer que l'entrée ne contient que les caractères az ...

Entrées et sorties

bcdabcd
abcd

bcabcabca
abc


abcdabcd
abcd

bcdabcdab
abcd

barfoofoobarfoofoobar
arfoofoob

cccbbcccbbcccbb
bbccc

aaaaaaaaaaaaaaaa
a

thequickbrownfox
brownfoxthequick

ababa
ab

abaa
aab

1
Renard brun, le vif! Chien, le paresseux!
JiminP

Belle solution, assez courte et probablement la meilleure complexité ici! Vous pouvez jouer au golf un peu - par exemple, vous n'avez pas besoin de "int" pour comparer les chaînes; et remplacez "while i> 0" par "while i" et "y = y + y" par "y * = 2".
Jules Olléon

En fait il y a un problème: pour abaa ça imprime aaa ...
Jules Olléon

@Jules Merci pour le commentaire! Je n'y ai pas pensé ...
JiminP

Vous pouvez faire i-=1au lieu de i=i-1. De même pour l'incrément.
Lowjacker

1

Mathematica 124 octets

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

Les espaces et les retours à la ligne (en présence de points-virgules à la fin des lignes) n'ont aucune signification dans Mathematica et sont inclus ici pour plus de lisibilité.

L'entrée passe entre les guillemets de la première ligne. Si la refonte est une fonction, cela prend une entrée de chaîne comme ceci:

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

alors c'est 128 octets.

La Forboucle prend les premiers icaractères de l'entrée et les répète au moins jusqu'à la longueur de l'entrée, puis vérifie si l'entrée est une sous-chaîne du résultat. Après avoir trouvé la longueur de la période de la chaîne, la StringPartitioncommande concatène deux copies de cette période et en prend toutes les sous-chaînes (obtient essentiellement toutes les permutations cycliques), puis First@Sorttrouve la première d'entre elles lorsqu'elle est ordonnée lexicographiquement.


0

javascript 96 caractères.

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

Plunkr de travail


1
Bienvenue dans la communauté! Je n'ai pas pu tester votre code cependant, pourriez-vous fournir la lecture de code à partir de GET / POST et l'écriture avec alert ou console.log ou une fonction prenant l'entrée en paramètre et renvoyant la sortie?
Aaron

@AaronGOUZIT a ajouté pluckr
ngLover

Merci, ça aide. Pourtant, le code que vous avez publié ne peut pas être utilisé seul, ce qui trompe le nombre d'octets. Plus important encore, je crains que votre code ne respecte pas les spécifications: je pense que vous renvoyez un ensemble de lettres uniques utilisées plutôt qu'une "chaîne de génération", que nous devrions pouvoir répéter (dans son ensemble) avec une troncature facultative à obtenir l'entrée. J'ai hâte de voir votre code mis à jour!
Aaron
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.