Disconnect 4 bits

Jelly, 18 bytes + 0 penalties = 18

79Ọv2;$ḅ⁹b2+4\b4FẠ

Returns 1 if there are no equal bit strings of length 4 or more in the 8-bit word representation of the ASCII string input, and 0 otherwise.

Try it online! (test suite with some extra cases added)

Using Jelly's codepage there are no length 4 or longer substrings of equal bits:

7    0x37    00110111
9    0x39    00111001
Ọ    0xB5    10110101
v    0x76    01110110
2    0x32    00110010
;    0x3B    00111011
$    0x24    00100100
ḅ    0xD4    11010100
⁹    0x89    10001001
b    0x62    01100010
2    0x32    00110010
+    0x2B    00101011
4    0x34    00110100
\    0x5C    01011100
b    0x62    01100010
4    0x34    00110100
F    0x46    01000110
Ạ    0xAB    10101011

With equal-bit run lengths of:

221323221211111312322133122121221111213121123132213111122211311332313211313211111112

How?

Tricks to avoid demerits are:

  • to avoid the "convert from character to ordinal" monad O by converting the number 79 to a character using followed by an "evaluation of Jelly code with input", v.

  • to avoid direct conversion to binary using B (0x42, 1000010) by the simple two-byte alternative b2 using the generic dyadic base conversion.

  • to avoid a few normal choices for counting the runs of equal bits - first choice would be "all overlapping slices of given length", (0xF5 or 11110101). A second choice might be to utilise "all sublists", (0xCF or 11001111).
    A workaround I used before the current one was to take the increments (between consecutive elements) with I (putting zeros and ones on an equal footing), and to look for any occurrence of three zeros in a row. To do that I converted all the zeros to ones by use of the binomial function with 2c i.e. 2Cx - making the -1s become 0s the 1s become 2s, and the 0s become 1s; that way the code can look for the first occurrence of the sublist [1,1,1] with w111.
    However a shorter way became apparent - to mimic the action of "all overlapping slices of given length", , one can use a 4-wise overlapping reduce with some dyad, <dyad>4\. If this is performed with addition, +4\, it counts the 1s, so then any 0 or 4 being present is the indicator to return a truthy value. The issue here is that the next obvious step would be to take the modulo 4 of that to put the 0 and 4 entries on an equal footing while leaving the other possible values (1, 2, and 3) unchanged, but +\%4 has \% inside, which has bit-value 0101110000100100. In order to avoid that penalty the numbers are all converted to base 4 with b4 (mapping 0 to [0], 1 to [1], 2 to [2], 3 to [3], and 4 to [1,0]) and the whole list is flattened with F. Now the last test is simply to check if there are any 0s in the list, achievable directly with the monad .

79Ọv2;$ḅ⁹b2+4\b4FẠ - Main link: printable ASCII character list
79                 - 79
  Ọ                - character from ordinal : 'O'
   v               - evaluate as Jelly code : input -> 'O' converts the input to ordinals
      $            - last two links as a monad
    2              -     2
     ;             -     concatenate (why? see the note beneath the code block)
       ḅ⁹          - convert from base 256 : gets an integer representing the byte string
         b2        - convert to base 2 AKA binary
            4\     - 4-wise reduce with
           +       -     addition (sums all overlapping slices of length 4)
              b4   - convert to base 4 (vectorises)
                F  - flatten into a single list
                 Ạ - any falsy?

Note: The reason a 2 is concatenated with the ordinal list is to deal with the edge cases where the only run of 4 in the input string is in the leading zeros of the very first character - these characters are: tab; line-feed; and carriage-return. Without this the base 256 conversion effectively strips leading zeros from the (fully concatenated) binary string; with the leading 2 the leading zeros will be there and an extra one and zero before them. Since no printable ASCII has exactly three leading zeros there is no need to discard these extra bits before the rest of the check.


Java 7, 812 726 673 644 634 616 599 588 145 bytes + 10*44 = 585

boolean
b(char[]b){String
g="";for(char
c:b)g+=g.format("%"+(1-1)+"8d",new
Integer(Integer.toString(c,2)));return!g.matches(".*(.)\\1\\1\\1.*");}

I am using newlines instead of spaces to try to minimize penalty...

Try it online!

Binary

01100010011011110110111101101100011001010110000101101110000010100110001000101000011000110110100001100001011100100101101101011101011000100010100101111011010100110111010001110010011010010110111001100111000010100110011100111101001000100010001000111011011001100110111101110010001010000110001101101000011000010111001000001010011000110011101001100010001010010110011100101011001111010110011100101110011001100110111101110010011011010110000101110100001010000010001000100101001000100010101100101000001100010010110100110001001010010010101100100010001110000110010000100010001011000110111001100101011101110000101001001001011011100111010001100101011001110110010101110010001010000100100101101110011101000110010101100111011001010111001000101110011101000110111101010011011101000111001001101001011011100110011100101000011000110010110000110010001010010010100100101001001110110111001001100101011101000111010101110010011011100010000101100111001011100110110101100001011101000110001101101000011001010111001100101000001000100010111000101010001010000010111000101001010111000101110000110001010111000101110000110001010111000101110000110001001011100010101000100010001010010011101101111101


Old bitshifting solution 141 bytes + 10*101 = 1,151

boolean
b(char[]b){
int
o=0,p=0,i;
for(char
c:b){for(i=0;i<8;){if((c&(1<<i++))<1){o=0;p++;}else{p=0;o++;}if(3<o|3<p)return
6<5;}}return
5<6;}

Try it online!

Binary

011000100110111101101111011011000110010101100001011011100000101001100010001010000110001101101000011000010111001001011011010111010110001000101001011110110000101001101001011011100111010000001010011011110011110100110000001011000111000000111101001100000010110001101001001110110000101001100110011011110111001000101000011000110110100001100001011100100000101001100011001110100110001000101001011110110110011001101111011100100010100001101001001111010011000000111011011010010011110000111000001110110010100101111011011010010110011000101000001010000110001100100110001010000011000100111100001111000110100100101011001010110010100100101001001111000011000100101001011110110110111100111101001100000011101101110000001010110010101100111011011111010110010101101100011100110110010101111011011100000011110100110000001110110110111100101011001010110011101101111101011010010110011000101000001100110011110001101111011111000011001100111100011100000010100101110010011001010111010001110101011100100110111000001010001101100011110000110101001110110111110101111101011100100110010101110100011101010111001001101110000010100011010100111100001101100011101101111101

APL (Dyalog Classic), 26 + 1 × 10 = 36 bytes

Notes

Contains one 4-run of 1s. Requires ⎕IO←0 which is default on many systems. Note that this must be run on a Classic interpreter so that strings are one byte per character.

Submission

1≠⊃⌽⌈\∊(×4\¨⍳≢⍬⍬)⍷¨⊂11⎕DR⍞

Try it online!

Binary source

0011000110101100100111001011001010010111010111001011100100101000110101110011010001011100101010001011110010111011101010111010101100101001101110101010100010011011001100010011000110001100010001000101001010001101

Explanation

 Prompt for string input

11 ⎕DR convert to 1-bit Boolean (1) Data Representation

 enclose so we can apply multiple things to it

() ⍷¨ binary indicators where each of the following sequences begin…

× sign (no-op on binary data, but included as spacer to split runs)

4 \¨ expand (copy) each to length four

 the integers up to

 the tally of

⍬⍬  the list consisting of two empty numeric lists

 enlist (flatten)

⌈\ cumulative maximum

 reverse

 pick the first

1 ≠ is one different from? (i.e. NOT)

Walk-through

We will input "48" to the ungolfed un-de-runned version ~ ∨/ ∊ (0 0 0 0)(1 1 1 1) ⍷¨ ⊂ 11 ⎕DR ⍞:

11 ⎕DR ⍞ converts "48" to 0 0 1 1 0 1 0 0 0 0 1 1 1 0 0 0 (i.e. Dec 52 56, Hex 34 38)

(0 0 0 0)(1 1 1 1) ⍷¨ ⊂ finds beginnings of 0-runs and 1-runs; (0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)

∨/ ∊ looks if there is any Truth (i.e. any runs); 1

~ negates that; 0