44
\$\begingroup\$

In an earlier challenge I asked code golfers to produce strings which copy each character in a string. For example:

TThhiiss  iiss  ddoouubbllee  ssppeeaakk!!

This challenge is simply to detect if some text meets the definition of a double speak string.

  • There is an even number of characters.
  • When split into pairs, every pair consists of two of the same character.

The challenge

  • It's code golf, do it in few bytes.
  • Use any language you choose.
  • Please include a link to an online interpreter.
  • The code will accept some text.
    • For simplicity, the input will only consist of printable ASCII characters
  • It will return an indication of whether or not the input is double speak. It could be:
    • A boolean
    • Strings ('true', 'false', 'yes', 'no' etc)
    • Integers 0 or 1

Test Cases:

  • aba - false
  • abba - false
  • aabb - true
  • aaabb - false
  • tthhiiss - true
  • ttthhhiiisss - false
\$\endgroup\$
  • 6
    \$\begingroup\$ May we error on inputs of length < 2? \$\endgroup\$ – cole Aug 6 at 16:06
  • 3
    \$\begingroup\$ Suggested test case: abba which should be falsey \$\endgroup\$ – Giuseppe Aug 6 at 16:29
  • 2
    \$\begingroup\$ Suggested test case: aabbbb which should be truthy \$\endgroup\$ – Khuldraeseth na'Barya Aug 6 at 17:30
  • 2
    \$\begingroup\$ @val Well, I'm not going to argue with standard I/O \$\endgroup\$ – AJFaraday Aug 7 at 8:27
  • 2
    \$\begingroup\$ Suggested test case: 0 which should be falsey. \$\endgroup\$ – 640KB Aug 7 at 16:06

71 Answers 71

3
\$\begingroup\$

Mathematica, 31 bytes

AllTrue[Length/@Split@#,EvenQ]&

This works by converting the input (an array of characters, according to @attinat) into a list of characters, splitting this list into sublists of contiguous identical elements, and checking that each sublist has an even number of elements.

\$\endgroup\$
  • 1
    \$\begingroup\$ An answer should be a full program or function; this is a snippet that requires s to be defined beforehand. \$\endgroup\$ – attinat Aug 7 at 19:34
  • \$\begingroup\$ @attinat fixed; I was adopting the convention used by other answers (and see with amusement you pointed this out after I asked about your exclusion of Characters@) \$\endgroup\$ – Anti Earth Aug 7 at 19:40
  • \$\begingroup\$ 28 bytes by using GCD instead of AllTrue. See also this n-speak solution. \$\endgroup\$ – Roman Aug 13 at 18:37
  • 1
    \$\begingroup\$ 28 bytes by using And instead of AllTrue. \$\endgroup\$ – Roman Aug 13 at 21:17
3
\$\begingroup\$

Scala, 44 bytes

_.grouped(2).forall(t=>t.size>1&&t(0)==t(1))

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Cubix, 18 bytes

;U;;A-!/@/n\nW.\O?

Try it online! Outputs 1 if True and nothing if False.

I suppose that it is fitting that this is twice the length to my answer to the previous question

    ; U
    ; ;
A - ! / @ / n \
n W . \ O ? . .
    . .
    . .

Watch it run

  • A Put all input onto the stack
  • - subtract the TOS and start of the test loop
  • ! test result for 0
  • @ if not 0, halt (FALSE for double speak)
  • /;U;; if 0, pop subtraction result and top two items from the stack, u-turn sends it in the right direction.
  • !\n/? an ignored "if 0", reflect, negate, reflect and test for EOI (now 1)
  • O\/@ if positive (1) output and reflect a couple of times onto the halt (TRUE for double speak)
  • nW if negative, reverse the negation and shift lane onto the start of the test loop.
\$\endgroup\$
3
\$\begingroup\$

C# (Visual C# Interactive Compiler), 40 bytes

s=>s.Where((c,i)=>c!=$"{s}"[i|1]).Any()

Try it online!

Each character is tested against it's neighbor for inequality. If any inequalities exist, the result is false.

Since input is limited to printable ASCII characters, a control character is appended to input which is compared to the last character of an odd length string.

Outputs are reversed.

-3 bytes inspired by @Oliver

\$\endgroup\$
  • \$\begingroup\$ 35 bytes? \$\endgroup\$ – Oliver Aug 7 at 17:24
  • \$\begingroup\$ @Oliver - this throws an exception on inputs like a, aaa, aaaaa, etc. You might be into something though, I'll keep fiddling. \$\endgroup\$ – dana Aug 7 at 22:31
  • 1
    \$\begingroup\$ I was able to knock off a few bytes at least :) \$\endgroup\$ – dana Aug 8 at 0:43
3
\$\begingroup\$

Brain-Flak, 36 10 42 30 bytes

(<>)<>{({}[{}]<>){{}{}}{}<>}<>

Outputs 0 if it is double speak, and nothing if it isn't

-12 bytes thanks to Nitrodon

How it works

(<>) Pushes 0 to the second stack
<>   Swaps back to the first stack
{    Begins a loop that will run until the stack is empty
({}[{}]<>)    Pops the top two items off of the first stack and pushes their difference to the second stack
{{}{}}{}      If the difference is zero, it gets popped and nothing happens. 
If there difference is one, the zero that was put on at the beginning gets popped, so nothing will get outputted at the end 
<>   Swaps back to the first stack
}    End loop
<>   Swap to the second stack for output

Try it Online!

\$\endgroup\$
  • \$\begingroup\$ Fixed both of the problems \$\endgroup\$ – EdgyNerd Aug 7 at 15:11
  • \$\begingroup\$ ({}<>)<>({}<>)({}[{}]) can be simplified to ({}[{}]<>). \$\endgroup\$ – Nitrodon Aug 9 at 20:57
  • \$\begingroup\$ oh wow, no clue why I decided to pop and swap stacks twice, thanks :) \$\endgroup\$ – EdgyNerd Aug 9 at 21:50
2
\$\begingroup\$

PowerShell, 27 24 bytes

-3 bytes thanks to mazzy

!($args-creplace"(.)\1")

Try it online!

Uses the regex method going around. If the string is emptied out, it will return true, otherwise false.

\$\endgroup\$
  • 1
    \$\begingroup\$ you can omit ,'' Try it online! \$\endgroup\$ – mazzy Aug 6 at 16:37
  • 1
    \$\begingroup\$ @mazzy Ha ha, I'm smrt. Thanks \$\endgroup\$ – Veskah Aug 6 at 16:40
2
\$\begingroup\$

Charcoal, 10 bytes

⬤⪪S²⁼ι⮌…ι²

Try it online! Link is to verbose version of code. Outputs Charcoal's default boolean format, which is - for true and nothing for false. Explanation:

  S         Input string
 ⪪ ²        Split into substrings of length up to 2
⬤           All substrings
        ι   Current substring
       … ²  Extended to length 2
      ⮌     Reversed
    ⁼       Equals
     ι      Current substring
            Implicitly print
\$\endgroup\$
2
\$\begingroup\$

Whitespace, 73 bytes

[N
S S N
_Create_Label_LOOP][S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   S _Read_input_as_character][T   T   T   _Retrieve][S N
S _Duplicate_input][S S S T S T S N
_Push_10][T S S T   _Subtract][N
T   S S N
_If_0_Jump_to_Label_EXIT][S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   S _Read_input_as_character][T   T   T   _Retrieve][T    S S T   _Subtract][N
T   S N
_If_0_Jump_to_Label_LOOP][S S S N
_Push_0][T  N
S T _Print_as_integer][N
S S S N
_Create_Label_EXIT]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Since Whitespace inputs one character at a time, the input should contain a trailing newline so it knows when to stop reading characters and the input is done.

Outputs 0 for falsey, or nothing for truthy.

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Start LOOP:
  Character c = STDIN as character
  If(c == '\n'):
    Stop program
  Character d = STDIN as character
  If(c == d):
    Go to next iteration of LOOP
  Print 0
\$\endgroup\$
2
\$\begingroup\$

SNOBOL4 (CSNOBOL4), 63 bytes

	I =INPUT
R	I LEN(1) . X
	I X X =	:S(R)
	OUTPUT =IDENT(I) 1
END

Try it online!

Matches the first character LEN(1) and saves it . to X. If I matches X concatenated with itself, it replaces that substring and repeats. If the remaining string is empty, IDENT(I,<implicit empty string>), then 1 is output, else nothing is output.

\$\endgroup\$
2
\$\begingroup\$

Stax, 6 bytes

:GF2%p

Run and debug it at staxlang.xyz!

Outputs integers. Zero for double speak and nonzero otherwise, as allowed here.

:GF2%p
:G        Array of run lengths
  F       For each run length:
   2%       Modulize by two
     p      Pop and print with no newline

Any odd run length means a 1 in the long string of output.

\$\endgroup\$
2
\$\begingroup\$

K (oK), 12 bytes

Solution:

&/1==/'0N 2#

Try it online!

Explanation:

&/1==/'0N 2# / the solution
       0N 2# / reshape into Nx2 grid
    =/'      / equals (=) over (/) each (')
  1=         / equal to 1 (ie a match)
&/           / take the minimum

Extra:

  • (~).+0N 2# works(ish) for 10 bytes, but not if the only difference is a character on the end of one of the strings :(
\$\endgroup\$
  • \$\begingroup\$ Wouldn't just &/=/'0N 2# work? \$\endgroup\$ – Traws Aug 13 at 16:27
  • 1
    \$\begingroup\$ Not for odd-length input :( \$\endgroup\$ – streetster Aug 13 at 16:39
2
\$\begingroup\$

APL+WIN, 20 15 bytes

5 bytes saved thanks to Adam.

Prompts for input of string:

n≡(2×2|⍳⍴n)/n←⎕

Try it online! Courtesy of Dyalog Classic

\$\endgroup\$
2
\$\begingroup\$

dzaima/APL, 14 11 bytes

⊢≡⊢⌿⍨2 0⍴⍨≢

Try it online!

-3 thanks to Adám!

\$\endgroup\$
2
\$\begingroup\$

Kotlin, 56 52 bytes

{it.chunked(2).filter{it.toHashSet().size>1}.size<1}

Try it online!

Thank you Khuldraeseth na'Barya for saving 4 bytes

\$\endgroup\$
2
\$\begingroup\$

INTERCAL, 192 bytes

PLEASE,1<-#2DOCOMEFROM(2)DOWRITEIN,1DO.5<-#1$',1SUB#1'~#256PLEASE(1)NEXTDOREADOUT#1DOGIVEUP(1)DO(1002)NEXTDO.5<-#1$',1SUB#2'~,1SUB#2DO(3)NEXTDOREADOUT#0PLEASEGIVEUP(3)DO(1002)NEXT(2)DOFORGET#2

Try it online!

Output is done with INTERCAL's native "butchered Roman numerals", so the true output of 1 prints as \nI\n, and the false output of 0 prints as _\n\n.

I don't feel like writing out a full explanation at the moment, but the ungolfed code is here, I lifted the control flow from something I wrote earlier, and the gist of what it does is read two characters at a time from the input through the usually unhelpful "Turing Tape" I/O until either the first resulting number is 256 (in which case the entire input has been validated and has even length, so it is double-speak), or the second resulting number is not 0 (in which case the second character is different from the first or does not exist, and the input is not double-speak).

I think I might be able to restructure this to cut down on redundancy, but I'm not quite feeling up to that at the moment either.

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 50 bytes

Returns 0 if double-speak (or empty string), truthy otherwise.

f(s,i)char*s;{for(i=*s;i&(i=*s++)&&i==*s++;);s=i;}

Try it online!

If the input string is assumed to always be at least 2 characters (gives incorrect result for single-character strings):

C (gcc), 38 bytes

f(char*s){while(*s&&*s++==*s++);s=*s;}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ The second suggestion seems to treat single character strings the same as any other odd length strings? \$\endgroup\$ – Taemyr Aug 8 at 7:30
  • \$\begingroup\$ Wouldn't putting s=i at the end of for braces (for(i=*s;i&(i=*s++)&&i==*s++;s=i) save you one ;? \$\endgroup\$ – Przemysław Czechowski Aug 8 at 17:47
  • \$\begingroup\$ @PrzemysławCzechowski s=i is used to return the value: it's not part of the loop. I'm using i to capture the character value, so assigning it to s during the loop would mess up the pointer (and likely crash the program!) \$\endgroup\$ – ErikF Aug 8 at 18:04
  • \$\begingroup\$ @ErikF my bad, I thought s=i is repeated in every iteration. \$\endgroup\$ – Przemysław Czechowski Aug 8 at 18:23
2
\$\begingroup\$

Pip, 31 bytes

a:qFb,#a{b%2?x(ab+1)Qa@b?xi:1}i

Try it online!

slightly different approach with fold operator, 31 bytes

a:qFb,#a{I!b%2i:$Q[a@b(ab+1)]}i

outputs 0 if double speak, 1 otherwise

\$\endgroup\$
2
\$\begingroup\$

Perl 6, 14 bytes

{!S:g/(.)$0//}

Try it online!

Replaces all pairs of identical characters with nothing and then boolean NOTs the result to return true if is an empty string (i.e. all characters were next to an identical one), or false otherwise.

\$\endgroup\$
2
\$\begingroup\$

PHP, 51 50 38 bytes

echo preg_match("/^((.)\2)+$/",$argn);

Checks whether input matches pairs of chars where the chars in each pair are the same (using back ref).

Run like this:

echo 'dd00uubbllee' | php -nR 'echo preg_match("/^((.)\\2)+$/",$argn);';echo
  • -1 byte thanks to @manatwork
  • -12 bytes by using preg_match with back references.
\$\endgroup\$
  • \$\begingroup\$ Wouldn't /.(.?)/ be enough to handle odd length strings? \$\endgroup\$ – manatwork Aug 8 at 9:29
  • \$\begingroup\$ @manatwork you're right, thanks \$\endgroup\$ – aross Aug 8 at 9:32
2
\$\begingroup\$

PHP, 37 40 bytes

+3 bytes to fix '0' issue

<?=''==preg_replace('/(.)\1/','',$argn);

Try it online!

Similar to other RegEx answers.


PHP, 55 bytes

for(;($l=$argn[$i++])==$argn[$i++]&&$l.$l;);echo$l=='';

Try it online!

Loops to the end of the string as long as every even character (0th, 2nd, 4th, etc ...) is equal to the character after it, else stops the loop. Finally, checks if it has arrived at the end of the string, which means the string is a double speak.


Outputs 1 for double speak and nothing for not double speak.

\$\endgroup\$
  • \$\begingroup\$ Your first one is close, but it negates the resulting string. "0" is falsey in PHP, so an input of "000" will be deemed doublespeak \$\endgroup\$ – aross Aug 8 at 9:59
  • \$\begingroup\$ @aross: Thanks for pointing it out, yeah that '0' == false is always an issue. Fixed! \$\endgroup\$ – Night2 Aug 8 at 11:38
2
\$\begingroup\$

Java (JDK), 64 bytes

s->{int i=s.length;for(;i>1;)i=s[--i]==s[--i]?i:i|1;return i<1;}

Try it online!

Explanations

s->{
 int i=s.length;
 for(;i>1;)                 // while the length is 2 or greater.
  i=s[--i]==s[--i]?i:i|1;   // check the 2 previous values. If they're identical, don't do anything. Else, make i odd so that it fails at the return.
 return i<1;                // i will be 0 only when the size is even and all characters were doubled.
}
\$\endgroup\$
2
\$\begingroup\$

Malbolge (unlimited memory access variant), Around 4 megabytes

You asked the golfers, but for the second time forgot about the bowlers.

This is too big to include in the answer for obvious reason so here is gist link.

You might want to use the fast interpreter to test this program, as it's hellishly slow (hellishly, get it?). I'm going to include the TIO.run link after Dennis (hopefully) takes on my issue on TIO tracker.

// Edit: Nope, no TIO link as the answer size limit is 65536 bytes, and no abusing url shorteners because they just refuse to shorten it

\$\endgroup\$
  • \$\begingroup\$ what is this monstrosity :) \$\endgroup\$ – streetster Aug 13 at 16:45
1
\$\begingroup\$

Befunge-98 (PyFunge), 11 bytes

~#@~# -_#q1

Try it online!

Returns 1 if double speak, 0 if not.

10 byte solution which returns 0 for double speak and non-0 otherwise:

~#q~#1-_#q

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 75 bytes

lambda s:all[([s[2*i]==s[2*i+1]for i in range(int(len(s)/2))]),0][len(s)%2]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Ruby, 21 bytes

->s{s[/((.)\2)*/]==s}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Gema, 17 characters

?$1=
?=0@end
\Z=1

Outputs 1 on double speak and 0 on not.

Sample run:

bash-5.0$ echo -n 'TThhiiss  iiss  ddoouubbllee  ssppeeaakk!!' | gema '?$1=;?=0@end;\Z=1'
1

Try it online!

Gema, 12 characters

?$1=
?=@fail

Terminates with exit code 0 on double speak and 2 on not.

Sample run:

bash-5.0$ echo -n 'TThhiiss  iiss  ddoouubbllee  ssppeeaakk!!' | gema '?$1=;?=@fail'
bash-5.0$ echo $?
0

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Kotlin, 59 57 bytes

{s->(0..s.length-1 step 2).fold(""){t,c->t+s[c]+s[c]}==s}

Try it online!

-1 byte thanks to Khuldraeseth na'Barya

-1 byte changing it -> s


Slightly lazy attempt - basically just took my answer from the doublespeak question, applied it to every second char of the input and see if the result is the input.

\$\endgroup\$
  • \$\begingroup\$ Save a byte \$\endgroup\$ – Khuldraeseth na'Barya Aug 6 at 19:25
  • \$\begingroup\$ @Khuldraesethna'Barya updated, thanks! did not know that was a thing \$\endgroup\$ – Quinn Aug 6 at 19:32
1
\$\begingroup\$

Kotlin, 4649 bytes

-3 bytes thanks to @cubic lettuce

{it.chunked(2).all{it.length>1&&it[0]==it[1]}}

Try it online!

{it.length%2==0&&it.chunked(2).all{it[0]==it[1]}}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Save 3 bytes by {it.chunked(2).all{it.length>1&&it[0]==it[1]}} ;) \$\endgroup\$ – cubic lettuce Aug 7 at 20:41
1
\$\begingroup\$

C (tcc), 59 55 50 bytes

f(char *s){while(*s==*++s)s++;return!*--s&&s!="";}

Try it online!

Thanks to Jo King for the 4 bytes and Unrelated String for saving 5 bytes

Can it be even shorter?

\$\endgroup\$
  • \$\begingroup\$ *s==*++s, how is this not UB when *s points to the end of the string? \$\endgroup\$ – Taemyr Aug 7 at 11:26
  • \$\begingroup\$ the *s will always point to the last character of the string given in argument which is not last character because string here ends with '\0' so the *++s gets the \0 \$\endgroup\$ – Loki Aug 7 at 11:36
  • 1
    \$\begingroup\$ You increment s by two each time through the loop, so if there is an even number of actuall characters in the string I do not see how you can guarantee that *s never points to the '\0' \$\endgroup\$ – Taemyr Aug 7 at 11:58
  • \$\begingroup\$ You could golf it considerably by replacing *--s=='\0' with the simple !*--s, but also note that most challenges require submissions to be either functions or full programs, and this is neither. \$\endgroup\$ – Unrelated String Aug 7 at 19:37
  • \$\begingroup\$ Thanks guys for helping shortening it and @Taemyr play with this code TIO I don't need to care if *s gets the \0 character cause then the *++s will get the first character from the string used in printf. \$\endgroup\$ – Loki Aug 8 at 5:07
1
\$\begingroup\$

Rust, 73 bytes

|s:&str|!s.chars().enumerate().any(|(i,c)|s.chars().nth(i|1).unwrap()!=c)

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.