39
\$\begingroup\$

Given a set of letters, output all strings made of those letters. (This is Kleene star of the set.) For example, for {'a','b'}, the strings are:

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

Input: A non-empty collection of distinct letters a..z. These may be characters or single-character strings.

Output: All strings in those letters, in any order, without repeats. You may use lists of chars as strings.

This is an infinite list, so you can output it by:

  • Running forever writing more and more strings. These strings can be written in any flat separated format, meaning that they you can tell where each string ends, but the strings aren't subdivided into groups.
  • Taking a number n as input and outputting the first n strings in any flat separated format
  • Yielding each string in turn from a generator object
  • Producing an infinite object

Be sure that your method eventually produces every string in the output, since it's possible to produce infinitely many strings from the set while never getting to some strings.

You may not output it by

  • Producing the nth string given n
  • Providing a membership oracle that decides if a given string belongs to the set

Built-ins are allowed, but I ask voters to give attention to answers that implement the operation themselves over ones that mostly rely on a built-in.

var QUESTION_ID=74273,OVERRIDE_USER=20260;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/74273/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

\$\endgroup\$
11
  • \$\begingroup\$ @Cyoce Not sure what you mean. I clarified that the strings must be separated, so you can tell the empty string from nothing. \$\endgroup\$
    – xnor
    Feb 26, 2016 at 20:54
  • \$\begingroup\$ Please explain why "producing the Nth string given N" is not allowed. \$\endgroup\$ Feb 26, 2016 at 21:02
  • 6
    \$\begingroup\$ @CatsAreFluffy It was a judgment call. I think producing the Nth string would be too easy compared to the alternatives and make the challenge less interesting, especially because some languages have built-in arbitrary-base conversion. Also, I didn't think it captured the idea of generating an infinite set rather than querying it. \$\endgroup\$
    – xnor
    Feb 26, 2016 at 21:04
  • \$\begingroup\$ Can you explain "producing an infinite object"? Does that mean we can for example push each string onto the stack (for stack languages) and let it run "forever", even if no output will ever be produced because the program won't finish? \$\endgroup\$
    – Luis Mendo
    Feb 26, 2016 at 21:55
  • \$\begingroup\$ @DonMuesli Is output to the stack an accepted output method for such languages? And, will the stack contain only these strings at any point in time? \$\endgroup\$
    – xnor
    Feb 26, 2016 at 21:58

28 Answers 28

26
\$\begingroup\$

Python 2, 53 56

-3 after realizing that yield x can be used as an expression.

def f(s):yield'';[(yield w+c)for w in f(s)for c in s]
\$\endgroup\$
1
  • \$\begingroup\$ One byte shorter, but starts at 'aa' rather than at '': S=lambda s:(c+w for f in[str,S]for w in f(s)for c in s). Also doesn't work for the empty input. \$\endgroup\$
    – orlp
    Feb 27, 2016 at 0:50
22
\$\begingroup\$

Haskell, 24 bytes

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

Produces an infinite list.

*Main> f "abc"
["","a","b","c","aa","ba","ca","ab","bb","cb","ac","bc","cc","aaa","baa","caa","aba","bba","cba",…
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Too bad (:)<$>s<*>f s would give the wrong order. There's f s="":(flip(:)<$>f s<*>s) but it's longer. \$\endgroup\$
    – xnor
    Mar 1, 2016 at 0:05
  • \$\begingroup\$ Yeah. I had found the 23-byte f s=[]:(f s<**>map(:)s) except that <**> isn’t in Prelude. \$\endgroup\$ Mar 1, 2016 at 6:58
10
\$\begingroup\$

Mathematica, 32 31 Bytes

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

Edit:

CatsAreFluffy scraped off one byte.

\$\endgroup\$
0
10
\$\begingroup\$

JavaScript (ES6), 61 bytes

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

Port of @feersum's Python generator. The let is necessary. Save 2 bytes by using an array comprehension (failed ES7 proposal, but works in Firefox 30-57):

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

Alternative version for 73 bytes that returns the first n elements yielded by the above generator:

(s,n)=>Array(n).fill('').map(g=(r,i)=>i--?g(r+s[i%l],i/l|0):r,l=s.length)
\$\endgroup\$
1
  • \$\begingroup\$ JS has generators? :0000000 \$\endgroup\$
    – cat
    Feb 29, 2016 at 16:46
8
\$\begingroup\$

Perl, 39 37 35 bytes

(First describes an older version. The new shorter program is at the end)

Includes +3 for -alp

Run with the set of characters on STDIN, e.g. perl -alp kleene.pl <<< "a b c"

kleene.pl (this version is 34+3 bytes):

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

Add +2 for -F (drop implicit -a if no spaces between input characters, or -6 (only @a="" before }) if we already put commas between the characters on STDIN

Explanation:

The -alp options make the code effectively:

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

As you can see <> in perl is not only used for readline, but can also do shell style globbing (in fact in ancient perls it was implemented by calling the shell).

For example <{a,b}{1,2}> will expand to "a1","a2","b1","b2"

So if we have the elements in @F we just need to add commas inbetween. The default inbetween character for interpolation is space, which is stored in special variable $". So setting $" to , will turn "{@F}" into {a,b} if @F=qw(a b) (globs expand as strings)

In fact I would really have liked to loop with something like glob"{@F}"x$n++, but I kept running into the problem that the first empty line doesn't get generated and all workarounds I found made the code too long.

So another essential part of this code is that if you use a for to loop over an array you can actually push extra elements on it during the loop and the loop will also pick up these new elements. So if in the loop we are e.g. at element "ab", then <{@F}$_> will expand to <{a,b}ab> which in list context becomes ("aab", "bab"). So if I push these on @a then the strings extended one to the left become available too

All I still need to do is prime the loop with an empty string. That is done using$#a = 0 (, in numeric context becomes 0) which causes the first and only element of @a to become undef which will behave like "" when I use it

Improvement

In fact by doing tests for this explanation I found a short way to use a growing glob that properly handles the first empty entry. Run as perl -ap kleene0.pl <<< "a b" (so add 2 bytes for -ap)

kleene0.pl (this version is 33+2 bytes):

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

All these solutions will keep more and more of the output in memory and that will cause the program to fail after some time. You can also use perl globs for lazy generation by using them in scalar context, but that makes the programs longer....

\$\endgroup\$
1
  • \$\begingroup\$ Can you please explain what is going on around:<{@F}$_>? Thanks! \$\endgroup\$ Feb 28, 2016 at 1:50
6
\$\begingroup\$

Pyth, 7

<s^LzQQ

Try it here

This computes the cartesian product of the input with each number from 0..n-1, joins them, and then only keeps the first n. This will time out online for numbers or strings that are much bigger than 3-4.

Alternatively, to get infinite output look at Jakube's answer.

\$\endgroup\$
6
\$\begingroup\$

Jelly, 8 6 bytes

⁷³p$Ȯ¿

Try it online!

How it works

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

Alternate version, 6 bytes

R’ḃL}ị

This is a dyadic link that accepts an alphabet and the desired number of strings as left and right arguments, respectively.

Try it online!

How it works

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.
\$\endgroup\$
4
\$\begingroup\$

Python 2, 89 84 83 bytes

x,n=input()
l=len(x)
for i in range(n):
 s=''
 while i:i-=1;s+=x[i%l];i/=l
 print s
\$\endgroup\$
1
  • \$\begingroup\$ Wow. Shorter and without builtins. \$\endgroup\$ Feb 26, 2016 at 21:33
4
\$\begingroup\$

CJam, 16 10 bytes

Thanks to jimmy23013 for saving 6 bytes.

N{eam*_o}h

Input is one command-line argument per character. Output is one string on each line.

Try it online! (But kill it immediately...)

Explanation

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
\$\endgroup\$
0
4
\$\begingroup\$

Nekomata, 2 bytes

Ňŧ

Attempt This Online!

Ňŧ
Ň       Nondeterministically choose an natural number, say n
 ŧ      Nondeterministically choose a tuple of n elements from the input list

In the default mode, Nekomata prints all possible outputs.

\$\endgroup\$
3
\$\begingroup\$

Pyth, 7 bytes

.V0j^zb

Alternative to @fry. This program reads a string and keeps on printing strings until infinity.

Explanation:

.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

Alternatively the following will also work. A little bit more hacky though.

u
M^zH7
\$\endgroup\$
3
\$\begingroup\$

Haskell, 33 bytes

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

For exampe, k "xyz" is the infinite list ["","x","y","z","xx","xy","xz","yx","yy","yz","zx","zy","zz","xxx",...]

\$\endgroup\$
3
\$\begingroup\$

MATL, 10 bytes

0cD`G@Z^DT

Try it online! But don't leave it running for long, to avoid large computational load on the server.

The program displays the strings dynamically, each string on a different line.

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
\$\endgroup\$
3
\$\begingroup\$

Husk, 6 7 5 bytes

Θṁπ⁰N

Try it online!

Explanation

 ṁ  N map natural numbers to:
  π⁰  cartesian power of input
 ṁ    and join
Θ     prepend empty string
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Nice answer, but you need the strings to have a consistent separator between them like all in one line or all in separate lines, due to the rule 'These strings can be written in any flat separated format, meaning that they you can tell where each string ends, but the strings aren't subdivided into groups." \$\endgroup\$
    – xnor
    Nov 27, 2020 at 5:28
  • 1
    \$\begingroup\$ I don't think it outputs the empty string, since it starts with length-1 strings. \$\endgroup\$
    – Bubbler
    Nov 27, 2020 at 5:58
  • \$\begingroup\$ @Bubbler added.. \$\endgroup\$
    – Razetime
    Nov 27, 2020 at 8:16
2
\$\begingroup\$

Python 3, 95

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

Why must itertools functions have such long names.

\$\endgroup\$
1
  • 3
    \$\begingroup\$ combinations_with_replacement is never worth it. I'm pretty sure it's shorter to use loops. Always. \$\endgroup\$
    – mbomb007
    Feb 26, 2016 at 22:37
2
\$\begingroup\$

Ruby, 65 60 bytes

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

Such long builtin names...

\$\endgroup\$
3
  • 1
    \$\begingroup\$ AFAIK You don't need the space before & and you can use p instead of puts. \$\endgroup\$
    – anon
    Feb 26, 2016 at 22:56
  • \$\begingroup\$ @QPaysTaxes The space cannot be dropped, and p calls inspect on its arguments which would produce output like [] ["a","b"] ["aa", "ab", ... \$\endgroup\$
    – Doorknob
    Feb 27, 2016 at 6:15
  • \$\begingroup\$ I misunderstood your answer. I thought it was generating an infinite array and printing it. However, I'm fairly sure that on Array, to_s is aliased to inspect, so puts and p have the same output. ruby-doc.org/core-2.2.0/Array.html#method-i-to_s WRT the space: Did you check? Admittedly I'm not certain, but I'm fairly sure about it. \$\endgroup\$
    – anon
    Feb 27, 2016 at 12:39
2
\$\begingroup\$

Scala, 69

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

Lazy streams are quite nice for this kind of thing.

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 99 97 95 93 bytes

-2 bytes thanks to @ceilingcat (replaced putchar(v[~s[i++]]) by printf(v+~s[i++])).

-2 more bytes thanks to @ceilingcat (made i a pointer rather than an index).

-2 bytes once more, again thanks to ceilingcat (replaced (*i)--+l by --*i==~l, reversing the last two arguments of the ternary conditional operator, making it possible to remove the parentheses around *i++=-1).

s[999];*i;f(v,l)int*v;{for(i=s;printf(v+~*i++););for(i=s,puts("");;)--*i==~l?*i++=-1:f(v,l);}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Pyke (commit 31), 10 9 bytes

=blR.fbtp

Explanation:

=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(^)
\$\endgroup\$
1
\$\begingroup\$

Japt, 50 40 34 28 bytes

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

Input is "string", number of items. Output is sorted by length, then reverse alphabet order. Test it online!

How it works

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.

This version takes a while if you want to do any more than 100 items. If you want a faster version, try this 32-byte one:

V*2 o ms1+Ul)f@!Xf'0î£UgXnH}ïV
\$\endgroup\$
1
\$\begingroup\$

Cinnamon Gum, 6 bytes

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

Non-competing because Cinnamon Gum was made after this challenge.

Try it online (TIO limits output).

Explanation

The h puts Cinnamon Gum in format and generate mode. The rest of the string decompresses to [%s]*. The %s is then replaced with the input, and a generator is created that outputs all possible strings matching the regex.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 9 bytes

g<∞*εÅв¦J

Try it 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
\$\endgroup\$
1
\$\begingroup\$

R, 53 50 bytes

-3 bytes thanks to Dominic van Essen

r=scan(,s<-"");repeat cat("",s<-outer(s,r,paste0))

Try it online!

Prints the infinite list, separated by spaces.

\$\endgroup\$
2
  • \$\begingroup\$ 50 bytes by putting s into scan and losing the repeat parentheses... \$\endgroup\$ Nov 27, 2020 at 11:40
  • \$\begingroup\$ @DominicvanEssen Thanks! I always forget that repeat is not a regular function. \$\endgroup\$ Nov 27, 2020 at 12:36
1
\$\begingroup\$

05AB1E, 6 bytes

∞€ã˜õš

Try it online!

∞        # push a list of all positive integers
 ۋ      # take the input to each cartesian power
   ˜     # flatten the resulting list of lists
    õ    # push the empty string
     š   # prepend it to the infinite list of strings

Taking a string the 0th cartesian cartesian yields [[]], which would get completely lost when flattening (˜), this is why the empty string is prepended manually.
∞<€ã€` is an alternative 6-byter which uses [] to represent the empty string.

\$\endgroup\$
1
\$\begingroup\$

Curry (KiCS2), 18 bytes

f s=""?anyOf s:f s

Attempt This Online!

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 4 bytes

ƛ⁰τḢ

Try it Online! Takes the number of strings and the string.

ƛ    # For each number in 1...n
 ⁰τ  # Convert to base <string>
   Ḣ # Remove the first character

Alternatively, a version that prints infinitely (and is probably more efficient)

Vyxal, 6 bytes

{:⁋,ẊṠ

Try it Online!

{      # Forever
 :⁋,   # Print the current string joined by newlines
    ẊṠ # Take the cartesian product with the input
\$\endgroup\$
0
\$\begingroup\$

Python, 55 bytes

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

This is longer than feersum's 53-byte solution, but it illustrates a different method with printed output. The list l is updated while it is iterated over, by appending every one-character suffix of each string that is read.

It's equally long to use map:

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

The same length can be done in Python 3, losing a char for print(), and saving one by input unpacking.

s,*l=input(),''
for x in l:print(x);l+=[x+c for c in s]
\$\endgroup\$
0
\$\begingroup\$

Zsh, 31 bytes

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

Try it online!

Print the array, then zip on the arguments before recursing. Despite including the function name, this is one byte shorter than the iterative version:

for ((;;))<<<${(F)a}&&a=($^a$^@)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.