不要在剪刀石头布中重复自己


26

在有传闻说Codegolf将会举办Rock-Paper-Scissors锦标赛时,您可以看看无方字的话题。由字母R,组成的单词如果不包含重复两次的序列PS则是无平方的。也就是说,这个词不能写成

a x x b

其中ab是任何长度的单词和x至少一个长度的字,所有制成的字母RPS

任务

写生成的程序无平方的字母的字RPS长度的n其中数字1 <= n <= 10被作为输入。

例如,长度为3 的无平方字为

RPRRSRRPSRSPSPSSRSSRPSPRPRPPSPPSRPRS

长度为4的是

RPRSRPSRRPSPRSRPRSPRRSPSPRPSPRSRPRSPPSRPPSRSPSPRSRPRSRPSSRSPSPRPSPRSSPSR

并注意例如SPSPPRPR不是正方形

规则

  • 这是代码高尔夫球,最短的程序获胜,标准漏洞被关闭。
  • 您可以打印单词或在内存中创建单词。
  • 您的程序可以作为函数编写。

参考文献

维基百科条目上的无平方字

给定长度的无平方三进制字数在https://oeis.org/A006156中

相关:任意长度三进制Squarefree词


4
一个测试用例n>3将是一个好主意,因为关于重复字符与重复序列存在一些混淆。
Laikoni '17

请在沙盒中对计划的后续行动发表评论:codegolf.meta.stackexchange.com/a/14133/45211
mschauer

6
我认为“自然语言”标签不应该在此处应用
-Leo

1
啊,“单词”在“自然语言”中得到了扩展,我删除了它。
mschauer

1
不,它包含方形SP SP
mschauer's

Answers:


20

Ruby,39个字节

->n{(?P*n..?S*n).grep_v /[^RPS]|(.+)\1/}

这个效率低下的函数会生成所有长度为N的字符串,这些字符串按字母顺序位于N Ps和N Ss之间,然后过滤掉包含非RPS字符的绝大多数字符串。实际的squarefree检查仅使用Regexp后向引用:(.+)\1

更多惯用的65个字节,在N = 10的合理时间内完成:

->n{%w[R P S].repeated_permutation(n).map(&:join).grep_v /(.+)\1/}

编辑:感谢GB节省了一个字节。


您不需要在grep_v上加上括号,只需在它和斜杠之间保留一个空格(节省1个字节)
GB

6
效率低下 ”可能在此站点上描述了很多答案。
基金莫妮卡的诉讼

10

果冻15 14字节

“RPS”ṗẆ;"f$$Ðḟ

在线尝试!

怎么运行的

“RPS”ṗẆ;"f$$Ðḟ  Main link. Argument: n

“RPS”ṗ          Cartesian power; yield all strings of length n over this alphabet.
            Ðḟ  Filterfalse; keep only strings for which the quicklink to the left 
                returns a falsy result.
           $      Monadic chain. Argument: s (string)
      Ẇ             Window; yield the array A of all substrings of s.
          $         Monadic chain. Argument: A
       ;"             Concatenate all strings in A with themselves.
         f            Filter; yield all results that belong to A as well.

7

视网膜,28字节

+%1`1
R$'¶$`P$'¶$`S
A`(.+)\1

在线尝试!

接受一元输入。

说明

+%1`1
R$'¶$`P$'¶$`S

这将生成所有RPSlength 组成的字符串n。我们这样做的方法是我们重复替换1每一行中的第一行。让我们把这行看做是<1>,哪里<是比赛前的>一切,又是比赛后的一切(它们分别是$`$'分别是regex替换语法,但看起来不太直观)。我们更换1R>¶<P>¶<S,哪里有换行。所以这种替代的完整的结果居然是<R>¶<P>¶<S>,这是该行的三个副本,与1替换为RPS分别在三个副本。一旦所有1都被替换,该过程就停止。

A`(.+)\1

最后,我们简单地丢弃所有包含重复的行。


我会反复替换为1(.*)$1R¶$1P¶$1S但是字节数是相同的。
尼尔

6

外壳15 14字节

-1个字节感谢Zgarb!

fȯεfoE½QΠR"RPS

在线尝试!

构建正确长度的所有可能序列,并仅保留所有子字符串(空字符串除外)由两个不同的半部分组成的序列。

该死,我真的很想在这里击败果冻。


3
与Jelly绑定的14个字节
Zgarb


5

爪哇8,285个 277字节

import java.util.*;Set r=new HashSet();n->p("",((1<<3*n)+"").replaceAll(".","PRS"),n)void p(String p,String s,int n){int l=s.length(),i=0;if(l<1&&(s=p.substring(0,n)).equals(s.replaceAll("(.*)\\1","")))r.add(s);for(;i<l;p(p+s.charAt(i),s.substring(0,i)+s.substring(++i,l),n));}

尽管Java几乎总是很冗长,但在这种情况下,它绝对不是解决此类挑战的正确语言。用子字符串生成置换对性能不利且效率低下。

当然,可以打更多的球。

-8个字节,感谢@Jakob

说明:

在这里尝试。(对于3个以上的测试用例,性能太差了,但是它确实可以在本地工作。)

import java.util.*;   // Required import for Set and HashSet

Set r=new HashSet();  // Result-Set on class-level

n->                   // Method with integer parameter and no return-type
  p("",((1<<3*n)+"").replaceAll(".","PRS"),n)
                      //  Get all permutations and save them in the Set
                      // End of method (implicit / single-line return-statement)

void p(String p,String s,int n){
                      // Separated method with 2 String & int parameters and no return-type
  int l=s.length(),   //  The length of the second input-String
      i=0;            //  Index-integer, starting at 0
  if(l<1              //  If the length is 0,
     &&(s=p.substring(0,n)).equals(s.replaceAll("(.*)\\1","")))
                      //  and it doesn't contain a repeated part:
    r.add(s);         //   Add it to the result-Set
  for(;i<l;           //  Loop (2) from 0 to `l`
    p(                //   Recursive-call with:
      p+s.charAt(i),  //    Prefix-input + the character of the second input at index `i`
      s.substring(0,i)+s.substring(++i,l),
                      //    and the second input except for this character
      n)              //    and `n`
  );                  //  End of loop (2)
}                     // End of separated method

1
这个怎么样拉姆达:n->p("",((1<<3*n)+"").replaceAll(".","PRS"),n)。另外,为什么不重构for(;i<1;p(...));while(i<l)p(...);
雅各布

@Jakob谢谢。for(;...;)老实说,我总是用在习惯代码之外。最坏的情况是与字节数相同while(...),最好的情况是可以在for循环中放置一些内容以节省字节。因此,我尝试完全不使用while代码高尔夫,因为无论如何它永远不会有益于字节数。它要么增加它,要么保持不变,所以我个人并不为更好的可读性而烦恼。;)
Kevin Cruijssen

1
是的,我总是尝试在给定的字节数下使我的高尔夫球代码尽可能可读。可能是徒劳的追求!
雅各布

等等,我的lambda实际上在这里工作吗?我有点粗心...它生成了n个 PRS序列的字符串,而您的原始循环生成了2 ^(n -2)个序列。
雅各布

@Jakob n次“ PRS”是正确的。我的之所以能够产生更多的数据,是因为它节省了字节(并降低了性能,但是谁在乎Codegolf的性能)。;)
Kevin Cruijssen



4

Perl 5,37个字节

sub r{grep!/(.+)\1/,glob"{R,S,P}"x<>}

在线尝试!

函数返回平方自由字符串的数组。

解释:

glob生成与长度R,S,&P的所有组合等于输入。该grep语句将那些不是正方形的对象过滤掉。


大量使用括号扩展!
唐·黑斯廷斯

3

R,97字节

cat((x=unique(combn(rep(c('p','r','s'),n),n<-scan(),paste,collapse='')))[!grepl("(.+)\\1",x,,T)])

在线尝试!

combn(rep(c('p','r','s'),n),n,paste,collapse='')计算所有n以字符数限制的字符串prs,但遗憾的是许多重复(*),所以我们uniquify它,把那些符合该正则表达式(.+)\1使用Perl样式匹配,那么我们打印出结果的列表。

(*)从技术上讲,它一次生成3次重复生成3n字母的所有组合,然后将其应用于每个组合,而不是直接计算字符串,但这比(真正的笛卡尔积)要复杂得多。p,r,snpaste(..., collapse='')3^nexpand.grid


3

JavaScript(Firefox 30-57),69个字节

f=n=>n?[for(x of f(n-1))for(y of'RPS')if(!/(.+)\1/.test(y+=x))y]:['']

由于所有无平方词的子字符串也都是无平方的,因此可以递归进行检查。



2

JavaScript(ES6),93个字节

n=>[...Array(3**n)].map(g=(d=n,i)=>d?'RPS'[i%3]+g(d-1,i/3|0):'').filter(s=>!/(.+)\1/.test(s))

使用RPS数字将所有从0到3ⁿ的整数转换为(反向填充)以3 为底的整数,并将其过滤为无平方字。


2

朱莉娅88岁

f(n)=[filter(A->!ismatch.(r"(.+)\1",join(A)),Iterators.product(repeated("RPS",n)...))...]

没有什么花哨。


1

C#/ LINQ,169

Enumerable.Range(0,(int)Math.Pow(3,n)).Select(i=>string.Concat(Enumerable.Range(1,n).Select(p=>"PRS"[(i/(int)Math.Pow(3,n-p))%3]))).Where(s=>!Regex.IsMatch(s,@"(.+)\1"))

必须有一个更好的方法来做到这一点:)



1

k,56个字节

f:{$[x;(,/"RPS",/:\:f x-1){x@&~~/'(2,y)#/:x}/1_!x;,""]}

缺乏本地正则表达式使k一次落后于曲线。我采用了递归解决方案,因为实现它的字符是通过更简单的squarefree检查保存的。

$[ test ; if-true ; if-false ]

是k的三元运算符,这里我们对非零长度进行有趣的处理,如果要求输入零长度的单词,则返回一个空字符串。

(,/"RPS",/:\:f x-1)

取“ RPS”和所有n-1个长度的无平方字的笛卡尔乘积。,/:\:将右边的每个元素连接到左边,得到长度为3的数组,长度为n个数组。,/将其展平为长度为3n的数组。

{x@&~~/'(2,y)#/:x}

接受每个字符串的前n个字母,并将其与后n个字母进行比较,然后将数组缩小到仅不匹配的位置。因为我们知道之前的结果是无平方的,所以只有从第一个字符开始的子字符串才需要匹配-简化此处的检查值得实现递归的字符。最后,

/1_!x

将lambda应用于左侧的初始结果集,并在每个子字符串长度(从1到(字长)-1)之间进行迭代。!x生成从0到x-1的列表,然后1_删除第一个元素(因为0长度的子字符串将始终匹配)

牺牲一些字符,我们可以使用.zs进行自引用,而不是依赖函数名,并且不检查长度不超过n-1的子字符串,仅检查floor(n / 2)的性能。它在7700k上约120秒内找到了所有长度49个单词(其中有5207706个),超过了我遇到的免费32位k的4GB限制。

{$[x;(,/"RPS",/:\:.z.s x-1){x@&~~/'(2,y)#/:x}/1+!_x%2;,""]}

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.