text:
Is it double speak?
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

Can the Booleans or integers be (consistently) reversed? 1 for non-double speak, 0 for double speak

@LuisMendo Unusual, but sounds okay to me.

May we error on inputs of length < 2?

Suggested test case: abba which should be falsey

Suggested test case: aabbbb which should be truthy

I guess correct spelling is not an issue, so something like "lleetteerr" would be considered truthy, right? Even though this could come from a program that says "double all characters except 't'".

@Corak that’s correct. We’re not interested in the validity of words, just whether the characters all repeat.

Can I use exit code (0/1) to output? Standard I/O rules allow that.

@val Well, I'm not going to argue with standard I/O

Suggested test case: 0 which should be falsey.

What about the empty string?

Suggested test case: "aab" caught me up, since I didn't check that the input was of even length, only that the pairs were equal

Python 3, 24 bytes
lambda s:s[::2]==s[1::2]

Try it online!

brainfuck, 20 bytes
Saved 1 byte thanks to Jo King.
+>,[>,[-<->]<[<],]<.

Try it online!
Readable output!
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.
Try it online!
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

Um... who is "Heda"? :D

"Heda" is German for "Hey! You!"

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)

Japt, 4 bytes
ó r¶

Try it
ó r¶     :Implicit input of string
ó        :Uniterleave
  r      :Reduce by
   ¶     :  Testing equality

Alternative
ó
¥o

Try it

Stax, 5 bytes
■◄┼$Δ

Run and debug it
Procedure:

Calculate run-lengths.
Get GCD of array.
Is even?

Ahh, you got one that packs. Nice.

i like this algorithm!

Retina, 9 bytes
(.)\1

^$

Try it online.
Explanation:
Remove all pair of the same characters:
(.)\1

Check if there are no characters left:
^$

You can provide a more traditional output by using ^$ as your final stage.

@Neil Ah of course, thanks! That indeed looks better. I always think it's strange outputting false as truthy and true as 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.

Jelly, 3 bytes
ŒœE

Try it online!

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

JavaScript, 28 bytes
s=>s.every((x,y)=>x==s[y|1])

Try it online!

23 bytes using wastl's regex
s=>/^((.)\2)*$/.test(s)

Try it online!

24 bytes, but outputs an array for true, null for false: Try it online!

27 bytes s=>!s.some((x,y)=>x>s[y|1])

@tsh Unfortunately, that would only work if you replaced > with !=

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!

Suggest using LOOPE instead of JNZ/LOOP to save 2 bytes.

@ErikF, brilliant! Completely forgot about that!

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

what is this monstrosity :)

PHP, 58 56 bytes
function f($s){return!$s?:$s[0]==$s[1]&f(substr($s,2));}

Try it online!
As a recursive function.
PHP, 61 56 52 bytes
while(''<$l=$argn[$i++])$r|=$l!=$argn[$i++];echo!$r;

Try it online!
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!

This appears to output 1 for a non-double speak string, as well as a double speak string.

@AJFaraday try now - is double speak, is not double speak

Haskell, 28 23 bytes
f(x:y:z)|x==y=f z
f[]=1

Try it online!
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)

Try it online!
Removes every doubled character, then checks if the result is empty.

why not just i:gsub("(.)%1","") and check if i==""?

this is 34 bytes, not totally sure it's valid since I've never written Lua before, but it appears to work.

welcome to Code Golf Stack Exchange though!

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!

@Giuseppe Managed to chisel out one extra byte from your solution

Very nice! I only asked since the R solution takes a similar gsub approach; glad to help you golf it down :-)

Nice idea! arg[1] can be replaced with (...) to save one byte.

Perl 5, 15 bytes
$_=/^((.)\2)*$/

Try it online!
Outputs 1 for double-speak, nothing for non-double-speak.

MathGolf, 2 bytes
½=

Try it online!
Basically the same as the 05AB1E answer, ½ splits the string into even and odd characters, then check for equality. Passes for the empty string.

PowerShell, 39 38 bytes
!$($args|?{+$p*($p="$_"[$p-eq$_])};$p)

Try it online!
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

Try it online!
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.

Try it online!
Exits with error if the input is double speak, and with warning if it is not double speak (which is allowed by default).

Husk, 6 4 bytes
-2 bytes thanks to Razetime!
ETC2

Try it online!
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)

-2

@Razetime That doesn't appear to check if the length is even

this should work

Vyxal, 2 bytes
y=

Try it Online!
Look ma, no Unicode!

Julia 1.0, 25 bytes
s->s[1:2:end]==s[2:2:end]

Try it online!

It's shorter to use a symbol instead of f, e.g !a=.... Or to use an anonymous function: s->...

Yes, you're right. I fixed it

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

J, 13 11 10 bytes
-:2#_2{.\]

Try it online!
-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?

-:]#~2 0$~#

-:2#_2{.\] should save another byte

very nice, thanks @miles

PowerShell, 64 59 bytes
filter f($n){$a,$b,$r=$n;$a-eq$b-and$(if($r){f $r}else{1})}

Try it online!
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

de-duplicate Try it online!

@mazzy Thanks! I was missing the $ before the statement block and couldn't figure out why it wasn't working.

Brachylog, 5 bytes
ġ₂z₂=

Try it online!
Succeeds or fails.
ġ₂       The at-most-length-2 chunks of the input,
  z₂     which have equal length, zipped together,
    =    are equal.

Wolfram Language (Mathematica), 27 26 24 bytes
2==GCD@@Length/@Split@#&

Try it online!
        Length/@Split@#&    (*for the lengths of runs of characters*)
2==GCD@@                    (*check that they are all even*)

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 of Characters@)

@AntiEarth What's a string?

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.

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

Try it online!

The < should be a >

And, uh, 10 bytes with -rR flag

6 bytes with -rR flag

For the sake of it, 5 bytes using -ir, -lp and -rR

Curry, 18 bytes
Tested to work in both PAKCS and KiCS2
f(a:a:x)=f x
f[]=1

Try it online!
Test it on smap!
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.

Vyxal, 14 bitsv2, 1.75 bytes
y=

Try it Online!
Basically every other answer
Explained
y=
y   # Uninterleave the input, dumping to stack
 =  # Are the two items equal?

Brain-Flak, 26, 22 bytes
({<({}[{}])>{()<>}{}})

Try it online!
Outputs 1 for false and 0 for true.
Readable version:
({
    <({}[{}])>
    {
        ()
        <>
    }
    {}
})

I originally had this:
{
    ({}[{}])

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

Which is 10 bytes longer.

Does 0/non0 count as a boolean? If so, you can do ({({}[{}]){{}}{}})

lol at the "Readable version" - its so very readable :P

@riley No that's not valid. However, I found a better trick.

@quinn Looks readable to me :P

JavaScript, 26 23 bytes
s=>/^((.)\2)+$/.test(s)

Try it online!
Recursive Solution, 30 bytes
Thanks to Arnauld for a fix at the cost of 0 bytes.
f=([x,y,...s])=>x?x==y&f(s):!y

Try it online!

Fixed recursive version?

Thanks, @Arnauld :)

@Oliver, crap; only saw your original solution before posting mine. I'm happy to roll back to 26 if you got to that 23 before me - let me know.

R, 53 34 bytes
-19 bytes thanks to Giuseppe
function(a)gsub("(.)\\1","",a)==""

Try it online!

I think gsub("(.)\\1","",a)=="" would do the trick as well; many others use the same regex.

@Giuseppe This whole regex thing is pretty new to me. Thanks.

R + pryr gets you a 32-byter trivially modified from this answer.

If input can be taken as a vector, then function(a)!sum(rle(a)$l%%2) for 28

QuadR, 11 bytes
''≡⍵
(.)\1

Try it online!
''≡⍵ the result is an empty string when
(.)\1 a character followed by itself
 is replaced by nothing

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

35 bytes?

@Oliver - this throws an exception on inputs like a, aaa, aaaaa, etc. You might be into something though, I'll keep fiddling.

I was able to knock off a few bytes at least :)

Red, 36 bytes
func[s][parse s[any[copy t skip t]]]

Try it online!
Longer alternative:
Red, 40 bytes
func[s][(extract s 2)= extract next s 2]

Try it online!

Prolog (SWI), 60 45 bytes
thanks to Unrelated String
+[].
+[A,A|T]:- +T.
-X:-string_chars(X,Y),+Y.

Try it online!
Converting it from a string to a list of atoms kind of ruined the score, but well..

45 bytes

...it looks like you can also use atom_chars instead of string_chars, even though you're taking a string as input, and not an atom. But that may be irrelevant if you can take a backtick-delimited string--that is, a list of char codes.

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!

Fixed both of the problems

({}<>)<>({}<>)({}[{}]) can be simplified to ({}[{}]<>).

oh wow, no clue why I decided to pop and swap stacks twice, thanks :)

Zsh, 36 bytes

My Zsh answer to the previous challenge can be found here.

Exits truthy (0) if NOT double speak, and falsy (1) if double speak. (As allowed in a comment.)
for a b (${(s::)1})r+=${a#$b}
[ $r ]

for a b (${(s::)1})r+=${a#$b}
         ${(s::)1}             # split $1 characterwise
for a b (         )            # take pairs of characters from ${(s::)1}, assign to $a and $b
                      ${a   }  # first character
                      ${ #$b}  # remove second character as prefix
                   r+=         # append to $r as string
[ $r ]                         # exit truthy if $r is non-empty

Try it online!

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.

An answer should be a full program or function; this is a snippet that requires s to be defined beforehand.

@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@)

28 bytes by using GCD instead of AllTrue. See also this n-speak solution.

28 bytes by using And instead of AllTrue.

Scala, 44 bytes
_.grouped(2).forall(t=>t.size>1&&t(0)==t(1))

Try it online!

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.

Gaia, 3 bytes
2Zy

Almost as trivial as the solution to the other challenge. Errors with an input size < 2, which was never confirmed to be allowed, so might be invalid.
Try it online!
2Z   Unzip input by 2
  y  All equal?

Unzipping by 2 basically undoes the result of interleaving 2 strings. So if two equal strings are interleaved, then it is doublespeak.

Pip, 5 bytes
$QUWa

The existing solution used a longer iterative comparison. Thankfully, the unweave function exists.
Try it online!

Labyrinth, 13 bytes
,:,
" -@
""}!

Try it online!
That's a whole lot of no-ops, but I can't find any easy way to remove them.
Prints -1 if the input is a double speak, nothing otherwise. Allowed by this I/O method.
How it works
,:,    Push char input (,), duplicate (:), push another char input
-      Subtract the top two.
       It can be nonzero for two reasons: the string has odd length or
       the last two chars differ.
       In either case, take a turn and exit, producing no output (@)
}      Remove the top number from scope and reveal the first char pushed
       (out of the last two). If it is negative (EOF), turn left,
       print it as number (-1), and exit (@).
"""    Otherwise, turn right and go through the no-op path back to
       the start of the program.

Factor, 28 bytes
[ 2 group [ = ] assoc-all? ]

Try it online!

2 group Split a sequence every 2 elements, e.g. { 1 1 2 2 3 3 } -> { { 1 1 } { 2 2 } { 3 3 } }
[ = ] assoc-all? Does every pair in a sequence consist of equal values?

Factor, 26 24 bytes
[ 2 group flip 1 cut = ]

Try it online!
Thanks to @Bubbler!
-2 bytes from me

flip Transpose a matrix. e.g. { { 1 1 } { 2 2 } { 3 3 } } -> { { 1 2 3 } { 1 2 3 } }
1 cut Split the matrix in two between its first and second rows. If there isn't a second row, outputs { }. e.g. { { 1 2 3 } { 1 2 3 } } -> { { 1 2 3 } } { { 1 2 3 } }
= Are they equal?

Alternative 26 bytes.

@Bubbler that's really nice. I tried the flip approach at first but forgot about conditional first2.

@ Bubbler we can save 2 more bytes with 1 cut instead of ?first2.

Desmos, 225 bytes
f\left(i\right)=\left\{\operatorname{total}\left(\left[\left\{i\left[a\cdot2+1\right]=i\left[a\cdot2+2\right]\right\}\operatorname{for}a=\left[0...\frac{\operatorname{length}\left(i\right)}{2}-1\right]\right]\right)>0\right\}

Input is taken as a list of ASCII character codes, I don't know much about Desmos, so I'd love to know if there's a better way!
Try it online!

Damn, that's amazing.

Lexurgy, 22 bytes
Essentially the inverse of my "DDoouubbllee ssppeeaakk!!" answer.
Capture any character twice, and delete it.
If it's double speak, the result is empty string, and a non-empty string otherwise.
a:
{[]$1 $1,$$ $$}=>*

Thunno 2, 2 bytes
zạ

Attempt This Online!
Explanation
zạ  # Implicit input                -> s
z   # Uninterleave the input        -> [s[0::2], s[1::2]]
 ạ  # Check if they are both equal  -> s[0::2] == s[1::2]
    # Implicit output

Nekomata + -e, 2 bytes
ĭ=

Attempt This Online!
ĭ       Deinterleave
 =      Check equality

Since Nekomata doesn't have the concept of booleans or truthiness, the flag -e is required for every decision-problem challenge.

Uiua, 11 bytes
≅⊃'▽¬▽◿2⇡⧻.

Try it!
≅⊃'▽¬▽◿2⇡⧻.
          .  # duplicate
         ⧻   # length
        ⇡    # range
      ◿2     # modulo two
 ⊃'▽¬▽       # get the elements at even and odd indices
≅            # do they match?

fails for "aaa".

@DominicvanEssen Thanks. Fixed for +1.

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 :(

Wouldn't just &/=/'0N 2# work?

Not for odd-length input :(

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.

you can omit  ,'' Try it online!

@mazzy Ha ha, I'm smrt. Thanks

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.

Charcoal, 10 bytes
⬤⪪Ｓ²⁼ι⮌…ι²

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:
  Ｓ         Input string
 ⪪ ²        Split into substrings of length up to 2
⬤           All substrings
        ι   Current substring
       … ²  Extended to length 2
      ⮌     Reversed
    ⁼       Equals
     ι      Current substring
            Implicitly print

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

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

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!

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!

Stax, 6 5 bytes
╩3╦x╨

Run and debug it at staxlang.xyz!
Outputs integers. Zero for double speak and nonzero (one now!) otherwise, as allowed here. Replace 1I below with |e if you want the opposite behavior, but I think this version looks nicer.
Unpacked (6 bytes) and explanation
:G|g1I
:G        Array of run lengths
  |g      GCD
    1I    Is odd? Could use 2% instead

The GCD of run lengths will be even exactly when all run lengths are.

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.

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

@aross: Thanks for pointing it out, yeah that '0' == false is always an issue. Fixed!

dzaima/APL, 14 11 bytes
⊢≡⊢⌿⍨2 0⍴⍨≢

Try it online!
-3 thanks to Adám!

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

Save a handful. Welcome to the site!

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

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!

The second suggestion seems to treat single character strings the same as any other odd length strings?

Wouldn't putting s=i at the end of for braces (for(i=*s;i&(i=*s++)&&i==*s++;s=i) save you one ;?

@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!)

@ErikF my bad, I thought s=i is repeated in every iteration.

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.
}

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.

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.

Wouldn't /.(.?)/ be enough to handle odd length strings?

@manatwork you're right, thanks

Pushy, 13 bytes
LL2%}2/:=};P#

Try it online!

L              \ Push len(input)
 L2%           \ Take (len(input) + 1) % 2. This will be 1 only if the input had even length.
    }          \ Move this to the bottom of the stack for later.
     2/:  ;    \ Length of original input, divided by 2, times do:
        =      \    Pop top two characters, and check equality. (Pushes 0 or 1)
         }     \    Move this to the bottom of the stack for later.
           P   \ Push the stack's product. If the input had odd length, or any two characters
               \ did not match, then the stack will contain a 0, so the product will be 0.
               \ Else, it will be 1.
            #  \ Print the product.

naz, 50 bytes
2a2x1v1x1f1r3x1v2e2x2v1r3x2v1e0m1o0x1x2f0m1a1o0x1f

Works for any input string, provided it's passed as a file terminated with the control character STX (U+0002).
Explanation (with 0x commands removed)
2a2x1v                       # Set variable 1 equal to 2
1x1f1r3x1v2e                 # Function 1
                             # Read a byte and jump to function 2 if it equals variable 1
            2x2v             # Otherwise, store it in variable 2
                1r3x2v1e     # Read another byte
                             # Jump back to the start of function 1 if it equals variable 2
                        0m1o # Otherwise, output 0
1x2f0m1a1o                   # Function 2
                             # Output 1
1f                           # Call function 1

Burlesque, 8 bytes
J2en)J==

Try it online!
                           [AABBCC]         [ABC]
J   #Duplicate             [AABBCC,AABBCC]  [ABC,ABC]
2en #Every other character [AABBCC,ABC]     [ABC,AC]
)J  #Duplicated            [AABBCC,AABBCC]  [ABC,AACC]
==  #Is the same           [1]              [0]

Burlesque, 11 bytes
=[{L[2dv}al

Try it online!
=[   # Group consecutive like values
{
 L[  # Length of (group)
 2dv # Divisible by 2
}al  # All

Marbelous, 84 bytes
No output for false, output one \u0000 for true using this standard I/O rule
@0@1
0000
]]]]&101
eqal\\&1
@0@1..=0\/
:eqal
@0..@1
}0..}1
--..--
<1&0<1&0
{0@0{1@1

interpretor

JavaScript (Node.js), 23 bytes
z=>/^((.)\2)+$/.test(z)

Uses a regular expression that match two of the same characters one or more times
Try it online!

Risky, 5 bytes
0?/20_?:?

Try it online!
Doesn't work with the empty string; OP hasn't clarified if that's a problem.
Explanation
0   transpose
?       input
/     split into groups of
2       2
0 reduce
_
?       accumulator
:     =
?       item

PHP4 (45 chars)
Given $argv[1] as a command line argument :
echo preg_match('#^((.)\2)*$#',$argv[1])?1:0;

The script will output 0 or 1 to answer.
PHP7.4 (41 chars)
The $f arrow function will return the answer :
$f=fn($s)=>preg_match('#^((.)\2)*$#',$s);

C gcc (27 chars)
Function f today return an indication of whether or not the input is double speak :
f(char*s){1[s]-*s||f(s+2);}

Usage :
#include <stdio.h>

int main() {
    printf("EXPECT %5s ... %-5s .. aba\n","NO", f("aba")?"NO":"YES");
    printf("EXPECT %5s ... %-5s .. abba\n","NO", f("abba")?"NO":"YES");
    printf("EXPECT %5s ... %-5s .. aabb\n","YES", f("aabb")?"NO":"YES");
    printf("EXPECT %5s ... %-5s .. aaabb\n","NO", f("aaabb")?"NO":"YES");
    printf("EXPECT %5s ... %-5s .. tthhiiss\n","YES", f("tthhiiss")?"NO":"YES");
    printf("EXPECT %5s ... %-5s .. ttthhhiiisss\n","NO", f("ttthhhiiisss")?"NO":"YES");
}

Try it Online
C Variants :
g(char*s){s=*s&&g(s+2)+s[1]-*s;} // 32 chars
h(char*s){return*s&&h(s+2)+s[1]-*s;} // 36 chars

><> (Fish), 22 bytes
l2%?v>l?v1n;
 ;n0<^?=<

Try it

X86_64/Linux Machine Code, 19-Bytes
Try it online!
Usage:
$> gcc -Wl,-Tbss=0x80000000 -DIDEAL_BSS -s -static -nostartfiles -nodefaultlibs -nostdlib -Wl,--build-id=none double-speak.S -o double-speak
$> echo -n "<input> | ./double-speak; echo $?

Program reads input from stdin (it is sensitive to the exact byte count of input, i.e stray spaces/new lines will change result).
Returns 0 for double-speak, and non-zero otherwise.
Notes:

Size is measured in machine code (i.e 19 bytes of PROGBITS; .text, .data, etc...)
The 19-byte size assumes the above compile command which sets the BSS address at an ideal value. With generic compile commands (no linker inputs), its 21-bytes.

Program:
/* Uncomment below if BSS was setup at 2^20.  */
/* #define IDEAL_BSS */
    .global _start
    .text
_start:
    /* Incoming registers are zero.  */

    decl    %edx
#ifdef IDEAL_BSS
    btsl    %edx, %esi
#else
    movl    $G_mem, %esi
#endif
    /* eax == 0 == SYS_read.  */
    /* edi == 0 == STDIN.  */
    syscall
    xchgl   %eax, %ecx
loop:
    /* Load next pair.  */
    lodsw
    /* Need to decr by 2 each loop.  */
    decl    %ecx
    /* Check that bytes match.  */
    xorb    %ah, %al
    /* Break if ne or end of count.  */
    loope   loop

    /* edi is zero (clears hi bits of eax). eax is zero if double-
       speak. Otherwise non-zero.  */
    xchgl   %eax, %edi
    /* Exit.  */
    movb    $60, %al
    syscall
    .section .bss
G_mem:  .space(4096 * 8)

Example/Test:
$> for x in aba abba aabb aaabb tthhiiss ttthhhiiisss; do echo -n "${x}" | ./double-speak; echo "${x} -> $?"; done
aba -> 3
abba -> 3
aabb -> 0
aaabb -> 3
tthhiiss -> 0
ttthhhiiisss -> 28

TypeScript's Type System, 86 bytes
type F<S>=S extends`${infer C}${infer D}${infer R}`?C extends D?F<R>:0:S extends""?1:0

Try it at the TypeScript playground!
This is a generic type F taking a string-literal type parameter S, and outputting 0 for non-double-speak and 1 for double-speak.
None of the test cases offer a case where all of the pairs are equal but the whole string is of odd length, which tripped me up a bit. This is likely golfable, maybe that last extends clause can be dropped with something clever.
Explanation:
type F<S> =
  // Match S to extract the first two chars C and D and the rest R
  S extends `${infer C}${infer D}${infer R}`
  // if it matched: is C the same type as D?
  ? C extends D
    ? F<R> // if so, recurse with R
    : 0 // otherwise, it's not double-speak; return 0
  // if it didn't match, we check if the string is empty or has one character.
  : S extends "" ? 1 : 0

JavaScript (Node.js), 26 bytes
f=([a,b,...c])=>a==b&&f(c)

Attempt This Online!
Outputs via exit-code. I think this is really nice and clean but that's just my opinion. Unfortunately, this doesn't beat the tried-and-true regex.
Explanation:

f=([a,b,...c])=>...
Makes a function f that destructures its string argument into the first
character a, the second character b, and rest of the string c.

a==b&&f(c)
Check if a is equal to b. The && (AND) operator only evaluates its
right argument if its left is true, so if it is true we recurse with c.
If a and b aren't equal, then it can't be double speak, so we stop
recursion to output with a 0 exit code.
If they're equal, we keep checking the next two until either

A) recursion stops because a isn't equal to b, or
B) a and b are both undefined because we've reached the end of the string and there are no more characters left, so we recurse until the recursion depth is hit, giving an exit code of 1.

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.

Save a byte

@Khuldraesethna'Barya updated, thanks! did not know that was a thing

Ruby -n, 21 14+1 = 15 bytes
p~/^((.)\2)*$/

Try it online!

Lua, 90 87 86 82 bytes
a,e=1,os.exit;(...):gsub('.',load's=...a=a~=1 and(a==s and 1 or e(1))or s')e(a==1)

Try it online!
Take input as argument, use exit code as output.
Explanation
This is based on abusing few Lua features:

os.exit could accept either number, allowing short code for exit or boolean, making last check possible (true meaning success, false meaning failure).
gsub can be also used to iterate over string in callback-style, not only for doing replacement.
load is shorter than function(...) end.
... is often shorter than arg[1].

Whole idea hidden behind those tricks:

For each character: either remember if nothing is already it or perform check: if current is different from remembered, fail. Otherwise, reset remembered value and continue.
When done, make sure that there's nothing pending in the buffer (e(a==1)). This is required to fail on strings with odd length.

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!

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?

s==++s, how is this not UB when *s points to the end of the string?

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

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'

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.

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.

Although I don't know exactly how that works(if someone could explain thanks) and I tried it with putchar too changing printf to putchar also gives the *++s some character value.

@Loki I see no printf in your code.  In the TIO you get the first char of whatever the compiler puts after the string you are looking at, so you are in UB.

https://tio.run/##XY7NDoIwEITvPMW2BtIfMZ6t9exDcMECoQlW05Z4IDx7LVoMMdm9fDOZGVV6pcJOGzWMTQtn5xv9OPSX0BHV1xaYo9Or10NLmJOSce6o41w8rTa@IzhvIFeVwXvm4lERKViJWFm6onBIYry1fo30H318P7rRo0iFbf1oDVgxhyX9XmtDaDYBQBYf0kqJEcJiQ24SV0dj6gTXyKuGE6TepYsKWJNS0VFkc3gD

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!

Save 3 bytes by {it.chunked(2).all{it.length>1&&it[0]==it[1]}} ;)

T-SQL 2012, 76 bytes
Looping using the following logic.

Finding the first match on the first character in the rest of the string.
If the match is on the second position, the first 2 characters are removed.
if the match is on a later position, character 0 to 1 is removed, resulting in null string.
If there are no matches, characters 3-4 are removed. Repeating this will eventually result in a null string.

The final string will be an empty string or a null string.
Empty string is "double speak"(1).
Null string is not "double speak"(0).
DECLARE @ varchar(max)='ccbbddeeff'

WHILE @>''SET
@=stuff(@,-3/~charindex(left(@,1),@,2),2,'')PRINT
iif(@=0,1,0)

Try it online

C++ (gcc), 156 145 bytes
#include <iostream>
int f(){
    char a[2]; while(std::cin.get(a, 3)) if(a[0] != a[1]) return 0; return 1;
}
int main()
{
    std::cout << f();
}

Try it online!

Welcome to the site! C++ is pretty lenient about whitespace so you can save bytes by removing a bunch of it.

@SriotchilismO'Zaic Thank you!

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

Try it online!

C++ (gcc), 48 47 45 43 bytes
-2 bytes thanks to @ceilingcat
-2 bytes thanks to @JoKing
recursive function assuming zero terminated char table

int f(char*s){return!*s||*s==s[1]&&f(s+2);}

Try it online!

@ceilingcat cool, I didn't now you can be that concise

@JoKing it works, there's just a warning because I'm using string literals to generate right kind of input - zero-terminated char* - which is not exactly legal in c++ but gcc allows it

Ah sorry, I thought the lack of output meant it wasn't working. 43 bytes

EDIT:
This solution is totally broken as demonstrated by the aabbbb test case. Thanks to @manatwork for pointing this out. Do not pass Go! Do not collect 200 dollars!
Bash and Gnu utils, 46 45 bytes
fold -1|uniq -c|grep -qv "2 "&&echo 0||echo 1

Try it online!
-1 byte by skipping the first space in grep expression

Not sure if I can use grep exit codes and return output there?
Instead of this &&echo 0||echo1

This works fine on the question's test cases, but as I understand the challenge, it should output 1 on Khuldraeseth na'Barya's suggested test case, “aabbbb”.

@manatwork You're right. This solution is buggy in that sense.

JavaScript (Node.js), 26 bytes
s=>!s.replace(/(.)\1/g,'')

Try it online!

Rust, 61 58 39 bytes
|s:&[u8]|s.chunks(2).all(|n|n[0]==n[1])

Try it online!
This is a closure that takes the input as a byte slice (b prefix on a string), e.g.
println!("{}", f(b"aabb"));

Does not work for b"aab", unless the panic is intended.

Swift, 109 bytes
func a(b:String){let c=Array(b),l=c.count;var d=0,i=0;while i<l-1{if c[i]==c[i+1]{d+=1};i+=2;};print(d*2==l)}

Try it online!

C#, 190 bytes
public class P{public static void Main(string[]a){bool d=true;if(a[0].Length%(double)2>0)d=false;else for(int i=0;i<a[0].Length;i+=2){d=a[0][i]==a[0][i+1]?d:false;}System.Console.Write(d);}}

Try Online

Oracle SQL, 47 bytes
select*from t where regexp_like(x,'^((.)\2)+$')

It works with an assumption that input data is stored in a table t(x), e.g.
with t(x) as (select 'hheelllloo' from dual)

Returns either original string or no rows.

Clojure, 48 bytes
(fn[x](every? #(apply = %)(partition 2 2[\0]x)))

Try it online!

GolfScript, 7 bytes
2/zip~=

Try it online!
Explanation
2/      # Split input into parts of 2,            e.g. tt,ee,ss,tt
  zip   # Read the list horizontally,         yielding test, test
     ~  # Put the two strings onto the stack, yielding test,test
      = # Check whether they are equal,       yielding 1

# False case:
#  tteesst
#->tt,ee,ss,t
#->test,tes
#->0
```

Perl 5 + -pF/^((.)\2)+$/, 7 bytes
Outputs 0 for falsy and 2 for truthy.
$_=@F^1

Try it online!

Rockstar, 108 97 88 69 bytes
listen to S
cut S
D's 1
while D and S
let D be roll S's roll S

say D

Try it here (Code will need to be pasted in)
listen to S       :Read input string into variable S
cut S             :Split into an array
D's 1             :Initialise D as 1
while D and S     :While D is truthy and S is not empty
let D be          :  Reassign to D
  roll S          :    Pop the first element from S
  's              :    Check equality with
  roll S          :    Pop the first element from S
                  :End while loop
say D             :Output D

I quite like the output of 'mysterious' if it's false.

Odd, @AJFaraday, could've sworn I has it outputting 0 for falsey. Must've changed something before posting without realising. Anyway, long's you're OK with that, I'll leave it as-is. Could save some more by looping forever with no output if the result is truthy but that would probably be pushing things!

SM83, 7 bytes
Input in hl. Output is in z flag. All other flags are off.
2A B7 C8 BE 23 28 F9 C9

isdbl:
 ld a,(hl+)                 // 2A       load first byte and inc
 or a                       // B7       test if zero
 ret z                      // C8       return if at end (with z on)
 xor (hl)                   // BE       test sameness
 inc hl                     // 23       inc again (does not change flags)
 jr z,isdbl                 // 28 F9    loop if same
 ret                        // C9       else return

C++, 69 bytes
a solution which would put myself between this and this.
EDIT: you, people, are soooo clever. I love yall
[](string a){int c=0,d=1,k;for(int i:a)k=c++%2?d*=k==i,k:i;return d;}

@ceilingcat if you mean the one in the ranged for statement, I believe I cannot as the following if-else statement is not reducible to a single semicolon.

@ceilingcat thank you, that works!

78 bytes by using a single return.

Pyth, 7 bytes
q{Q.-Q{

Try it online!


text:
Write The Shortest Program to Calculate Height of a Binary Tree
The height of a binary tree is the distance from the root node to the node child that is farthest from the root.
Below is an example:
           2 <-- root: Height 1
          / \
         7   5 <-- Height 2
        / \   \
       2   6   9 <-- Height 3
          / \  /
         5  11 4 <-- Height 4

Height of binary tree: 4
Definition of a Binary Tree
A tree is an object that contains a signed integer value and either two other trees or pointers to them.
The structure of the binary tree struct looks something like the following:
typedef struct tree
{
  struct tree * l;

  struct tree * r;

  int v;

} tree;

The challenge:
Input
The root of a binary tree
Output
The number that represents the height of a binary tree
Assuming you are given the root of a binary tree as input, write the shortest program that calculates the height of a binary tree and returns the height. The program with least amount of bytes (accounting whitespaces) wins.

What do languages without pointers take?

Good question, they take a reference to the instance of the tree object. I think  I might want to provide the implementation of a tree object in that case.

...but then my tree object could just have a property, say h. Might be better to define a specific structure made just of lists for the purpose of this challenge.

@T.Salim In the future, please consider posting in the sandbox first.

Sure wizzwizz4. Will do.

So, is a valid representation a list of length 3 [root_value, left_node, right_node] where each of left_node and right_node are also binary trees acceptable? It'll be trivial in many languages, but might be fun in some others.

As long as it works as a valid binary tree structure, sure.

Can you edit the question to include what constitutes a valid binary structure? Perhaps a definition like a tree is an object that contains a value and either two other trees or pointers to them. A definition that is inclusive of languages without objects would also be nice too.

Yes, I have added a Definition of Binary Tree section.

Can we exclude the value part of the tree, since it has no bearing on the challenge itself?

If not, what values can the value be? The struct has only integers, but can they also be strings or trees themselves?

I specified that each node must store a signed integer value.

Can you please add some more test cases?

Jelly, 3 bytes
ŒḊ’

A monadic Link accepting a list representing the tree: [root_value, left_tree, right_tree], where each of left_tree and right_tree are similar structures (empty if need be), which yields the height.
Try it online!
How?
Pretty trivial in Jelly:
ŒḊ’ - Link: list, as described above
ŒḊ  - depth
  ’ - decremented (since leaves are `[value, [], []]`)

Jonathon Allen, that is an interesting language you are using. As a newcomer, may you provide a link or a website referral that tutors people how to use Jelly?

Click the link in the header - it's a golfing Language developed by Dennis, one of the site's moderators.

I wonder how controversial it would be to represent a leaf as x instead of [x, [], []]...

@EriktheOutgolfer To keep with the "pointer" and "struct" nature of the question I think every node should be of the same form.

Python 2,  35  33 bytes
Thanks to Arnauld for noicing an oversight and saving 4.
f=lambda a:a>[]and-~max(map(f,a))

A recursive function accepting a list representing the tree: [root_value, left_tree, right_tree], where each of left_tree and right_tree are similar structures (empty if need be), which returns the height.
Try it online!
Note that [] will return False, but in Python False==0.

The same person is allowed to give two different answers to the same question?

Yeah, of course, golf is a competition at a language level. Even a second entry in the same language is sometimes acceptable, if the approach is very different.

@Arnauld Guess so (I'd assumed non-integers might be present for some reason)

05AB1E, 11 7 5 bytes
Δ€`}N

-4 bytes thanks to @ExpiredData.
-2 bytes thanks to @Grimy.
Input format is similar as the Jelly answer: a list representing the tree: [root_value, left_tree, right_tree], where each of left_tree and right_tree are similar structures (optionally empty). I.e. [2,[7,[2,[],[]],[6,[5,[],[]],[11,[],[]]]],[5,[],[9,[4,[],[]],[]]]] represents the tree from the challenge description.
Try it online or verify a few more test cases.
Explanation:
Δ     # Loop until the (implicit) input-list no longer changes:
  €`  #  Flatten the list one level
}N    # After the loop: push the 0-based index of the loop we just finished
      # (which is output implicitly as result)

Note that although 05AB1E is 0-based, the changes-loop Δ causes the output index to be correct, because it needs an additional iteration to check it no longer changes.

7 bytes?

@ExpiredData Ah, of course.. Thanks! :)

5 bytes

@Grimy I thought using the index outside a loop only worked in the legacy code.. :S Thanks!

Haskell, 33 bytes
h L=0
h(N l r _)=1+max(h l)(h r)

Using the custom tree type data T = L | N T T Int, which is the Haskell equivalent of the C struct given in the challenge.
Try it online!

Perl 6, 25 bytes
{($_,{.[*;*]}...*eqv*)-2}

Input is a 3-element list (l, r, v). The empty tree is the empty list.
Try it online!
Explanation
{                       }  # Anonymous block
    ,        ...  # Sequence constructor
  $_  # Start with input
     {.[*;*]}  # Compute next element by flattening one level
               # Sadly *[*;*] doesn't work for some reason
                *eqv*  # Until elements doesn't change
 (                   )-2  # Size of sequence minus 2

Old solution, 30 bytes
{+$_&&1+max map &?BLOCK,.[^2]}

Try it online!

The &?BLOCK trick is interesting but it's a couple of bytes shorter to assign the block to $!

@JoKing I don't know. Storing the challenge solution in a volatile global like $! or $/ feels like cheating to me.

(Ab)using variables like $! and $/ is fairly standard practice for golfing P6.

JavaScript (ES6),  35  33 bytes
Input structure: [[left_node], [right_node], value]
f=([a,b])=>a?1+f(f(a)>f(b)?a:b):0

Try it online!
Commented
f =                       // f is a recursive function taking
([a, b]) =>               // a node of the tree split into
                          // a[] = left child, b[] = right child (the value is ignored)
  a ?                     // if a[] is defined:
    1 +                   //   increment the final result for this branch
    f(                    //   and add:
      f(a) > f(b) ? a : b //     f(a) if f(a) > f(b) or f(b) otherwise
    )                     //
  :                       // else:
    0                     //   stop recursion and return 0

Looks like you can save a byte with a&&-~.

@Shaggy That would lead to comparisons with undefined.

C, 43 bytes
h(T*r){r=r?1+(int)fmax(h(r->l),h(r->r)):0;}

Structure of binary tree is the following:
typedef struct tree
{
  struct tree * l;

  struct tree * r;

  int v;

} tree;

55 bytes Try it online! Some C-specific golfing tricks are here!

@ErikF Or 45 bytes

Thanks ErikF and Arnauld. I should try out the ternary operator more often instead of if-else-if chains.

43 bytes

If your submission relies on flags, can you please add them to the header of your submission?

Building on @nwellnhof 42 bytes

JavaScript (Node.js), 32 bytes
f=a=>/,,/.test(a)&&f(a.flat())+1

Try it online!
Using the name flat instead of flatten or smoosh is a great idea for code golf.
Using [] for null node in the tree, and [left, right, value] for nodes. value here is an integer.

Wolfram Language (Mathematica), 10 bytes
Depth@#-2&

Try it online! Takes input as a nested list {v, l, r}.

If 2[7[2,6[5,11]],5[9[4,],]] is a valid representation of the tree, Depth works

Haskell, 28 bytes
Using the following data definition:
data T a = (:&) a [T a]

The height is:
h(_:&x)=foldr(max.succ.h)0 x

Scheme, 72 Bytes
(define(f h)(if(null? h)0(+ 1(max(f(car(cdr h)))(f(car(cdr(cdr h))))))))

More Readable Version:
(define (f h)
   (if (null? h)
      0
      (+ 1
         (max
             (f (car (cdr h)))
             (f (car (cdr (cdr h))))
         )
      )
   )
)

Using lists of the form (data, left, right) to represent a tree.  E.g.
   1
  / \
  2  3
 /\
 4 5

is represented as: (1 (2 (4 () ()) (5 () ())) (3 () ())

(1
   (2
      (4 () ())
```   (5 () ())
   (3 () ())
)

Try it Online!

R, 51 bytes
function(L){while(is.list(L<-unlist(L,F)))T=T+1;+T}

Try it online!

Input: a nested list in the format : list(ROOT_ELEMENT, LEFT_TREE, RIGHT_TREE)
Algorithm: Iteratively flattens the tree by one level until it becomes a flat vector : the iterations count corresponds to the max depth.

Inspired by @KevinCruijssen solution

Recursive alternative :
R, 64 bytes
`~`=function(L,d=0)'if'(is.list(L),max(L[[2]]~d+1,L[[3]]~d+1),d)

Try it online!
Redefines the function/operator '~' making it able to compute the max depth of a tree stored in a list structure.
The list structure of a tree is in the format : list(ROOT_ELEMENT, LEFT_TREE, RIGHT_TREE)

-2 thanks to @Giuseppe

why do you use d=1 and then d-1 at the end? Couldn't you start at 0?

Also I switched > to ~ here so the test cases are easier to input

@Giuseppe: of course...I was missing the obvious ♂

Japt, 8 bytes
@eU=c1}a

Try it
Original, 9 bytes
Î©¡ÒßXÃrw

Try it

Kotlin, 45 bytes
val Tree.h:Int get()=1+maxOf(l?.h?:0,r?.h?:0)

Assuming the following class is defined
class Tree(var v: Int, var l: Tree? = null, var r: Tree? = null)

Try it online

K (ngn/k), 4 bytes
Solution:
#,/\

Try it online!
Explanation:
I think I may have missed the point.
Representing a tree as the 3-item list (parent-node;left-child;right-child), the example can be represented as
(2;
  (7;
    (,2);
    (6;
      (,5);
      (,11)
    )
  );
  (5;
    ();
    (9;
      (,4);
      ()
    )
  )
)

or: (2;(7;(,2);(6;(,5);(,11)));(5;();(9;(,4);()))).
So the solution is to iteratively flatten, and count the iterations:
#,/\ / the solution
   \ / iterate
 ,/  / flatten
#    / count

Charcoal, 29 bytes
⊞θ⁰⊞υθＦυ«≔⊕⊟ιθＦΦι∧κλ⊞υ⊞Ｏκθ»Ｉθ

Try it online! Link is to verbose version of code. Temporarily modifies the tree during processing. Explanation:
⊞θ⁰

Push zero to the root node.
⊞υθ

Push the root node to the list of all nodes.
Ｆυ«

Perform a breadth-first search of the tree.
≔⊕⊟ιθ

Get the depth of this node.
ＦΦι∧κλ

Loop over any child nodes.
⊞υ⊞Ｏκθ

Tell the child node its parent's depth and push it to the list of all nodes.
»Ｉθ

Once all the nodes have been traversed print the depth of the last node. Since the traversal was breadth-first, this will be the height of the tree.

Stax, 5 bytes
▐▌µ╡⌂

Run and debug it
Stax has neither pointers nor null values, so I represent the input like [2,[7,[2,[],[]],[6,[5,[],[]],[11,[],[]]]],[5,[],[9,[4,[],[]],[]]]].  Maybe that's an unfair advantage, but it was the closest I could get.
Unpacked, ungolfed, and commented, the code looks like this.
        The input starts on top of the input stack
Z       Tuck a zero underneath the top value in the stack.  Both values end up on the main stack.
D       Drop the first element from array
F       For each remaining element (the leaves) run the rest of the program
  G^    Recursively call the entire program, then increment
  T     Get maximum of the two numbers now ow the stack

Run this one

Julia, 27 bytes
f(t)=t≢()&&maximum(f,t.c)+1

With the following struct representing the binary tree:
struct Tree
    c::NTuple{2,Union{Tree,Tuple{}}}
    v::Int
end

c is a tuple representing the left and right nodes and the empty tuple () is used to signal the absence of a node.

Kotlin, 42 bytes
fun N.c():Int=maxOf(l?.c()?:0,r?.c()?:0)+1

Try it online!
Where
data class N(val l: N? = null, val r: N? = null, val v: Int = 0)

Jq, 18 bytes
Takes input as [Value, Left, Right] or any permutation of this.
[paths|length]|max

 paths             # for each path as a list of indexes to follow
                   # to get to an element or array inside the input
                   # e.g. [0,2,1] to represent array[0][2][1]
      |length      # its length
[            ]     # collect into an array
              |max # the maximum of this array

jq play it!

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Repeated! Factorials!
Not to be confused with Find the factorial!
Introduction
The factorial of an integer n can be calculated by
$$n!=n\times(n-1)\times(n-2)\times(...)\times2\times1$$
This is relatively easy and nothing new. However, factorials can be extended to double factorials, such that
$$n!!=n\times(n-2)\times(n-4)\times(...)\times4\times2$$
for even numbers, and
$$n!!=n\times(n-2)\times(n-4)\times(...)\times3\times1$$
for odd numbers. But we're not limited to double factorials. For example
$$n!!!=n\times(n-3)\times(n-6)\times(...)\times6\times3$$
or
$$n!!!=n\times(n-3)\times(n-6)\times(...)\times5\times2$$
or
$$n!!!=n\times(n-3)\times(n-6)\times(...)\times4\times1$$
depending on the starting value.
In summary:
$${\displaystyle n!^{(k)}={\begin{cases}1&{\text{if }}n=0 \\n&{\text{if }}0<n\leq k\\n\cdot\left({(n-k)!}^{(k)}\right)&{\text{if }}n>k\end{cases}}}$$
where
$${\displaystyle n!^{(k)}=n\underbrace{!\dots!}_{k}}$$
Or, in plain English: Subtract the factorial count from the base number repeatedly and multiply all resulting positive integers.
The Challenge
Write a function that will calculate any kind of repeated factorial for any non-negative integer.
Input
Either

A string containing a non-negative base-ten integer, followed by 1 or more exclamation marks. E.g. "6!" or "9!!" or "40!!!!!!!!!!!!!!!!!!!!".

or

The same values represented by two integers: one non-negative base value and one positive value representing the factorial count. This can be done according to any format from the default I/O rules.

Output
The result of said calculation.
Challenge remarks

0! equals 1 by definition. Your code must account for this.
The factorial count is limited by $$ 0 < factorial~count \leq base~value $$outside this range, you are free to output whatever. Aside from 0!, which is the only exception to this rule.

Examples
Input                              Output

3!!!                               3
0!                                 1
6!                                 720
9!!                                945
10!!!!!!!!                         20
40!!!!!!!!!!!!!!!!!!!!             800
420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  41697106428257280000000000000000

Try it with an ungolfed Python implementation: Try it online!
General remarks

This is code-golf, so the answer using the fewest bytes in each language wins.
Standard rules, I/O rules and loophole rules apply.
Please include a Try it Online-link to demonstrate your code working.
Please motivate your answer with an explanation of your code.

The examples list 0! but the challenge remarks say that the factorial count will be less than or equal to the base value.

Wouldn't 3!!! be zero? n*(n-3) = 3*(3-3) = 0.

@ouflak If it works like 1!, not really. It's more like 1! = 1. 2!! = 2. 3!!! = 3. There's no calculation, because you are at the end of the recursiveness. No 0 in products or else every single factorial would drop down to 0 in the end.

3!!!!!!! should not be undefined—it should just yield the answer 3. It's the same as 1!!=1 (not undefined). Also your input specification says that there will always be at least one !, so the first example 3 doesn't fit the specification.

Thanks all! I reviewed the comments and have edited the post accordingly. It is indeed so that a factorial count higher than the base number should return the base number. It seems a bit unfair to change it now, but I think most answers comply with it anyway.

Tile should actually be "Repeated factorials!!!!".

I'm surprised that nobody found a language yet where the solution is 0 or 1 Bytes. There are many that automatically print the output and surely there must be one that automatically parses the input as calculation or has one command to parse a string input as calculation and also supports repeated factorials.

@FabianRöling: But that's not what this is.  It's not (3!)! instead it's removing terms from a factorial.  It's a misleading name; I came in assuming it was going to be applying the Factorial function repeatedly in a chain and had to read carefully to see what it actually was.  Fortunately the question does explain it clearly.  A better name might be stride factorial or step factorial or something.

R, 33 bytes
function(n,k)prod(seq(n+!n,1,-k))

Try it online!
Handles \$n=0\$ by adding the logical negation of \$n\$.

ArnoldC, 702 698 634 bytes
LISTEN TO ME VERY CAREFULLY f
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE n
I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE p
GIVE THESE PEOPLE AIR
HEY CHRISTMAS TREE r
YOU SET US UP 1
HEY CHRISTMAS TREE c
YOU SET US UP 0
STICK AROUND n
GET TO THE CHOPPER r
HERE IS MY INVITATION r
YOU'RE FIRED n
ENOUGH TALK
GET TO THE CHOPPER n
HERE IS MY INVITATION n
GET DOWN p
ENOUGH TALK
GET TO THE CHOPPER c
HERE IS MY INVITATION 0
LET OFF SOME STEAM BENNET n
ENOUGH TALK
BECAUSE I'M GOING TO SAY PLEASE c
GET TO THE CHOPPER n
HERE IS MY INVITATION 0
ENOUGH TALK
YOU HAVE NO RESPECT FOR LOGIC
CHILL
I'LL BE BACK r
HASTA LA VISTA, BABY

Try it online!
Translated to pseudocode:
f(n,p) {
  r=1;
  c=0;
  while (n) {
    r=r*n;
    n=n-p;
    c=n<0;
    if (c) n=0;
  }
  return r;
}

Note: ArnoldC has only one type of data: 16-bit signed integer. Hence I cannot test the 420!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! case.

Just curious about your psuedocode. What is the variable 'c' for?

@ouflak I edited my answer a couple of times and forgot it. The c variable actually stores the value of the comparison between n and 0.

+1 and I borrowed it (minus the 'c') for my LUA answer.

Jelly, 4 bytes
RṚmP

Try it online!
How? Given \$n\$ and \$k\$, it first generates the range \$n,\cdots, 1\$ (with RṚ), then with m it keeps every \$k^{\text{th}}\$ element of this range (so \$n, n-k, n-2k,\cdots,n-\lfloor n/k\rfloor k\$), and finally multiplies them using P.

Works well, and so simple in the end. I don't know Jelly at all but at least it looks good :)

@V.Courtois Given $n$ and $k$, it first generates the range $n,\cdots, 1$ (with RṚ), then with m it keeps every $k^{\text{th}}$ element of this range (so $n, n-k, n-2k,\cdots,n-\lfloor n/k\rfloor k$), and finally multiplies them using P. Just the straightforward approach. Edit: I added this explanation in the answer.

Hah thank you very much. One day I might want to golf in this language so I'll have to learn those monads, dyads etc.

Alternative that looks like CJam: r1mP.

Isn't the Ṛ itself 3 bytes (\xe1\xb9\x9a), making this 6 bytes total?  (Or, I'm new to code golf, and "byte" here means one unicode character...).

@KyeWShi  Jelly has its own codepage, so each of the 256 characters it contains is encoded as 1 byte.

@Mr.Xcoder Oh, I see!  Thanks.

RUmP is a more direct ASCII-only version as well.

Haskell, 21 bytes
n%a=product[n,n-a..1]

Try it online!
Combining the built-in product function with stepped range enumeration beats what I could code up recursively (even with flawr saving a byte).
22 bytes
n%a|n<1=1|m<-n-a=n*m%a

Try it online!
Here's a solution taking input in string format like 9!!, which I think is more interesting.
42 bytes
(\[(n,a)]->product[n,n-length a..1]).reads

Try it online!

I think you could shorten the recursive solution to n%a|n<1=1|m<-n-a=n*m%a

APL (Dyalog Extended), 7 bytesSBCS
Anonymous tacit prefix function. Takes [n,b] as argument.
×/-\…1¨

Try it online!
1¨ one for each element of the argument; [1,1]
-\ cumulative difference; [n,n-b]
… range using second element of left argument as indicator of step, e.g. [9,7] continues with 5
×/ product

Pyth, 6 bytes
These are all equivalent 6-byters:
*F:Q1E
*F:E1Q
*F%E_S

Try it online! (*F:Q1E)
Or, 11 bytes, taking input as a string:
*F:.vQ1/Q\!

Test suite.

JavaScript (ES6), 21 bytes
Takes input as (k)(n).
k=>g=n=>n<1||n*g(n-k)

Try it online!
Or 24 bytes to support BigInts.

JavaScript (ES6), 55 bytes
Takes input as a string, using the format described in the challenge.
s=>(a=s.split`!`,k=a.length-1,g=n=>n<1||n*g(n-k))(a[0])

Try it online!

05AB1E, 10 8 7 bytes
Ý¦RIιнP

Input as two separated inputs: first input being base; second input being factorial.
Try it online or verify all test cases.
-2 bytes thanks to @Mr.Xcoder.
-1 byte thanks to @JonathanAllan.
Explanation:
Ý        # Create a list in the range [0, (implicit) base-input]
 ¦       # And remove the first item to make it the range [1, base]
         # (NOTE: this is for the edge case 0. For the other test cases simply `L` instead
         #  of `Ý¦` is enough.)
  R      # Reverse this list so the range is [base, 1]
   Iι    # Uninterleave with the second input as step-size
         #  i.e. base=3, factorial=7: [[3],[2],[1],[],[],[],[]]
         #  i.e. base=10, factorial=8: [[10,2],[9,1],[8],[7],[6],[5],[4],[3]]
         #  i.e. base=420, factorial=30: [[420,390,360,...,90,60,30],[419,389,359,...],...]
     н   # Only leave the first inner list
      P  # And take the product of its values
         # (which is output implicitly as result)

Original 10 bytes answer:
L0KD¤-IÖÏP

Input as two separated inputs: first input being base; second input being factorial.
Try it online or verify all test cases.
Explanation:
L           # Create a list in the range [1, (implicit) base-input]
 0K         # Remove all 0s (edge case for input 0, which will become the list [1,0])
   D        # Duplicate this list
    ¤       # Get the last value (without popping)
            # (could also be `Z` or `¹` for max_without_popping / first input respectively)
     -      # Subtract it from each item in the list
      IÖ    # Check for each if they're divisible by the second factorial-input
        Ï   # In the list we copied, only leave the values at the truthy indices
         P  # And take the product of those
            # (which is output implicitly as result)

This 6-byter: LR²ιнP (Try it online!) works for every test case, except for 0.

But I guess that 0 case can be fixed in at most 2 bytes. If you figure out a way to fix it, you may take it :) EDIT: Perhaps LR²ιн0KP for 8 bytes?

@Mr.Xcoder Nice answer! Never even used uninterleave with a given step. :)

0K should be unnecessary as 0! is an invalid input by the specification (even though it's been included in the examples) - I have commented about this.

...and if 0! is in the input domain Ý¦RXιнP saves a byte.

@JonathanAllan Nice way to save a byte. And now that you've mentioned it, it's indeed a bit confusing that the 0 is included when it's outside the specified range. (I know the range has been added later than the 0 edge case in the Sandbox, though.)

I was looking at the documentation, doesn't 05AB1E have a maximum of two elements command? I.e. pop(a, b), push(max(a, b)).

@maxb Nope. it does have popAndGetMaxOfList (à), maxOfListWithoutPopping (Z), and maxOfStack (M). So if you cannot use M because it also has other elements on the stack, you could use ‚à (pair + popAndPushMax) instead.

I tried getting it to 6 bytes, but I needed a swap to get the uninterleave working correctly. I ended up with MLRsιнP, which needs the input to be in the header.

Whitespace, 91 bytes
[S S S T    N
Push_1][S N
S _Duplicate_1][S N
S _Duplicate_1][T   N
T   T   _Read_STDIN_as_integer_(base)][T    T   T   _Retrieve_base][S S S N
_Push_0][T  N
T   T   _Read_STDIN_as_integer_(factorial)][N
S S N
_Create_Label_LOOP][S N
S _Duplicate_base][S S S T  N
_Push_1][T  S S T   _Subtract][N
T   T   S N
_If_negative_jump_to_Label_PRINT_RESULT][S N
S _Duplicate_base][S T  S S T   S N
_Copy_0-based_2nd_(result)][T   S S N
_Multiply][S N
T   _Swap_top_two][S S S N
_Push_0][T  T   T   _Retrieve_factorial][T  S S T   _Subtract][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_PRINT_RESULT][S N
N
_Discard_top][T N
S T _Print_result_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.
Try it online (with raw spaces, tabs and new-lines only).
Explanation in pseudo-code:
Integer result = 1
Integer base = STDIN as integer
Integer factorial = STDIN as integer
Start LOOP:
  If(base <= 0):
    Call function PRINT_RESULT
  result = result * base
  base = base - factorial
  Go to next iteration of LOOP

function PRINT_RESULT:
  Print result as integer to STDOUT

Python 2, 29 bytes
f=lambda n,b:n<1or n*f(n-b,b)

Try it online!

Perl 6, 22 bytes
{[*] $^a,*-$^b...^1>*}

Try it online!
Anonymous codeblock that returns the product of the range starting from the first input, decreasing by the second until it is below 1, excluding the last number. This works for 0, since the base case of a the reduce by product is 1, so the output is 1.

x86-64 machine code, 12 bytes
Same machine code does the same thing in 32-bit mode, and for 16-bit integers in 16-bit mode.
This is a function, callable with args n=RCX, k=ESI.  32-bit return value in EAX.
Callable from C with the x86-64 System V calling convention with dummy args to get the real args into the right registers. uint32_t factk(int, uint32_t k, int, uint64_t n);  I couldn't just use Windows x64 because 1-operand mul clobbers RDX, and we don't want REX prefixes to access R8/R9.  n must not have any garbage in the high 32 bits so JRCXZ works, but other than that it's all 32-bit.
NASM listing (relative address, machine code, source)
 1                         factk:
 2 00000000 6A01             push 1
 3 00000002 58               pop rax             ; retval = 1
 4 00000003 E306             jrcxz  .n_zero      ; if (n==0) return
 5                         .loop:                ; do {
 6 00000005 F7E1              mul   ecx            ; retval *= n  (clobbering RDX)
 7 00000007 29F1              sub   ecx, esi       ; n -= k
 8 00000009 77FA              ja   .loop         ; }while(sub didn't wrap or give zero)
 9                         .n_zero:
10 0000000B C3               ret

0xc = 12 bytes

Or 10 bytes if we didn't need to handle the n=0 special case, leaving out the jrcxz.
For standard factorial you'd use loop instead of sub/ja to save 2 bytes, but otherwise the exact same code.

Test caller that passes argc as k, with n hard-coded.
align 16
global _start
_start:
  mov  esi, [rsp]
;main:
  mov  ecx, 9
  call factk

  mov  esi, eax
  mov  edx, eax
  lea  rdi, [rel print_format]
  xor  eax, eax
extern printf
  call printf
extern exit
  call exit

section .rodata
print_format: db `%#x\t%u\n`

```

APL (Dyalog Unicode), 11 bytesSBCS
Anonymous tacit infix function. Takes n as right argument and b as left argument.
×/1⌈⊢,⊢-×∘⍳

Try it online!
×∘⍳ multiply b by the ɩntegers 1 through n
⊢- subtract that from n
⊢, prepend n
1⌈ max of one and each of those
×/ product

Java 10, 44 bytes
f->b->{int r=1;for(;b>0;b-=f)r*=b;return r;}

Takes the factorial as first input, base as second.
Try it online.
This above doesn't work for the largest test case due to the limited integer range (32-bits). To fix this we can use BigIntegers, which coincidentally is exactly double the size - 88 79 bytes:
f->b->{var r=f.ONE;for(;b.signum()>0;b=b.subtract(f))r=r.multiply(b);return r;}

-9 bytes thanks to @OlivierGrégoire.
Try it online.
Explanation:
f->b->{       // Method with two integer parameters and integer return-type
  int r=1;    //  Result-integer, starting at 1
  for(;b>0;   //  Loop as long as the base is still larger than 0
      b-=f)   //    After every iteration: decrease the base by the factorial
    r*=b;     //   Multiply the result by the base
  return r;}  //  Return the result

I'm sorry I broke your coincidental exact size doubling... :(

@OlivierGrégoire Np, and thanks! :)

Ruby, 25 bytes
f=->s,r{s<1?1:s*f[s-r,r]}

Try it online!

Wolfram Language (Mathematica), 22 21 bytes
1##&@@Range[#,1,-#2]&

Try it online!
-1 thanks to attinat: Times --> 1##&
Explanation: use Range to make a list of the values {n, n-k, n-2k, n-3k, ...}, stopping before going below 1 (i.e., stopping just right). Then multiply all numbers in this list with Times (or 1##&).

-1 byte with 1##& instead of Times

Vyxal, 4 bytes
ɾṘḞΠ

Try it Online!

Knight, 34 33 bytes
;=p=xE P;=yP;W<0=x-x y=p*x pO+p!p

Try it online!
-1 byte thanks to Aiden Chow

33 bytes: ;=pT;=xP;=yP;W<0x;=p*x p=x-Ex yOp.

@AidenChow I tried that initially. That doesn't work for 0! as it will output true instead.

Oops didn't test it lol. What about this? ;=p=xE P;=yP;W<0=x-x y=p*x pO+p!p

Japt, 8 bytes
TõUV f ×

Try it
-1 thanks to EoI pointing out how dumb uncaffeinated Shaggy can be!

kT can be replaced with f for 1 byte

@EmbodimentofIgnorance, of course it can! I knew it was too early for golf! :\

C (gcc), 41 bytes
r;f(n,k){for(r=1;n>0;n-=k)r*=n;return r;}

Try it online!

36 bytes r;f(n,k){for(r=1;n>0;n-=k)r*=n;n=r;} for C(gcc)

MathGolf, 7 6 bytes
╙╒x%ε*

Try it online!
Found a clever way to handle 0! without changing the other test cases. Takes input as k n (reverse order), which helps with implicit popping.
Explanation
╙        maximum of two elements (pops largest of k and n,
         which is n for every valid case except 0!, where 1 is pushed)
 ╒       range(1,n+1)
  x      reverse int/array/string
   %     slice every k:th element
    ε*   reduce list with multiplication

Scala, 53 bytes
Takes two arguments, the first being the number and the second being the ! count.

Somehow breaks on the big test case. This step range costs many bytes in the end because of this -1* so improvements ought to be possible by refactoring.

I have, as always, a doubt about how we count bytes for function declarations, because everyone doesn't do the same way everywhere down there, so well... It's 17 bytes less, so 36 bytes, if we count out func variables' (a and b) declaration and func brackets.
(a:Int,b:Int)=>{var s=1
for(i<-a to b by -1*b)s*=i
s}

Try it online! I commented out the broken test cases, because, well, they do break.

You need the function declaration, otherwise this would be a snippet that takes input via predefined variables. Typically only the function assignment is left out since anonymous functions are allowed as submissions, though it depends on the language and the question

Ok thanks, so it is 53 indeed.

Attache, 21 19 bytes
${x<y∨x*$[x-y,y]}

Try it online! Pretty direct recursive implementation. (Note: true is essentially 1, as it can be used in arithmetic operations as 1.) This is one of the few programs I've written for this site where using a unicode operator saves bytes (1, to be precise).
Alternatives
20 bytes: ${x<y or x*$[x-y,y]}
21 bytes: Prod@${{_%y=x%y}\1:x}
27 bytes: ${x*[`1,$][x>y][x-y,y]∨1}
27 bytes: ${If[x>y,x*$[x-y,y],_or 1]}
27 bytes: ${x*[`1,$][x>y][x-y,y]or 1}
29 bytes: ${If[x>y,x*$[x-y,y],_+not _]}

Rust, 92 73 61 bytes
fn f(n:i128,k:i128)->i128{if n<=0{return 1}return n*f(n-k,k)}

I am just starting to learn rust, so I'm sure this can be shorter. Will update as I learn. The return value should be i128 in order to compute the last test.
Edit: Recursion is shorter.
Try it online!
You can add your own test, or edit one of the already existing ones.

q, 59 57 55 53 bytes
{prd 2+(&)1_i=last i:("J"$x(&)not[n])#(!)sum n:"!"=x}

explanation:
q)x:"12!!" / let our input be 12!!, assign to x
q)sum n:"!"=x / count "!"s
2i
q)(!)sum n:"!"=x / (!)m -> [0,m)
0 1
q)("J"$x(&)not[n]) / isolate the number in input
12
q)("J"$x(&)not[n])#(!)sum n:"!"=x / x#y means take x items from list y, if x>y, circle around
0 1 0 1 0 1 0 1 0 1 0 1
q)i:("J"$x(&)not[n])#(!)sum n:"!"=x / assign to i
q)i
0 1 0 1 0 1 0 1 0 1 0 1
q)(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / take last elem of i and see which are equal in i
010101010101b
q)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / drop first elem
10101010101b
q)(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / indices of 1b (boolean TRUE)
0 2 4 6 8 10
q)2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / add 2 across array
2 4 6 8 10 12
q)prd 2+(&)1_(last i)=i:("J"$x(&)not[n])#(!)sum n:"!"=x / product across array
46080

here also is a version in k (same logic), 4241 bytes
{*/2+&1_i=last i:("J"$x@&~:n)#!+/n:"!"=x}

Welcome to the site! I've added code formatting to your post which can be done with four spaces before the line or by enclosing it with triple backticks.

@SriotchilismO'Zaic thanks :-)

I recommend adding an explanation and maybe a link to an online interpreter like TIO. Code-only answers are usually automatically flagged as low quality.

@mbomb007 interesting. is there a bot flagging answers? what happens to low-quality submissions? i will update soon!

Yes, there is a bot. StackExchange uses bots to look for potential spam and low quality answers. People with high enough reputation can view the Review Queue. https://meta.stackexchange.com/a/161391/285610

Additionally there is an obscure feature of casting automatic downvote on answers marked as potential low quality. Though the exact behavior changed in time (see Community should not autodownvote “low quality” autoflags cleared by edits), the best strategy is to avoid being marked.

Factor + math.unicode, 30 29 24 bytes

Saved 1 byte thanks to @Bubbler
Saved 5 bytes thanks to @chunes!

[ 1 rot neg <range> Π ]

Try it online!
Takes k (which -th factorial) and then n. First we push an n onto the stack, then rot makes the stack look like n 1 k. neg negates k, which will act as the step for a range from n to 1 (made using <range>). Then Π finds the product of that range, and that's it.

If you take the arguments in k n order, you can do 1 rot neg instead of neg 1 swap to save a byte.

You can save 5 bytes with Π from math.unicode instead of product.

Nibbles, 3.5 bytes (7 nibbles)
`*`%@\,

      ,         # get the range from 1..first input,
     \          # reverse it,
   %            # and take each element in steps of
    @           # the second input,
`*              # and finally get the product

Or 7.5 bytes (15 nibbles) with input as string of a base-ten integer followed by exclamation marks:
`*`%,|$\$D\,`r$

Physica, 22 bytes
f=>n;k:n<1||n*f[n-k;k]

Try it online!

26 bytes
Re-learning how to use my own "language" \o/... If I knew how to write a parser 2 years ago, this would have been 20 bytes :(
->n;k:GenMul##[n…1]{%%k}

or
->n;k:GenMul##Range[n;1;k]

Try it online!

Japt, 8 bytes
1õUV f ×

Try it

Retina, 66 bytes
^0
1
\d+
*!,
+`(!+)(!+),\1$
$1$2,$2,$1
!+$
1
+`(!+),(\d+)
$.($2*$1

Try it online! Link includes faster test cases. Mauls numbers without exclamation marks. Explanation:
^0
1

Fix up 0!.
\d+
*!,

Convert n to unary and add a separator.
+`(!+)(!+),\1$
$1$2,$2,$1

Repeatedly subtract k from n while n>k, and collect the results.
!+$
1

Replace k with 1 (in decimal).
+`(!+),(\d+)
$.($2*$1

Multiply by each intermediate value in turn, converting to decimal.

PHP, 47 bytes
Recursive function with tests
function f($n,$c){return$n>0?f($n-$c,$c)*$n:1;}

Try it online!

PHP, 54 bytes
Loop version (original answer)
for($n=$argv[1],$f=1;$n>0;$f*=$n,$n-=$argv[2]);echo$f;

Try it online!

First argument is the the base value and second one is the factorial count.
Supports specified valid range, but outputs big numbers in scientific notation. For example the last sample is shown as 4.1697106428257E+31.

JavaScript (Node.js), 35 bytes
(n,i,f=i)=>i-n<1?f:r(n,i-n,f*(i-n))

Try it online!

Forth (gforth), 50 bytes
: f 1 1 2over / 1+ 0 do 2over i * - 1 max * loop ;

Try it online!
Code Explanation
: f                \ start a new word definition
  1 1              \ add placeholder and accumulator to stack
  2over / 1+       \ get the number of times to run the loop (num/factorial + 1)
  0 do             \ start loop from 0 to num/factorial
    2over          \ copy num and factorial to the top of the stack
    i * -          \ get the current number to multiply by (num - factorial * i)
    1 max          \ make sure it can't be 0 or negative [set to 1 if it is]
    *              \ multiply accumulator by result
  loop             \ end loop
;                  \ end the word definition

Perl 5 -Mbigint -p, 45 bytes
$b=s/!//g;$\=1*$_||1;$\*=$_ while($_-=$b)>0}{

Try it online!

Stax, 6 bytes
å▐█ΩV∟

Run and debug it
It takes input in the form {count} {base}.

Gaia, 6 bytes
…)¦v%Π

Try it online!
Takes input as n, k, so input of 3 4 would be 3!!!!.
…	 push [0...n-1], or [] if n == 0
 )¦	 increment each value (does nothing if [])
   v	 reverse list
    %	 take every k'th element
     Π	 product; product([]) = 1.

Bash + coreutils, 27
seq -s\* $[$1+!$1] -$2 1|bc

Try it online!

Lua, 150 145 129 bytes
i=io.read()p,c=i.gsub(i,"!","")p=p+0
function f(n,c)r=1 if n~=0 then
while(n>0) do r=r*n n=n-c
end
end
return r end
print(f(p,c))

Try it online!
Ported from Charlie's ArnoldC psuedocode.
-16 bytes thanks to Charlie

You can submit only the function as answer, which can also be improved.

@Charlie, Yeah when I get more comfy with the idea of headers and footers in TIO, I'll experiment a bit more.

Python 3 (Input as string), 82 bytes
m=lambda n,s:n<1or n*m(n-s,s)
f=lambda x:int(m(int(x.split("!")[0]),x.count("!")))

Try it online!
Note: the outer int() in f is solely for the fact that without it, 0! will output True

Nice approach! True == 1 in Python, so without conversion it is still valid.

Regex  (RME / PCRE2 v10.35+), 25 bytes
^(x+),((?*x+)(?>\1|.*))*$

Attempt This Online! - PCRE2
Try it on replit.com! - RegexMathEngine, in ECMAScript+(?*)+(?>) mode
Takes its input in unary, as two strings of x characters whose lengths represent the numbers, in the order {factorial count, base value}, joined/delimited by a ,. Returns its output as the number of ways the regex can match. (The rabbit emoji indicates this output method.)
^(x+),      # \1 = input factorial count; tail = input base value
(
    (?*x+)  # Assert tail > 0; multiply the number of possible matches by tail
    (?>     # Atomic group – lock in this match once it's finished
        \1  # tail -= \1
    |       # or
        .*  # tail = 0
    )
)*          # Iterate the above as many times as possible, minimum zero
$           # Assert tail == 0

Regex  (RME / PCRE2 v10.35+), 26 bytes
^((?=(x*).*,\2)(?*x+)\2)*,

Attempt This Online! - PCRE2
Try it on replit.com! - RegexMathEngine, in ECMAScript+(?*) mode
Takes the two numbers in the order {base value, factorial count}. Although this is 1 byte longer, it does not need an atomic group to be this length, using an atomic lookahead instead.
^             # tail = input base value
(
    (?=       # Atomic lookahead
        (x*)  # \2 = maximum value ≤ tail for which the following matches:
        .*,   # tail = input factorial count
        \2    # Assert tail ≥ \2
    )
    (?*x+)    # Assert tail > 0; multiply the number of possible matches by tail
    \2        # tail -= \2
)*            # Iterate the above as many times as possible, minimum zero
,             # Assert tail == 0

Thunno 2, 5 bytes
RrẈhp

Try it online!
Explanation
RrẈhp  # Implicit input
Rr     # Push the range [n..1]
  Ẉ    # Uninterleave into k pieces
   hp  # Product of first group
       # Implicit output

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/