26
\$\begingroup\$

This is sequel to this challenge by Adnan. If you like this challenge, chances are you'll like the other one too. Check it out!


A multiple choice test with 8 questions each with 4 choices might have the answers: BCADBADA. Converted to four different arrays, with true and false if the current letter is the answer, it will look like this

Q#: 1  2  3  4  5  6  7  8
    B  C  A  D  B  A  D  A
A: [0, 0, 1, 0, 0, 1, 0, 1]
B: [1, 0, 0, 0, 1, 0, 0, 0]
C: [0, 1, 0, 0, 0, 0, 0, 0]
D: [0, 0, 0, 1, 0, 0, 1, 0]

This can be compressed using a bit of logic. Each of the choices A, B, C and D can be represented by two true/false values shown below:

A: 1 0
B: 0 1
C: 0 0
D: 1 1

Using this logic, we can compress the four vectors above to just two:

 1  2  3  4  5  6  7  8
 B  C  A  D  B  A  D  A
[0, 0, 1, 1, 0, 1, 1, 1]
[1, 0, 0, 1, 1, 0, 1, 0]

That is, the solution to your test is simply: 00110111, 10011010. By concatenating these, we get the binary number 0011011110011010, or 14234 in decimal. Use this decimal value to cheat on your test!

Challenge

Take a number N in the (inclusive) range [0, 65535], and output a string with the answer to the multiple choice test.

Test cases:

14234
BCADBADA

38513
ABBDCAAB    

0
CCCCCCCC

120
CBBBBCCC

65535
DDDDDDDD

39253
ABCDABCD

The output may be in upper or lower case letters, but you can not use other symbols.

\$\endgroup\$
  • \$\begingroup\$ Does the output have to be the string as shown, or can the letters be on separate lines, in a list, etc? \$\endgroup\$ – xnor Sep 25 '16 at 16:47
  • \$\begingroup\$ @xnor Optional :-) \$\endgroup\$ – Stewie Griffin Sep 25 '16 at 17:10
  • \$\begingroup\$ Why not the obvious A=00,B=01,C=10,D=11? \$\endgroup\$ – user253751 Sep 26 '16 at 1:57
  • \$\begingroup\$ The reason was I first made A=10, B=01, then C=nor(A,B), and D=and(A,B), inspired by Adnan's challenge. In hindsight it might have been better to do it the other way around, but well... Too late now... \$\endgroup\$ – Stewie Griffin Sep 26 '16 at 6:35

13 Answers 13

3
\$\begingroup\$

Jelly, 14 bytes

d⁹+⁹BZḄḊị“BADC

Try it online! or verify all test cases.

How it works

d⁹+⁹BZḄḊị“BADC  Main link. Argument: n

d⁹              Divmod 256; yield [n : 256, n % 256].
  +⁹            Add 256; yield [n : 256 + 256, n % 256 + 256].
    B           Binary; convert both integers to base 2.
     Z          Zip; group the quotient bits with corresponding remainder bits.
      Ḅ         Unbinary; convert from base 2 to integer.
       Ḋ        Dequeue; discard the first integer, which corresponds to the
                dummy value introduced by adding 256 to quotient and remainder.
        ị“BADC  Index into that string, mapping [1, 2, 3, 0] to "BADC".
\$\endgroup\$
10
\$\begingroup\$

05AB1E, 19 18 16 bytes

Code:

žH+b¦2äøC’c‰±’sè

Uses the CP-1252 encoding. Try it online!

Explanation:

First, we add 65536 to the number (žH is a constant defined to 65536), which is also 10000000000000000 in binary. This is to pad the number with zeroes. Let's take the number 14234 as an example. 14234 + 65536 is equal to 79770. Which in binary is:

10011011110011010

We remove the first character, resulting in:

0011011110011010

We split the string into two pieces using :

00110111, 10011010

After that, we zip the array with ø:

01, 00, 10, 11, 01, 10, 11, 10

Converting them back into decimal (using C) results in:

1, 0, 2, 3, 1, 2, 3, 2

Now, we only need to index it with the string cbad. The compressed version for this string is ’c‰±’, which can also be tested here. Finally, we get the characters at the index of the above array. For the above example, this results in:

1, 0, 2, 3, 1, 2, 3, 2
b  c  a  d  b  a  d  a
\$\endgroup\$
6
\$\begingroup\$

JavaScript (ES6), 55 48 bytes

f=(n,i=8)=>i--?"CBAD"[n>>i&1|n>>i+7&2]+f(n,i):''

console.log(f(14234)); // BCADBADA
console.log(f(38513)); // ABBDCAAB
console.log(f(0));     // CCCCCCCC
console.log(f(120));   // CBBBBCCC
console.log(f(65535)); // DDDDDDDD
console.log(f(39253)); // ABCDABCD

Non-recursive version (55 bytes)

Using a regular expression, we can do:

n=>"76543210".replace(/./g,i=>"CBAD"[n>>i&1|n>>+i+7&2])
\$\endgroup\$
  • \$\begingroup\$ How did you think of doing the bitwise operations? \$\endgroup\$ – ericw31415 Sep 25 '16 at 19:26
  • \$\begingroup\$ @ericw31415 - Even if it's not doing so explicitly, the challenge is actually describing these bitwise operations in reverse order (starting at "This can be compressed using a bit of logic.") \$\endgroup\$ – Arnauld Sep 25 '16 at 20:09
  • 3
    \$\begingroup\$ ...a bit of logic... \$\endgroup\$ – Neil Sep 26 '16 at 9:16
4
\$\begingroup\$

Python 2, 53 bytes

f=lambda n,k=8:k*'_'and f(n/2,k-1)+'CBAD'[n>>7&2|n&1]

Test it on Ideone.

\$\endgroup\$
  • \$\begingroup\$ I was trying to use (n&257)%127 but it's longer. Too bad 127 is prime. Maybe you can think of a way to optimize it. \$\endgroup\$ – xnor Sep 25 '16 at 18:13
4
\$\begingroup\$

CP-1610 assembly, 24 DECLEs (30 bytes)

This code is intended to be run on an Intellivision. (1)

A CP-1610 opcode is encoded with a 10-bit value, known as a 'DECLE'. The actual function is 24 DECLEs long, starting at $4809 and ending at $4820.

The CPU registers are however 16-bit wide, so it will support any input value in 0x0000 .. 0xFFFF.

                            ROMW  10            ; use 10-bit ROM
                            ORG   $4800         ; start program at address $4800
4800 0002                   EIS                 ; enable interrupts (to enable display)

                    ;; ---- usage example
4801 0001                   SDBD                ; load parameter in R0
4802 02B8 009A 0037         MVII  #14234, R0    ;
4805 0004 0148 0009         CALL  cheat         ; call function
4808 0017                   DECR  PC            ; infinite loop

                    ;; ---- 'Cheat Your Test' function
                    cheat   PROC  

4809 0082                   MOVR  R0,     R2    ; copy R0 to R2
480A 0040                   SWAP  R0            ; swap LSB/MSB in R0
480B 02BC 0214              MVII  #$214,  R4    ; R4 = pointer to 2nd row of screen memory

480D 01DB           @@loop  CLRR  R3            ; clear R3
480E 0052                   RLC   R2            ; extract highest bit of R2 to carry
480F 0053                   RLC   R3            ; inject carry into R3
4810 0050                   RLC   R0            ; extract highest bit of R0 to carry
4811 0053                   RLC   R3            ; inject carry into R3
4812 0001                   SDBD                ; add pointer to lookup table to R3
4813 02FB 001D 0048         ADDI  #@@tbl, R3    ;
4816 029B                   MVI@  R3,     R3    ; read character value
4817 0263                   MVO@  R3,     R4    ; write it to screen memory (also does R4++)
4818 037C 021C              CMPI  #$21C,  R4    ; 8 characters written? ...
481A 0225 000E              BLT   @@loop        ; ... if not, jump to @@loop

481C 00AF                   JR    R5            ; return

481D 011F 0117      @@tbl   DECLE $11F, $117    ; characters 'B', 'C', 'A' and 'D'
481F 010F 0127              DECLE $10F, $127    ; in white, using the built-in font

                            ENDP

Output

screenshot


(1) Granted that at least one compiler, several emulators and copyright-free replacement ROM files are freely available, I think that it doesn't infringe any PPCG submission rule. But please let me know if I'm wrong.

\$\endgroup\$
  • 1
    \$\begingroup\$ We score in bytes, so add up the total number of bits, and your score is the decimal (float) result of dividing that value by eight. In this case, 27.5 bytes. \$\endgroup\$ – mbomb007 Sep 26 '16 at 20:31
3
\$\begingroup\$

CJam, 22 bytes

ri2bG0e[8/:.{1$=)^'A+}

Try it online!

Explanation

Powered by magic...

The mapping of bit pairs to letters in this challenge is a bit arbitrary. If we represent ABCD by 0, 1, 2, 3 (so we can just add them to the character A) then we want the following mapping:

i1   i2   o
0    0    2
0    1    1
1    0    0
1    1    3

This mapping can be computed with a magical little formula: ((i1 == i2) + 1) ^ i1, where the equality check returns 0 or 1. Check out the following table, where each column corresponds to one input, each row corresponds to one operation, and each cell will show the stack at that point:

[i1, i2]:  [0, 0]     [0, 1]     [1, 0]     [1, 1]
copy i1:   [0, 0, 0]  [0, 1, 0]  [1, 0, 1]  [1, 1, 1]
equals:    [0, 1]     [0, 0]     [1, 0]     [1, 1]
inc:       [0, 2]     [0, 1]     [1, 1]     [1, 2]
xor:       [2]        [1]        [0]        [3]

With that in mind here is the full breakdown of the source code:

ri     e# Read input, convert to integer.
2b     e# Get binary representation.
G0e[   e# Pad to 16 bits with zeros.
8/     e# Split into two halves of 8 bits each.
:.{    e# For each pair of bits, i1 and i2...
  1$   e#   Copy i1.
  =    e#   Check equality with i2.
  )    e#   Increment.
  ^    e#   Bitwise XOR.
  'A+  e#   Add to 'A'
}

An alternative solution with the same byte count which is decidedly less magical:

ri2bG0e[8/z2fb"CBAD"f=

And in case it's useful to anyone, if you turn the i1 and i2 bits back into a single number (i.e. when you want the mapping 0 -> 2, 1 -> 1, 2 -> 0, 3 -> 3) this can be computed even more easily as (~n - 1) & 3 or (~n - 1) % 4 if your language gets modulo on negative values right. I think this can be written concisely as 3&~-~n in many languages. In CJam this turns out to be a byte longer, because of the additional conversion back from base 2.

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

PHP, 57 Bytes

for($i=8;$i--;)echo CBAD[($n=$argv[1])>>$i+7&2|$n>>$i&1];

Version without Bitwise operators 70 Bytes

for(;$i<8;)echo CABD[($s=sprintf("%016b",$argv[1]))[$i]+$s[8+$i++]*2];
\$\endgroup\$
  • \$\begingroup\$ Where is variable $i defined? \$\endgroup\$ – ericw31415 Sep 25 '16 at 16:08
  • \$\begingroup\$ @ericw31415 In the first use of a variable is initialized and automatically declared PHP this variable with a null reference \$\endgroup\$ – Jörg Hülsermann Sep 25 '16 at 16:45
  • \$\begingroup\$ That's PHP (tm) \$\endgroup\$ – tomsmeding Sep 25 '16 at 21:57
3
\$\begingroup\$

Mathematica, 75 73 68 66 bytes

StringPart["CBAD",#+##+1]&@@IntegerDigits[#,2,16]~Partition~8<>""&

Thanks to @MartinEnder for saving 2 bytes.

\$\endgroup\$
  • \$\begingroup\$ @MartinEnder #+## and Infix work, but using StringPart is inevitable because the head of "C"["B","A","D"][[#+##]] is "C", not List; StringJoin doesn't work. \$\endgroup\$ – JungHwan Min Sep 25 '16 at 18:40
  • 1
    \$\begingroup\$ Oh, I didn't realise that # and #2 were the entire lists. \$\endgroup\$ – Martin Ender Sep 25 '16 at 18:43
3
\$\begingroup\$

Perl, 42 bytes

Includes +1 for -n

Give input on STDIN:

perl -nE 'say+(A..D)[2-($`>>8-$_&257)%127]for/$/..8' <<< 39253

Just the code:

say+(A..D)[2-($`>>8-$_&257)%127]for/$/..8
\$\endgroup\$
3
\$\begingroup\$

JavaScript, 113 93 90 88 bytes

A big thanks to @Neil for helping me save 20 bytes!
-3 bytes thanks to @Cyoce

n=>{r="";b=("0".repeat(15)+n.toString(2)).slice(-16);for(i=0;i<8;i++)r+="CBAD"[parseInt(b[i]+b[i+8],2)];return r}

n=>{r="";b=(65536+n).toString(2).slice(1);for(i=0;i<8;i++)r+="CBAD"[+b[i+8]+2*b[i]];return r}

n=>eval('r="";b=(65536+n).toString(2).slice(1);for(i=0;i<8;i++)r+="CBAD"[+b[i+8]+2*b[i]]')

n=>eval('r="";b=n.toString(2).padStart(16,0);for(i=0;i<8;i++)r+="CBAD"[+b[i+8]+2*b[i]]')

Sadly, JavaScript lacks functions like decbin, bindec, and str_pad that PHP has.

\$\endgroup\$
  • 1
    \$\begingroup\$ (65536+n).toString(2).slice(1) and [+b[i+8]+2*b[i]] would be shorter, for example. \$\endgroup\$ – Neil Sep 26 '16 at 9:21
  • \$\begingroup\$ padStart, should it be accepted into a future version of ECMAscript, would result in a bigger saving. \$\endgroup\$ – Neil Sep 26 '16 at 9:24
  • 1
    \$\begingroup\$ Instead of {…;return }, use eval("…") \$\endgroup\$ – Cyoce Oct 2 '16 at 16:55
  • \$\begingroup\$ @Neil It seems that padStart now exists in ECMAScript. \$\endgroup\$ – ericw31415 Dec 2 '17 at 0:41
1
\$\begingroup\$

MATL, 16 bytes

16&B8eXB'BADC'w)

Try it Online!

or Verify all test cases

Explanation

        % Implicitly grab input
16&B    % Convert to binary string with at least 16 bits
8e      % Reshape the resulting string to have 8 rows and 2 columns
XB      % Convert each row from binary to decimal
'BADC'  % Push this string literal
w)      % Use the decimal numbers to index into this string (modular indexing)
        % Implicitly display the resulting string
\$\endgroup\$
1
\$\begingroup\$

Julia, 73 Bytes

Gives a function f taking N as input and returning the answer as string.

f(N)=(b=bin(N,16);join(["CBAD"[parse("0b$(b[i])$(b[i+8])")+1]for i=1:8]))

Try it

Depending if a char array counts as string, one can omit the join (67 Bytes)

f(N)=(b=bin(N,16);["CBAD"[parse("0b$(b[i])$(b[i+8])")+1]for i=1:8])

Try it

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

R, 110 bytes

Came up with a vectorized solution in R. This should probably by golfable by coming up with a smarter conversion int to binary conversion.

x=as.integer(intToBits(scan()));cat(LETTERS[1:4][match(paste0(x[16:9],x[8:1]),c("10","01","00","11"))],sep="")
\$\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.