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


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

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

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.


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


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.


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

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.


0

javascript 96 znaków.

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

Working Plunkr


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.