Output all strings

34

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>

xnor

Posted 2016-02-26T20:47:27.743

Reputation: 115 687

@Cyoce Not sure what you mean. I clarified that the strings must be separated, so you can tell the empty string from nothing. – xnor – 2016-02-26T20:54:47.890

Please explain why "producing the Nth string given N" is not allowed. – CalculatorFeline – 2016-02-26T21:02:31.640

4@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. – xnor – 2016-02-26T21:04:34.077

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? – Luis Mendo – 2016-02-26T21:55:19.507

@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? – xnor – 2016-02-26T21:58:10.380

@xnor The stack will only contain those strings at the end of each iteration. Each iteration k does intermediate computations to generate all k-length strings, but the intermediate objects are consumed. I think output to the stack is acceptable, because it's like a function output, and most stack languages display the stack at the end anyway. The problem is, this program has no end... – Luis Mendo – 2016-02-26T22:00:57.817

@DonMuesli It's not OK that the stack holds other things while running, since then it cannot be taken as an output of all strings. If your language has a separate output stack onto which only output strings are pushed, that would be fine. – xnor – 2016-02-26T22:03:44.380

@xnor Ok. Anyway my current version produces the strings dynamically to stdout, so it fulfills the challenge requirements. Another thing: MATL "displays" the empty string by producing no output. So it's not seen at stdout. Is that acceptable? – Luis Mendo – 2016-02-26T22:05:55.427

@DonMuesli Unfortunately, also no. The empty string needs to be apparent. – xnor – 2016-02-26T22:06:41.803

@xnor Ok. I'll add it explicitly as an empty line – Luis Mendo – 2016-02-26T22:07:11.880

How about a language like JavaScript working in theory, but being limited due to, say, browser freezing? – Conor O'Brien – 2016-02-27T15:56:54.433

Answers

26

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]

feersum

Posted 2016-02-26T20:47:27.743

Reputation: 29 566

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. – orlp – 2016-02-27T00:50:51.617

20

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

Anders Kaseorg

Posted 2016-02-26T20:47:27.743

Reputation: 29 242

Too bad (:)<$>s<*>f s would give the wrong order. There's f s="":(flip(:)<$>f s<*>s) but it's longer. – xnor – 2016-03-01T00:05:39.523

Yeah. I had found the 23-byte f s=[]:(f s<**>map(:)s) except that <**> isn’t in Prelude. – Anders Kaseorg – 2016-03-01T06:58:15.800

11

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)

Neil

Posted 2016-02-26T20:47:27.743

Reputation: 95 035

JS has generators? :0000000 – cat – 2016-02-29T16:46:24.400

10

Mathematica, 32 31 Bytes

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

Edit:

CatsAreFluffy scraped off one byte.

murphy

Posted 2016-02-26T20:47:27.743

Reputation: 635

8

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

Ton Hospel

Posted 2016-02-26T20:47:27.743

Reputation: 14 114

Can you please explain what is going on around:<{@F}$_>? Thanks! – andlrc – 2016-02-28T01:50:23.360

6

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.

FryAmTheEggman

Posted 2016-02-26T20:47:27.743

Reputation: 16 206

5

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.

Dennis

Posted 2016-02-26T20:47:27.743

Reputation: 196 637

4

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

Martin Ender

Posted 2016-02-26T20:47:27.743

Reputation: 184 808

4

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

Dennis

Posted 2016-02-26T20:47:27.743

Reputation: 196 637

Wow. Shorter and without builtins. – Morgan Thrapp – 2016-02-26T21:33:14.997

3

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

Jakube

Posted 2016-02-26T20:47:27.743

Reputation: 21 462

3

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

Luis Mendo

Posted 2016-02-26T20:47:27.743

Reputation: 87 464

3

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

Lynn

Posted 2016-02-26T20:47:27.743

Reputation: 55 648

2

Ruby, 65 60 bytes

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

Such long builtin names...

Doorknob

Posted 2016-02-26T20:47:27.743

Reputation: 68 138

1AFAIK You don't need the space before & and you can use p instead of puts. – Fund Monica's Lawsuit – 2016-02-26T22:56:48.870

@QPaysTaxes The space cannot be dropped, and p calls inspect on its arguments which would produce output like [] ["a","b"] ["aa", "ab", ... – Doorknob – 2016-02-27T06:15:35.823

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. http://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.

– Fund Monica's Lawsuit – 2016-02-27T12:39:22.800

2

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.

Morgan Thrapp

Posted 2016-02-26T20:47:27.743

Reputation: 3 574

3combinations_with_replacement is never worth it. I'm pretty sure it's shorter to use loops. Always. – mbomb007 – 2016-02-26T22:37:32.647

1

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

Grimmy

Posted 2016-02-26T20:47:27.743

Reputation: 12 521

1

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

ETHproductions

Posted 2016-02-26T20:47:27.743

Reputation: 47 880

1

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

Blue

Posted 2016-02-26T20:47:27.743

Reputation: 26 661

1

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.

Joe K

Posted 2016-02-26T20:47:27.743

Reputation: 1 065

1

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.

a spaghetto

Posted 2016-02-26T20:47:27.743

Reputation: 10 647

0

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

GammaFunction

Posted 2016-02-26T20:47:27.743

Reputation: 2 838

0

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]

xnor

Posted 2016-02-26T20:47:27.743

Reputation: 115 687