Najkrótszy, najmniejszy leksykograficznie ciąg generujący

16

Łańcuch x generuje łańcuch, yjeśli yjest podciągiem nieskończonego powtórzenia x. Na przykład abcgeneruje bcabcab.

Napisz program, aby znaleźć najkrótszy, najmniejszy leksykograficznie ciąg znaków, który wygeneruje dane wejściowe. Przy standardowym wprowadzaniu podawany jest pojedynczy wiersz tekstu. Powinieneś wydrukować ciąg generujący na standardowe wyjście. Na przykład:

Wejście

bcabcabca

wynik

abc

Najkrótszy kod wygrywa. Możesz założyć, że dane wejściowe zawierają tylko znaki az (i końcowy znak nowej linii, jeśli chcesz).

Keith Randall
źródło
Wyjście powinno być w dowolnej kolejności? Powiedz, że wynik może być bacw twoim przykładzie, a nie abc?
Ant's
@GroovyUser: nie, dane wejściowe nie są podciągiem powtarzającego się wzoru bacs.
Keith Randall
Ale dane wejściowe mogą składać się z podłańcucha (bca)^n, co oznacza, że bcajest tak samo ważne dla podanego przykładu, jak abc.
JAB
1
@JAB: bcanie jest najmniejszym leksykograficznie.
Keith Randall
Ach, jakoś tęskniłem za tą częścią.
JAB

Odpowiedzi:

9

Ruby 1.9, 40 znaków

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

Zakłada, że ​​wejście nie jest zakończone znakiem nowej linii. Prawdopodobnie jest też absurdalnie powolny dla większych wyników.

$ echo -n "bcabcabca" | ruby genlex.rb 
abc
$ echo -n "barfoobarfoobarfoo" | ruby1.9 genlex.rb 
arfoob
Ventero
źródło
2

Python 88 185 znaków

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

Wynik:

bcabcabca
abc

aaa
a

abc
abc

cccbbcccbbcccbb
bbccc

barfoofoobarfoofoo
arfoofoob

bacabac
abacbac
Vader
źródło
Nie podaje leksykograficznie najmniejszego ciągu dla niektórych danych wejściowych, np. „Bacabac”
Howard
@Jak masz rację. Zaktualizowałem swój kod, jest teraz znacznie dłuższy, ale obsługuje ciągi jak bacabacpoprawnie.
Vader
„abac” byłoby poprawne, patrz odpowiedź @ yogsototh: bacabac abac.
Howard
2

Haskell, 299 128 znaków

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

Dzięki jloy! Teraz wersja jest znacznie krótsza i uważam, że jest poprawna.

jogurt
źródło
1
Dobrą wiadomością jest to, że możliwe jest uzyskanie golfa w tym rozwiązaniu do około 91 znaków, jeśli zaakceptujesz dane wejściowe na standardowe wejście, jak w rozwiązaniu Ruby firmy Ventero. Niestety dane wejściowe są cabcabcabcgenerowane abcabc, więc tego rozwiązania nie ma. Myślę, że musisz zmodyfikować q++q++q, aby uzyskać pożądany wynik. Jednak moja szybka próba naprawienia podskoczyła do 145 znaków. (Spoilery są tutaj: gist.github.com/1035161 )
Dzięki! Nie wiedziałem o interakcji ani nigdy o inits << = reszka, aby uzyskać wszystkie podciągi. Lekko zmodyfikowałem twoją wersję, aby zyskać trochę postaci. Usunąłem sortowanie i zmieniłem filtr (nie zerowy) według filtra ((/ =) „”). Dzięki jeszcze raz!
yogsototh
Dlaczego potrzebujesz (/=)""warunku? Wydaje się, że nic nie robi. Ponadto pomaga pozbyć się lambdas: możesz całkowicie pozbyć się w za pomocą .operatora i zmienić główną funkcję, main=interact saby zapisać kilka znaków.
Rotsor
Myślę, że odpowiedź na „bca” jest błędna. Powinien to być „abc”, ale teraz jest „bca”.
Rotsor
Jednym z możliwych rozwiązań jest użycie permutationszamiast tails.
Rotsor
2

Python, 121 137 129 znaków

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)

EDYCJA: naprawiono błąd wykryty przez JiminP

Jules Olléon
źródło
Wow to świetnie! Niestety, drukuje aababdla łańcucha ababa... :(
JiminP
Ok, naprawione ... robi się coraz dłużej :(
Jules Olléon
2

Ruby 1.9, 36

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

Stosuje to samo podejście, co rozwiązanie Ventero.

Lowjacker
źródło
2

Pyton, 161 159 166 140 141 141 134 132 znaki

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

EDYCJA : Odczytałem kod po przeczytaniu komentarza Julesa Olléona. Usunięto błąd, który bcdabcdabpowoduje abbc.

EDYCJA 2 : Naprawiono błąd ( abaawyniki w aaa) zauważony przez Julesa Olléona.

Nie znam dobrze Pythona, więc ten kod prawdopodobnie nie jest „golfem”.

Uwielbiam tę zasadę:

Możesz założyć, że dane wejściowe zawierają tylko znaki az ...

Wejścia wyjścia

bcdabcd
abcd

bcabcabca
abc


abcdabcd
abcd

bcdabcdab
abcd

barfoofoobarfoofoobar
arfoofoob

cccbbcccbbcccbb
bbccc

aaaaaaaaaaaaaaaa
a

thequickbrownfox
brownfoxthequick

ababa
ab

abaa
aab
JiminP
źródło
1
Brązowy lis, szybki! Pies leniwy!
JiminP
Ładne rozwiązanie, dość krótkie i prawdopodobnie najlepsza tutaj złożoność! Możesz trochę zagrać w golfa - na przykład nie potrzebujesz „int” do porównywania ciągów; i zamień „while i> 0” na „while i” i „y = y + y” na „y * = 2”.
Jules Olléon
W rzeczywistości jest problem: dla abaa drukuje aaa ...
Jules Olléon
@Jules Dzięki za komentarz! Nie myślałem o tym ...
JiminP
Możesz zrobić i-=1zamiast i=i-1. Podobnie dla przyrostu.
Lowjacker
1

Matematyka 124 bajty

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

Białe znaki i znaki nowej linii (w obecności średników na końcach wierszy) nie mają znaczenia w Mathematica i zostały tutaj uwzględnione dla czytelności.

Dane wejściowe znajdują się między znakami cudzysłowu w pierwszym wierszu. W przypadku przekształcenia jako funkcji, pobiera ciąg znaków w następujący sposób:

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

to jest 128 bajtów.

ForPętla zajmuje pierwsze iznaki wejścia i powtarza je co najmniej do długości wejściowych, a następnie sprawdza, czy wejście jest podciąg wyniku. Po znalezieniu długości okresu łańcucha, StringPartitionpolecenie konkatenuje dwie kopie tego okresu i pobiera z niego wszystkie podciągi o tej długości (w zasadzie pobiera wszystkie permutacje cykliczne), a następnie First@Sortwyszukuje pierwszy z nich, gdy jest uporządkowany leksykograficznie.

LLAMAMYP
źródło
0

javascript 96 znaków.

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

Working Plunkr

ngLover
źródło
1
Witamy w społeczności! Nie mogłem jednak przetestować twojego kodu, czy możesz podać odczyt kodu z GET / POST i napisanie z alertem lub console.log lub funkcją przyjmującą dane wejściowe jako parametr i zwracającą dane wyjściowe?
Aaron,
@AaronGOUZIT dodał pluckr
ngLover
Dzięki, to pomaga. Mimo to kodu, który opublikowałeś, nie można używać osobno, więc oszukiwa licznik bajtów. Co ważniejsze, obawiam się, że Twój kod nie przestrzega specyfikacji: uważam, że zwracasz zestaw użytych unikalnych liter zamiast „ciągu generującego”, który powinniśmy być w stanie powtórzyć (jako całość) z opcjonalnym obcięciem, aby uzyskać dane wejściowe. Czekam na Twój zaktualizowany kod!
Aaron,