This is taken from this question (with permission ofcourse). I'll quote:
Create a function which takes a string, and it should return true or false based on whether the input consists of only a repeated character sequence. The length of given string is always greater than 1 and the character sequence must have at least one repetition.
Some examples:
'aa' //true
'aaa' //true
'abcabcabc' //true
'aba' //false
'ababa' //false
'weqweqweqweqweqw' // false
Specifically, the check for a string strictly composed of repeating substrings (Update) can output any true or false representation, but no error output please. Strictly alphhanumeric strings. Otherwise standard code golf rules. This is Code Golf, so shortest answer in bytes for each language wins.
-
4\$\begingroup\$ Hm, I was going to close this challenge as a dupe of that one, but I noticed that the other one scores on character count. So maybe we should close the other one (it also has an accepted answer) as a dupe of this one instead. \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2019年04月24日 15:14:44 +00:00Commented Apr 24, 2019 at 15:14
-
\$\begingroup\$ Let us continue this discussion in chat. \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2019年04月24日 15:36:30 +00:00Commented Apr 24, 2019 at 15:36
43 Answers 43
JavaScript (ES6), 22 bytes
Returns a Boolean value.
s=>/^(.*)1円+$/.test(s)
Without a regular expression, (削除) 33 (削除ここまで) 29 bytes
Returns either null (falsy) or an object (truthy).
s=>(s+s).slice(1,-1).match(s)
NB: Technically, \$s\$ is converted to a regular expression for match(), so the above title is a lie.
Brachylog,(削除) 4 (削除ここまで)3 bytes
ġ=Ṁ
Explanation
ġ=Ṁ Implicit input, say "abcabc"
ġ Split into chunks of equal lengths (except maybe the last one): ["abc","abc"]
= Apply the constraint that all of the chunks are equal,
Ṁ and that there are multiple of them.
The program prints true. if the constraints can be satisfied, and false. if not.
-
\$\begingroup\$ I was just struggling through trying to get something like
~j↙or=Ṁcworking before I noticed you posted this an hour ago \$\endgroup\$Unrelated String– Unrelated String2019年04月24日 21:27:35 +00:00Commented Apr 24, 2019 at 21:27 -
4\$\begingroup\$ Oh, yeah, this could be one byte shorter:
ġ=Ṁ\$\endgroup\$Unrelated String– Unrelated String2019年04月24日 21:36:39 +00:00Commented Apr 24, 2019 at 21:36 -
\$\begingroup\$ (
Ṁis a variable constrained to be a list of two or more elements) \$\endgroup\$Unrelated String– Unrelated String2019年04月24日 21:39:09 +00:00Commented Apr 24, 2019 at 21:39 -
1\$\begingroup\$ @UnrelatedString Great, thanks! I didn't think to check the variables wiki page. \$\endgroup\$Zgarb– Zgarb2019年04月25日 09:12:49 +00:00Commented Apr 25, 2019 at 9:12
-
1\$\begingroup\$ A lot of great answers, and the LUA answer has a special place in my heart. Arnauld's answer is particularly sweet since the original question that I based this on (not the dupe) is actually tagged Javascript. Mainly selecting this one just because it does appear to be the overall shortest for all languages and, as this is my first question, I get a badge. \$\endgroup\$ouflak– ouflak2019年05月01日 06:40:38 +00:00Commented May 1, 2019 at 6:40
grep, 19
grep -qxE '(.+)1円+'
Test
while read; do
<<<"$REPLY" grep -qxE '(.+)1円+' && t="true" || t="false"
echo "$REPLY: $t"
done < infile
Output:
aa: true
aaa: true
abcabcabc: true
aba: false
ababa: false
weqweqweqweqweqw: false
Japt, 6 bytes
2é ¤øU
Saved one byte thanks to @Shaggy
Implicit input, stored in variable 'U'
2 U+U, "abcabc" -> "abcabcabcabc"
é Rotate 1 char to the right "abcabcabcabc" -> "cabcabcabcab"
¤ Remove first two chars, "cabcabcabcab" -> "bcabcabcab"
øU Check if U is in the above
-
\$\begingroup\$ Nice one :) You can replace the
p<space>with²to save a byte. \$\endgroup\$Shaggy– Shaggy2019年04月24日 16:25:34 +00:00Commented Apr 24, 2019 at 16:25
Java, (削除) 25 (削除ここまで) 24 bytes
-1 byte thanks to Olivier Grégoire!
Boring regex answer
s->s.matches("(.+)\1円+")
Try it online!
(削除) It's just 1 byte longer than the python answer aaaaa (削除ここまで) I'm tied now :)
-
3\$\begingroup\$ You can remove the final
$as thematchesmethod is an exact match, not a substring match by default. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2019年04月24日 23:18:56 +00:00Commented Apr 24, 2019 at 23:18 -
\$\begingroup\$ I forgot
matchesadds its own$to the regex. Thanks! \$\endgroup\$Benjamin Urquhart– Benjamin Urquhart2019年04月24日 23:34:18 +00:00Commented Apr 24, 2019 at 23:34
Excel, 26 bytes
=FIND(A1,A1&A1,2)<=LEN(A1)
Inputs from A1, outputs to whatever cell you put this formula.
-
\$\begingroup\$ You could save 4 bytes if you defined a single-letter range name (e.g.
A) and set that as your input. \$\endgroup\$i_saw_drones– i_saw_drones2019年04月24日 18:54:44 +00:00Commented Apr 24, 2019 at 18:54 -
\$\begingroup\$ @i_saw_drones - I think that is disallowed by standard I/O rules: here's a link to the meta answer that would apply to that method; it's currently at -36 votes. \$\endgroup\$Sophia Lechner– Sophia Lechner2019年04月24日 20:17:34 +00:00Commented Apr 24, 2019 at 20:17
-
\$\begingroup\$ Apologies I hadn't seen that post, although thinking about it, isn't
A1also a "variable" since it contains the input value? :) \$\endgroup\$i_saw_drones– i_saw_drones2019年04月24日 23:05:55 +00:00Commented Apr 24, 2019 at 23:05 -
1\$\begingroup\$ I would feel that way if I were doing anything special with the fact that it's A1 specifically, like if I relied somehow on its ROW(_) being 1. As is, though, it's just the most natural way of providing an Excel function with an arbitrary input. \$\endgroup\$Sophia Lechner– Sophia Lechner2019年04月25日 17:03:40 +00:00Commented Apr 25, 2019 at 17:03
R, 28 bytes
grepl("(.+)\1円+$",scan(,''))
Simple Regex version. R is (sometimes) very similar to Python, so this is similar to TFeld's Python 2 regex answer, albeit shorter!
Question (if anyone knows the answer)
I am still confused why this works, as the substring can be any length and will always work, and still works when I add a letter to the front of a valid string, like "cABABABABAB". If I personally read the regex, I see (.+), which captures any group of any length. And then \1円+$ which repeats the captured group any number of times until the end.
So why doesn't it capture just "AB" and find that it is repeated until the end of the string, especially since there is no restriction specified as to where the substring can start?
-
1\$\begingroup\$ Interesting, this seems to be a bug in R's regex engine. Adding the option
perl=TRUEmakes it match cABABAB, as you'd expect. Runninggrep -E '(.*)1円+$'in bash also matches cABABAB, even thoughgrep -Euses ERE, the same regex flavor R is supposed to support. \$\endgroup\$Grimmy– Grimmy2019年04月25日 15:43:29 +00:00Commented Apr 25, 2019 at 15:43 -
2\$\begingroup\$ My guess is that this is an incorrectly applied optimization. Changing
.+at the start of a pattern to^.+is an important optimization, but if the.+is inside capturing parens it stops being valid. \$\endgroup\$Grimmy– Grimmy2019年04月25日 15:50:29 +00:00Commented Apr 25, 2019 at 15:50
Jelly, (削除) 5 (削除ここまで) 4 bytes
I see now that the optimal way is to follow xnor's method!
Ḋ;Ṗw
A monadic Link that accepts a list of characters and outputs an integer - the shortest possible length of a repeating slice or zero if none exists. Note that zero is falsey while non-zero numbers are truthy in Jelly.
How?
Ḋ;Ṗw - Link: list of characters, S e.g. "abcabcabc" or "abababa"
Ḋ - dequeue S "bcabcabc" "bababa"
Ṗ - pop from S "abcabcab" "ababab"
; - concatenate "bcabcabcabcabcab" "bababaababab"
w - first index of sublist 3 ^---here! 0 (not found)
Python 2, 24 bytes
lambda s:s in(s*2)[1:-1]
Shamelessly stolen from xnor's answer to the original question.
More intuitive version:
Python 2, (削除) 59 (削除ここまで) (削除) 55 (削除ここまで) 53 bytes
lambda s:s in[len(s)/i*s[:i]for i in range(1,len(s))]
Boring regex version:
Python 2, 44 bytes
lambda s:re.match(r'(.+)1円+$',s)>0
import re
Wolfram Language (Mathematica), (削除) 24 (削除ここまで) 23 bytes
StringMatchQ[x__..~~x_]
StringMatchQ[ (*a function that checks if its input (string) matches:*)
x__.. (*a sequence of one or more characters, repeated one or more times*)
~~x_] (*and one more time*)
GNU Bash, 28 bytes
[[ ${1:1}${1::-1} == *1ドル* ]]
Save the above script into a file, and run bash file.sh "string to test".
Exit code 0 is truthy and non-zero is falsy. (as all Unix shells would interpret)
05AB1E, 5 bytes
xnor's method from the previous question appears to be optimal in 05AB1E as well.
«¦ ̈så
Try it online! or as a Test Suite
Explanation
« # append input to input
¦ ̈ # remove the first and last character of the resulting string
så # check if the input is in this string
-
1\$\begingroup\$ Of course.. I was about to make a 05AB1E answer when I saw none were there. Colleague asked me some questions and talked about his vacation. I look back at the screen: one new answer. Tada, beat again XD \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2019年04月25日 06:55:11 +00:00Commented Apr 25, 2019 at 6:55
-
\$\begingroup\$ @KevinCruijssen: That's typical. Has happened to me a bunch of times as well ;) \$\endgroup\$Emigna– Emigna2019年04月25日 06:56:54 +00:00Commented Apr 25, 2019 at 6:56
PowerShell, (削除) 23 (削除ここまで) 24 bytes
+1 byte to fully match rules
"$args"-match"^(.+)1円+$"
Pretty boring. Based on the other Regex answers. Luckily PowerShell doesn't use \ as an escape character!
C# (Visual C# Interactive Compiler), 70 bytes
xnor's shameless adaptation (46 bytes)
s=>(s+s).Substring(1,s.Length*2-2).Contains(s)
My non Regex Solution:
s=>s.Select((x,y)=>y).Count(z=>s.Replace(s.Substring(0,z+1),"")=="")>1
Explanation:
Replace every possible substring that starts at index 0 with an empty string. If the result is an empty string, the string is entirely made of that substring. Since this includes evaluating the entire string with itself, the amount of expected results must be greater than 1.
Example: abcabc
Possible substrings starting at index 0:
'a', 'ab', 'abc', 'abca', 'abcab', 'abcabc'
If we replace them with empty strings
Substring Result
'a' => 'bcbc'
'ab' => 'cc'
'abc' => ''
'abca' => 'bc'
'abcab' => 'c'
'abcabc' => ''
Since there is a substring other than 'abcabc' that returns an empty string, the string is entirely made of another substring ('abc')
Python 3, (削除) 62 (削除ここまで) (削除) 60 (削除ここまで) (削除) 56 (削除ここまで) 54 bytes
-4 bytes thanx to ArBo
lambda s:s in(len(s)//l*s[:l]for l in range(1,len(s)))
- Iterate over all possible prefixes in the string.
- Try to build the string out of the prefix.
- Return whether this succeeds with any prefix at all.
-
1
-
1\$\begingroup\$ Nice catch with the list membership, thanx! I won't switch to Python 2, as this is like switching the language, which is obviously not the point here ;) Also, is there a convenient way to test an anonymous function in TIO, keeping the byte-count? \$\endgroup\$movatica– movatica2019年04月26日 14:13:01 +00:00Commented Apr 26, 2019 at 14:13
-
1\$\begingroup\$ @movatica In the header, put `f = ` (\ is the line continuation character in python) \$\endgroup\$Miriam– Miriam2019年04月26日 15:33:36 +00:00Commented Apr 26, 2019 at 15:33
-
\$\begingroup\$ Annoyingly, \ is also an escape character. Here, without code formatting, is what you should put in the header: f = \ \$\endgroup\$Miriam– Miriam2019年04月26日 15:35:19 +00:00Commented Apr 26, 2019 at 15:35
Japt, 10 bytes
Returns a positive number if truthy and 0 if falsey. If you want a bool output just add -¡ flag
å+ k@rXÃÊÉ
å+ k@rXÃÊÉ Full program. Implicit input U.
e.g: U = "abcabcabc"
å+ Take all prefixes
U = ["a","ab","abc","abca","abcab","abcabc","abcabca","abcabcab","abcabcabc"]
k@ Filter U by:
rXÃ Values that return false (empty string)
when replacing each prefix in U
e.g: ["bcbcbc","ccc","","bcabc","cabc","abc","bc","c",""]
take ↑ and ↑
U = ["abc","abcabcabc"]
ÊÉ Get U length and subtract 1. Then return the result
Husk, 6 bytes
Ṡ€ȯhtD
I feel like this is one byte more than optimal, but I couldn't find an arrangement that made the explicit composition ȯ unnecessary.
Explanation
Ṡ€ Find the argument in the result of applying the following function to the argument
ȯhtD Duplicate the argument, then remove the first and last elements.
-
2\$\begingroup\$
€htD¹avoids theȯ. \$\endgroup\$Zgarb– Zgarb2019年04月24日 19:30:11 +00:00Commented Apr 24, 2019 at 19:30 -
\$\begingroup\$ That's fantastic! I had thought about
λ€htD¹but I didn't realize that lambdas would be added implicitly \$\endgroup\$Sophia Lechner– Sophia Lechner2019年04月24日 20:10:44 +00:00Commented Apr 24, 2019 at 20:10
Mathematica 11.x, 74 bytes
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&
where, throughout, # represents the input string, and
StringCases[#,<pattern>]
finds substrings of the input string matching the pattern
StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")
This pattern requires matches, x, must start at the start of the string and must satisfy the condition that (1) the match is not the whole input string and (2) if we replace occurrences of the match in the input string with the empty string we obtain the empty string. Finally, comparing the list of matches to the empty list,
{}!=
is True if the list of matches is nonempty and False if the list of matches is empty.
Test cases:
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["aa"]
(* True *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["aaa"]
(* True *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["abcabc"]
(* True *)
and
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["aba"]
(* False *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["ababa"]
(* False *)
{}!=StringCases[#,StartOfString~~x__/;(x!=#&&StringReplace[#,x->""]=="")]&["weqweqweqweqweqw"]
(* False *)
Python 3, 84 bytes
import textwrap
lambda s:any(len(set(textwrap.wrap(s,l)))<2 for l in range(1,len(s)))
Uses textwrap.wrap (thanks to this answer) to split the string into pieces of length n to test each possible length of repeating substring. The split pieces are then compared to each other by adding them to a set. If all of the pieces are equal, and the set is of length 1, then the string must be a repeating string. I used <2 instead of ==1 because it saves a byte, and the length of the input string was guaranteed to be greater than zero.
If there is no n for which repeating substrings of length n make up the entire string, then return false for the whole function.
Clean, 73 bytes
Doesn't use regex.
import StdEnv,Data.List
$s=or[isPrefixOf s(cycle t)\\t<-tl(tails s)|t>[]]
Defines $ :: [Char] -> Bool.
Checks if the given string is a prefix of the repetition of any sub-string taken from the end.
Zsh, 19 bytes
Outputs via error code:
[[ 1ドル1ドル = ?*1ドル*? ]]
However, the challenge did specify "output on stdout":
Zsh, 22 bytes
Outputs an empty string if true, and a non-empty string for false:
<<<${${:-1ドル1ドル}/?*1ドル*?}
If the output must be fixed:
Zsh, 25 bytes
Outputs 0 for true, 1 for false
[[ 1ドル1ドル = ?*1ドル*? ]]
<<<$?
The heart of these solutions is ?*1ドル*?, which is a glob which matches the string in question surrounded by at least one character on each side: * is a string of any length, and ? is a single character. This is an alternate version of xnor's solution, but using globs to match extra characters rather than removing leading and trailing characters.
C++ (gcc), 36 bytes
#define f(x)(x+x).find(x,1)<x.size()
Another port of xnor's solution. Uses a macro to expand the argument into the expression. The argument is assumed to be of type std::string.
K (ngn/k), 11 bytes
&/1_=':#'=:
Thanks to PyGamer0 for the "check if all the values of a list are equal" code snippet!
Return 1 for true and 0 for false
Explanations:
&/1_=':#'=: Main function. Takes implicit input with : on the right-most
= Group the characters into a dictionary
#' Get the length in the values of each of the keys
(The values are the occurence positions of the characters in the string)
: Apply everything on the left to the right
=' Check if the values of the values in the dictionary are equal
1_ Weed out the first one (as we know it will always be false)
&/ Get the minimum value
Vyxal r, (削除) 5 (削除ここまで) 4 bytes
dḢṪc
-1 byte by porting xnor's answer from the other question
Concatenates the string to itself, removes the first and last characters, then checks if the input string is in that.
QlikView Variable, 27 bytes
This should be defined as a variable, which then allows you to pass parameters, e.g. 1ドル as your input value.
It returns 0 or -1 (equivalent to QlikView's TRUE() function).
=substringcount(1ドル&1,ドル1ドル)>2