String.prototype.isRepeated


41

更新isaacg的Pyth提交是赢家!


你们中的许多人一定听说过,城镇中有一个比较凉爽的JavaScript版本(阅读ES6),该版本中的方法String.prototype.repeat可以使您

"Hello, World!".repeat(3)

并得到

"Hello, World!Hello, World!Hello, World!"

作为输出。

您的工作是用您选择语言编写一个函数或程序,以检测字符串是否经过了这种转换。

即,输入字符串可以表示为n较小字符串的精确重复次数。如果字符串可以是,则输出(作为函数的return语句或STDOUT)应为true;如果字符串不能表示为较小字符串的重复,则输出为false。

一些样本输入:

"asdfasdfasdf"  // true
"asdfasdfa"     // false
"ĴĴĴĴĴĴĴĴĴ"     // true
"ĴĴĴ123ĴĴĴ123"  // true
"abcdefgh"      // false

请注意,最后一个输入为false,因此n应大于1

完整规则

  • 编写任何语言的函数/程序以输入(通过函数参数/命令行args / STDIN)字符串
  • 如果给定的字符串是由较小的字符串的精确重复形成的,则返回/打印真实值,至少重复两次。
  • 理想情况下,输入字符串的最大大小为Infinity
  • 字符串可以具有所有可能的ASCII字符
  • 这是一个因此以字符为单位的最小代码获胜。

空字符串“”应该返回什么?(它包含无数个空字符串的副本。)
billpg

@billpg虚假值
Optimizer

您是否以投票方式打破平局?我认为通常的做法是提早提交(好吧,第一个打到平局得分的人)。但是我不确定是否将其记为默认的决胜局,所以最终由您决定。
Martin Ender 2014年

他们发布之间的时间只有30分钟。我认为这不足以赢得:)。由于那段时间现在不会更改,但是投票可以更改,我投了赞成票
Optimizer

这个问题应该改名为xnor :)他是这个人!
Silviu Burcea 2014年

Answers:


16

珀斯 9

/:+zz1_1z

要么

}z:+zz1_1

这些都是@xnor的python答案的近似翻译,除了它们从STDIN接收输入并打印出来。第一个等效于:

z = input()
print((z+z)[1:-1].count(z))

0代表False,1代表True。

第二行等效于:

z = input()
print(z in (z+z)[1:-1])

False代表False,True代表True。

Pyth的官方编译器存在与第二个漏洞相关的错误,我刚刚对其进行了修补,因此第一个是我的正式提交的错误。


我只是在寻找一种方法来通知您有关该错误的信息(不打印布尔值)。没想到第一个,使用x时间太长了……
Dennis

是的,该错误现已修复。另外,如果您想报告错误,一个好的方法可能是在github站点上打开一个问题,这里是:github.com/isaacg1/pyth/issues
isaacg 2014年

哦,还有它。我不知道如何绕过GitHub,也从未注意到右侧的导航面板...
Dennis

81

巨蟒(24)

lambda s:s in(s+s)[1:-1]

检查字符串是否是其自身串联的子字符串两次,消除第一个和最后一个字符以避免琐碎的匹配。如果是,则它本身必须是一个非平凡的循环置换,因此必须是重复段的总和。


8
琐碎的翻译成Golfscript会产生10个字符:..+);(;\?)
贾斯汀

3
我不太了解这是如何工作的。您能否举一个手工解释的例子来说明如何处理字符串?
Nzall 2014年

8
@NateKerkhofs接abcabcs+s变成abcabcabcabc[1:-1]两端的排骨屈服bcabcabcabcab。然后s in ...尝试找到abcabc它的子字符串。此子字符串无法在原始的一半中找到,因为它们都已缩短,因此必须跨越两个半部。特别是,它在开始之前必须有自己的结尾,这意味着它必须由相同的(重复的)子字符串组成。
Martin Ender 2014年

6
将其加倍后将其切碎。abababba,所以它返回false,而aa成为aaaa成为aa,返回true。
histocrat

1
@SargeBorsch它的工作原理相同:qweqweqweweqweqweqweqweqwis中True
xnor 2014年

30

正则表达式(ECMAScript风格),11个字节

听起来像是正则表达式的工作!

^([^]+)\1+$

在这里测试。

我选择了ECMAScript,因为它是唯一可以[^]匹配任何字符的样式(我知道)。在所有其他情况下,我要么需要一个标志来更改其行为,.要么使用[\s\S]要长三个字符的标志。

根据我们是如何计算的标志,这可能当然是一个字节短。例如,如果我们要计算模式+标志(例如忽略定界符),则PCRE / Perl等价于

/^(.+)\1+$/s

10个字节,忽略定界符。

在这里测试。

这仅匹配由某个子字符串的至少两个重复组成的字符串。

这是一个完整的26字节ES6函数,但是我认为正则表达式提交通常是有效的:

f=s->/^([^]+)\1+$/.test(s)

^(.+)\1+$为我工作,这是9个字节。它对您不起作用吗?
Optimizer

@Optimizer尝试使用带换行符的字符串。
马丁·恩德

我试过了asd\nasd\nasd\n。它的工作原理
优化

@Optimizer refiddle.com/refiddles/5417fb2475622d4df7e70a00似乎对我不起作用(它不应该)
Martin Ender 2014年

是的,这不起作用。也许它逃脱\ 时,我写\n手动
优化

12

CJam,9岁

q__+)@+#)

类似于xnor的想法。

q      " Read input. ";
__+    " Duplicate twice and concatenate them together. ";
)      " Remove the last character of the longer string. ";
@+     " Insert that character at the beginning of the shorter string. ";
#)     " Find the shorter string in the longer string, and increase by one. ";


为什么需要决赛)?我认为平均-1表示假,> = 0表示真是合理的
Digital Trauma

@DigitalTrauma我认为CJam中的0是虚假的...对于像g和这样的运算符?
jimmy23013 2014年

@DigitalTrauma:是否最终需要取决于OP,但严格来说,在CJam中只有零被认为是虚假的。
丹尼斯

@ user23013 @Dennis但是#find运算符呢?从成功与失败的角度来看,这样做的结果肯定也是“真实的”吗?
Digital Trauma 2014年

7

APL,11

2<+/x⍷,⍨x←⍞

说明
将来自屏幕的字符串输入
x←分配给变量,x
,⍨将字符串与其自身
x⍷搜索连接在一起x,生成结果字符串。返回一个数组,该数组由在比赛开始位置的1和在其他位置的0组成。
+/对数组求和,
2<检查总和是否大于2(因为将有2个平凡的匹配项)


7

CJam,10个字节

我发现了CJam错误。我的第一个答案,因此大概可以再打一些:

q__+(;);\#

输出-1表示FALSE,数字> = 0表示TRUE


5
欢迎来到俱乐部!
丹尼斯

5

GolfScript,10个字节

..+(;);\?)

xnor的聪明点子的另一个实现。


哈哈哈,我刚才发布了此消息:codegolf.stackexchange.com/questions/37851/…。我考虑过将其发布为答案,但我认为琐碎的翻译没有意思。
贾斯汀

这次,我什至没有检查新的答案,但是没有检查新的注释)。当不匹配时,将打印-1。如果您打算将其发布为答案,我会很乐意删除我的。
丹尼斯2014年

)在您发布答案之前添加了(我编辑了评论)
贾斯汀2014年

1
改进版(CJam) q__+)@+#)。它在GolfScript中不起作用。
jimmy23013 2014年

1
@ user23013:不再。我只是要发布那个!到目前为止,那里的CJammers太多了……:P
Dennis

3

蟒蛇-59 57

lambda s:any([s*n==s[:n]*len(s)for n in range(2,len(s))])

3

纯bash,30个字节

@xnor的聪明答案的简单端口:

[[ ${1:1}${1:0: -1} =~ "$1" ]]

对于TRUE,退出代码为0;对于FALSE,退出代码为1:

$ for s in 'Hello, World!Hello, World!Hello, World!' 'asdfasdfasdf' 'asdfasdfa' 'ĴĴĴĴĴĴĴĴĴ' 'ĴĴĴ123ĴĴĴ123' 'abcdefgh'; do echo "./isrepeated.sh "\"$s\"" returns $(./isrepeated.sh "$s"; echo $?)"; done
./isrepeated.sh "Hello, World!Hello, World!Hello, World!" returns 0
./isrepeated.sh "asdfasdfasdf" returns 0
./isrepeated.sh "asdfasdfa" returns 1
./isrepeated.sh "ĴĴĴĴĴĴĴĴĴ" returns 0
./isrepeated.sh "ĴĴĴ123ĴĴĴ123" returns 0
./isrepeated.sh "abcdefgh" returns 1
$ 

注意=~[[ ... ]]在bash正则表达式运算符。但是,“可以引用模式的任何部分以强制将其匹配为字符串”。因此,就像bash经常遇到的情况一样,正确地引用非常重要-在这里我们只想检查字符串子匹配项而不是正则表达式匹配项。


3

TI-BASIC-32

我以为我会尝试使用标记化语言。使用Ans中的字符串运行,如果为false,则返回0,如果为true,则返回重复字符串的长度。

inString(sub(Ans+Ans,1,2length(Ans)-1),sub(Ans,length(Ans),1)+Ans

令人惊讶的是它是单线的。


但是...但是...我要使用TI-BASIC:P +1
Timtech

@Timtech好吧,请注意在TI-BASIC中尝试字符串操作的任何人:不要在TI-BASIC中尝试字符串操作。:P很难进行和优化。
Josiah Winslow 2014年

好主意。字符串操作是最难的事情之一。但是,我已经发布了几个这样的答案,所以我想现在您有一个竞争对手;)
Timtech

来吧!:P
Josiah Winslow 2014年

3

ECMAScript 6(189)

(function(){var S=String.prototype,r=S.repeat;S.isRepeated=function(){return!1};S.repeat=function(c){var s=new String(r.call(this,c));if(c>1)s.isRepeated=function(){return!0};return s}}());

 

< console.log("abc".isRepeated(),"abc".repeat(10).isRepeated());
> false true

当然这是唯一有效的解决方案?例如,单词(字符串)nana不一定是从"na".repeat(2)


"nana"不是,但是问题不是要测试是否.repeat使用过。而是,该字符串是否为重复字符串
Optimizer

我知道,我只是想做个聪明人:P
Mardoxx


2

C 85

l,d;f(s){return l=strlen(s),strstr(d,strcpy(strcpy(d=alloca(l*2+1),s)+l,s)-1)-d-l+1;}

原来很长,但是外部功能总是这样。我想到我可以重写每个字符串函数,用一个循环或一个递归函数代替它们。但是以我的经验,结果会更长,坦率地说,我不想尝试。

经过一番研究,我看到了高性能的解决方案,但没有xnor的解决方案聪明(而且简短)。只是为了原创...我在c中重写了相同的想法。

说明:

int length, 
    duplicate;
int is_repetition(char *input)
{
    // length = "abc" -> 3
    length = strlen(input);
    // alloca because the function name is as long as "malloc" 
    // but you don't have to call free() because it uses the stack
    // to allocate memory
    // duplicate = x x x x x x + x
    duplicate = alloca(length*2 + 1);
    // duplicate = a b c 0 x x + x
    strcpy(duplicate, input);
    // duplicate = a b c a b c + 0
    strcpy(duplicate + length, input);
    if (strstr(duplicate,duplicate + length - 1) != duplicate + length - 1)
        // repetition
        // e.g. abab -> abababab -> aba[babab]
        // -> first occurence of [babab] is not aba[babab]
        // but a[babab]ab -> this is a repetition
        return 1;
    else
        // not repetition
        // e.g. abc -> abcabc -> ab[cabc]
        // -> first occurence of [cabc] is ab[cabc]
        // it matches the last "cabc"
        return 0;
}

1

ECMAScript 6(59 62 67 73

不是赢家,但似乎对于实际使用该问题的ES6,实际上至少应该有一个答案 repeat功能的:

f=i=>[...i].some((_,j)=>i.slice(0,j).repeat(i.length/j)==i)

必须在支持ES6的浏览器(例如Firefox)的控制台中运行。

它执行了许多不必要的迭代,但是为什么要延长它以避免这种情况,对吗?

  • 编辑#1:通过将其转换为函数保存了一些字节。感谢优化器!
  • 编辑#2:感谢hsl提供的扩展运算符技巧,以节省更多字节!
  • 编辑#3:感谢Rob W.的另外3个字节!

您可以将其转换为函数以在其中保存更多字节
Optimizer

@Optimizer是的,我想它不一定是“ stdin”。不辜负您的名字:)
IngoBürk2014年

我没有测试过这一点,但你应该能够使用传播经营者[...i],而不是i.split('')
NinjaBearMonkey

1
@hsl疯狂,有效。我不知道散布算子如何工作。最初,我拼命尝试使用它来创建具有range的数组0..N。谢谢!
IngoBürk2014年

1
.slice(0,j).substr(0,j)。短一个字符。此外,|0可以消除不必要地转换为整数的情况(使用|0该方法实际上会降低该方法的实用性,因为如果重复超过2 ^ 31,它将失败)。
Rob W


0

Java 8,28字节

s->s.matches("(?s)(.+)\\1+")

在线尝试。

说明:

检查输入字符串是否与正则表达式匹配,其中 String#matches隐式添加^...$以匹配整个字符串。
正则表达式本身的说明:

^(s?)(.+)\1+$
^                Begin of the string
 (s?)            Enable DOTALL-mode, where `.` also matches new-lines
     (           Open capture group 1
      .+          One or more characters
        )        Close capture group 1
         \1+     Plus the match of the capture group 1, one or more times
            $    End of the string

因此,它基本上检查子字符串是否重复两次或更多次(支持换行)。

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.