Sign up ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Given any unsigned 16 bit integer, convert its decimal form (i.e., base-10) number into a 4x4 ASCII grid of its bits, with the most-significant bit (MSB) at the top left, least-significant bit (LSB) at bottom right, read across and then down (like English text).

Examples

Input: 4242

+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
| # |   |   | # |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+

Input: 33825

+---+---+---+---+
| # |   |   |   |
+---+---+---+---+
|   | # |   |   |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+

Specific Requirements

  1. Input must be in decimal (base-10), however you may convert to binary any way you wish (including using language built-ins, if available).

  2. Output table format must match exactly. This means you must use the specific ASCII characters (-, +, and |) for the table grid lines as shown, each cell's interior is 3 characters, and true bits are represented by # while false is represented by a space ().

  3. Leading or trailing whitespace is not permitted. Final newline is required.

  4. Bit order must match the examples as described.

Allowances

  1. Input must be a base-10 number on the command line, standard input, or user input, but must not be hard-coded into your source code.

May the clearest shortest code win! :-)

share|improve this question
1  
Related –  Sp3000 yesterday
1  
The first sentence sounds confusing to me, where it says "convert its decimal form". Based on the rest of the post and the example, it looks like the input is given in decimal form, but you have to convert the binary form of the value into a grid. –  Reto Koradi yesterday
    
@RetoKoradi you are essentially correct, but the question does require you to convert a decimal number into a binary grid. There is no explicit requirement to ever work with a binary number, only a likely implementation detail. –  type_outcast yesterday
    
Does writing a function with the base-10 number as the function argument count as user input? –  Alex A. yesterday
1  
Since you say that the given number is an "unsigned 16 bit integer", it is by definition in binary form. When I first read this, it actually sounded like the input would be given in binary form. It all becomes clear towards the end. But at least for me, the first paragraph really doesn't capture the problem at all. –  Reto Koradi yesterday

17 Answers 17

J, 26 bytes

('   ';' # '){~4 4$_16{.#:

An anonymous verb. Thankfully, J is very good at drawing boxes. Let's try it out:

   f =. ('   ';' # '){~4 4$_16{.#:
   f 4242
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
| # |   |   | # |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+

As some commenters have mentioned, the way J draws boxes is system-dependent: on some platforms, this code will work under the default settings, but on others, the boxes will be drawn using Unicode line drawing characters. (The commands 9!:6 and 9!:7 allow you to query and set the characters to draw boxed values with, respectively.)

share|improve this answer
    
Do you (or anyone else) know if there's a consensus on the box drawing command for golf scoring, then? I personally think the assumption with code golf is that solutions work on a majority of systems that the solution's language runs on, right? What would a solution look like that outputs the correct boxes on all (or almost all) J installations? I really like your solution, by the way! My brain is still working its way through, which is exactly what I like about code golf. –  type_outcast yesterday
4  
@type_outcast We don't require portability for code golf challenges. As long as it works with some implemenation on one platform, it's valid. –  Dennis yesterday
    
Thanks for the response @Dennis. I'm happy my presumption was incorrect, then, because I (still) really like Mauris' solution! :-) –  type_outcast yesterday

Julia, 156 143 bytes

n->(p=println;l="+"*"---+"^4;for i=1:4 p(l,"\n| ",join([j>"0"?"#":" "for j=reshape(split(lpad(bin(n),16,0),""),4,4)[:,i]]," | ")," |")end;p(l))

Ungolfed:

function f(n::Int)
    # Convert the input to binary, padded to 16 digits
    b = lpad(bin(n), 16, 0)

    # Split b into a 4x4 matrix
    m = reshape(split(b, ""), 4, 4)

    # Store the line separator for brevity
    l = "+" * "---+"^4

    # Print each column of the matrix as a row
    for i = 1:4
        println(l, "\n| ", join([j > "0" ? "#" : " " for j = m[:,i]], " | "), " |")
    end

    # Print the bottom of the table
    println(l)
end

Try it online

share|improve this answer

Python 2, 157 153 bytes

J=''.join;R='+---'*4;i=format(int(input()),'016b')
print J(R+'+\n|'+J(' '+('#'if int(l)else' ')+' |'for l in i[n*4:(n+1)*4])+'\n'for n in range(4)),R+'+'

Thanks to Morgan Thrapp for saving 4 bytes.

Usage

$ python test.py
33825
+---+---+---+---+
| # |   |   |   |
+---+---+---+---+
|   | # |   |   |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
share|improve this answer
    
You can save two bytes if you pull '+---'*4 into a variable and two more if you do j=''.join –  Morgan Thrapp yesterday
    
Thanks for the tip. Edited my answer. @MorganThrapp –  Zach Gates yesterday
    
No problem! I was actually working on a very similar solution. –  Morgan Thrapp yesterday

JavaScript (ES6), 102

... or 96 using return instead of console.log.

Test running the snippet below in an EcmaScript 6 compliant browser.

f=n=>{for(o=h=`
+---+---+---+---+
`,z=16;z--;n/=2)o=(z&3?'':h+'|')+` ${' #'[n&1]} |`+o;console.log(o)}

// TEST
console.log=x=>O.innerHTML=x+O.innerHTML

function test(n) { f(n); console.log(n); }
<input id=I value=4680><button onclick='test(+I.value)'>-></button>
<pre id=O></pre>

share|improve this answer
4  
Is "JavaScripy" some strange javascript/python mashup? ;-) –  Digital Trauma yesterday
3  
@DigitalTrauma of course. But as the world is not ready (tvtropes.org/pmwiki/pmwiki.php/Main/TheWorldIsNotReady) for this new evolution, I'll revert to JavaScript –  edc65 yesterday

Ruby, 118 114

b="%016b"%gets
l=?++"---+"*4
1.upto(16){|i|puts l if i%4==1
print"| #{b[i-1]==?0?' ':?#} "
puts ?|if i%4<1}
puts l

thanks for @w0lf for saving some characters.

share|improve this answer
1  
You can save some bytes if you write literal characters using the ? notation (ex: ?| instead of '|'). This works for everything except space. –  w0lf 10 hours ago

Befunge-93, 196 218 bytes

&00p12*v>>4>"---+",v v <
v*:*:*:<   | :-1,,,< #
>:*2/10p^  >"+",25*,10g|
     > #v^#         $< @
 25*,^  >4" |",,v ,*<>
v>"#",00g10g-00p 10g
 |`-1g01g00     <>48^
v>" ",10g
>2/10p>"| ",,1-:#^_$>^

To run the program...

  1. Go to the online interpreter.
  2. Paste this code in the big text box.
  3. Click Show.
  4. Input the desired number in the Input box.
  5. Click Run. (Or change Slow to something like 5 milliseconds and then click Show.)
  6. Ta-da!

Output for 4242:

+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
| # |   |   | # |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+

Output for 33825:

+---+---+---+---+
| # |   |   |   |
+---+---+---+---+
|   | # |   |   |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+

Explanation

Oh goodness, what have I got myself into? Well, here goes! (Irrelevant code is replaced with .s.)

Part 1: Get input (store in 0,0) and calculate 32768 (store in 1,0).

&00p12*v>
v*:*:*:< 
>:*2/10p^

Part 2: Print out "+---+---+---+---".

>4>"---+",v
  | :-1,,,<

Part 3: Print "+" and a newline and check to see if (1,0) is 0 (i.e. we're done). If so, terminate. Otherwise, continue.

 ........... v <
   | ....... # 
   >"+",25*,10g|
v.#         $< @
>4" |",,v ...

Part 4: Get binary digits of input, updating (0,0) and (1,0) as we go along. Print the right things. I take advantage of Befunge's wrap-around behavior.

 .....  >4" |",,v ,*<.
v>"#",00g10g-00p 10g
 |`-1g01g00     <>48^
v>" ",10g
>2/10p>"| ",,1-:#^_...

Part 5: Print a newline and go back to the part that prints "+---+---+---+---+". Wrap-around trick is used.

     > #.^.         .. .
 25*,^  ......... ...>
................ ...
 .........      .....
........
.................._$>^

Ta-da!

share|improve this answer

GNU sed + dc, 116

Score includes +1 for -r flags to sed:

s/.*/dc -e2o&p/e
:
s/^.{,15}$/0&/;t
s/./| & /g
s/.{16}/\n+---+---+---+---+\n&|/g
y/01/ #/
s/\n([-+]+)(.*)/\1\2\n\1/

Test output:

$ { echo 4242 ; echo 33825 ; } | sed -rf 16bitgrid.sed
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
| # |   |   | # |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+
+---+---+---+---+
| # |   |   |   |
+---+---+---+---+
|   | # |   |   |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
$ 

Alternatively:

Pure sed, 146

You might think it's cheating to use sed's GNU extension to eval a dc command. In that case, we can do this a little differently, according to this meta-answer. Of course the question clearly states that input must be in base 10, but here I'm attempting to claim that we can override that for sed answers and use unary (base 1) instead.

:
s/11/</g
s/<([ #]*)$/< \1/
s/1/#/
y/</1/
t
:a
s/^.{,15}$/0&/;ta
s/./| & /g
s/.{16}/\n+---+---+---+---+\n&|/g
y/01/ #/
s/\n([-+]+)(.*)/\1\2\n\1/

Test output

Using printf to generate the necessary unary string:

$ printf "%33825s" | tr ' ' 1 | sed -rf 16bitgrid.sed 
+---+---+---+---+
| # |   |   |   |
+---+---+---+---+
|   | # |   |   |
+---+---+---+---+
|   |   | # |   |
+---+---+---+---+
|   |   |   | # |
+---+---+---+---+
$ 
share|improve this answer
    
Nice one. This looks somewhat similar to the Perl solution I came up with as a (private) proof of concept while fine-tuning the question. –  type_outcast yesterday
    
@type_outcast BTW its perfectly OK to post your own solution as an answer :) –  Digital Trauma yesterday
    
I know :-) I didn't spend much time golfing it, as I was more focused on putting up a good question, but I may yet revisit it and post it if I can golf it into something at least halfway respectable. At the moment I'm having too much fun grokking everyone else's answers. –  type_outcast yesterday

PowerShell, 203 Bytes

param($a)$l="+---+---+---+---+`n|";$o=$l;$b=([int64][convert]::ToString($a,2)).ToString(@(,"0"*16)-join'');1..16|%{if($b[$_-1]-eq'1'){$o+=" # |"}else{$o+="   |"};if($_%4-eq0){$o+="`n$l"}};$o.TrimEnd('|')

Ooooooooof.

Drawing in PowerShell is hard. Working with binary digits in PowerShell is hard. I'm pretty sure this is only minimally optimized, but I wanted to get something up since it was bugging me. I'll keep golfing this and see what else I can do to it.

Uses built-ins to [convert] the input integer to a string representation in binary, then re-cast back to an [int64] so we can re-call .ToString() in order to prepend/pad the appropriate number of zeroes. Then, take a simple for-loop checking each digit to build up our output string $o, then finally -join'' that back together and Trim() the | off the end (thanks to the loop order).

share|improve this answer
    
I hope it was a "fun hard". :-) +1 for your explanation; it helped my limited understanding of PowerShell. –  type_outcast yesterday

Javascript (ES6), 216 207 bytes

Defines an anonymous function.

i=>(","+("0".repeat(16)+i.toString(2)).slice(-16).split``.map((v,l,a)=>l%4<1?"| "+a.slice(l,l+4).map(v=>v?"#":" ").join` | `+" |":"").filter(v=>!!v).join`,`+",").replace(/,/g, `
+---+---+---+---+
`).slice(1)

Thanks to ETHproductions for tips!

share|improve this answer
    
Nice work! Since you're using ES6, here's a few tips: 1. Anytime you need to use a string as a function's only parameter, you can use a template string, like so: .join` | `​ 2. You can also use template strings for interpolating values: i=>`,${"0".repeat....join`,`},`.replace... 3. You can find more ES6 tips on this thread. –  ETHproductions yesterday
    
This seems to have stopped working, but by golfing it a bit more, I can get 197 with the correct result: i=>`,${("0".repeat(16)+i.toString(2)).slice(-16).split``.map((v,l,a)=>l%4?"":"| "+a.slice(l,l+4).map(v=>' #'[v]).join` | `+" |").filter(v=>v).join`,`},`.replace(/,/g,`<line break>+---+---+---+---+<line break>`).slice(1) –  ETHproductions yesterday
2  
("0".repeat(16)+i.toString(2)).slice(-16) --> (65536|i).toString(2).slice(1) –  edc65 22 hours ago
    
Keeping your exact logic, this can be golfed to 169, see jsfiddle.net/76fp7aw6 –  edc65 9 hours ago

C++11, 193 191 190 176 172 bytes

My first solution on codegolf ever, so do not blame me.

#include<iostream>
int n,j,i=65536;int main(){std::cin>>n;for(;j<9;){for(int k:{0,0,0,0})if(j%2)printf("| %s",n&(i/=2)?"# ":"  ");else printf("+---");puts(j++%2?"|":"+");}}

Ungolfed

#include <iostream>
int n, i = 65536, j;

int main()
{
    std::cin >> n;

    for (; j < 9;)
    {
        for(int k:{0,0,0,0})
        {
            if (j % 2)
            {
                printf("| %s", n & (i /= 2) ? "# " : "  ");
            }
            else
            {
                printf("+---");
            }
        }
        puts(j++ % 2 ? "|" : "+");
    }
}

Previous version

#include <iostream>
using namespace std;

int n, i = 65536, j;
int main()
{
    cin >> n;

    for (; j < 9;)
    {
        for(int k:{0,0,0,0})
        {
            if (j % 2)
            {
                cout << "| " << (n & (i /= 2) ? "# " : "  ");
            }
            else
            {
                cout << "+---";
            }
        }
        cout << (j++ % 2 ? "|\n" : "+\n");
    }
}
share|improve this answer
    
Hint: 0x10000 is 65536, having '0x' prefix, hex is always longer than decimal –  edc65 yesterday
    
Hint 2: youd should avoid using namespace std in production code. And it's not useful here too. –  edc65 yesterday
    
@edc65 dec->hex good idea, I always thought of hex having shorter representation, but forget about 0x. using namespace std saves few bytes, because I do not have to prefix cout and cin with std::. Even using just using std::cout; wont help. –  Zereges yesterday
    
Hey Zereges. You can remove the space between the include and the library.. and remove the return type for the main function. –  wendelbsilva yesterday
    
C++ does not support auto int. –  Zereges yesterday

CJam, 62 bytes

"+---|   "4/{4*_c+N+}%4*_0=]sqi2bG0e[ee{~{_9*\4%5*-K+'#t0}&;}/

Try it online.

share|improve this answer

Ruby, 102

n=gets.to_i
print j="+---"*4+"+
" 
19.downto(0){|i|print i%5>0?"| #{((n>>i*4/5)%2*3+32).chr} ":"|
"+j}

Algorithm

Print a horizontal divider

Loop 20 times (19..0)

If loop number does not divide by 5, convert into a number in the range 16..0 by multiplying by 4/5. Print a space (ascii 32) or # (ascii 32+3=35) preceded by | and followed by a space.

If loop number divides by 5, print a terminating |, newline, and a horizontal divider identical to the first.

share|improve this answer

Python 2, 122 121 120 bytes

n=bin(4**8+input())[3:]
i=0
exec"print'| %s |'%' | '.join(' #'[x>'0']for x in n[:4])*i or'+---'*4+'+';n=n[4*i:];i^=1;"*9

-1 byte thanks to @xnor's neat 4**8+ trick. The main printing is done by looping 9 times, selecting the appropriate row for odd/even.

share|improve this answer
    
I think that bin(4**8+input())[3:] saves a byte over format –  xnor 14 hours ago
    
@xnor Oh, that's neat :) –  Sp3000 14 hours ago

Python 2, 94

n=input()
s=();exec"s=(' #'[n%2],)+s;n/=2;"*16
a='+---'*4+'+\n'
print(a+'| %s '*4+'|\n')*4%s+a

The idea is to take the pattern

+---+---+---+---+
| _ | _ | _ | _ |
+---+---+---+---+
| _ | _ | _ | _ |
+---+---+---+---+
| _ | _ | _ | _ |
+---+---+---+---+
| _ | _ | _ | _ |
+---+---+---+---+

except with %s in place of blanks and perform tuple substitution. The tuple looks like

('#', ' ', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#', ' ', ' ', ' ', ' ', '#')

It is created by taking taking off digits from the input in binary and adding the corresponding symbol to the front of the tuple. An expression with explicit tuple gave equal length.

%tuple(' #'[c>'0']for c in bin(input()+4**8)[3:])

Thanks to Sp3000 for 2 bytes.

share|improve this answer

Pyth, 50 bytes

j.i*5]<3*5"+---"ms.i*5\|dc4mj@" #"qd\1*2\ .[Z16.BQ

Explanation will have to wait until another time, I'm posting this on my phone!

share|improve this answer

CJam, 43 bytes

'+5*'-3**N+ri2bG0e[4/{{'|S@'#S?S}%"|
"+1$}/

Definitely golfable, but it's a start I guess. Generates the top row, then for each 4 bits it creates an even row and copies the previous odd row.

Try it online.

share|improve this answer

Perl, 103 bytes

$_=(($l='+---'x4 .'+
').'| x 'x4 .'|
')x4 .$l;@n=(sprintf'%016b',<>)=~/./g;s/x/$n[$x++]?'#':$"/eg;print

Lots of string repetition to make a grid of xs, convert the input to binary and then s/// the xs to # or $" () depending on the flag at the specified position ($x).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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