Emette tutte le stringhe


34

Dato un insieme di lettere, genera tutte le stringhe fatte di quelle lettere. (Questa è la stella di Kleene del set.) Ad esempio, per {'a','b'}, le stringhe sono:

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

Input: una raccolta non vuota di lettere distinte a..z. Questi possono essere caratteri o stringhe a carattere singolo.

Output: tutte le stringhe in quelle lettere, in qualsiasi ordine, senza ripetizioni. È possibile utilizzare elenchi di caratteri come stringhe.

Questo è un elenco infinito, quindi puoi produrlo come segue:

  • Correre per sempre scrivendo sempre più stringhe. Queste stringhe possono essere scritte in qualsiasi formato separato piatto, il che significa che puoi dire dove finisce ogni stringa, ma le stringhe non sono suddivise in gruppi.
  • Prendendo un numero ncome input e producendo le prime nstringhe in qualsiasi formato separato piatto
  • Rendere ogni stringa a turno da un oggetto generatore
  • Produrre un oggetto infinito

Assicurati che il tuo metodo alla fine produca ogni stringa nell'output, poiché è possibile produrre infinitamente molte stringhe dal set senza mai arrivare ad alcune stringhe.

Si può non uscita dal

  • Produrre la nstringa datan
  • Fornire un oracolo di appartenenza che decide se una determinata stringa appartiene all'insieme

Gli built-in sono consentiti, ma chiedo agli elettori di prestare attenzione alle risposte che implementano l'operazione su quelle che si basano principalmente su un built-in.


@Cyoce Non sono sicuro di cosa intendi. Ho chiarito che le stringhe devono essere separate, in modo da poter distinguere la stringa vuota dal nulla.
xnor

Spiegare perché non è consentito "produrre l'ennesima stringa data N".
CalculatorFeline,

4
@CatsAreFluffy Era una chiamata di giudizio. Penso che produrre l'ennesima stringa sarebbe troppo facile rispetto alle alternative e rendere la sfida meno interessante, soprattutto perché alcune lingue hanno una conversione base arbitraria integrata. Inoltre, non pensavo che catturasse l'idea di generare un set infinito piuttosto che interrogarlo.
xnor

Puoi spiegare "produrre un oggetto infinito"? Ciò significa che possiamo ad esempio spingere ogni stringa nello stack (per le lingue dello stack) e lasciarla funzionare "per sempre", anche se non verrà mai prodotto alcun output perché il programma non finirà?
Luis Mendo,

@DonMuesli L'output nello stack è un metodo di output accettato per tali lingue? E lo stack conterrà solo queste stringhe in qualsiasi momento?
xnor

Risposte:


26

Python 2, 53 56

-3 dopo aver realizzato che yield xpuò essere usato come espressione.

def f(s):yield'';[(yield w+c)for w in f(s)for c in s]

Un byte più brevi, ma parte da 'aa'anziché a '': S=lambda s:(c+w for f in[str,S]for w in f(s)for c in s). Inoltre non funziona per l'input vuoto.
Orlp,

20

Haskell, 24 byte

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

Produce un elenco infinito.

*Main> f "abc"
["","a","b","c","aa","ba","ca","ab","bb","cb","ac","bc","cc","aaa","baa","caa","aba","bba","cba",…

Peccato (:)<$>s<*>f sdarebbe l'ordine sbagliato. C'è f s="":(flip(:)<$>f s<*>s)ma è più lungo.
xnor

Si. Avevo trovato il 23 byte f s=[]:(f s<**>map(:)s)tranne che <**>non è in Prelude.
Anders Kaseorg

11

JavaScript (ES6), 61 byte

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

Generatore Python di Port of @ feersum. Il letè necessario. Salva 2 byte utilizzando una comprensione dell'array (proposta ES7 non riuscita, ma funziona in Firefox 30-57):

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

Versione alternativa per 73 byte che restituisce i primi nelementi prodotti dal generatore sopra:

(s,n)=>Array(n).fill('').map(g=(r,i)=>i--?g(r+s[i%l],i/l|0):r,l=s.length)

JS ha generatori? : 0000000
gatto,

10

Mathematica, 32 31 byte

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

Modificare:

CatsAreFluffy ha cancellato un byte.


8

Perl, 39 37 35 byte

(Prima descrive una versione precedente. Il nuovo programma più breve è alla fine)

Include +3 per -alp

Esegui con il set di caratteri su STDIN, ad es perl -alp kleene.pl <<< "a b c"

kleene.pl (questa versione è di 34 + 3 byte):

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

Aggiungi +2 per -F(rilasciare implicito -ase non ci sono spazi tra i caratteri di input, o -6 (solo @a=""prima }) se mettiamo già delle virgole tra i caratteri su STDIN

Spiegazione:

Le -alpopzioni rendono efficace il codice:

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

Come puoi vedere <>in perl non è solo usato per readline, ma può anche fare globbing in stile shell (in effetti nei perls antichi è stato implementato chiamando la shell).

Ad esempio <{a,b}{1,2}>si espanderà a"a1","a2","b1","b2"

Quindi, se abbiamo gli elementi, @Fdobbiamo solo aggiungere delle virgole tra di loro. Il carattere predefinito tra l'interpolazione è lo spazio, che è memorizzato in una variabile speciale $". Quindi l'impostazione $"su ,si trasformerà "{@F}"in {a,b}if @F=qw(a b)(i globs si espandono come stringhe)

In realtà mi sarebbe davvero piaciuto fare un ciclo con qualcosa del genere glob"{@F}"x$n++, ma ho continuato a imbattermi nel problema che la prima riga vuota non viene generata e tutti i rimedi che ho trovato hanno reso il codice troppo lungo.

Quindi un'altra parte essenziale di questo codice è che se usi un forciclo su un array puoi effettivamente spingere elementi extra su di esso durante il ciclo e il ciclo prenderà anche questi nuovi elementi. Quindi se nel loop ci troviamo ad es. In element "ab", allora <{@F}$_>ci espanderemo a quello <{a,b}ab>che diventa nel contesto dell'elenco ("aab", "bab"). Quindi, se li premo, @adiventano disponibili anche le stringhe estese a sinistra

Tutto quello che devo ancora fare è innescare il ciclo con una stringa vuota. Questo viene fatto usando $#a = 0( ,nel contesto numerico diventa 0) che fa diventare il primo e unico elemento di @adiventare indefinito che si comporterà come ""quando lo uso

Miglioramento

In effetti, facendo dei test per questa spiegazione ho trovato un modo breve per usare un glob in crescita che gestisce correttamente la prima voce vuota. Esegui come perl -ap kleene0.pl <<< "a b"(quindi aggiungi 2 byte per -ap)

kleene0.pl (questa versione è di 33 + 2 byte):

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

Tutte queste soluzioni manterranno sempre più output in memoria e ciò causerà il fallimento del programma dopo qualche tempo. Puoi anche usare perl globs per la generazione pigra usandoli in un contesto scalare, ma ciò rende i programmi più lunghi ....


Puoi spiegare cosa sta succedendo in giro <{@F}$_>:? Grazie!
Andlrc,

6

Pyth, 7

<s^LzQQ

Provalo qui

Questo calcola il prodotto cartesiano dell'input con ciascun numero da 0..n-1, li unisce e quindi mantiene solo il primo n. Questo sarà il timeout online per numeri o stringhe che sono molto più grandi di 3-4.

In alternativa, per ottenere un output infinito, guarda la risposta di Jakube .


5

Gelatina, 8 6 byte

⁷³p$Ȯ¿

Questo è un collegamento monadico che accetta un alfabeto e stampa un infinito elenco di stringhe. Provalo online!

Come funziona

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

Versione alternativa, 6 byte (non competitiva)

R’ḃL}ị

Questo è un collegamento diadico che accetta un alfabeto e il numero desiderato di stringhe come argomenti sinistro e destro, rispettivamente.

Considero questa versione non competitiva, poiché utilizza la conversione di base biiettiva, che è stata implementata dopo che questa sfida è stata sandbox. Provalo online!

Come funziona

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 byte

x,n=input()
l=len(x)
for i in range(n):
 s=''
 while i:i-=1;s+=x[i%l];i/=l
 print s

Wow. Più corto e senza builtin.
Morgan Thrapp,

4

CJam, 16 10 byte

Grazie a jimmy23013 per aver salvato 6 byte.

N{eam*_o}h

L'input è un argomento della riga di comando per carattere. L'output è una stringa su ogni riga.

Provalo online! (Ma uccidilo immediatamente ...)

Spiegazione

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 byte

.V0j^zb

Alternativa a @fry. Questo programma legge una stringa e continua a stampare stringhe fino all'infinito.

Spiegazione:

.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

In alternativa, funzionerà anche quanto segue. Un po 'più confuso però.

u
M^zH7

3

Haskell, 33 byte

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

Ad esempio, k "xyz"è l'elenco infinito["","x","y","z","xx","xy","xz","yx","yy","yz","zx","zy","zz","xxx",...]


3

MATL , 10 byte

0cD`G@Z^DT

Provalo online! Ma non lasciarlo in esecuzione a lungo, per evitare un grande carico computazionale sul server.

Il programma visualizza le stringhe in modo dinamico, ciascuna stringa su una riga diversa.

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

Perché le funzioni itertools devono avere nomi così lunghi.


3
combinations_with_replacementnon ne vale mai la pena. Sono abbastanza sicuro che è più breve usare i loop. Sempre.
mbomb007,

2

Rubino, 65 60 byte

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

Nomi così lunghi ...


1
AFAIK Non hai bisogno dello spazio prima e puoi usare p invece di put.
Finanzi la causa di Monica il

@QPaysTaxes Lo spazio non può essere eliminato e prichiama i inspectsuoi argomenti che genererebbero output come[] ["a","b"] ["aa", "ab", ...
Doorknob

Ho frainteso la tua risposta. Ho pensato che stesse generando un array infinito e stampandolo. Tuttavia, sono abbastanza sicuro che su Array to_s sia aliasato da esaminare, quindi put e p hanno lo stesso output. ruby-doc.org/core-2.2.0/Array.html#method-i-to_s WRT lo spazio: hai controllato? Certo, non ne sono certo, ma ne sono abbastanza sicuro.
Finanzi la causa di Monica il

1

Pyke (commit 31), 10 9 byte

=blR.fbtp

Spiegazione:

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

I flussi pigri sono abbastanza belli per questo tipo di cose.


1

Japt, 50 40 34 28 byte

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

L'input è "string", number of items. L'output viene ordinato per lunghezza, quindi in ordine alfabetico inverso. Provalo online!

Come funziona

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.

Questa versione richiede del tempo se si desidera eseguire più di 100 elementi. Se vuoi una versione più veloce, prova questa a 32 byte :

V*2 o ms1+Ul)f@!Xf'0î£UgXnH}ïV

1

Gomma alla cannella, 6 byte

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

Non competitiva perché Cinnamon Gum è stata prodotta dopo questa sfida.

Provalo online (TIO limita l'output).

Spiegazione

Il hmette Cinnamon Gum nel formato e genera la modalità . Il resto della stringa si decomprime in [%s]*. La %sviene quindi sostituita con l'ingresso, e un generatore viene creata uscite tutte le possibili stringhe corrispondenti la regex.


1

05AB1E , 9 byte

g<∞*εÅв¦J

Provalo 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 byte

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

Questo è più lungo di soluzione a 53 byte feersum , ma illustra un metodo diverso con l'output stampato. L'elenco lviene aggiornato mentre è ripetuto, aggiungendo ogni suffisso di un carattere di ogni stringa che viene letta.

È ugualmente lungo da usare map:

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

La stessa lunghezza può essere fatta in Python 3, perdendo un carattere per print()e salvandone uno inserendo la decompressione.

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

0

Zsh , 31 byte

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

Provalo online!

Stampa l'array, quindi comprimi gli argomenti prima di ricorrere. Nonostante includa il nome della funzione, questo è un byte più corto della versione iterativa:

for ((;;))<<<${(F)a}&&a=($^a$^@)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.