# Cheating a multiple choice test, part 2

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

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.

• Does the output have to be the string as shown, or can the letters be on separate lines, in a list, etc?
– xnor
Sep 25, 2016 at 16:47
• @xnor Optional :-) Sep 25, 2016 at 17:10
• Why not the obvious A=00,B=01,C=10,D=11? Sep 26, 2016 at 1:57
• 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... Sep 26, 2016 at 6:35

# 05AB1E, 1918 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 2ä:

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


## JavaScript (ES6), 55 48 bytes

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

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])

• How did you think of doing the bitwise operations? Sep 25, 2016 at 19:26
• @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.") Sep 25, 2016 at 20:09
• ...a bit of logic...
– Neil
Sep 26, 2016 at 9:16

# 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.

• 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.
– xnor
Sep 25, 2016 at 18:13

## 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 (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.

• 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. Sep 26, 2016 at 20:31

# Jelly, 14 bytes

d⁹+⁹BZḄḊị“BADC


### 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".


## 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:      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.
}


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.

# PHP, 57 Bytes

for($i=8;$i--;)echo CBAD[($n=$argv)>>$i+7&2|$n>>$i&1];  Version without Bitwise operators 70 Bytes for(;$i<8;)echo CABD[($s=sprintf("%016b",$argv))[$i]+$s[8+$i++]*2];  • Where is variable $i defined? Sep 25, 2016 at 16:08
• @ericw31415 In the first use of a variable is initialized and automatically declared PHP this variable with a null reference Sep 25, 2016 at 16:45
• That's PHP (tm) Sep 25, 2016 at 21:57

# Mathematica, 757368 66 bytes

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


Thanks to @MartinEnder for saving 2 bytes.

• @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. Sep 25, 2016 at 18:40
• Oh, I didn't realise that # and #2 were the entire lists. Sep 25, 2016 at 18:43

# 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


# JavaScript, 1139390 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.

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

# MATL, 16 bytes

16&B8eXB'BADC'w)


Try it Online!

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


# 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

## 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="")