g | x | w | all
Bytes Lang Time Link
068AWK241104T165029Zxrs
01605AB1E220908T082115ZKevin Cr
020Regex POSIX ERE / RE2 or better220908T011928ZDeadcode
026Retina 0.8.2230825T190713Zmbomb007
086C gcc220908T231328ZNoodle9
019Nekomata + e230704T034432Zalephalp
058C gcc230703T080007Zl4m2
057JavaScript Node.js230703T113503Zl4m2
068jq230223T204721ZGammaFun
016Japt220921T105846ZShaggy
013Vyxal220908T010356ZnaffetS
101Rust220909T154552ZLamdba
039sed220908T153809ZJonah
017Husk220909T111354ZDominic
023Husk220908T230031ZCalga
070Prolog SWI220908T062834ZRazetime
054Zsh220908T004440ZGammaFun
020Brachylog220908T212108ZDLosc
050Python220908T171623Zloopy wa
016Jelly220908T170340ZJonathan
058JavaScript ES6220908T130101ZArnauld
061Python3220908T003552ZAjax1234
024MathGolf220908T090230ZKevin Cr
021Charcoal220908T084515ZNeil
036Factor220908T072641Zchunes
039JavaScript V8220908T021255Zthejonym
021APL Dyalog Classic220908T004137Zatt
042Raku220908T013712ZJo King
042Curry PAKCS220908T013406Zalephalp

AWK, 68 bytes

{while(sub(/[Tt][Uu][Tt]-[Tt][Uu][Tt]/,"TUTTUT"));$0=$0!~/[a-z\-]/}1

This is another one that doesn't seem to work on TIO. With some inspiration from the sed answer. Couldn't figure out a better way to regex with AWK.

Try it online!

05AB1E, 17 16 bytes

ºìü13"tut-"ûδåßΘ

Port of @GammaFunction's Zsh answer, so make sure to upvote that answer as well!
-2 bytes porting @JonathanAllan's Jelly answer

Could be -1 byte without the trailing Θ if default truthy/falsey output was allowed, instead of two distinct outputs.. :/

Try it online or verify all test cases.

Explanation:

º                # Mirror the (implicit) input-string
                 #  (e.g. "abc" to "abccba")
 ì               # Prepend it to the (implicit) input-string
                 #  (e.g. "abccba" to "abcabccba")
  ü13            # Pop and create overlapping parts of size 13
     "tut-"û     # Push string "tut-" and palindromize it to "tut-tut"
            δ    # Map over each overlapping part using "tut-tut" as argument:
             å   #  Check if the part contains "tut-tut" as substring
              ß  # Minimum to check all are truthy and it's not empty
               Θ # (Explicit ==1 check to convert the empty strings to 0s..)
                 # (after which the result is output implicitly)

Regex (POSIX ERE / RE2 or better), 23 21 20 bytes

^\b((t?\But)?-tut)+$

Based on regexes by thejonymyster and Bubbler.

Try it on regex101! - RE2
Try it online! - GNU ERE (Bash + egrep)
Try it online! - ECMAScript
Try it online! - Perl
Try it online! - Raku:P5
Try it online! - PCRE
Try it online! - Java
Try it online! – Try It Online") - Boost
Try it online! - Python
Try it online! - Ruby
Try it online! - .NET

^            # Anchor to start of string.
\b           # Assert there is a word boundary here. Given the context, this is
             # equivalent to asserting that the first character isn't "-".
(
    (
        t?   # Optionally match and consume "t".
        \B   # Assert that this is not a word boundary. Given the context, this
             # is equivalent to asserting that the string does not start here.
        ut   # Match and consume "ut".
    )?       # Optionally match the above.
    -tut     # Match and consume "-tut".
)+           # Iterate the above as many times as possible, minimum one.
$            # Assert we've reached the end of the string.

Alternative 20 bytes:

^(tut-(tu\Bt?)?)+\b$

Try it on regex101! - RE2
Try it online! - ECMAScript
Try it online! - PCRE

This version doesn't work properly in GNU ERE; it matches tut-tuttut-tu. This appears to be a bug in GNU ERE, and is still present in the latest version. Note that ^(a\Bb?){2}$ incorrectly matches aba:

Try it online! - GNU ERE (bug) / Attempt This Online! (bug)
Try it online! - PCRE (no bug)

But ^a\Bb?a\Bb?$ correctly doesn't match aba:

Try it online! - GNU ERE / Attempt This Online!

21 bytes without word-boundary assertions (GNU ERE or better):

^(tut-(tut?|))+tut$\2

21 bytes without word-boundary assertions or backreferences (ECMAScript or better):

^(?=t)((t?ut)?-tut)*$

Regex (ECMAScript or better), 22 bytes

^((?=tut-tut).{1,7})*$

Try it online! - ECMAScript
Try it online! - Perl
Try it online! - Raku:P5
Try it online! - PCRE
Try it online! - Java
Try it online! - Boost
Try it online! - Python
Try it online! - Ruby
Try it online! - .NET

^                 # Anchor to start of string
(
    (?=tut-tut)   # Assert that the following 7 characters match "tut-tut",
                  # without consuming them.
    .{1,7}        # Skip anywhere from 1 to 7 characters
)*                # Iterate the above as many times as possible
$                 # Assert we've reached end of string

Alternative 22 bytes:

^(t(?=ut-tut).{0,6})*$

Regex (Perl v5.34+ / PCRE2 v10.43+ / Python / Ruby), 21 bytes

^((?=tut-tut).{,7})*$

Attempt This Online! - Perl v5.40+
Attempt This Online! - PCRE2 v10.44+
Try it online! - Python
Try it online! - Ruby

Python and Ruby support the quantifier shorthand of {,N} to mean {0,N}. So too do the latest versions of Perl and PCRE.

Alternative 21 bytes:

^(t(?=ut-tut).{,6})*$

Attempt This Online! - Perl v5.40+
Attempt This Online! - PCRE2 v10.44+
Try it online! - Python
Try it online! - Ruby

Regex (Raku), 25 21 bytesSBCS

^tut»((t?ut)?\-tut)+$

Ported from a previous (21 byte) version of the "POSIX ERE / RE2 or better" regex.

Try it online!

Porting the 21 byte lookahead-using version comes to 28 bytes:

^<?before t>((t?ut)?\-tut)*$

Try it online!

\$\large\textit{Anonymous functions}\$

Raku, 29 25 bytesSBCS

{/^tut»((t?ut)?\-tut)+$/}

Try it online!

Ruby, 29 28 30 bytes

->s{s=~/^\b((t?\But)?-tut)+$/}

Try it online!

Julia v1.5+, 32 bytes

endswith(r"^\b((t?\But)?-tut)+")

Attempt This Online!

-5 bytes compared to v1.2+, thanks to MarcMush

Julia v1.2+, 39 38 37 bytes

s->endswith(s,r"^\b((t?\But)?-tut)+")

Attempt This Online!

JavaScript, 35 34 33 bytes

s=>/^\b((t?\But)?-tut)+$/.test(s)

Try it online!

PowerShell, 35 34 bytes

$args-match'^\b((t?\But)?-tut)+$'

Try it online!

Java, 36 bytes

s->s.matches("((?=tut-tut).{1,7})*")

Try it online!

s->s.matches("tut\\b((t?ut)?-tut)+")

Try it online!

s->s.matches("\\b((t?\\But)?-tut)+")

Try it online!

R, 40 bytes

\(L)grepl('^((?=tut-tut).{1,7})*$',L,,1)

Attempt This Online!

\(L)grepl('^tut\\b((t?ut)?-tut)+$',L,,1)

Attempt This Online!

\(L)grepl('^\\b((t?\\But)?-tut)+$',L,,1)

Attempt This Online!

PHP, 47 bytes

fn($s)=>preg_match('/^\b((t?\But)?-tut)+$/',$s)

Try it online!

Python, 54 53 bytes

lambda s:re.match(r'\b((t?\But)?-tut)+$',s);import re

Try it online!

\$\large\textit{Full programs}\$

Retina, 21 20 bytes

^\b((t?\But)?-tut)+$

Try it online!

Pip, 25 24 21 bytes

+`(t?\But|\b)-tut`~=a

Try it online!

Thanks to DLosc for demonstrating this syntax. This is apparently shorthand for ^((t?\But|\b)-tut)+$. This regex is slightly less inefficient speed-wise, but by moving all distinctive operations inside the loop, it allows this shortcut to be used.

Ruby -n, 25 24 bytes

p~/^\b((t?\But)?-tut)+$/

Try it online!

Prints nil for false and 0 for true, which are respectively falsey and truthy in Ruby. If printing 0 or 1 is desired, replace p~ with p !! (+2 bytes).

Perl -p, 27 26 25 bytes

$_=/^\b((t?\But)?-tut)+$/

Try it online!

MATL, 25 bytes

'^\<((t?\But)?-tut)+$'XXn

Try it online!

MATL appears to have \< and \> as its word boundary assertions, and apparently doesn't support \b, yet somehow still supports \B. I can't currently explain this; I thought it used PCRE.

Zsh, 35 34 bytes

[[ $1 =~ '^\<((t?\But)?-tut)+$' ]]

Try it online!

Zsh uses GNU ERE as its regex engine, so while \b would work, \< should be slightly more efficient due to only checking for the type of word boundary that can occur at that location.

PHP -F, 48 47 46 bytes

<?=preg_match('/^\b((t?\But)?-tut)+$/',$argn);

Try it online! - bare-bones test harness
Try it online! - fancier test harness

Retina 0.8.2, 26 bytes

I know it's not as short as some other answers, but here's my solution.

^(tut(-tut))(\1|(ut)?\2)*$

Try it online!

C (gcc), 94 86 bytes

d;b;f(char*s){for(b=~0;b&&s[3]|b+4;s-=b=d&b|d==1?0:~3)s+=d=strstr(s,"tut-tut")-s;b=b;}

Try it online!

Saved 8 bytes thanks to c--

Inputs a pointer to a string.
Returns ~3 if the input is constructed of overlapping or concatenated instances of the string "tut-tut" or 0 otherwise.

Nekomata + -e, 19 bytes

ʷ{;"tut-tut"=ip,}ᵗN

Attempt This Online!

A port of my Curry answer. See also @DLosc's Brachylog answer.

ʷ{;"tut-tut"=ip,}ᵗN
ʷ{              }       Loop until failure
  ;                         Split the input into two parts
   "tut-tut"=               Check if the second part is "tut-tut"
             ip             Take a proper prefix of the second part
               ,            Append it to the first part
                 ᵗN     Check if the result is empty

C (gcc), 58 bytes

Assumes non-empty input

f(char*s){s=bcmp(s,"tut-tut",7)?!*s:f(s+4)|f(s+6)|f(s+7);}

Try it online!

C (gcc), 62 bytes

f(char*s){s=bcmp(s,"tut-tut",7)?0:!s[7]|f(s+4)|f(s+6)|f(s+7);}

Try it online!

-7 bytes from xnor's comment to another answer and 2 from ceilingcat

JavaScript (Node.js), 57 bytes

x=>x.split`-tut`.every(i=>+{ut:1,tut:1,'':x[3]+1}[j=i])>j

Try it online!

Regless

See another regless solution here

jq, 78 68 bytes

[range(length) as $i|"xxxxxx\(.)"[$i:13+$i]|contains("tut-tut")]|all

Try it online! Try it online!

Port of my Zsh answer. The <> as $<> feels optimizable, but I couldn't figure it out. EDIT: Turns out, it was optimizable!

Japt, 16 bytes

pÔiU ãD eø`t©-t©

Try it

pÔiU ãD eø`t©-t©     :Implicit input of string U
p                    :Append
 Ô                   :  Reverse
  iU                 :Prepend input
     ã               :Substrings of length
      D              :  13
        e            :All
         ø           :  Contain
          `t©-t©     :    Compressed string "tut-tut"

Vyxal, 16 14 13 bytes

mp13l‛≠₈‹∞vcg

Try it Online! | 12 bytes with g flag

Returns 1 for true, or falsy for false (0 or an empty list).

mp13l‛≠₈‹∞vcg
m              # Mirror the input - append its reverse
 p             # Append the input to that
  13l          # Get all overlapping strings of length 13
     ‛≠₈‹∞vc   # For each, does it contain "tut-tut"?
            g  # Minimum. Returns an empty list for an empty list (no idea why)

-3 from porting Jonathan Allan's Jelly answer!

-1 thanks to emanresu A.

Previously:

Vyxal, 16 bytes

6Iø.13l`≠₈-`∞vcA

Try it Online!

Uses the same idea as @GammaFunction's Zsh answer.

6Iø.13l`≠₈-`∞vcA
6Iø.              # Surround the input with 6 spaces on both sides
    13l           # Get all overlapping strings of length 13
       `≠₈-`∞vcA  # Do all of them contain "tut-tut"?

Rust, 101 bytes

|s:&str|(0..s.len()).scan(0,|r,i|{if s[i..].starts_with("tut-tut"){*r=7}*r-=1;Some(*r)}).all(|i|i>=0)

Playground

Returns a boolean with the obvious meaning.

sed, 39 bytes

:a
s/tut-tut/TUTTUT/i
ta
s/[^TU]//
T
cN

Truthy test cases -- outputs nothing

Falsy test cases -- outputs one N for each line

The idea here is quite simple:

sed, 29 bytes, straight regex, thanks to Deadcode

s/^((t?\But)?\b-tut)+$//
t
cN

Attempt This Online!

Thanks to Deadcode for this alternate approach which forgoes looping and solves it with a single application of a true regex.

Husk, 22 18 17 bytes

Edit: saved 4 5 bytes based on Jonathan Allan's idea

▼M€X13‼S+↔⁰¨μζ-μζ

Try it online!

      ‼   ⁰             # apply twice to the input:
       S+↔              #   join to itself reversed
   X13                  # and split this into strings of 13 characters;
 M                      # now map over these
  €                     #   do they contain
           ¨μζ-μζ¨      #   the compressed string "tut-tut"?
▼                       # and return the minimum result

Husk, 24 23 bytes

Edit: saved 1 byte based on Dominic van Essen's comment.

±Λ≤7Ẋ-J¥¨μζ-μζ¨X7¹e_6→L

Try it online!

Explanation

±Λ≤7Ẋ-J¥¨μζ-μζ¨X7¹e_6→L

±Λ≤7                          check if all differences are ≤7
    Ẋ-                        take the difference of all adjacent elements in list
      J                       put indices list the into the middle of [-6,1+len(input)]
       ¥                      create indices list of all occurrences of "tut-tut" in substring list
        ¨μζ-μζ¨               "tut-tut"
                X7¹           create list of substrings of input with length 7
                   e_6→L      list [-6,1+len(input)]

Prolog (SWI), 70 bytes

b-->"tut-tut".
n-->(b;"ut-tut";"-tut"),(n;"").
t-->b;b,n.
+X:-t(X,[]).

Try it online!

-4 from jo king.

Zsh, 66 54 bytes

-6 bytes thanks to Neil, -6 bytes by switching to -e thanks to pxeger.

s=xxxxxx$1
repeat $#1 [[ ${s:$[i++]:13} = *tut-tut* ]]

Try it online! Try it online!

The problem stated is equivalent to: Every sliding 13-character window of xxxxxx[string]xxxxxx contains tut-tut. In Bash and Zsh, the ${var:${idx}:13} is valid even if the string isn't long enough, so the trailing xxxxxx are unneeded.

We loop over each window, and exit out if any single test fails thanks to errexit.

Brachylog, 20 bytes

Ẹ|a₀"tut-tut"sl;?b₍↰

Try it online!

Explanation

This is a pretty straight-at-the-problem approach; possibly something more subtle would be shorter.

Ẹ|a₀"tut-tut"sl;?b₍↰
Ẹ                     Either the input is the empty string
 |                    Or
  a₀                  A prefix of the input
    "tut-tut"         is "tut-tut"
             s        Take a nonempty substring of "tut-tut"
              l       Get its length
               ;?b₍   Remove that many characters from the start of the input string
                   ↰  Recurse

Python, 50 bytes

def f(s):s[:7]=="tut-tut"and f(s[~ord(s[7])%5|4:])

Signals by exit code: errors out if the input is "tut-tut"-decomposible.

How?

Recursively checks that input starts with "tut-tut". Based on the next character directly computes where the next "tut-tut" has to start.

0 1 2 3 4 5 6   7   8 9 ...
               ---
t u t - t u t | - |
              |   |
 ==>    t u t | - | t u t
               ---


               ---
t u t - t u t | u |
              |   |
 ==>        t | u | t - t u t
               ---


               ---
t u t - t u t | t |
              |   |
 ==>          | t | u t - t u t
               ---

The figure shows offsets inferred from char at position 7:

The magic formula ~x%5|4 implements this map. x is the code point of input character.

Importantly, any input is mapped to 4,5,6,7, so the algorithm can neither get stuck nor skip any characters.

Now, if we can cover the input with "tut-tut"s we will eventually reach the end and error out as soon as we try to access out-of-bounds characters. Otherwise the algorithm will simply stop at the first place that cannot be covered.

Attempt This Online!

Thanks to eagle-eyed @Jonathan Allan for spotting a problem with my first attempt.

Wrong Python, 54 bytes

def f(s):s[:7]=="tut-tut"and f(s[~ord(s[7])%31%12%8:])

Attempt This Online!

Jelly, 16 bytes

m0;w13Ƥ“"ṁĿ4ṘṘ»Ṃ

A monadic Link that accepts a list of characters and yields 1 if constructible or 0 if not.

Try it online!

How?

The input must (a) start with tut-tut, (b) end with tut-tut, and (c) have tut-tut as a contiguous substring of all of its length \$13\$ slices. We can, however, just test that (c) holds for the input concatenated with its reverse concatenated with the input (e.g. abc -> abccbaabc). This works since tut-tut is palindromic and any bad starts or bad ends in the input will now nest between any tut-tuts.

m0;w13Ƥ“"ṁĿ4ṘṘ»Ṃ - Link: list of characters, S e.g. "abc"
m0               - reflect -> "abccba"
  ;              - concatenate -> "abccbaabc"
      Ƥ          - for infixes...
    13           - ...of length 13:
   w   “"ṁĿ4ṘṘ»  -   first 1-indexed index of "tut-tut" or 0 if not found
               Ṃ - minimum (an empty list yields 0)

Bit of a shame it takes half the code to make "tut-tut"!

JavaScript (ES6), 58 bytes

A non-regex solution.

f=([c,...a],i)=>i>6?!c:c=="tut-"[i&3]&&f(a,-~i)|3%~-i&f(a)

Try it online!

How?

We use a pointer \$i\$ into the string \$s=\$ "tut-tut". At each iteration, we make sure that the current character from the input string matches \$s[i]\$, then we either increment \$i\$ or restart with \$i=0\$ if we are allowed to do so. The parsing is successful if we end up with \$i=7\$ exactly when the end of the input string is reached.

The table below summarizes after which positions it's possible to restart with \$i=0\$ and how this can be computed with the expression 3 % ~-i & 1.

i = position character restart after? 3 % ~-i 3 % ~-i & 1
0 t No 0 0
1 u No NaN 0
2 t No 0 0
3 - Yes 1 1
4 t No 0 0
5 u Yes 3 1
6 t Yes 3 1

Python3, 61 bytes:

f=lambda x:x==''or'tut-tut'==x[:6|f(x[4:])|f(x[6:])|f(x[7:])]

Try it online!

MathGolf, 24 bytes

☼▌☼▐l£{_C<ÿtut-ñ╧\╞};]ε*

Port of @GammaFunction's Zsh answer, so make sure to upvote him/her as well!

Try it online.

Explanation:

☼▌               # Prepend a leading "100000" in front of the (implicit) input-string
  ☼▐             # Append "100000" as well
l£               # Push the input-string, pop and push its length
  {            } # Loop that many times:
   _             #  Duplicate the current string
    C<           #  Pop the copy, and keep its first 13 characters
      ÿtut-ñ     #  Push string "tut-", and palindromize it to "tut-tut"
            ╧    #  Check if the string contains this "tut-tut" as substring
             \   #  Swap so the string we've duplicated is at the top of the stack again
              ╞  #  Remove its leading character
;                # After the loop, discard the remaining string from the stack
 ]               # Wrap everything else on the stack into a list
  ε*             # Product (reduce by multiplication) to verify whether all checks were
                 # truthy
                 # (after which the entire stack is output implicitly as result)

Charcoal, 21 bytes

⬤θ№✂⁺×⁶ψθκ⁺¹³κ¹…tut-⁷

Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. - for a valid string, nothing if not. Explanation: A port of my golf to @GammaFunction's zsh answer.

 θ                      Input string
⬤                       All indices satisfy
      ⁶                 Literal integer `6`
     ×                  Repetitions of
       ψ                Null byte
    ⁺                   Plus
        θ               Input string
   ✂          ¹         Sliced from
         κ              Current index to
           ¹³           Literal integer `13`
          ⁺             Plus
             κ          Current index
  №                     Contains
                tut-    Literal string `tut-`
               …        Extended to length
                    ⁷   Literal integer `7`

Factor, 36 bytes

[ R/ tut\b((t?ut)?-tut)+/ matches? ]

Try it online!

Port of Deadcode's (Bubbler's/thejonymyster's) regex answer.

Factor + math.unicode, 63 bytes

[ "xxxxxx"dup surround 13 clump [ "tut-tut"swap subseq? ] ∀ ]

Try it online!

Port of GammaFunction's Zsh answer.

JavaScript (V8), 39 bytes

x=>x.replace(/(?=tu)((t?ut)?-tut)*/,"")

Try it online!

Returns a falsy string if the string is correctly composed of tut-tuts, and a truthy string otherwise.

Mostly the same logic as my (slightly broken) regex solution, except instead of having the "this regex matches the entire string or else it fails" logic be in the regex, its in the fact that we only delete one occurrence of the pattern. If the entire string is not composed of the pattern, there will be string remaining after the replacement, and in js, any nonempty string is truthy, with the empty string being the only falsy string :-)

(in case you wonder why this doesn't fail for cases where two valid strings are concatenated: regex is greedy, and will grab the largest match it can grab)

Breakdown:

x=>x.replace(/(?=tu)((t?ut)?-tut)*/,"") // full function

x=>x.replace(/                    /,"") // return the string with exactly one
                                        // match of the following regex removed
              (?=tu)                    //   string starting with "tu"
                    (           )*      //   which contains at least 0 of
                                        //   the following pattern
                                        //   (actually at least 1, since otherwise,
                                        //   the pattern would be empty and 
                                        //   thus would fail the "tu" check)
                     (t?ut)?-tut        //     any of "-tut"
                                        //     (will never be at the start due to the
                                        //     "tu" check, but can appear in cases
                                        //     where the entire "tut" overlaps),
                                        //     "ut-tut"
                                        //     (in cases where just the "t" is overlapping,
                                        //     also can never be at the start)
                                        //     or "tut-tut"
                                        //     (this one always comes first
                                        //     due to the "tu" check)

BTW this regex saves a byte over the straightforward regex /tut-tut((t?ut)?-tut)*/ because we don't actually have to use the entire "tut-tut"; the first group ((t?ut)?-tut) is forced to complete to tut-tut once it's forced to start with tu, if that makes sense... :-)

APL (Dyalog Classic), 21 bytes

∧/7∨/'tut-tut'⍷6∘↓⍣¯1

Try it online!

               6∘↓⍣¯1   pad with leading spaces
     'tut-tut'⍷         find occurrences of tut-tut
∧/7∨/                   present in every group of 7 consecutive positions

Raku, 42 bytes

{^.comb⊆m:ex/tut\-tut/>>.&{.from..^.to}}

Try it online!

An anonymous function that takes a string and returns a true/false value for if it is composed of overlapping 'tut-tut's.

Explanation

{                                      } # Anonymous function block
 ^.comb    # The range 0 to length of input
       ⊆   # is a subset or equal to
        m:ex/tut\-tut/                  # Match all instances of 'tut-tut'
                      >>.&{           } # And map them to
                           
                           .from..^.to  # The range of covered indexes

This basically finds the indexes covered by each 'tut-tut' and makes sure that they cover the entire string. Note that you could easily generalise this function to any string.

Curry (PAKCS), 42 bytes

f""=1
f(a@(_:_++b)++c)|a=="tut-tut"=f$b++c

Try it online!

Returns 1 for truth, and nothing otherwise.