Kürzeste, lexikographisch kleinste generierende Saite

16

Ein String x erzeugt einen String, ywenn yes sich um einen Teilstring einer unendlichen Wiederholung von handelt x. Zum Beispiel abcerzeugt bcabcab.

Schreiben Sie ein Programm, um die kürzeste, lexikografisch kleinste Zeichenfolge zu finden, die die Eingabe generiert. Sie erhalten bei der Standardeingabe eine einzelne Textzeile. Sie sollten den generierenden String auf die Standardausgabe drucken. Beispielsweise:

Eingang

bcabcabca

Ausgabe

abc

Kürzester Code gewinnt. Sie können davon ausgehen, dass die Eingabe nur die Zeichen az enthält (und, wenn Sie möchten, eine nachgestellte Zeile).

Keith Randall
quelle
Die Ausgabe sollte in beliebiger Reihenfolge erfolgen. Angenommen, die Ausgabe kann bacin Ihrem Beispiel statt abc?
Ameisen
@GroovyUser: nein, die Eingabe ist keine Teilzeichenfolge eines wiederholten Musters von bacs.
Keith Randall
Die Eingabe könnte aber auch aus einem Teilstring von bestehen (bca)^n, was bcafür das gegebene Beispiel genauso gilt wie abc.
JAB
1
@JAB: bcaist nicht die kleinste lexikografisch.
Keith Randall
Ah, ich habe diesen Teil irgendwie verpasst.
JAB

Antworten:

9

Ruby 1.9, 40 Zeichen

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

Angenommen, die Eingabe wird nicht durch einen Zeilenumbruch beendet. Außerdem ist es für größere Ergebnisse wahrscheinlich lächerlich langsam.

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

Python 88 185 Zeichen

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

Ausgabe:

bcabcabca
abc

aaa
a

abc
abc

cccbbcccbbcccbb
bbccc

barfoofoobarfoofoo
arfoofoob

bacabac
abacbac
Vader
quelle
Gibt Ihnen nicht die lexikographisch kleinste Zeichenfolge für einige Eingaben, z. B. "Bacabac"
Howard
@Howard Du hast recht. Ich habe meinen Code aktualisiert, der jetzt viel länger ist, aber Zeichenfolgen bacabackorrekt verarbeitet.
Vader
"abac" wäre richtig, siehe @ yogsotoths Antwort: ein Bacabac abac.
Howard
2

Haskell, 299 128 Zeichen

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

Danke an jloy! Jetzt ist die Version beide viel kürzer und ich glaube richtig.

yogsototh
quelle
1
Die gute Nachricht ist also, dass es möglich ist, diese Lösung auf etwa 91 Zeichen herunterzuspielen, wenn Sie wie in Venteros Ruby-Lösung Standardeingaben akzeptieren. Leider wird die Eingabe cabcabcabcerzeugt abcabc, sodass diese Lösung nicht ganz da ist. Ich denke, Sie müssen modifizieren q++q++q, um das gewünschte Ergebnis zu erzielen . Mein schneller Versuch, gestoßene Dinge wieder auf 145 Zeichen zu bringen. (Spoiler sind hier: gist.github.com/1035161 )
Vielen Dank! Ich wusste weder über Interaktion noch über Inits << = Tails Bescheid, um alle Teilzeichenfolgen abzurufen. Ich habe deine Version leicht modifiziert, um ein bisschen Charakter zu bekommen. Ich habe sort entfernt und filter (not.null) by filter ((/ =) "") geändert. Danke noch einmal!
Yogasototh
Warum brauchst du (/=)""Kondition? Es scheint nichts zu tun. Außerdem hilft es, Lambdas loszuwerden: Sie können w mithilfe des .Operators ganz loswerden und die Hauptfunktion auf ändern main=interact s, um ein paar Zeichen zu speichern.
Rotsor
Ich denke die Antwort für "bca" ist falsch. Es sollte "abc" sein, ist aber jetzt "bca".
Rotsor
Eine mögliche Lösung ist, permutationsanstelle von zu verwenden tails.
Rotsor
2

Python, 121 137 129 Zeichen

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)

BEARBEITEN: Der von JiminP entdeckte Fehler wurde behoben

Jules Olléon
quelle
Wow, das ist großartig! Leider druckt es aababfür Zeichenfolge ababa... :(
JiminP
Ok, behoben ... es wird länger :(
Jules Olléon
2

Ruby 1.9, 36

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

Verwendet den gleichen Ansatz wie die Lösung von Ventero.

Lowjacker
quelle
2

Python, 161 159 166 140 141 134 132 Zeichen

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 : Golfed den Code nach dem Lesen von Jules Olléon Kommentar. Ein Fehler, der dazu führte, wurde bcdabcdabbehoben abbc.

EDIT2 : Der von Jules Olléon entdeckte Fehler ( abaaresultiert in aaa) wurde behoben.

Ich weiß nicht gut über Python Bescheid, daher ist dieser Code wahrscheinlich "nicht golfen".

Ich liebe diese Regel:

Sie können davon ausgehen, dass die Eingabe nur die Zeichen az enthält ...

Eingänge Ausgänge

bcdabcd
abcd

bcabcabca
abc


abcdabcd
abcd

bcdabcdab
abcd

barfoofoobarfoofoobar
arfoofoob

cccbbcccbbcccbb
bbccc

aaaaaaaaaaaaaaaa
a

thequickbrownfox
brownfoxthequick

ababa
ab

abaa
aab
JiminP
quelle
1
Brauner Fuchs, der Schnelle! Hund, der Faule!
20.
Schöne Lösung, ziemlich kurz und wahrscheinlich die beste Komplexität hier! Sie könnten ein bisschen Golf spielen - zum Beispiel brauchen Sie kein "int", um die Saiten zu vergleichen. und ersetze "while i> 0" durch "while i" und "y = y + y" durch "y * = 2".
Jules Olléon
Eigentlich gibt es ein Problem: für abaa gibt es aaa aus ...
Jules Olléon
@Jules Danke für den Kommentar! Ich habe nicht darüber
nachgedacht
Sie können i-=1anstelle von tun i=i-1. Ebenso für das Inkrement.
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]

Leerzeichen und Zeilenumbrüche (bei Vorhandensein von Semikolons am Zeilenende) haben in Mathematica keine Bedeutung und werden hier zur besseren Lesbarkeit angegeben.

Die Eingabe erfolgt zwischen den Anführungszeichen in der ersten Zeile. Wenn Recast als Funktion ausgeführt wird, werden Zeichenfolgen wie folgt eingegeben:

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

dann sind es 128 Bytes.

Die ForSchleife nimmt die ersten iZeichen der Eingabe und wiederholt sie mindestens bis zur Länge der Eingabe. Anschließend prüft sie, ob die Eingabe eine Teilzeichenfolge des Ergebnisses ist. Nachdem der StringPartitionBefehl die Länge des Zeitraums der Zeichenfolge ermittelt hat, verknüpft er zwei Kopien dieses Zeitraums und entnimmt ihm alle Teilzeichenfolgen dieser Länge (im Grunde genommen erhält er alle zyklischen Permutationen) und First@Sortfindet dann die erste von ihnen, wenn sie lexikografisch geordnet ist.

LLlAMnYP
quelle
0

Javascript 96 Zeichen.

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

Working Plunkr

ngLover
quelle
1
Willkommen in der Community! Ich konnte Ihren Code jedoch nicht testen. Können Sie entweder das Lesen von Code aus GET / POST und das Schreiben mit alert oder console.log bereitstellen oder eine Funktion, die die Eingabe als Parameter verwendet und die Ausgabe zurückgibt?
Aaron
@AaronGOUZIT hat pluckr
ngLover
Danke, das hilft. Der von Ihnen eingegebene Code kann jedoch nicht alleine verwendet werden, sodass die Anzahl der Bytes betrogen wird. Wichtiger ist jedoch, dass Ihr Code die Spezifikationen nicht einhält: Ich glaube, Sie geben eine Reihe eindeutiger Buchstaben zurück, die anstelle einer "generierenden Zeichenfolge" verwendet werden. Diese sollten wir (als Ganzes) mit optionaler Kürzung wiederholen können Holen Sie sich die Eingabe. Ich freue mich auf Ihren aktualisierten Code!
Aaron