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.


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

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",…

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)

JS ma generatory? : 0000000
— kot

10

Mathematica, 32 31 bajtów

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

Edytować:

CatsAreFluffy zeskrobał jeden bajt.


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


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 .


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.

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

Ł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

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

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",...]


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

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.


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


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(^)

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.


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

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.


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

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]

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$^@)
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.