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:
input -> output
aba -> false
aab -> false
abba -> false
aabb -> true
aaabb -> false
tthhiiss -> true
ttthhhiiisss -> false
102 Answers 102
brainfuck, 20 bytes
Saved 1 byte thanks to Jo King.
+>,[>,[-<->]<[<],]<.
Takes input two characters at a time, and moves away from the 1 on the tape if any pair doesn't match. EOF is treated as 0 and thus handled automatically.
Output is a null byte if the string is not double speak, and 0x01 if it is. The readable version outputs these as characters at a cost of 14 bytes.
MATL, 4 bytes
Heda
Input is a string, enclosed with single qoutes. Output is 0 for double speak, 1 otherwise.
Explanation
Consider input 'TThhiiss iiss ddoouubbllee ssppeeaakk!!' as an example.
H % Push 2
% STACK: 2
% Implicit input (triggered because the next function requires two inputs): string
% STACK: 'TThhiiss iiss ddoouubbllee ssppeeaakk!!', 2
e % Reshape as a 2-column matrix of chars, in column-major order. Pads with char(0)
% if needed. Note that char(0) cannot be present in the input
% STACK: ['This is double speak!';
'This is double speak!']
d % Difference of each column
% STACK: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
a % Any: gives 0 if and only if all elements are 0
% STACK: 0
% Implicit display
-
14\$\begingroup\$ Um... who is "Heda"? :D \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2019年08月06日 16:01:17 +00:00Commented Aug 6, 2019 at 16:01
-
12\$\begingroup\$ "Heda" is German for "Hey! You!" \$\endgroup\$QBrute– QBrute2019年08月09日 12:47:45 +00:00Commented Aug 9, 2019 at 12:47
05AB1E, (削除) 6 (削除ここまで) (削除) 5 (削除ここまで) 2 bytes
ιË
Input as a list of characters.
-3 bytes by porting @Shaggy's Japt answer, so make sure to upvote him!
Try it online or verify a few more test cases.
Explanation:
ι # Uninterleave the (implicit) input-list of characters
# i.e. ["t","t","t","t","e","e","s","s","t","t","!","!","!"]
# → [["t","t","e","s","t","!","!"],["t","t","e","s","t","!"]]
Ë # Check if both inner lists are equal
# → 0 (falsey)
# (after which the result is output implicitly)
-
\$\begingroup\$ Ahh, you got one that packs. Nice. \$\endgroup\$Khuldraeseth na'Barya– Khuldraeseth na'Barya2019年08月06日 18:20:06 +00:00Commented Aug 6, 2019 at 18:20
-
1\$\begingroup\$ i like this algorithm! \$\endgroup\$Jonah– Jonah2019年08月06日 18:51:27 +00:00Commented Aug 6, 2019 at 18:51
Retina, 9 bytes
(.)1円
^$
Explanation:
Remove all pair of the same characters:
(.)1円
Check if there are no characters left:
^$
-
1\$\begingroup\$ You can provide a more traditional output by using
^$as your final stage. \$\endgroup\$Neil– Neil2019年08月06日 16:38:00 +00:00Commented Aug 6, 2019 at 16:38 -
\$\begingroup\$ @Neil Ah of course, thanks! That indeed looks better. I always think it's strange outputting
falseas truthy andtrueas falsey (but if it saves a byte and it's allowed, I will still use it). ;) But since this is an equal bytes solution outputting the expected results, this is better. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2019年08月06日 16:42:36 +00:00Commented Aug 6, 2019 at 16:42
-
1\$\begingroup\$ Hey I like this! It took me 80mns to do the same lol, I was like "hey let's learn Jelly now" then I learned. I was about to post this but looked if Jelly answers were already there... and then saw this ^^ My steps:
¹©s2L€=2Ạa®s2E€Ạ...ḢƝs2E€Ạ... but I couldn't manage to get what I wanted, and then I sawŒœlol \$\endgroup\$V. Courtois– V. Courtois2019年08月07日 14:21:19 +00:00Commented Aug 7, 2019 at 14:21
JavaScript, 28 bytes
s=>s.every((x,y)=>x==s[y|1])
23 bytes using wastl's regex
s=>/^((.)2円)*$/.test(s)
-
\$\begingroup\$ 24 bytes, but outputs an array for true,
nullfor false: Try it online! \$\endgroup\$wastl– wastl2019年08月06日 16:52:52 +00:00Commented Aug 6, 2019 at 16:52 -
\$\begingroup\$ 27 bytes
s=>!s.some((x,y)=>x>s[y|1])\$\endgroup\$tsh– tsh2019年08月07日 05:51:09 +00:00Commented Aug 7, 2019 at 5:51 -
\$\begingroup\$ @tsh Unfortunately, that would only work if you replaced
>with!=\$\endgroup\$Oliver– Oliver2019年08月07日 15:48:18 +00:00Commented Aug 7, 2019 at 15:48
x86 machine code, (削除) 9 (削除ここまで) 8 bytes
D1 E9 SHR CX, 1 ; divide length in half
L1:
AD LODSW ; load next two chars into AH/AL
3A E0 CMP AH, AL ; compare AH and AL
E1 FB LOOPE L1 ; if equal, continue loop
C3 RET ; return to caller
Callable function. Input string in SI, input string length in CX. Output ZF if is double speak.
Or 14 bytes as a complete PC DOS executable:
B4 01 MOV AH, 01H ; DOS read char from STDIN (with echo)
CD 21 INT 21H ; read first char into AL
92 XCHG DX, AX ; put first char into DL
B4 08 MOV AH, 08H ; DOS read char from STDIN (no echo)
CD 21 INT 21H ; read second char into AL
3A C2 CMP AL, DL ; compare first and second char
74 F3 JE -13 ; if the same, continue loop
C3 RET ; otherwise exit to DOS
Input is via STDIN, either pipe or interactive. Will echo the "de-doubled" input until a non-doubled character is detected, at which point will exit (maybe bending I/O rules a little bit, but this is just a bonus answer).
Build and test ISDBL2.COM using xxd -r:
00000000: b401 cd21 92b4 08cd 213a c274 f3c3 ...!....!:.t..
Original 24 bytes complete PC DOS executable:
D1 EE SHR SI, 1 ; SI to DOS PSP (080H)
AD LODSW ; load string length into AL
D0 E8 SHR AL, 1 ; divide length in half
8A C8 MOV CL, AL ; put string length into BL
CLOOP:
AD LODSW ; load next two chars into AH/AL
3A E0 CMP AH, AL ; compare AH and AL
E1 FB LOOPE CLOOP ; if equal, continue loop
DONE:
B8 0E59 MOV AX, 0E59H ; BIOS tty function in AH, 'Y' in AL
74 02 JZ DISP ; if ZF, result was valid double
B0 4E MOV AL, 'N' ; if not, change output char to N
DISP:
B4 0E MOV AH, 0EH
CD 10 INT 10H
C3 RET ; return to DOS
Input from command line, output to screen 'Y' if double, 'N' if not.
Build and test ISDBL.COM using xxd -r:
00000000: d1ee add0 e88a c8ad 3ae0 e1fb b859 0e74 ........:....Y.t
00000010: 02b0 4eb4 0ecd 10c3 ..N.....
Credits:
- -2 bytes thx to @ErikF!
-
2\$\begingroup\$ Suggest using
LOOPEinstead ofJNZ/LOOPto save 2 bytes. \$\endgroup\$ErikF– ErikF2019年08月07日 16:11:16 +00:00Commented Aug 7, 2019 at 16:11 -
\$\begingroup\$ @ErikF, brilliant! Completely forgot about that! \$\endgroup\$640KB– 640KB2019年08月07日 16:17:27 +00:00Commented Aug 7, 2019 at 16:17
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
-
\$\begingroup\$ what is this monstrosity :) \$\endgroup\$mkst– mkst2019年08月13日 16:45:40 +00:00Commented Aug 13, 2019 at 16:45
PHP, (削除) 58 (削除ここまで) 56 bytes
function f($s){return!$s?:$s[0]==$s[1]&f(substr($s,2));}
As a recursive function.
PHP, (削除) 61 (削除ここまで) (削除) 56 (削除ここまで) 52 bytes
while(''<$l=$argn[$i++])$r|=$l!=$argn[$i++];echo!$r;
Or standalone program. Input string via STDIN, output is truthy (1) if it is double speak, and falsey (0) if it is not double speak.
-4 bytes thx to @Night2!
-
1\$\begingroup\$ This appears to output 1 for a non-double speak string, as well as a double speak string. \$\endgroup\$AJFaraday– AJFaraday2019年08月06日 16:01:10 +00:00Commented Aug 6, 2019 at 16:01
-
\$\begingroup\$ @AJFaraday try now - is double speak, is not double speak \$\endgroup\$640KB– 640KB2019年08月06日 16:07:59 +00:00Commented Aug 6, 2019 at 16:07
Haskell, (削除) 28 (削除ここまで) 23 bytes
f(x:y:z)|x==y=f z
f[]=1
Very straightforward. Double speak is only empty or a repeated character prepended to double speak.
Less straightforward now. Outputs via presence or absence of an error, per meta consensus; no error means double speak. Pattern matching fails when the first two characters differ or when there are an odd number of characters. Thanks to Laikoni for these savings!
Lua, (削除) 67 (削除ここまで) (削除) 66 (削除ここまで) (削除) 63 (削除ここまで) (削除) 59 (削除ここまで) (削除) 33 (削除ここまで) 32 bytes
-25 bytes thanks to Giuseppe
-1 byte thanks to val
print(#(...):gsub("(.)%1","")<1)
Removes every doubled character, then checks if the result is empty.
-
1\$\begingroup\$ why not just
i:gsub("(.)%1","")and check ifi==""? \$\endgroup\$Giuseppe– Giuseppe2019年08月08日 16:26:52 +00:00Commented Aug 8, 2019 at 16:26 -
1
-
\$\begingroup\$ welcome to Code Golf Stack Exchange though! \$\endgroup\$Giuseppe– Giuseppe2019年08月08日 16:28:10 +00:00Commented Aug 8, 2019 at 16:28
-
\$\begingroup\$ I assumed that
"(.)%1"by itself included collisions, but it didn't occur to me that by replacing it once for all captures would be enough. Should I implement your solution or should you write your own answer? And thanks! \$\endgroup\$HugoBDesigner– HugoBDesigner2019年08月08日 17:03:11 +00:00Commented Aug 8, 2019 at 17:03 -
1\$\begingroup\$ Nice idea!
arg[1]can be replaced with(...)to save one byte. \$\endgroup\$val - disappointed in SE– val - disappointed in SE2019年08月12日 10:44:47 +00:00Commented Aug 12, 2019 at 10:44
PowerShell, (削除) 39 (削除ここまで) 38 bytes
!$($args|?{+$p*($p="$_"[$p-eq$_])};$p)
where $p contains a previous char.
No recursion, no regex :). Takes input as a char-array via a splatting string (see TIO link).
PowerShell, 48 bytes
for(;$b-eq$a-and$args){$a,$b,$args=$args}$b-eq$a
No recursion, no regex and no pipe :D. It also takes input as a char-array via a splatting string. It uses $b-eq$a instead $a-eq$b for a case when a last char has #0 code.
Shakespeare Programming Language, (削除) 204 (削除ここまで) 156 bytes
-48 bytes thanks to Jo King (mostly by changing the output method)
A.Ajax,.Puck,.Act I:.Scene I:.[Exeunt][Enter Ajax and Puck]Ajax:Open mind.Puck:Open
mind.Is I worse zero?If soSpeak thy.Is you as big as I?If soLet usAct I.
Exits with error if the input is double speak, and with warning if it is not double speak (which is allowed by default).
Keg, (削除) 19 (削除ここまで) 17 characters
?{!1<|=[|0.(_)]}1
Explanation:
? # read input
{ # while
!1< # stack length greater than 1?
| # end of while condition and beginning of while block
= # compare the 2 top values in the stack
[ # if (the condition is the top of stack)
| # end of then block and beginning of else block
0. # output 0
(_) # clear stack (discard top of stack in for loop stack length times)
] # end if
} # end while
1 # stack is already empty, push a truthy value
# implicitly output the stack content if there was no explicit output
-
\$\begingroup\$ The
<should be a>\$\endgroup\$2020年01月14日 03:53:38 +00:00Commented Jan 14, 2020 at 3:53 -
\$\begingroup\$ And, uh, 10 bytes with
-rRflag \$\endgroup\$2020年01月14日 03:56:55 +00:00Commented Jan 14, 2020 at 3:56 -
\$\begingroup\$ 6 bytes with
-rR flag\$\endgroup\$2020年01月14日 03:58:34 +00:00Commented Jan 14, 2020 at 3:58 -
\$\begingroup\$ For the sake of it, 5 bytes using
-ir, -lpand-rR\$\endgroup\$2020年01月14日 04:01:48 +00:00Commented Jan 14, 2020 at 4:01
Husk, (削除) 6 (削除ここまで) 4 bytes
-2 bytes thanks to Razetime!
ETC2
Hooray for all ASCII solutions! Outputs a positive number if the input is doublespeak, otherwise zero.
C2 Cut list into chunks of 2
T Transpose
E Check if list has all the same elements (return length of list if so)
-
-
\$\begingroup\$ @Razetime That doesn't appear to check if the length is even \$\endgroup\$Jo King– Jo King2021年02月19日 07:11:18 +00:00Commented Feb 19, 2021 at 7:11
-
3\$\begingroup\$ this should work \$\endgroup\$Razetime– Razetime2021年02月19日 07:12:54 +00:00Commented Feb 19, 2021 at 7:12
V (vim), 7 bytes
Ó±
ø^$
Try it online! or Verify test cases
Hexdump:
00000000: d388 b10a d85e 24 .....^$
Just two regexes. Explanation:
Ó " Remove all occurrences...
ˆ " Any character
± " Followed by itself
" This regex is actually just the compressed form of (.)1円
ø " Count the number of matches
^$ " An empty line
Brachylog, 5 bytes
ġ2z2=
Succeeds or fails.
ġ2 The at-most-length-2 chunks of the input,
z2 which have equal length, zipped together,
= are equal.
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
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.
PowerShell, (削除) 64 (削除ここまで) 59 bytes
filter f($n){$a,$b,$r=$n;$a-eq$b-and$(if($r){f $r}else{1})}
Recursive function, no regex. Takes input as a char-array (see TIO link). Peels off the first two elements into $a and $b, stores the remaining into $r. If we still have elements remaining, recurse along with $a -eq $b. Otherwise just check whether $a -eq $b. Output is implicit.
-5 bytes thanks to mazzy
-
1\$\begingroup\$ de-duplicate Try it online! \$\endgroup\$mazzy– mazzy2019年08月07日 04:19:10 +00:00Commented Aug 7, 2019 at 4:19
-
1\$\begingroup\$ @mazzy Thanks! I was missing the
$before the statement block and couldn't figure out why it wasn't working. \$\endgroup\$AdmBorkBork– AdmBorkBork2019年08月07日 12:37:33 +00:00Commented Aug 7, 2019 at 12:37
-
3\$\begingroup\$ It's shorter to use a symbol instead of
f, e.g!a=.... Or to use an anonymous function:s->...\$\endgroup\$H.PWiz– H.PWiz2019年08月06日 15:54:42 +00:00Commented Aug 6, 2019 at 15:54 -
\$\begingroup\$ Yes, you're right. I fixed it \$\endgroup\$Simeon Schaub– Simeon Schaub2019年08月07日 15:15:36 +00:00Commented Aug 7, 2019 at 15:15
J, (削除) 13 (削除ここまで) (削除) 11 (削除ここまで) 10 bytes
-:2#_2{.\]
-2 bytes thanks to Adám
-1 byte thanks to miles
TLDR explanation: Is the input the same as every other character of the input doubled?
-
\$\begingroup\$
-:]#~2 0$~#\$\endgroup\$Adám– Adám2019年08月06日 19:03:17 +00:00Commented Aug 6, 2019 at 19:03 -
\$\begingroup\$
-:2#_2{.\]should save another byte \$\endgroup\$miles– miles2019年08月07日 22:51:10 +00:00Commented Aug 7, 2019 at 22:51 -
\$\begingroup\$ very nice, thanks @miles \$\endgroup\$Jonah– Jonah2019年08月07日 22:56:37 +00:00Commented Aug 7, 2019 at 22:56
Curry, 18 bytes
Tested to work in both PAKCS and KiCS2
f(a:a:x)=f x
f[]=1
This returns 1 if string is double speak and nothing otherwise.
Explanation
This is a pretty straight forward translation of the Haskell program:
f(a:b:x)|a==b=f x
f[]=1
But it uses Curry's more powerful pattern matches to save a bunch of bytes. And while missing a pattern in Haskell is rather difficult to recover from, making this definitely pretty un-idiomatic at best and perhaps a little cheaty. In curry missing patterns just mean it's not a match which is idiomatic and recoverable. So it's shorter and I don't feel like I'm cheating.
Testing
TIO has a limited ability to test things like this. I recommend you use the smap link to test this.
This test handler I've made on smap will not work in KiCS2 or the newer version of PAKCS so you must select PAKCS 2.2.0 (both /one-value and /all-values work fine). This is because of the library Control.SetFunctions which I use for the test. But the function itself does work in the versions if you want to manually test it.
Wolfram Language (Mathematica), (削除) 27 (削除ここまで) (削除) 26 (削除ここまで) (削除) 24 (削除ここまで) 22 bytes
1##&@@@-1^Split@#0&
Input a list of characters. is \[VectorGreater].
Split@# runs
1##&@@@-1^ (-1)^lengths(runs)
0 all>0
-
\$\begingroup\$ You've excluded the necessary code to convert the string input into a list which can be fed to
Split(i.e. the 11 bytes ofCharacters@) \$\endgroup\$Anti Earth– Anti Earth2019年08月07日 17:14:55 +00:00Commented Aug 7, 2019 at 17:14 -
2\$\begingroup\$ @AntiEarth What's a string? \$\endgroup\$att– att2019年08月07日 19:30:17 +00:00Commented Aug 7, 2019 at 19:30
abbawhich should be falsey \$\endgroup\$aabbbbwhich should be truthy \$\endgroup\$