Wyjście wszystkich ciągów

34

Biorąc pod uwagę zestaw liter, wypisz wszystkie ciągi znaków z tych liter. (To jest gwiazda Kleene zestawu.) Na przykład {'a','b'}ciągi:

'', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', ...

Dane wejściowe: niepusty zbiór wyraźnych liter a..z. Mogą to być znaki lub ciągi jednoznakowe.

Wyjście: wszystkie ciągi w tych literach, w dowolnej kolejności, bez powtórzeń. Możesz używać list znaków jako ciągów znaków.

To jest nieskończona lista, więc możesz wygenerować ją przez:

  • Ciągłe pisanie coraz większej liczby łańcuchów. Ciągi te można zapisać w dowolnym formacie z separacją płaską, co oznacza, że ​​można powiedzieć, gdzie kończy się każdy ciąg, ale ciągi te nie są podzielone na grupy.
  • Biorąc liczbę njako dane wejściowe i wyprowadzając pierwsze nciągi znaków w dowolnym formacie z płaską separacją
  • Uzyskanie każdego łańcucha z kolei z obiektu generatora
  • Produkcja nieskończonego obiektu

Upewnij się, że twoja metoda w końcu generuje każdy ciąg na wyjściu, ponieważ możliwe jest wygenerowanie nieskończenie wielu ciągów ze zbioru, nigdy nie przechodząc do niektórych ciągów.

Nie możesz tego wygenerować

  • Wytworzenie npodanego ciągu thn
  • Dostarczenie wyroczni członkowskiej, która decyduje, czy dany ciąg należy do zestawu

Wbudowane są dozwolone, ale proszę wyborców o zwrócenie uwagi na odpowiedzi, które same wykonują operację, zamiast tych, które w większości opierają się na wbudowanym.

xnor
źródło
@Cyoce Nie jestem pewien, co masz na myśli. Wyjaśniłem, że ciągi muszą być oddzielone, aby można było odróżnić pusty ciąg od niczego.
xnor
Wyjaśnij, dlaczego „tworzenie N-tego ciągu o podanym N” jest niedozwolone.
CalculatorFeline
4
@CatsAreFluffy To było orzeczenie sądowe. Myślę, że napisanie N-tego ciągu byłoby zbyt łatwe w porównaniu z alternatywami i sprawiłoby, że wyzwanie stało się mniej interesujące, zwłaszcza że niektóre języki mają wbudowaną konwersję dowolnej bazy. Poza tym nie sądziłem, że uchwyciło to pomysł wygenerowania nieskończonego zestawu zamiast zapytania go.
xnor
Czy potrafisz wyjaśnić „wytwarzanie nieskończonego obiektu”? Czy to oznacza, że ​​możemy na przykład wepchnąć każdy ciąg na stos (w przypadku języków stosu) i pozwolić mu działać „na zawsze”, nawet jeśli nie zostanie wygenerowane żadne wyjście, ponieważ program się nie skończy?
Luis Mendo,
@DonMuesli Czy wyjście na stos jest akceptowaną metodą wyjścia dla takich języków? I czy stos będzie zawierał tylko te łańcuchy w dowolnym momencie?
xnor

Odpowiedzi:

26

Python 2, 53 56

-3 po uświadomieniu sobie, że yield xmożna go użyć jako wyrażenia.

def f(s):yield'';[(yield w+c)for w in f(s)for c in s]
feersum
źródło
Jeden bajt krótsze, ale rozpoczyna się 'aa'zamiast na '': S=lambda s:(c+w for f in[str,S]for w in f(s)for c in s). Nie działa również dla pustych danych wejściowych.
orlp
20

Haskell, 24 bajty

f s=[]:[b:a|a<-f s,b<-s]

Tworzy nieskończoną listę.

*Main> f "abc"
["","a","b","c","aa","ba","ca","ab","bb","cb","ac","bc","cc","aaa","baa","caa","aba","bba","cba",…
Anders Kaseorg
źródło
Szkoda (:)<$>s<*>f sdałoby niewłaściwy porządek. Jest, f s="":(flip(:)<$>f s<*>s)ale jest dłużej.
xnor
Tak. Znalazłem 23 bajty, f s=[]:(f s<**>map(:)s)ale <**>nie ma go Prelude.
Anders Kaseorg
11

JavaScript (ES6), 61 bajtów

function*g(s){yield'';for(let r of g(s))for(c of s)yield c+r}

Port generatora Python @ feersum. Jest letto konieczne. Zaoszczędź 2 bajty, używając rozumienia tablicowego (nieudana propozycja ES7, ale działa w przeglądarce Firefox 30-57):

function*g(s){yield'';[for(r of g(s))for(c of s)yield c+r]}

Alternatywna wersja dla 73 bajtów, która zwraca pierwsze nelementy wygenerowane przez powyższy generator:

(s,n)=>Array(n).fill('').map(g=(r,i)=>i--?g(r+s[i%l],i/l|0):r,l=s.length)
Neil
źródło
JS ma generatory? : 0000000
kot
10

Mathematica, 32 31 bajtów

Do[Echo/@#~Tuples~n,{n,0,∞}]&

Edytować:

CatsAreFluffy zeskrobał jeden bajt.

murphy
źródło
8

Perl, 39 37 35 bajtów

(Najpierw opisuje starszą wersję. Nowy krótszy program jest na końcu)

Obejmuje +3 za -alp

Uruchom z zestawem znaków na STDIN, np perl -alp kleene.pl <<< "a b c"

kleene.pl (ta wersja ma 34 + 3 bajty):

$#a=$"=","}for(@a){push@a,<{@F}$_>

Dodaj +2 dla -F(niejawnie upuść, -ajeśli nie ma spacji między znakami wejściowymi lub -6 (tylko @a=""wcześniej }), jeśli już wstawiamy przecinki między znakami na STDIN

Wyjaśnienie:

Te -alpopcje skutecznie wprowadzać kod:

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    our @F = split(' ', $_, 0);
    $#a = $" = ',';
}
foreach $_ (@a) {
    use File::Glob ();
    push @a, glob('{' . join($", @F) . '}' . $_);
}

Jak widać <>w perlu, jest on używany nie tylko do readline, ale może także wykonywać operacje globowania w stylu powłoki (w rzeczywistości w starożytnych perlach było to realizowane przez wywołanie powłoki).

Na przykład <{a,b}{1,2}>rozwinie się do"a1","a2","b1","b2"

Więc jeśli mamy elementy @F, wystarczy dodać przecinki między nimi. Domyślnym znakiem między interpolacją jest spacja, która jest przechowywana w specjalnej zmiennej $". Więc ustawienie $"na ,zmieni się "{@F}"w {a,b}if @F=qw(a b)(globusy rozwijają się jako łańcuchy)

W rzeczywistości chciałbym zapętlić się z czymś takim glob"{@F}"x$n++, ale ciągle napotykałem problem, że pierwsza pusta linia nie jest generowana, a wszystkie znalezione obejścia spowodowały, że kod był zbyt długi.

Kolejną istotną częścią tego kodu jest to, że jeśli użyjesz forpętli nad tablicą, możesz wcisnąć na nią dodatkowe elementy podczas pętli, a pętla również odbierze te nowe elementy. Jeśli więc w pętli znajdujemy się np. W elemencie "ab", <{@F}$_>rozwiniemy się do <{a,b}ab>kontekstu listy ("aab", "bab"). Więc jeśli je @apopchnę, struny rozszerzone po lewej stronie staną się dostępne

Muszę tylko zalać pętlę pustym łańcuchem. Odbywa się to za pomocą $#a = 0( ,w kontekście numerycznym staje się 0), co powoduje, że pierwszy i jedyny element @astaje się undef, który zachowuje się tak, jak ""go używam

Poprawa

W rzeczywistości, wykonując testy dla tego wyjaśnienia, znalazłem krótki sposób na użycie rosnącego globu, który poprawnie obsługuje pierwszy pusty wpis. Uruchom jako perl -ap kleene0.pl <<< "a b"(więc dodaj 2 bajty dla -ap)

kleene0.pl (ta wersja to 33 + 2 bajty):

$"=",";print<$z,>;$z.="{@F}";redo

Wszystkie te rozwiązania będą utrzymywały coraz więcej danych wyjściowych w pamięci, co po pewnym czasie spowoduje awarię programu. Możesz także używać globów Perla do leniwego generowania, używając ich w kontekście skalarnym, ale to wydłuża programy ...

Ton Hospel
źródło
Czy możesz wyjaśnić, co się dzieje wokół <{@F}$_>:? Dzięki!
andlrc
6

Pyth, 7

<s^LzQQ

Wypróbuj tutaj

To oblicza iloczyn kartezjański danych wejściowych z każdą liczbą od 0..n-1, łączy je, a następnie zachowuje tylko pierwszą n. Spowoduje to przekroczenie limitu czasu online dla liczb lub ciągów, które są znacznie większe niż 3-4.

Alternatywnie, aby uzyskać nieskończoną moc wyjściową, spójrz na odpowiedź Jakube .

FryAmTheEggman
źródło
5

Galaretka, 8 6 bajtów

⁷³p$Ȯ¿

Jest to monadyczny link, który akceptuje alfabet i drukuje nieskończoną listę ciągów. Wypróbuj online!

Jak to działa

⁷³p$Ȯ¿    Monadic link. Argument: A (alphabet)

⁷         Set the return value to '\n'.
     ¿    While loop.
            Condition:
    Ȯ         Print the current return value and return it (always truthy).
            Body:
   $          Combine the two links to the left into a single, monadic link.
 ³              Yield A.
  p             Perform the Cartesian product of A and the current return value,
                updating the return value in the process.

Wersja alternatywna, 6 bajtów (niekonkurująca)

R’ḃL}ị

To diademiczne łącze akceptuje alfabet i pożądaną liczbę ciągów znaków odpowiednio jako lewy i prawy argument.

Uważam tę wersję za niekonkurencyjną, ponieważ wykorzystuje ona dwukierunkową konwersję bazy, która została zaimplementowana po piaskownicy tego wyzwania. Wypróbuj online!

Jak to działa

R’ḃL}ị    Dyadic link. Arguments: n (integer), A (alphabet)

R         Range; yield [1, ..., n].
 ’        Decrement; yield [0, ..., n-1].
   L}     Yield l, the length of A.
  ḃ       Convert every i in [0, ..., n-1] to bijective base l.
     ị    For each array of digits, retrieve the corresponding characters of A.
Dennis
źródło
4

Python 2, 89 84 83 bajtów

x,n=input()
l=len(x)
for i in range(n):
 s=''
 while i:i-=1;s+=x[i%l];i/=l
 print s
Dennis
źródło
Łał. Krótszy i bez wbudowanych.
Morgan Thrapp
4

CJam, 16 lat 10 bajtów

Dzięki jimmy23013 za oszczędność 6 bajtów.

N{eam*_o}h

Dane wejściowe to jeden argument wiersza polecenia na znak. Dane wyjściowe to jeden ciąg w każdej linii.

Wypróbuj online!(Ale zabij to natychmiast ...)

Wyjaśnienie

N      e# Push [\n]. At each step this array will contain all strings of length N,
       e# each followed by a linefeed.
{      e# Infinite loop...
  ea   e#   Read command-line arguments.
  m*   e#   Cartesian product: pairs each letter with each string in the list.
  _o   e#   Output all the strings of the current length.
}h
Martin Ender
źródło
3

Pyth, 7 bajtów

.V0j^zb

Alternatywa dla @ fry. Ten program odczytuje ciąg znaków i drukuje ciągi aż do nieskończoności.

Wyjaśnienie:

.V0      for b in (0 to infinity):
    ^zb     compute all strings of length b consisting of the input alphabet
   j        print each one on a separate line

Alternatywnie będą również działać następujące. Trochę bardziej zuchwały.

u
M^zH7
Jakube
źródło
3

Haskell, 33 bajty

k u=do s<-[0..];mapM(\_->u)[1..s]

Przykładem k "xyz"jest lista nieskończona["","x","y","z","xx","xy","xz","yx","yy","yz","zx","zy","zz","xxx",...]

Lynn
źródło
3

MATL , 10 bajtów

0cD`G@Z^DT

Wypróbuj online!Ale nie pozostawiaj go długo uruchomionego, aby uniknąć dużego obciążenia obliczeniowego na serwerze.

Program wyświetla ciągi dynamicznie, każdy ciąg w innej linii.

0cD             % force display of a newline to represent the empty string
   `      T     % infinite do-while loop
    G           % push input, or nothing if no input has been taken yet
     @          % push iteration. Gives 1, 2,... in each iteration
      Z^        % Cartesian power. In the first iteration takes input implicitly 
       D        % display
Luis Mendo
źródło
2

Python 3, 95

from itertools import*
def f(x,l=0):
 while 1:print(*combinations_with_replacement(x*l,l));l+=1

Dlaczego funkcje itertools muszą mieć tak długie nazwy.

Morgan Thrapp
źródło
3
combinations_with_replacementnigdy nie jest tego warte. Jestem pewien, że użycie pętli jest krótsze. Zawsze.
mbomb007
2

Rubinowy, 65 60 bajtów

->a{n=-1;loop{puts a.repeated_permutation(n+=1).map &:join}}

Takie długie wbudowane nazwy ...

Klamka
źródło
1
AFAIK Nie potrzebujesz spacji wcześniej i możesz użyć p zamiast puts.
Pozew Fund Moniki w
@QPaysTaxes Nie można upuścić miejsca i pwywołuje inspecton argumenty, które generowałyby dane wyjściowe takie jak[] ["a","b"] ["aa", "ab", ...
Doorknob
Źle zrozumiałem twoją odpowiedź. Myślałem, że generuje nieskończoną tablicę i drukuje ją. Jestem jednak całkiem pewien, że w Array to_s jest aliasowany do inspekcji, więc put i p mają takie same wyniki. ruby-doc.org/core-2.2.0/Array.html#method-i-to_s WRT przestrzeń: Sprawdziłeś? Wprawdzie nie jestem pewien, ale jestem tego całkiem pewien.
Pozew Fund Moniki w
1

Pyke (zatwierdzenie 31), 10 9 bajtów

=blR.fbtp

Wyjaśnienie:

=b         -    set characters for base conversion to eval_or_not(input())
  l        -   len(^)
   R      -  [^, eval_or_not(input()]
    .f    - first_n(^)
      b   -    conv_base(^)
       t  -   ^[-1]
        p -  print(^)
niebieski
źródło
1

Scala, 69

def f[A](s:Set[A]):Stream[List[A]]=Nil#::f(s).flatMap(x=>s.map(_::x))

Leniwe strumienie są całkiem miłe dla tego rodzaju rzeczy.

Joe K
źródło
1

Japt, 50 40 34 28 bajtów

V²o ®s1+Ul)£UgXnH)¯X¦0}Ãâ ¯V

Dane wejściowe to "string", number of items. Dane wyjściowe są sortowane według długości, a następnie w odwrotnej kolejności alfabetycznej. Przetestuj online!

Jak to działa

V²  o ®   s1+Ul)£  UgXnH)¯  X¦ 0}Ã â ¯  V
Vp2 o mZ{Zs1+Ul)mX{UgXnH)s0,X!=0}} â s0,V

Vp2 o      // Create the range [0..V²).
mZ{     }  // Map each item Z in this range to:
Zs1+Ul)    //  Take the base-(1+U.length) representation of Z.
mX{     }  //  Map each char X in this to:
XnH        //   Parse X as a base-32 number.
Ug   )     //   Take the char at index -^ in U.
s0,X!=0    //   If X is 0, slice it to an empty string.
â          // Uniquify the result.
s0,V       // Slice to the first V items.

Ta wersja zajmuje trochę czasu, jeśli chcesz zrobić więcej niż 100 pozycji. Jeśli chcesz szybszej wersji, wypróbuj tę 32-bajtową wersję :

V*2 o ms1+Ul)f@!Xf'0î£UgXnH}ïV
ETHprodukcje
źródło
1

Guma cynamonowa, 6 bajtów

0000000: 6801 301c e74b                           h.0..K

Nie konkuruje, ponieważ guma cynamonowa powstała po tym wyzwaniu.

Wypróbuj online (TIO ogranicza moc wyjściową).

Wyjaśnienie

hStawia Cinnamon Gum w formacie i tryb generowania . Reszta ciągu dekompresuje się do [%s]*. Następnie %sjest zamieniany na wejście i tworzony jest generator, który wypisuje wszystkie możliwe ciągi pasujące do wyrażenia regularnego.

spaghetto
źródło
1

05AB1E , 9 bajtów

g<∞*εÅв¦J

Wypróbuj online!

g             # length of the input
 <            # - 1
  ∞           # infinite list [1, 2, 3, …]
   *          # multiply each by the length-1
    ε         # for each:
     Åв       #  custom base conversion, using the input as the list of digits
       ¦      #  chop off the first digit
        J     #  join the rest to a string
Ponury
źródło
0

Python, 55 bajtów

s=input();l=['']
for x in l:print x;l+=[x+c for c in s]

Jest to dłuższe niż 53-bajtowe rozwiązanie Feersum , ale ilustruje inną metodę z wydrukami . Listal jest aktualizowana podczas iteracji, dodając każdy jednoznakowy przyrostek każdego czytanego ciągu.

Równie długi jest czas użycia map:

s=input();l=['']
for x in l:print x;l+=map(x.__add__,s) 

Tę samą długość można wykonać w Pythonie 3, tracąc znak print()i zapisując go przez rozpakowanie danych wejściowych.

s,*l=input(),''
for x in l:print(x);l+=[x+c for c in s]
xnor
źródło
0

Zsh , 31 bajtów

f(){<<<${(F)a};a=($^a$^@);f $@}

Wypróbuj online!

Wydrukuj tablicę, a następnie spakuj argumenty przed rekurencją. Pomimo podania nazwy funkcji jest to o jeden bajt krótszy niż wersja iteracyjna:

for ((;;))<<<${(F)a}&&a=($^a$^@)
Funkcja Gamma
źródło