9
\$\begingroup\$

Eyeballing the binary values printed as ovals and sticks is not so easy... To help with that, you must write a function (or a program) that prints numbers in custom binary representation.
So I want to take a number, say 3 (00000011) and output the bits in user-defined format, for example with space separated pairs:

00 00 00 11

or, say, in reversed order and with some decorators, e.g.:

11_00_00_00

Furthermore, there must be possibilty to show '0' and '1' as custom characters to distinguish them better, e.g.:

XX oo oo oo

So the challenge is to write the code which does that all whithin the following specification.

Specification

The function takes input like this: f(A, mask, zeros, ones)

Parameters:

A -- input number -- any (unsigned) integer in range 0-255.
mask -- a string parameter which defines the construction of the output.
zeros -- a string of the same length, defines 'zero' glyphs for each output slot.
ones -- a string of the same length, defines 'one' glyphs for each output slot.

Rules for the output construction:

Look at this image with example closely to understand how the output is generated:

enter image description here

So only the single digits in the mask are parsed and replaced by corresponding bits of A, other characters are left as is. Further, if the value of the taken bit is 1 then it shows up in the final output as "X" and if it is 0 then it shows up as "o". In the above example all four taken bits are "1" so we see "X" in all slots.

If the input number was 128, then, logically, the output would be X foo bar ooo. Characters in parameters "zeros" and "ones": any printable ASCII chars, assume they are always char-aligned with the mask.

Notes:

  • Bits are 0-indexed: 0th bit is the MSB.
  • Assume that digits 8,9 are not allowed in the mask string.
  • Input Strings include any printable ASCII chars.
  • 'Zeros' and 'ones' are char-aligned with the mask.
  • For special characters/modifiers in your language: we can assume they will not appear in the input string.

For the clarity, see more examples.

Input -> Output examples

Output all 8 bits in common order with a space delimiter, in common oval-and-stick notation:

mask  =  "0123 4567"  
zeros =  "0000 0000"  
ones  =  "1111 1111"  

A=1 ->    0000 0001


Output in reversed order, in dash-and-glyph notation:

mask =    "| 7654 3210 |"
zeros=    "  ---- ----  "
ones =    "  ssss ssss  "

A=1  ->    | s--- ---- |
A=3   ->   | ss-- ---- |
A=128->    | ---- ---s |


Diverse notations in one output, e.g. for packed data:

mask =       "0 | 123 4567"
zeros=       "    --- ----"
ones =       "X   kkk ssss"

A= 15  ->       | --- ssss
A= 16  ->       | --k ----
A= 32  ->       | -k- ----
A= 128 ->     X | --- ----
A= 255 ->     X | kkk ssss


Repeating patterns:

mask =    "| 7 66 555 4444 |"
zeros=    "  . .. ... ....  "
ones =    "  0 00 000 0000  "

A= 0 ->    | . .. ... .... |
A= 1 ->    | 0 .. ... .... |
A= 2 ->    | . 00 ... .... |
A= 3 ->    | 0 00 ... .... |
A= 4 ->    | . .. 000 .... |

Update

The rules have been slightly simplified - the program must print one number only (not array/list of numbers as it was proposed initially).

\$\endgroup\$
  • \$\begingroup\$ Can we also submit a program that accepts the four inputs? Some languages don't do functions too well. \$\endgroup\$ – Stephen May 27 '17 at 1:14
  • \$\begingroup\$ @StephenS I suppose yes, but I am not sure I'll understand those :/ \$\endgroup\$ – Mikhail V May 27 '17 at 1:17
  • 2
    \$\begingroup\$ The last two arguments seem entirely irrelevant in most languages, why not just require 1 and 0? The first argument being a list doesn't seem to do much besides make regular languages add a simple loop/recursion while making it much harder for more esoteric languages to compete. \$\endgroup\$ – FryAmTheEggman May 27 '17 at 1:21
  • \$\begingroup\$ @MikhailV if you want to understand all of the submissions on your challenges, good luck :/ most of them have TryItOnline links so you can see them works, but they most golfing languages look like nonsense until you know what they do \$\endgroup\$ – Stephen May 27 '17 at 1:22
  • \$\begingroup\$ @FryAmTheEggman I also don't understand what A does, since it is the same in all of the test cases \$\endgroup\$ – Stephen May 27 '17 at 1:22
2
\$\begingroup\$

JavaScript (ES6), 57 bytes

(A,M,O,I)=>M.replace(/[\d]/g,(d,i)=>(A>>7-d)%2?I[i]:O[i])

f=
(A,M,O,I)=>M.replace(/[\d]/g,(d,i)=>(A>>7-d)%2?I[i]:O[i])

console.log( f(1, "0123 4567", "0000 0000", "1111 1111") )
console.log( f(3, "| 7654 3210 |", "  ---- ----  ", " ssss ssss ") )
console.log( f(4, "| 7 66 555 4444 |", "  . .. ... ....  ", "  0 00 000 0000  ") )

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

Ruby, 48 bytes

->a,f,*b{f.gsub(/\d/){b[a[55-$&.ord]][$`.size]}}

The zeroes and ones parameters are treated as an array (*b) and with the zeroes parameter is stored in b[0] and the ones parameter stored in b[1].

The mask parameter f has each digit (/\d/) substituted with a character from the appropriate array. The special variable $`, which holds the text leading up to the current match, is (ab)used here to keep track of position.

Ruby's bit indexing calls 0 the least-significant bit, but the challenge calls 0 the most significant bit. ASCII subtraction from 55 (the '7' character) yields a usable Ruby bit index.

Try it online!

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

Perl 6, 60 bytes

->\a,$_,\o,\z{S:g|\d|{substr (z,o)[a+>(7-$/)%2],$/.from,1}|}
\$\endgroup\$
1
\$\begingroup\$

Python, 97 bytes

lambda A,M,Z,O:"".join([[Z,O][1&(A>>7-int(d))][i] if d.isdigit() else d for i,d in enumerate(M)])
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 131 bytes

""<>Table[(f/@{##2})[[x[[i]],i]],{i,Length[x=(f=Characters)@#2/.Table[ToString@i->2+Floor[#/2^(7-i)]~Mod~2,{i,0,7}]/._String->1]}]&
\$\endgroup\$
  • \$\begingroup\$ Length[x] can be Length@x and {#2,#3,#4} can be {##2}. \$\endgroup\$ – CalculatorFeline May 27 '17 at 16:16
  • \$\begingroup\$ Also, StringJoin@@ can just be StringJoin@ and #1 is just # \$\endgroup\$ – CalculatorFeline May 27 '17 at 16:45
  • \$\begingroup\$ I've simplified the rules slightly, see update. \$\endgroup\$ – Mikhail V May 27 '17 at 22:35
1
\$\begingroup\$

q/kdb+, 86 64 bytes

Solution:

f:{[A;M;Z;O]@[M;m;:;((-8#0b vs A)"I"$'M m)(Z;O)'m:(&)M in .Q.n]}

Examples:

q)f[1;"0123 4567";"0000 0000";"1111 1111"]
"0000 0001"
q)f[1;"| 7654 3210 |";"  ---- ----  ";"  ssss ssss  "]
"| s--- ---- |"
q)f[15;"0 | 123 4567";"    --- ----";"X   kkk ssss"]
"  | --- ssss"
q)f [0;"| 7 66 555 4444 |";"  . .. ... ....  ";"  0 00 000 0000  "]
"| . .. ... .... |"

Explanation:

Pull out indices where input mask M is a numeral, call it m this is where we will be modifying the input mask. Take the numerals out of the string, cast to integers and then index into our 8-bit array to get the correct ordering. Use this 8-bit array to index into either O (if 1 is set) or Z (if 0 is set), and then index into these lists at the indices given by m. Finally apply (:) this new list to the original mask at indices m.

{[A;M;Z;O]                                                   } / lambda function with 4 parameters
          @[ ; ; ;                                          ]  / apply, applies 3rd parameter to 1st parameter at indexes from parameter 2 with parameter 4 :)
                   (-8#0b vs A)                                / convert input number to binary (64 bit), take the last 8 items
                                              m:(&)M in .Q.n   / returns indices where mask is in "0123..789", stores in variable m
                               "I"$'M m                        / index into mask at indices m, then cast these numbers to an integer array
                  (                    )                       / we then index into our 8 bits a these offsets to get the output order
                                        (Z;O)                  / 2-item list of the zeroes and ones mask
                                             '                 / take each item on the left and right and apply them to (Z;O) (ie index in at 0 / 1 and then 123..67)
            M m :                                              / apply *this* list to M at each index given by m

Notes:

Could shave off a further 14 bytes if we were allowed to give the arguments in the form:

[A;M;(Z;O)]

as q allows for up to 3 arguments to be given to a function without being explicitly named (they are x, y and z respectively):

f:{@[y;m;:;((-8#0b vs x)"I"$'y m)z'm:(&)y in .Q.n]}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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