34
\$\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\$
  • \$\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 '16 at 20:54
  • \$\begingroup\$ Please explain why "producing the Nth string given N" is not allowed. \$\endgroup\$ – CalculatorFeline Feb 26 '16 at 21:02
  • 4
    \$\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 '16 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 '16 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 '16 at 21:58

21 Answers 21

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\$
  • \$\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 '16 at 0:50
20
\$\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\$
  • \$\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 '16 at 0:05
  • \$\begingroup\$ Yeah. I had found the 23-byte f s=[]:(f s<**>map(:)s) except that <**> isn’t in Prelude. \$\endgroup\$ – Anders Kaseorg Mar 1 '16 at 6:58
11
\$\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\$
  • \$\begingroup\$ JS has generators? :0000000 \$\endgroup\$ – cat Feb 29 '16 at 16:46
10
\$\begingroup\$

Mathematica, 32 31 Bytes

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

Edit:

CatsAreFluffy scraped off one byte.

\$\endgroup\$
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\$
  • \$\begingroup\$ Can you please explain what is going on around:<{@F}$_>? Thanks! \$\endgroup\$ – andlrc Feb 28 '16 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\$
5
\$\begingroup\$

Jelly, 8 6 bytes

⁷³p$Ȯ¿

This is a monadic link that accepts an alphabet and prints an infinite list of strings. 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 (non-competing)

R’ḃL}ị

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

I consider this version non-competing, since it uses bijective base conversion, which has been implemented after this challenge had been sandboxed. 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\$
  • \$\begingroup\$ Wow. Shorter and without builtins. \$\endgroup\$ – Morgan Thrapp Feb 26 '16 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\$
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\$
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\$
  • 3
    \$\begingroup\$ combinations_with_replacement is never worth it. I'm pretty sure it's shorter to use loops. Always. \$\endgroup\$ – mbomb007 Feb 26 '16 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\$
  • 1
    \$\begingroup\$ AFAIK You don't need the space before & and you can use p instead of puts. \$\endgroup\$ – Fund Monica's Lawsuit Feb 26 '16 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 '16 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\$ – Fund Monica's Lawsuit Feb 27 '16 at 12:39
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\$

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\$
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\$
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, privacy policy and cookie policy

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