输出所有字符串


34

给定一组字母,输出由这些字母组成的所有字符串。(这是该集合的Kleene星。)例如,对于{'a','b'},字符串为:

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

输入:包含不同字母的非空集合a..z。这些可以是字符或单字符字符串。

输出:这些字母中的所有字符串,以任何顺序排列,没有重复。您可以将字符列表用作字符串。

这是一个无限列表,因此您可以通过以下方式将其输出:

  • 永远运行越来越多的字符串。这些字符串可以用任何用平面分隔的格式编写,这意味着它们可以告诉每个字符串在何处结束,但是这些字符串不会细分为多个组。
  • 以数字n作为输入并n以任何单位分隔格式输出第一个字符串
  • 从生成器对象依次产生每个字符串
  • 产生无限物体

确保您的方法最终生成输出中的每个字符串,因为有可能从集合中生成无限多个字符串,而从不获取某些字符串。

您可能不会通过

  • 产生n给定的th字符串n
  • 提供一个成员资格oracle,该oracle决定给定字符串是否属于集合

允许使用内置函数,但是我要求选民注意那些比大多数依赖内置函数本身更能实现操作的答案。


@Cyoce不确定您的意思。我澄清了字符串必须分开,以便您可以将空字符串一无所获。
xnor

请解释为什么不允许“产生给定N的第N个字符串”。
CalculatorFeline

4
@CatsAreFluffy这是一个判断电话。我认为,与替代方法相比,生成Nth字符串会太容易了,并且使挑战变得不那么有趣了,特别是因为某些语言具有内置的任意基转换。另外,我认为它没有抓住生成无限集而不是查询它的想法。
xnor

你能解释“产生一个无限物体”吗?这是否意味着我们可以例如将每个字符串压入堆栈(对于堆栈语言)并让其“永远”运行,即使由于程序无法完成而不会产生任何输出?
Luis Mendo

@DonMuesli是否将此类语言的输出输出到堆栈?而且,堆栈在任何时间都只包含这些字符串吗?
xnor

Answers:


26

蟒蛇2,53 56

-3实现后yield x可以用作表达式。

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

缩短了一个字节,但从而'aa'不是从开始''S=lambda s:(c+w for f in[str,S]for w in f(s)for c in s)。对于空输入也不起作用。
orlp

20

Haskell,24个字节

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

产生无限列表。

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

太糟糕了(:)<$>s<*>f s会发出错误的命令。有,f s="":(flip(:)<$>f s<*>s)但是更长。
xnor

是的 我发现了23字节,f s=[]:(f s<**>map(:)s)除了<**>不在Prelude
Anders Kaseorg'3

11

JavaScript(ES6),61个字节

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

@feersum的Python生成器的端口。该let是必要的。通过使用数组理解来节省2个字节(失败的ES7提案,但可在Firefox 30-57中使用):

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

73个字节的备用版本,返回n上述生成器产生的第一个元素:

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

JS有发电机吗?:0000000

10

Mathematica,32 31字节

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

编辑:

CatsAreFluffy刮掉了一个字节。


8

Perl,39 37 35字节

(首先描述一个较旧的版本。新的较短的程序位于最后)

包括+3 -alp

在STDIN上使用字符集运行,例如 perl -alp kleene.pl <<< "a b c"

kleene.pl (此版本为34 + 3字节):

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

添加+2 for -F-a如果输入字符之间没有空格,则隐式删除;如果我们已经在STDIN上的字符之间加上逗号,则添加-6(仅@a=""在之前}))

说明:

这些-alp选项使代码有效:

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

正如您<>在perl 中看到的那样,perl不仅用于readline,还可以进行shell样式的遍历(实际上,在古代的perl中,它是通过调用shell来实现的)。

例如<{a,b}{1,2}>将扩展为"a1","a2","b1","b2"

因此,如果其中包含元素,@F则只需在两者之间添加逗号。插值的默认中间字符是空格,存储在特殊变量中$"。因此,设置$","{@F}"变成{a,b}if @F=qw(a b)(全局扩展为字符串)

实际上,我真的很想循环使用诸如之类的东西glob"{@F}"x$n++,但是我一直遇到一个问题,即不会生成第一个空行,而且我发现的所有变通办法都使代码太长。

因此,此代码的另一个重要部分是,如果使用a for循环遍历数组,则实际上可以在循环过程中将多余的元素压入该数组,并且该循环还将拾取这些新元素。因此,如果在循环中例如位于element "ab"<{@F}$_>则将扩展为<{a,b}ab>list上下文中的("aab", "bab")。因此,如果我将其按入,@a则向左延伸一个的字符串也将可用

我仍然需要做的只是用一个空字符串填充循环。这是通过使用$#a = 0,在数字上下文中变为0)来完成的,这将导致第一个也是唯一的元素@a变为undef,其行为将与""我使用它时的行为类似

改善

实际上,通过对这种解释进行测试,我找到了使用增长中的glob(正确处理第一个空条目)的简便方法。运行为perl -ap kleene0.pl <<< "a b"(因此为添加2个字节-ap

kleene0.pl (此版本为33 + 2字节):

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

所有这些解决方案将越来越多的输出保留在内存中,这将导致程序在一段时间后失败。您还可以通过在标量上下文中使用perl glob进行延迟生成,但这会使程序更长。


您能解释一下发生了什么<{@F}$_>吗?谢谢!
andlrc '16

6

佩斯,7

<s^LzQQ

在这里尝试

这将计算输入的笛卡尔积与每个数字的乘积0..n-1,将它们连接起来,然后仅保留第一个n。对于大于3-4的数字或字符串,这将在线超时。

另外,要获得无限的输出,请查看Jakube的答案


5

果冻,8 6个字节

⁷³p$Ȯ¿

这是一个单子链接,它接受字母并输出无限的字符串列表。在线尝试!

怎么运行的

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

备用版本,6字节(无竞争)

R’ḃL}ị

这是二元链接,该链接分别接受字母和所需的字符串数作为左和右参数。

我认为此版本不具有竞争性,因为它使用了双射基本转换,该转换是在解决了此挑战后实现的。在线尝试!

怎么运行的

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字节

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

哇。更短,没有内置函数。
Morgan Thrapp '16

4

CJam,16个 10字节

感谢jimmy23013节省了6个字节。

N{eam*_o}h

输入是每个字符一个命令行参数。输出是每一行一个字符串。

在线尝试!(但要立即杀死它...)

说明

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个字节

.V0j^zb

替代@fry。该程序读取一个字符串并继续打印字符串直到无穷大。

说明:

.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

或者,下面的方法也将起作用。虽然有点hacky。

u
M^zH7

3

Haskell,33个字节

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

例如,k "xyz"是无限列表["","x","y","z","xx","xy","xz","yx","yy","yz","zx","zy","zz","xxx",...]


3

MATL,10字节

0cD`G@Z^DT

在线尝试!但是不要让它长时间运行,以避免服务器上的大量计算负荷。

该程序动态显示字符串,每个字符串在不同的行上。

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

为什么itertools函数必须具有如此长的名称。


3
combinations_with_replacement永远都不值得。我很确定使用循环要短一些。总是。
mbomb007 '16

2

Ruby,65个 60字节

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

这么长的内置名称...


1
AFAIK&之前不需要空格,可以使用p代替puts。
Fund Monica的诉讼

@QPaysTaxes不能删除该空间,并p调用inspect其参数将产生输出,例如[] ["a","b"] ["aa", "ab", ...
Doorknob

我误会了你的答案。我认为它正在生成一个无限数组并打印它。但是,我相当确定在Array上,to_s是别名以进行检查,因此put和p具有相同的输出。ruby-doc.org/core-2.2.0/Array.html#method-i-to_s WRT空间:您检查了吗?诚然,我不确定,但是对此我相当确定。
基金莫妮卡的诉讼

1

Pyke(commit 31),10 9个字节

=blR.fbtp

说明:

=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

斯卡拉69岁

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

惰性流对于这种事情非常有用。


1

Japt,50 40 34 28字节

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

输入为"string", number of items。输出按长度排序,然后按相反的字母顺序排序。在线测试!

怎么运行的

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.

如果您要执行100多个项目,则此版本需要一段时间。如果您想要更快的版本,请尝试以下32字节的版本:

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

1

肉桂胶,6个字节

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

不参加比赛,因为肉桂胶是在挑战后制成的。

在线尝试(TIO限制输出)。

说明

h在把肉桂胶格式和生成模式。字符串的其余部分解压缩为[%s]*。在%s随后与输入代替,和发电机被创建输出所有可能的字符串相匹配的正则表达式。


1

05AB1E,9个字节

g<∞*εÅв¦J

在线尝试!

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个字节

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

这比feersum的53字节解决方案要长,但它说明了打印输出的另一种方法。l通过添加读取的每个字符串的每个单字符后缀,列表在迭代时进行更新。

使用map时间同样长:

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

在Python 3中可以完成相同的长度,为丢失一个char print(),并通过输入解压缩保存一个。

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

0

Zsh,31个字节

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

在线尝试!

打印数组,然后递归压缩参数。尽管包含函数名称,但它比迭代版本短一个字节:

for ((;;))<<<${(F)a}&&a=($^a$^@)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.