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
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.
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 code-golf, 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
6 Answers 6
Jelly, (削除) 36 (削除ここまで) 29 bytes
BUḟ0ドル"24HBSI"s2jœr1ɗẎḊḢ$?€ɗƒU
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.
Charcoal, (削除) 42 (削除ここまで) 41 bytes
≔−I⮌↨N20θF24HBSI≔E⪪θ2⪫⮌EΦκ∨μ¬ν⎇∧ν=μ1ωμιθθ
Try it online! Link is to verbose version of code. Supports numbers from 1
to 18446744073709551615
. Explanation:
≔−I⮌↨N20θ
Convert the input to a list of 1
s and empty strings according to the reverse of its binary representation.
F24HBSI
Loop over the additional possible "digits".
≔E⪪θ2⪫⮌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.
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
Your 232-1 case seems wrong
-
\$\begingroup\$ You're right, I forgot the
B
layer. I'll fix it. \$\endgroup\$Tbw– Tbw2023年12月22日 01:07:43 +00:00Commented Dec 22, 2023 at 1:07
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)
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.
Jelly, 42 bytes
l2l2Ḟ
WμÇ2*2*8d×ばつnJaƲ1Ƈ)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*8d×ばつnJaƲ1Ƈ)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
8 ɗ - last three links as a dyad - f(V, D):
9 - 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}
1Ƈ - 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
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]]
1
s in the correct places). \$\endgroup\$101100
, how did you decide to split it into10,1100
and not into1,01100
or101,100
? \$\endgroup\$