24
\$\begingroup\$

Take a string, s containing printable ASCII-characters as input, and output its "binary split sum". Need an explanation?

How do you get the binary split sum?

We'll use the string A4 as an example in the following explanation.

  • Convert the characters to binary, treating each letters as a 7-bit ASCII character

    A -> ASCII 65 -> 1000001
    4 -> ASCII 52 -> 0110100
    
  • Concatenate the binary numbers into a new binary number

    A4 -> 1000001 & 0110100 -> 10000010110100
    
  • Split the new binary number into chunks, where no 1 can have a 0 to its left. You should not split consecutive 1s.

    10000010110100 -> 100000, 10, 110, 100
    
  • Convert these binary numbers to decimal

    100000, 10, 110, 100 -> 32, 2, 6, 4
    
  • Take the sum of these numbers:

    32 + 2 + 6 + 4 = 44
    

So, the output for the string A4 should be 44.


Test cases:

a
49

A4
44

codegolf
570

Hello, World!
795
\$\endgroup\$
3
  • 2
    \$\begingroup\$ I think this would have been a nicer challenge without the ASCII conversion step, just taking the (decimal) number after step 2 as input. \$\endgroup\$
    – xnor
    May 14, 2017 at 20:37
  • \$\begingroup\$ Well, 8372 actually. \$\endgroup\$
    – xnor
    May 14, 2017 at 20:40
  • 1
    \$\begingroup\$ @xnor, you might be right, and it would be cleaner. I had fun solving this in Octave though, and I hope others will enjoy solving it too :) \$\endgroup\$ May 14, 2017 at 20:42

21 Answers 21

13
\$\begingroup\$

Python 2, 86 81 76 bytes

-5 bytes thanks Adnan
-5 bytes thanks xnor

s=0
for c in input():s=s*128+ord(c)
print eval(bin(s).replace('01','0+0b1'))

Try it online!

for c in input():s=s*128+ord(c) to do the ASCII conversion numerically, where *128 is used to left shift s 7 times (steps 1 and 2)
eval(('0'+new_bin).replace('01','0+0b1')) to split and sum (steps 3, 4 and 5)

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

Jelly, 13 bytes

Oḅ128BŒg;2/ḄS

Try it online!

How it works

Oḅ128BŒg;2/ḄS  Main link. Argument: s (string)

O              Ordinal; map characters to their code points.
 ḅ128          Unbase 128; convert the resulting list from base 128 to integer.
     B         Binary; Convert the resulting integer to base 2.
      Œg       Group consecutive, equal bits.
        ;2/    Concatenate all non-overlapping pairs.
           Ḅ   Unbinary; convert from base 2 to integer.
            S  Take the sum.
\$\endgroup\$
2
  • \$\begingroup\$ I've missed that trick of base conversion before. \$\endgroup\$ May 14, 2017 at 21:45
  • \$\begingroup\$ Ah, nice trick indeed! \$\endgroup\$
    – Adnan
    May 15, 2017 at 4:30
6
\$\begingroup\$

MATL, 14 bytes

YB!'1+0*'XXZBs

Try it online!

Explanation

Consider input 'A4' as an example.

YB        % Implicit input. Convert to binary using characters '0' and '1'. 
          % Gives a char matrix, where each row corresponds to a number
          % STACK: ['1000001'; '0110100']
!         % Transpose. This is necessary because MATL uses column-major 
          % order when linearizing a matrix into a vector
          % STACK: ['10'; '01'; '01'; '00'; '01'; '00'; '10']
'1+0*'    % Push this string: regexp pattern
          % STACK: ['10'; '01'; '01'; '00'; '01'; '00'; '10'], '1+0*'
XX        % Regexp. Linearizes the first input into a row (in column-major
          % order), and pushes a cell array of substrings that match the
          % pattern given by the second input
          % STACK: {'100000'; '10'; 110'; '100'}
ZB        % Convert each string into a decimal number. Gives numeric vector
          % STACK: [32; 2; 6; 4]
s         % Sum. Implicitly display
          % STACK: 44
\$\endgroup\$
5
\$\begingroup\$

05AB1E, 18 bytes

Code:

Çžy+b€¦JTR021:2¡CO

Explanation:

Ç                   # Take the ASCII value of each character
 žy+                # Add 128 to each value (to pad each with enough zeros)
    b               # Convert to binary
     €¦             # Remove the first character
       J            # Join the array
        TR021:      # Replace 01 by 021
              2¡    # Split on the number 2
                C   # Convert from binary to decimal
                 O  # Sum them all up

Uses the 05AB1E encoding. Try it online!

\$\endgroup\$
5
\$\begingroup\$

05AB1E, 14 bytes

Çžy+b€¦Jγ2ôJCO

A port of my Jelly answer, using the 128 offset from Adnan's 05ab1e answer (rather than the 256 in the Jelly answer I wrote).

Try it online!

How?

Çžy+b€¦Jγ2ôJCO
Ç              - to ordinals
   +           - add
 žy            - literal 128
    b          - to binary
     €         - for each
      ¦        -   dequeue
       J       - join
        γ      - group into chunks of equal elements
          ô    - split into chunks of
         2     - literal 2
           J   - join
            C  - from binary
             O - sum
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 97 92 bytes

s=>eval(s.replace(/./g,c=>(128+c.charCodeAt()).toString(2).slice(1)).replace(/1+/g,'+0b$&'))

Edit: Saved 5 bytes with some help from @ConorO'Brien.

\$\endgroup\$
3
  • \$\begingroup\$ My own solution was 97 bytes, too: s=>eval([...s].map(e=>(e.charCodeAt()+128).toString(2).slice(1)).join``.replace(/1+0*/g,'+0b$&')) You can use my replace method to save a byte, I think \$\endgroup\$ May 14, 2017 at 22:11
  • 1
    \$\begingroup\$ @ConorO'Brien More than a byte, I think! \$\endgroup\$
    – Neil
    May 14, 2017 at 23:03
  • \$\begingroup\$ Oo, n​i​c​e :​D \$\endgroup\$ May 14, 2017 at 23:07
3
\$\begingroup\$

Japt, 18 12 bytes

c_¤ùT7Ãò< xÍ
c_           // Firstly, take the input and map over it as charcodes.
  ¤          // Take the binary representation of each item
   ùT7       // and left-pad it with zeroes to standardize the items.
      Ã      // After all of the above,
       ò<    // partition the result where ever a 0 precedes a 1.
          xÍ // Then sum the numbers from base 2.

Takes input as a single string.
I also tried out the 128 or 256 addition used by other answers, but 0-padding was shorter to use.

Shaved off a whole whopping 6 bytes thanks to ETHproductions and Oliver.

Try it out here.

\$\endgroup\$
4
  • \$\begingroup\$ You can use more auto-functions here: òÈ<YÃ can be ò< (with trailing space), and Ën2Ãx can be xn2. You can also use T in place of 0 to save on the comma. (Also, feel free to join us in the Japt chatroom if you ever have questions or would like help with golfing :-) ) \$\endgroup\$ Apr 6, 2018 at 15:05
  • \$\begingroup\$ @ETHproductions Thanks again, especially for the T trick, didn't know you could (ab)use variables for that, that's very handy. The auto-function xn2 looks a bit weird when compiled, x("n", 2), so I think it will still take a bit before I fully understand the logic behind them. With your help, the Japt solution is now tied for the first place with the Jelly answer. \$\endgroup\$
    – Etheryte
    Apr 6, 2018 at 19:11
  • \$\begingroup\$ ETHproductions recently made a shortcut for n2 : Í. It hasn't hit TIO yet, but you can use it here: ethproductions.github.io/japt/?v=1.4.5&code=Y1+k+VQ3w/… \$\endgroup\$
    – Oliver
    Apr 6, 2018 at 20:25
  • \$\begingroup\$ @Oliver Wow, that's very bleeding edge, that isn't even covered in the interpreter shortcuts reference yet. Thanks a lot! \$\endgroup\$
    – Etheryte
    Apr 7, 2018 at 8:03
2
\$\begingroup\$

Jelly, 16 15 bytes

-1 byte thanks to Dennis (no need to flatten by 1 when a full flatten is fine - replace ;/ with F)

O+⁹Bṫ€3FŒg;2/ḄS

Try it online!

How?

O+⁹Bṫ€3FŒg;2/ḄS - Main link: list of characters, s    e.g. "A4"
O               - cast to ordinal (vectorises)        [65,52]
  ⁹             - literal 256
 +              - add (vectorises)                    [321, 308]
   B            - convert to binary (vectorises)      [[1,0,1,0,0,0,0,0,1],[1,0,0,1,1,0,1,0,0]]
    ṫ€3         - tail €ach from index 3              [[1,0,0,0,0,0,1],[0,1,1,0,1,0,0]]
       F        - reduce with concatenation           [1,0,0,0,0,0,1,0,1,1,0,1,0,0]
        Œg      - group runs of equal elements        [[1],[0,0,0,0,0],[1],[0],[1,1],[0],[1],[0,0]]
          ;2/   - pairwise reduce with concatenation  [[1,0,0,0,0,0],[1,0],[1,1,0],[1,0,0]]
             Ḅ  - convert from binary (vectorises)    [32,2,6,4]
              S - sum                                 44
\$\endgroup\$
1
  • 1
    \$\begingroup\$ ;/ can be replaced with F. \$\endgroup\$
    – Dennis
    May 14, 2017 at 21:32
2
\$\begingroup\$

PHP, 116 Bytes

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);$t=mb_split("(?<=0)(?=1)",$r);echo array_sum(array_map(bindec,$t));

Online Version

PHP, 117 Bytes

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);$t=preg_split("#0\K(?=1)#",$r);echo array_sum(array_map(bindec,$t));

Try it online!

PHP, 120 Bytes

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);preg_match_all("#1+0+#",$r,$t);foreach($t[0]as$b)$s+=bindec($b);echo$s;

Try it online!

or

for(;$c=ord($argn[$i++]);)$r.=sprintf("%07b",$c);preg_match_all("#1+0+#",$r,$t);echo array_sum(array_map(bindec,$t[0]));
\$\endgroup\$
1
\$\begingroup\$

Pyth, 21 bytes

It's too long...

siR2:.BiCMQ128"1+0+"1

Test suite.

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

[F#], 249 245 bytes

open System
let rec c a=function|[]->[a]|'0'::'1'::y->(a+"0")::(c""('1'::y))|x::y->c(a+string x)y
let x i=c""(String.Join("",(Seq.map(fun c->Convert.ToString(int c,2).PadLeft(7,'0'))i))|>Seq.toList)|>Seq.map(fun c->Convert.ToInt32(c,2))|>Seq.sum

Try it online!

Note: the version on tio.run has "open System" in the header, I've added its count to the code above. I'm not sure what the rules are on imports.

Ungolfed

let rec convert acc = function
    | [] -> [acc]
    | '0'::'1'::xs -> (acc + "0") :: (convert "" ('1'::xs))
    | x::xs -> convert (acc + string x) xs
    
let calculateSum input =
    let binary = Seq.map (fun x -> Convert.ToString(int x, 2).PadLeft(7, '0')) input

    String.Join("", binary)
    |> Seq.toList
    |> convert ""
    |>Seq.map (fun x -> Convert.ToInt32(x, 2))
    |>Seq.sum
\$\endgroup\$
2
  • \$\begingroup\$ if open System is the same as C#s using System; then yes you need to include it in the count. If you can do it in F# you could fully qualify whatever the System is for . For example, in C# System.Console... instead of using System;Console... \$\endgroup\$ May 15, 2017 at 16:27
  • \$\begingroup\$ @TheLethalCoder It is the same, yes. Also, thanks for clarifying this :) I opted for the "open.." version because it's not only String, but also Convert that live in that namespace. \$\endgroup\$
    – Brunner
    May 15, 2017 at 17:17
1
\$\begingroup\$

Ruby, 60 bytes

->s{s.bytes.map{"%07b"%_1}.join.scan(/1+0*/).sum{_1.to_i 2}}

Attempt This Online!

\$\endgroup\$
0
\$\begingroup\$

Perl 6, 62 bytes

{sum map {:2(~$_)},.comb».ord».fmt('%07b').join~~m:g/11*0*/}
\$\endgroup\$
1
0
\$\begingroup\$

J, 34 bytes

[:+/@(,#.;.1~1,1=2#.\,)(7#2)#:3&u:

Try it online!

Explanation

[:+/@(,#.;.1~1,1=2#.\,)(7#2)#:3&u:  Input: array of characters S
                              3&u:  Get ASCII values of each character
                       (7#2)        Array with 7 copies of the value 2
                            #:      Convert each value to a base 2 array with length 7
[:  (                 )             Operate on those binary values
                     ,                Flatten it
                 2  \                 For each infix of size 2
                  #.                    Convert it to decimal from binary
               1=                     Test each value for equality to 1
             1,                       Prepend a 1
      ,                               The flattened binary values
         ;.1~                         Chop that at each occurrence of a 1
       #.                               Convert each chop from binary to decimal
 +/@                                Reduce by addition
\$\endgroup\$
0
\$\begingroup\$

mathematica 193 bytes

f=FromDigits;l=Flatten;(S=Split@l@Table[PadLeft[IntegerDigits[ToCharacterCode@#,2][[k]],7],{k,StringLength@#}];Plus@@Table[f[RealDigits@f@Join[S[[i]],S[[i+1]]],2],{i,1,Length@S-1,2}]+Last@l@S)&
\$\endgroup\$
1
  • \$\begingroup\$ You can save 7 bytes by doing f=FromDigits;l=Flatten; at the start, and then replacing all instances of those two functions with f and l. \$\endgroup\$ May 15, 2017 at 7:37
0
\$\begingroup\$

J, 40 bytes

+/>#.&.>(1,}.|.1 0 E.|.b)<;.1 b=.,#:a.i.

usage:

+/>#.&.>(1,}.|.1 0 E.|.b)<;.1 b=.,#:a.i.'A4'

returns 44

\$\endgroup\$
0
\$\begingroup\$

Clojure, 150 bytes

#(loop[[c & C](for[i % j[64 32 16 8 4 2 1]](mod(quot(int i)j)2))p 0 r 0 R 0](if c(if(=(dec c)p 0)(recur C c 1(+ R r))(recur C c(+(* 2 r)c)R))(+ R r)))

Well I was hoping the conversion from ASCII to bytes was shorter than this. The actual loop body is quite short, using r to accumulate the current result and R to accumulate the total result. If the previous bit p is 0 and the current bit c is 1 then we split a new chunk and accumulate to R, otherwise we update the r and keep R as it was.

\$\endgroup\$
0
\$\begingroup\$

Python 123 bytes

lambda w:sum(map(lambda x:int(x,2),"".join(map(lambda x:bin(ord(x))[2:].zfill(7),list(w))).replace("01","0:1").split(":")))

Updated, thanks to Martin Ender.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Welcome to PPCG! All answers need to be either full programs or callable functions (as opposed to snippets where the input is stored in a hardcoded variable). The function can be unnamed, though, so including a lambda w: would be enough to make your answer valid. \$\endgroup\$ Mar 28, 2018 at 21:51
  • \$\begingroup\$ Sorry, I probably didn't phrase that well. Your edit is still invalid because a) the input is hardcoded, b) If this is a full program, it doesn't actually print the result. For a full program you'd have to read the input from standard input or a command-line argument, and print the result to standard output. That's why I said it's probably easiest if you submit it as a function by adding lambda w:. \$\endgroup\$ Mar 30, 2018 at 10:22
  • \$\begingroup\$ Ohhh, Ok, i get it, it would be enough like this: f=lambda w:sum(map(lambda x:int(x,2),"".join(map(lambda x:bin(ord(x))[2:].zfill(7),list(w))).replace("01","0:1").split(":"))) \$\endgroup\$
    – ShadowCat
    Apr 4, 2018 at 17:15
  • \$\begingroup\$ yep, that's valid. You don't even need the f=, because we allow unnamed functions (unless you reference the function name for recursive calls). \$\endgroup\$ Apr 4, 2018 at 21:01
0
\$\begingroup\$

K (oK), 31 bytes

Solution:

+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$

Try it online!

Examples:

+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$,"a"
49
+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$"A4"
44
+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$"codegolf"
570
+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$"Hello, World!"
795

Explanation:

Convert to ASCII values, convert to 7-bit binary, flatten, find where differs, and against original list to find where 1s differ. Cut at these indices, convert back to decimal and sum up:

+/2/'_[;x]&x&~~':x:,/(7#2)\'`i$ / the solution
                            `i$ / convert to integer
                     (7#2)      / draw from 2, 7 times => 2 2 2 2 2 2 2
                          \'    / decode each (convert to binary)
                   ,/           / flatten
                 x:             / save as x
             ~~':               / not-not-each previous (differ)
            &                   / and with
           x                    / x
          &                     / indices where true
     _[;x]                      / projection, cut x at ...
  2/'                           / encode each (convert from binary)
+/                              / sum up

Bonus

Managed a 31 byte version in K4 too, but as there's no TIO for it I'm posting my oK solution.

+/2/:'_[;x]@&x&~~':x:,/1_'0b\:'
\$\endgroup\$
0
\$\begingroup\$

APL (Dyalog), 30 bytes

{+/2⊥¨(1∘+⊆⊢)∊¯7↑¨2⊥⍣¯1¨⎕UCS⍵}

Try it online!

How?

⎕UCS⍵ - Unicodify

2⊥⍣¯1¨ - encode each in binary

¯7↑¨ - and pad to the left with zeros to 7 places

- flatten

1∘+⊆⊢ - partition by self increased by one

2⊥¨ - decode each from binary

+/ - sum

\$\endgroup\$
0
\$\begingroup\$

Factor + math.unicode, 73 bytes

[ [ "%07b"sprintf ] map-concat R/ (?<=0)(?=1)/ re-split [ bin> ] map Σ ]

Try it online!

  • [ "%07b"sprintf ] map-concat Convert each code point in the input string to a 7-bit binary number string and join them all together.
  • R/ (?<=0)(?=1)/ re-split Split into a sequence of strings down the middle of every 01.
  • [ bin> ] map Σ Convert each from binary string to decimal integer and sum.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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