Create a binary wall

Given an array of positive integers in base 10, where n > 0, output their representation of a binary wall.

How does this work?

1. Convert each number to it's binary representation.
2. Pad the representation with leading zeroes to the length of the longest one i.e. 1, 2 -> 1, 10 -> 01, 10.
3. Create a wall where the 1s are bricks and 0s are missing bricks.

A wall is a block of characters where any printable character represents a brick and a space (32) represents a missing brick. You may choose any character for the brick, it need not be distinct across the wall as long as it isn't a white space character. The missing brick character must be a space. For the example below I have used * for the bricks.

Example

Input:

[ 15, 7, 13, 11 ]

1. [ 1111, 111, 1101, 1011 ]
2. [ 1111, 0111, 1101, 1011 ]
3. Output:

****
***
** *
* **


Rules

• Input must be taken in base 10, if your language accepts other bases you may not use them.
• Leading and trailing new lines are allowed.
• Input may be taken as a list of integers, separate arguments or any reasonable format.
• Output may be in any reasonable format: new line separated string, array of lines, 2d array etc.
• Standard loopholes are disallowed.

Test Cases

Note that in the first test case all of layers have an empty brick at the end.

[ 14, 4, 6, 2 ]

***
*
**
*

[ 1, 2, 4, 8, 16 ]

*
*
*
*
*

[ 15, 11, 15, 15 ]

****
* **
****
****

[ 11, 10, 9, 8 ]

* **
* *
*  *
*


This is code golf so shortest code wins!

• Can the output be an array of lines or a 2d array of chars? – ovs Jul 24 '17 at 11:23
• @ovs Sorry thought I'd specified that, yes you can output an array or 2d array etc. Any reasonable format. – TheLethalCoder Jul 24 '17 at 11:26
• In the case of a 2D array, can we use numbers for the bricks instead of characters? e.g. [[1, " ", 1, " "], ...] – Arnauld Jul 24 '17 at 13:27
• @Arnauld Yeah that seems fine. – TheLethalCoder Jul 24 '17 at 13:45
• @Giuseppe New lines only, otherwise it will be confused for empty bricks. – TheLethalCoder Jul 24 '17 at 15:46

MATL, 5 bytes

B42*c


Try it online!

Explanation

B     % Implicitly input an array of numbers. Convert to binary.
% Gives a matrix with each row corresponding to a number
42    % Push 42 (ASCII code of '*')
*     % Multiply
c     % Convert to char. Char 0 is displayed as space. Implicitly display

• You may choose any character for the brick, it need not be distinct across the wall as long as it isn't a white space character. yeah that means you probably don't need 42* or something... – Erik the Outgolfer Jul 24 '17 at 12:37
• @EriktheOutgolfer I could choose any other number, but I do need those three bytes I think. – Luis Mendo Jul 24 '17 at 12:47
• What if there's a 1-byte builtin for 100 or some other number? – Erik the Outgolfer Jul 24 '17 at 12:51

J, 8 bytes

' *'{~#:


Try it online!

Explanation

' *'{~#:  Input: array of integers
#:  Convert each to binary with left-padding
' *'{~    Use the digits to index into the string ' *'

• Oh, so #: is why this beats Jelly. – Erik the Outgolfer Jul 24 '17 at 13:38

Jelly, 9 bytes

Bo⁶Uz⁶ZUY


Try it online!

EDIT: HOW J BEAT JELLY DAT IMPOSSIBLE >_<

Octave, 22 bytes

@(x)[dec2bin(x)-16,'']


Try it online

Explanation:

Saved some bytes thanks to Luis Mendo! Also, I didn't notice that I could choose which character to build the wall with, not only *.

@(x)                    % Take the input as a column vector
dec2bin(x)          % Convert each row of the input to a string with 1 and 0
% It gets automatically padded with zeros, to fit the longest number
dec2bin(x)-16       % Subtract 16, to get from the ASCII-values of 1/0 (48/49)
% to 32/33 (space and !)
@(x)[dec2bin(x)-16,'']  % Concatenate with the empty string to convert it to a string.


Or with de2bi:

Explanation:

@(x)                          % Take the input as a column vector
de2bi(x)       % Convert each row of the input to a binary number.
% Gets automatically padded to fit the longest number
42*de2bi(x)       % Multiply the matrix by 42, which is the ASCII-value for *
[42*de2bi(x),'']   % Concatenate the matrix with the empty string to convert
% it to a string. 0 are automatically displayed as spaces
@(x)fliplr([42*de2bi(x),''])


The following works on TIO, for 7 bytes more:

@(x)fliplr([42*(dec2bin(x)>48),''])


Try it here

Python 3, 88 84 71 74 72 bytes

A lambda that returns a list of Strings, representing each line.

lambda n:[bin(x)[2:].replace(*'0 ').rjust(len(bin(max(n)))-2)for x in n]


Try it online! (link to the newline separated version)

Explanation

• lambda n: - Creates an (anonymous) lambda, with a parameter n. Returns implicitly.

• [...] - Creates a list comprehension.

• bin(x)[2:] - Gets the binary representations of the numbers.

• .replace(*'0 ') - Replaces all the occurrences of 0 with a space.

• .rjust(len(bin(max(n)))-2) - Pads the binary representations to the length of the longest one.

• for x in n - Iterates through n, with the variable x.

Changelog

• -1 - 3 bytes thanks to @Rod, -(...)+2 = 2-(...), use of rjust()

• Added a version with bin() instead, that was invalid since it didn't work for 1 and 2.

• Fixed the bug above using format().

• Changed return type to list of Strings, because it was allowed by the OP.

• Fixed yet another bug using rjust() and switching back to bin(), spotted and fixed by @Rod.

JavaScript (ES6), 81 79 bytes

Saved 2 bytes by using numbers instead of characters for the bricks, as suggested by Rick Hitchcock

Returns a 2D array with 1's for the bricks.

f=(a,b=[],x=1)=>a.every(n=>n<x)?a.map(n=>b.map(i=>n&i?1:' ')):f(a,[x,...b],x*2)


Test cases

f=(a,b=[],x=1)=>a.every(n=>n<x)?a.map(n=>b.map(i=>n&i?1:' ')):f(a,[x,...b],x*2)

format = a => a.map(s => s.join).join\n

console.log(format(f([ 14, 4, 6, 2 ])))
console.log(format(f([ 1, 2, 4, 8, 16 ])))
console.log(format(f([ 15, 11, 15, 15 ])))
console.log(format(f([ 11, 10, 9, 8 ])))

f x|all(<1)x=x>>[""]|a<-f$map(div2)x=zipWith(++)a$map(cycle[" ","*"]!!)x


Try it online!

05AB1E, 9 bytes

bí.Bí»0ð‡


Try it online!

• Beat me by 38 seconds. I had b0ð:í.Bí» for 9 bytes as well. – Riley Jul 24 '17 at 13:09

Ruby, 63 59 bytes

-4 bytes with help from Alexis Andersen

->*n{puts n.map{|i|("%#{('%b'%n.max).size}b"%i).tr'0',' '}}


Try it online!

• you don't need the 0 in the string format. you could shave a byte by replacing n.max.to_s(2).size with ('%b'%n.max).size and you don't actually need to replace the 1 with * – Alexis Andersen Jul 24 '17 at 17:51
• @AlexisAndersen thanks :) – daniero Jul 24 '17 at 19:48

R, 87 88 bytes

Wall blocks represented by an 8, because, well lots of eights.

write(ifelse((I=sapply(scan(),intToBits))[(M=max(which(I>0,T)[,1])):1,],8,' '),1,M,,'')


Try it online!

Input integer list is converted to array of bits which are trimmed of trailing 0 bits and reversed.

The reduced array is then output using write and a column width which was determined when the array was trimmed.

ifelse() is the only IF option that works on vectors unfortunately.

• @Vlo pointed out you can use 1 rather than "" for the output file in write. – Giuseppe Mar 12 '18 at 14:54
• @Giuseppe thanks for the tip – MickyT Mar 12 '18 at 17:54

Python 2, 77 bytes

lambda k:[[' *'[i&2**y>0]for y in range(len(bin(max(k)))-3,-1,-1)]for i in k]


Try it online!

APL (Dyalog), 302220 14 bytes

Saved 6 bytes thanks to @Adám

' *'[⍉2⊥⍣¯1⊢⎕]


Try it online!

(assumes ⎕IO←0 as this is default on many machines)

This takes input as an array and returns a matrix with *s and  s.

Explanation

2⊥⍣¯1⊢⎕       Convert input to binary (returns a transposed matrix of 1s and 0s)
⍉              Transpose
' *'[ ... ]    Index into this string


T-SQL, 290 bytes

declare @ int;select @=max(log(a,2))+1from @i;with t as(select convert(varchar(max),a%2)b,a/2c,@-1m,ROW_NUMBER()over(order by(select 1))r from @i union all select convert(varchar(max),concat(c%2,b))b,c/2c,m-1,r from t where m>0)select replace(b,0,' ')from t where m=0group by r,b order by r


Uses 1 for the brick piece, assumes input comes from table @

Ungolfed, with some explanation

-- assume input is presented in an input table
declare @input table (a int)
insert into @input values (15), (7), (13), (11)

---- start here

-- figure out how many characters are needed, by taking log2
declare @max int
select @max = max(log(a, 2)) + 1
from @input

-- recursive cte
-- will join against itself, recursively finding each digit in the binary string
;with cte as
(
select
convert(varchar(max), a % 2) as b, -- is the least significant bit 1 or 0
a / 2 as c, -- remove least significant bit, for the next run
@max - 1 as max, -- keep track of iterations left
ROW_NUMBER() over (order by (select 1)) as rn -- keep the order of the input
from @input

union all -- recursive loop
-- below columns follow the same pattern

select convert(varchar(max),
concat(cte.c % 2, cte.b)) as b, -- prepend the current binary string with the newest least significant bit
cte.c / 2 as c,
cte.max - 1,
cte.rn
from cte
where cte.max > 0
)
select replace(b, 0, ' ') -- swap 0s for space
from cte
where max = 0 -- only take the last iteration
group by rn, b -- grab each unique input,
-- need to group by row number so it can be ordered by
-- need to group by binary string, so it can be selected
order by rn -- sort by the order the input arrived in


Mathematica, 40 bytes

Grid@PadLeft@IntegerDigits[#,2]/. 0->""&


Bricks are 1s

Mathematica, 48 bytes

Grid@PadLeft@IntegerDigits[#,2]/.{0->"",1->"#"}&


Bricks are #

• You should only need one slash in the //.. (/. means "replace once", //. means "keep doing the replacement until the thing stops changing".) – Not a tree Jul 24 '17 at 11:25
• ok-fixed-thanks – J42161217 Jul 24 '17 at 13:26
• You don't need the space after the comma in the IntegerDigits function. – Mark S. Jul 25 '17 at 0:14
• yes,I know,this happens when you copy/paste from notebook.fixed – J42161217 Jul 25 '17 at 0:17

C# (.NET Core), 112+18=130 86+41=127 bytes

a=>a.Select(n=>C.ToString(n,2).Replace("0"," ").PadLeft(C.ToString(a.Max(),2).Length))


Try it online!

The byte count includes 41 bytes from using System.Linq;using C=System.Convert;. Uses 1 as character for the wall. Nonetheless, this is way too long even for C#...

• Place in namespace System.Linq{} to save some bytes. Is a.Max() guaranteed to be true (I'm sure it is I'm just not the smartest with binary :P)? Would class Convert{} save any bytes? – TheLethalCoder Jul 24 '17 at 11:17
• If I place the program in a given namespace, shouldn't I submit the whole program instead of just a lambda? I'm not sure about the rules for that... – Charlie Jul 24 '17 at 11:23
• I've usually just placed in namespace with lambda. I don't think there's ever been a question about it and it is in the C# tips page. – TheLethalCoder Jul 24 '17 at 11:24
• I don't think this is valid, as you can't compile it without using static imports. – MetaColon Jul 24 '17 at 12:26
• @MetaColon that's the reason why I added the bytes in using System.Linq;using C=System.Convert; to byte count, as those two using directives are needed for the code to compile. – Charlie Jul 24 '17 at 12:40

Retina, 63 bytes

.+
$*#< +(#+)\1$1
#
#
{T<_^(<.+(¶|$))+$
m^<
<
(.)<
<$1  Try it online! Explanation: .+$*#<


Convert to unary, and suffix a <.

+(#+)\1
$1 # #  Convert to binary. {T<_^(<.+(¶|$))+$ Once all the <s have reached the left, delete them all. m^< <  Insert a space before any <s that have already reached the left. (.)< <$1


Move all the <s left one step. Rinse and repeat.

PowerShell, 100 bytes

$args|%{if(($c=($a=[convert]::ToString($_,2)).length)-gt$l){$l=$c}$a-replace0,' '}|%{$_.padleft($l)}


Try it online!

Ugh, converting to binary in PowerShell is so painful. Plus .lengthy calls to -replace the 0 with spaces, plus a long .padLeft() call to make them all the same .length, all adds up to a long submission.

Golfing suggestions to get below 100 are welcome.

PHP, 84 bytes

while(++$i<$argc)echo strtr(sprintf("\n%".-~log(max($argv),2).b,$argv[\$i]),10,"* ");


Luckily, the bit operation casts the log result to int. float wouldn´t work here.

Clojure, 185 bytes

(fn[i](let[b(map #(Long/toBinaryString %)i)](map #(clojure.string/replace(clojure.string/replace(format(str"%0"(reduce(fn[l i](max l(count i)))0 b)"d")(read-string %))"1""#")"0"" ")b)))


Ungolfed version:

(fn [i]
(let [b (map #(Long/toBinaryString %) i)]
(map
#(clojure.string/replace
(clojure.string/replace
(format
(str "%0"
(reduce
(fn [l i] (max l(count i))) 0 b)
"d")
"1"
"#")
"0"
" ")
b)))


Anonymous function that takes the argument as a list. Returns the lines as list.

Reading the other answers, I bet it could be smaller. clojure.string/replace takes an obscene amount of chars to write..

Japt, 33 30 bytes

¡'0p(¡X¤lÃn o)-X¤l)+X¤)£" *"gX


Try it online!

Saved 3 bytes thanks to @Justin Mariner

Explanation

¡                              // map input integers
(¡X¤lÃn o)                 // longest binary string length
-X¤l)            // minus current binary string length
'0p                           // repeat zero
+X¤)        // concat with current binary string
£       // map chars of binary string
" *"gX // swap 0 and 1 with ' ' and '*'

• You can drop the last 3 chars to just return an array of strings, and use the -R flag (not added to byte count) to see the newline-joined output: here. – Justin Mariner Jul 25 '17 at 10:28

Python 3, 92 90 bytes

lambda a:[' '*(len(bin(max(a)))-len(i)-2)+i for i in[bin(i)[2:].replace(*'0 ')for i in a]]


Try it online!

Returns a list of lines. Stacking them up shows they do indeed align properly.

['111 ', ' 1  ', ' 11 ', '  1 ']
>>>
111
1
11
1


The breakdown

Essentially converts the array to binary, then replaces all 0's with spaces. N number of spaces are added to the front of each line where N = [length of longest line] - [length of line].

-1 bytes Thanks to Mr. Xoder

Try it online!

• You can't have leading or trailing spaces in the output. – TheLethalCoder Jul 25 '17 at 8:58
• @TheLethalCoder Oh, must have misread the rules! Thanks for catching that. – Graviton Jul 25 '17 at 9:02
• 90 bytes, replace '0',' ' with *'0 '. – Mr. Xcoder Jul 25 '17 at 10:18
• @Mr.Xcoder Ah interesting, would never have thought about that. Thanks! – Graviton Jul 25 '17 at 22:17

Japt, 11 bytes

m¤z3 z ·r0S


Try it online!

Explanation

m¤z3 z ·r0S  Implicit input of array
m¤           Map the array to binary strings
z3 z       Rotate right 270° and then right 90°. This adds left padding to each string
·r0S  Join with newlines and replace 0s with spaces

• Nice exploit with z3 z. Not sure why y y doesn't work there, I'll look into it later... – ETHproductions Jul 29 '17 at 23:11

Java 7, 130108 88 bytes

Saved 22 thanks to @TheLethalCoder Saved 20 thanks to @Xanderhall

void a(int[]b){for(int i:b)System.out.println(Long.toBinaryString(i).replace('0',' '));}


Ungolfed:

void a(int[]b){
for(int i:b)
System.out.println(Long.toBinaryString(i).replace('0', ' '));
}

• Post increment i at b[i] to save a byte. You can keep the output with 1's so no need for the .replace('1','*'). Use Java 8 instead and compile to a lambda to save bytes. If you don't want to do that int[]b saves a byte. – TheLethalCoder Jul 25 '17 at 12:24
• Thank you! Could you please explain what "Post increment i at b[i] to save a byte." means? – Java Gonzar Jul 25 '17 at 12:35
• i++ evaluates i then increments it (whereas ++i does the opposite) so you can move the i++ out of the for loop and use b[i++] instead. Oh and whilst we're at it you only have one line inside your loop so the braces aren't needed. – TheLethalCoder Jul 25 '17 at 12:37
• True! Amazing, thank you – Java Gonzar Jul 25 '17 at 12:40
• You can save a few bytes by switching your loop to a foreach loop. for(int x:i) Also, you can use Long.toBinaryString instead of the Integer version to save 3 bytes. – Xanderhall Jul 26 '17 at 14:16

Python 2, 217 bytes

After 2 hours of coding i decided, that numpy is bad idea for this

import numpy as n
o=[n.copy(i)]
o[0].fill(10)
while n.count_nonzero(i)>0:
o.append(i%2+32)
i=n.vectorize(lambda x:x//2)(i)
print n.fliplr(n.array(o).T).astype('uint8').view('c').tostring().decode()


Usage in Ubuntu

Install numpy

python2 -m pip install numpy


Create file named i with input in format 14 4 6 2

Run

python2 prog.py


8th, 232254 250 bytes

Code

0 >r a:new swap ( nip 2 base drop >s decimal s:len r> n:max >r a:push ) a:each drop a:new swap ( nip '0 G:c# r@ G:#> s:fmt a:push ) a:each drop rdrop a:new swap ( nip /0/ " " s:replace! a:push ) a:each drop ( nip /1/ "*" s:replace! . cr ) a:each drop


\ convert to binary and save longest string length
: f 0 >r a:new swap ( nip 2 base drop >s decimal s:len r> n:max >r a:push ) a:each drop ;

\ pad binary number with zero
: f1 a:new swap ( nip '0 G:c# r@ G:#> s:fmt a:push ) a:each drop rdrop ;

\ replace every 0 with space
: f2 a:new swap ( nip /0/ " " s:replace! a:push ) a:each drop ;

\ replace every 1 with * and print each line of bricks
: f3 ( nip /1/ "*" s:replace! . cr ) a:each drop ;


These words must be invoked in sequence (see example)

Usage and examples

ok> [15,7,13,11] 0 >r a:new swap ( nip 2 base drop >s decimal s:len r> n:max >r a:push ) a:each drop a:new swap ( nip '0 G:c# r@ G:#> s:fmt a:push ) a:each drop rdrop a:new swap ( nip /0/ " " s:replace! a:push ) a:each drop ( nip /1/ "*" s:replace! . cr ) a:each drop
****
***
** *
* **


Or more clearly

ok> [15,11,15,15] f f1 f2 f3
****
* **
****
****


Pyth, 16 bytes

j_MC.tm_X.Bd\0\


Try it here. Mind the trailing space.

Excel VBA, 170 161 Bytes

Golfed

Anonymous VBE immediate window function that that takes input of format 1 2 3 .. n from range [A1] and outputs the corresponding binary wall to the VBE Immediate window via range [B1,C1,2:2]

n=Split([A1]):[A2].Resize(1,UBound(n)+1)=n:[C1]="=Int(1+Log(B1,2))":For Each i In n:[B1]=i:?Replace(Replace([Right(Rept(0,C1)&Dec2Bin(B1),C1)],1,"*"),0," "):Next


Formatted:

n=Split([A1])
[A2].Resize(1,UBound(n)+1)=n
[C1]="=Int(1+Log(B1,2))"
For Each i In n
[B1]=i
?Replace(Replace([Right(Rept(0,C1)&Dec2Bin(B1),C1)],1,"*"),0," ")
Next


Ungolfed

Full Subroutine that takes input of format Array(1, 2, 3...) and outputs the corresponding binary wall to the VBE Immediate window via range [A1,B1,2:2]

Sub a(ByRef n As Variant)
Let Range("A1").Resize(1,UBound(n)+1) = n
Let Range("C1").Value = "=Int(1+Log(A1,2))"
Dim i As Integer
For Each i In n
Let Range("A1").Value = i
Debug.Print Replace(
Replace(
[Right( Rept( 0, C1) & Dec2Bin( B1), C1)],
1,
"*"
),
0,
" "
)
Next
End Sub


Charcoal, 20 bytes

ＷＳ«⸿≔ＩιιＷι«←§ *ι≧÷²ι


Try it online! Link is to verbose version of code. Works by manually converting each input number to binary but printing it in right-to-left order. I take the input as a newline terminated string as Charcoal doesn't have a good way of inputting lists otherwise I would write something like this which unfortunately currently takes 21 bytes:

ＷＳ⊞υＩιＷ⌈υ«Ｅυ﹪κ²↓⸿≧÷²υ


Try it online! Link is to verbose version of code. This version vectorises over the input array, although its output is hardcoded to -s which saves a byte.