16
\$\begingroup\$

Introduction

In the video the best way to count, binary is proposed as the best system of counting numbers. Along with this argument is a proposal on how to say numbers in this system. First, we give names to each "double power of two", \$2^{2^n}\$ for each \$n\$.

number = symbol = spoken
============================
2^0    = 1      = "one"
2^1    = 2      = "two"
2^2    = 4      = "four"
2^4    = H      = "hex"
2^8    = B      = "byte"
2^16   = S      = "short"
2^32   = I      = "int"
2^64   = L      = "long"
2^128  = O      = "overlong"
2^256  = P      = "byteplex"

Then, to get from a number to its spoken binary, we

  1. Take its (big-endian) bit string and break off bits from the end equal to the number of zeros in the largest double power of two less than or equal to the number.

  2. Use the name for the corresponding double power of two in the middle, and recursively name the left and right parts through the same procedure. If the left part is one, it is not spoken, and if the right part is zero, it is not spoken.

This system is similar to how we normally read numbers: 2004 -> 2 "thousand" 004 -> "two thousand four".

For example, 44 in binary is 101100. Split at four bits from the end and insert "hex", meaning \$2^4\$: 10 "hex" 1100. 10 becomes "two" and 1100 splits into 11 "four" 00, or "two one four". So the final number is "two hex two one four" or 2H214 in symbols (note that this is not the recommended way of writing numbers, just speaking).

As a longer example, we have one thousand:

1111101000
11 B 11101000
2 1 B 1110 H 1000
2 1 B 11 4 10 H 10 4 00
2 1 B 2 1 4 2 H 2 4

Challenge

Your program must take a positive integer \$n\$ as input and output the string of symbols for the spoken binary of that number.

While numbers under \$2^{512}\$ are expressible in this system, you only need to handle integers up to and including \$2^{32}\$ = I, and as such, do not need to consider L, O, or P.

Standard loopholes are forbidden. As this is , shortest program wins.

Example Input and Output

1 -> 1
2 -> 2
3 -> 21
4 -> 4
5 -> 41
6 -> 42
7 -> 421
8 -> 24
9 -> 241
10 -> 242
11 -> 2421
12 -> 214
25 -> H241
44 -> 2H214
100 -> 42H4
1000 -> 21B2142H24
4294967295 -> 21421H21421B21421H21421S21421H21421B21421H21421
4294967296 -> I
\$\endgroup\$
16
  • \$\begingroup\$ May the input be taken as a list/string of binary digits? \$\endgroup\$ Commented Dec 21, 2023 at 22:21
  • 1
    \$\begingroup\$ I was actually looking for justification of the rule, but I worked out that not having the rule changes the problem into something else (all numbers can take the form ...242H242B242H242 and the value comes from inserting 1s in the correct places). \$\endgroup\$
    – Neil
    Commented Dec 22, 2023 at 0:20
  • 1
    \$\begingroup\$ Hi. Would you please consider adding a second different wording for "Take its (big-endian) bit string and break off bits from the end equal to largest power of two that can split the bit string into two parts."? I struggle to understand what is meant. What does "can split the bit string into two parts" mean? Looking at the example 101100, how did you decide to split it into 10,1100 and not into 1,01100 or 101,100? \$\endgroup\$
    – Stef
    Commented Dec 22, 2023 at 11:51
  • 1
    \$\begingroup\$ Regarding my previous comment, I can guess that maybe "Find the largest power of 2 which has a symbol and is less than or equal to the number" could be it? \$\endgroup\$
    – Stef
    Commented Dec 22, 2023 at 11:57
  • 1
    \$\begingroup\$ The narrator of TBWTC approves :) \$\endgroup\$
    – kepe
    Commented Dec 25, 2023 at 9:21

6 Answers 6

3
\$\begingroup\$

Jelly, 36 29 bytes

BUḟ€0“24HBSI”s2jœr1ɗẎḊḢ$?€ɗƒU

Try it online!

A full program that takes a single positive integer argument and prints the spoken binary form to STDOUT.

Explanation

BUḟ€0“24HBSI”s2jœr1ɗẎḊḢ$?€ɗƒU⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏⁠‎⁡⁠⁤⁡‏⁠‎⁡⁠⁢⁣⁤‏⁠‎⁡⁠⁢⁤⁡‏‏​⁡⁠⁡‌⁢⁡​‎‎⁡⁠⁤⁢‏⁠‎⁡⁠⁤⁣‏‏​⁡⁠⁡‌⁢⁢​‎‎⁡⁠⁢⁣⁣‏⁠‏​⁡⁠⁡‌⁢⁣​‎‎⁡⁠⁢⁢⁢‏⁠‎⁡⁠⁢⁢⁣‏⁠‎⁡⁠⁢⁢⁤‏⁠‎⁡⁠⁢⁣⁡‏⁠‎⁡⁠⁢⁣⁢‏‏​⁡⁠⁡‌⁢⁤​‎‎⁡⁠⁤⁤‏‏​⁡⁠⁡‌⁣⁡​‎‎⁡⁠⁢⁡⁡‏⁠‎⁡⁠⁢⁡⁢‏⁠‎⁡⁠⁢⁡⁣‏‏​⁡⁠⁡‌⁣⁢​‎‎⁡⁠⁢⁢⁡‏⁠‎⁡⁠⁣⁤⁣‏⁠‎⁡⁠⁢⁡⁢⁤⁤‏‏​⁡⁠⁡‌⁣⁣​‎‎⁡⁠⁢⁤⁢‏⁠‏​⁡⁠⁡‌­
B                             # ‎⁡‎⁡Convert to binary
 U                            # ‎⁢‎⁢Reverse
  ḟ€0                         # ‎⁣Filter out 0 from each
     “24HBSI”             ɗƒ  # ‎⁤‎⁢⁢Starting with this, reduce using each character in "24HBSI" as the right argument in turn and the following:
             s2               # ‎⁢⁡- Split into pieces of length 2
                         €    # ‎⁢⁢- For each piece:
                     ḊḢ$?     # ‎⁢⁣  - If length 2 and the second part is non-empty:
               j              # ‎⁢⁤    - Join with the relevant character
                œr1           # ‎⁣⁡    - Trim 1s from the end
                    Ẏ         # ‎⁣⁢  - Else: join outer lists
                            U # ‎⁣⁣Reverse order of final string (and implicit smashing print)
💎

Created with the help of Luminespire.

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 42 41 bytes

≔⁻I⮌↨N²0θF24HBSI≔E⪪θ²⪫⮌EΦκ∨μ¬ν⎇∧ν⁼μ1ωμιθθ

Try it online! Link is to verbose version of code. Supports numbers from 1 to 18446744073709551615. Explanation:

≔⁻I⮌↨N²0θ

Convert the input to a list of 1s and empty strings according to the reverse of its binary representation.

F24HBSI

Loop over the additional possible "digits".

≔E⪪θ²⪫⮌EΦκ∨μ¬ν⎇∧ν⁼μ1ωμιθ

Group the existing digit blocks into pairs, then for each pair, create a new digit block by removing any second part if it is zero, or making it the empty string if it is one, switching the parts, and joining on the next digit.

θ

Output the final result.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 84 79 77 bytes

f=(n,k=6,y=1,u=2**2**--k)=>n<y?'':~k?f(n/u,k,2)+['24HBSI'[n<u||k]]+f(n%u,k):1

Try it online!

Your 232-1 case seems wrong

\$\endgroup\$
1
  • \$\begingroup\$ You're right, I forgot the B layer. I'll fix it. \$\endgroup\$
    – Tbw
    Commented Dec 22, 2023 at 1:07
2
\$\begingroup\$

R, 129 bytes

\(x,`~`=paste0)Reduce(\(y,z)apply(matrix(y,2),2,\(w)gsub("^0*[1"~z~"]|0","",w[1]~z~w[2])),c(2,4,"H","B","S","I"),x%/%2^(63:0)%%2)

Attempt This Online!

An R translation (more-or-less) of my Jelly answer. A function that takes a single positive integer and returns the spoken binary form as a string.

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

Jelly, 42 bytes

l2l2Ḟ
WµÇ2*2*⁸d⁹jɗ×nJaƲ¹Ƈ)F$ÐLÇ»-ị“4HBSI12

A full program that accepts a positive integer and prints the spoken binary.

Try it online! Or see the test-suite.

How?

l2l2Ḟ - Link 1: integer, X -> floor(X log 2 log 2)
          Note when X = 1 l2l2 -> (-inf + nan j) and Ḟ takes the real part -> -inf

WµÇ2*2*⁸d⁹jɗ×nJaƲ¹Ƈ)F$ÐLÇ»-ị“4HBSI12 - Main Link: positive integer P
W                                    - wrap P in a list
                      ÐL             - apply while distinct:
                     $               -   last two links as a monad - f(Current):
 µ                 )                 -     for each {V in Current}:
  Ç                                  -       call Link 1 -> floor(V log 2 log 2)
   2*                                -       2 exponentiate {that}
     2*                              -       2 exponentiate {that}
                                               -> value of the digit to use, say D
       ⁸    ɗ                        -       last three links as a dyad - f(V, D):
         ⁹                           -         D
        d                            -         {V} div-mod {D}
          j                          -         join {that} with {D}
                Ʋ                    -       last four links as a monad - f(Parts=that):
              J                      -         indices {Parts} -> [1,2,3]
             n                       -         {Parts} not equal {that} (vectorises)
            ×                        -         {Parts} multiply {that} (vectorises)
               a                     -         {that} logical AND {Parts}
                 ¹Ƈ                  -       keep truthy values
                    F                -     flatten
                        Ç            - call Link 1 (vectorises)
                         »-          - max with -1 (convert -inf to -1)
                           ị“4HBSI12 - index into (1-based & modular) "4HBSI12"
                                     - implicit print
\$\endgroup\$
1
\$\begingroup\$

Haskell, 115 bytes

p=[2^2^i|i<-[6,5..0]]
c=concat
f x=c[c[f y|y>1]++c[[l]|y>0]|(l,n,m)<-zip3"ISBH421"p$tail p++[1],y<-[mod x n`div`m]]

Try it online!

\$\endgroup\$

Your Answer

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

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