19
\$\begingroup\$

A binary matrix represents a shape in the plane. 1 means a unit square at that position. 0 means nothing. The background is 0.

For example, the array [[0,1,0],[0,0,1],[1,1,1]] represents the following shape:

     o----o
     |////|
     |////|
     o----o----o
          |////|
          |////|
o----o----o----o
|////|////|////|
|////|////|////|
o----o----o----o

Challenge

You take input as the array and output the matching ASCII art.

As with all code-golfing challenges, the shortest code in terms of bytes wins.

Examples

[[1,1,1],[0,0,0]]

o----o----o----o
|////|////|////|
|////|////|////|
o----o----o----o

(You may or may not trim)

[[0,1,0],[1,0,1]]

     o----o
     |////|
     |////|
o----o----o----o
|////|    |////|
|////|    |////|
o----o    o----o

[[1,0,1,0],[0,0,0,0],[1,1,1,0]

o----o    o----o
|////|    |////|
|////|    |////|
o----o    o----o


o----o----o----o
|////|////|////|
|////|////|////|
o----o----o----o

[[1]]

o----o
|////|
|////|
o----o

You can choose whether or not to trim surrounding whitespace, from either rows, columns, both or neither

\$\endgroup\$
2
  • \$\begingroup\$ May we take the input as something like 0 1 0\n0 0 1\n1 1 1 if our language does not support arrays? \$\endgroup\$
    – Dion
    Commented May 17, 2022 at 8:19
  • 1
    \$\begingroup\$ @Dion Yes...... \$\endgroup\$ Commented May 17, 2022 at 9:00

7 Answers 7

7
\$\begingroup\$

Python, 232 223 209 bytes

-9 bytes thanks to @Kevin Cruijssen

-11 bytes thanks to @a stone arachnid

-3 bytes thanks to @Steffan

def f(a):R=range;E=enumerate;s=[[*" "*6*len(_)]for _ in 4*a];[s[I+3*i].__setitem__(J+j*5,"/|-o"[2*(I%3<1)+(J%5<1)])for i,r in E(a)for j,x in E(r)if x for I in R(4)for J in R(6)];print(*map("".join,s),sep="\n")

Attempt This Online!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Both ==0 can be <1 and [" "for _ in R(6*len(a[0]))] can be list(" "*6*len(a[0])) \$\endgroup\$ Commented May 10, 2022 at 10:01
  • \$\begingroup\$ Works!!!!!!!!!! \$\endgroup\$ Commented May 10, 2022 at 10:15
  • \$\begingroup\$ and list(" "*6*len(_)) can be [*" "*6*len(_)] \$\endgroup\$
    – naffetS
    Commented May 11, 2022 at 3:50
  • \$\begingroup\$ Normally, the smash everything into one line and use list comprehensions to nest loops is a win over multiple lines with indentation, but in this case it's costing you in the __setitem__ instead of = and the J loop instead of a slice. Try this. \$\endgroup\$ Commented May 17, 2022 at 23:46
5
\$\begingroup\$

Charcoal, 33 bytes

FA«Fι«FκP”{⊟∨¹↖﹪H✂sρSjυ%‖”M⁵→»⸿⸿⸿

Try it online! Link is to verbose version of code. Explanation:

FA«

Loop through the rows.

Fι«

Loop through the cells of this row.

FκP”{⊟∨¹↖﹪H✂sρSjυ%‖”

If this cell is 1 then output a compressed representation of the shape without moving the cursor.

M⁵→

In any case move the cursor five characters to the right. This causes adjacent shapes to overlap by one character.

»⸿⸿⸿

After each row move the cursor to the start of the bottom row of the current line, so that the next row will overlap by one character.

Drawing the shape using Charcoal commands turns out to also take 33 bytes:

FA«Fι«Fκ«F²F²«o⁻⁴⊗ν↷»↘¤/↖»M⁵→»⸿⸿⸿

Try it online! Link is to verbose version of code. Explanation: As above, except instead of P”{⊟∨¹↖﹪H✂sρSjυ%‖”:

F²F²«o⁻⁴⊗ν↷»

Draw a rectangle with os at the corners.

↘¤/↖

Fill the rectangle with /s.

If +s had been acceptable for corners then F²F²«o⁻⁴⊗ν↷» could have been replaced with B⁶¦⁴ saving eight bytes.

FA«Fι«Fκ«B⁶¦⁴↘¤/↖»M⁵→»⸿⸿⸿

Try it online! Link is to verbose version of code.

\$\endgroup\$
1
  • \$\begingroup\$ Works!!!!!!!!!! \$\endgroup\$ Commented May 10, 2022 at 10:14
3
\$\begingroup\$

J, 58 bytes

' -o/|'{~(1 3 3 1+/#:33)>./@((]$_3 _5&*@#:I.@,)|.*&$~{.[)]

Try it online!

Consider input:

  0 1 0
  0 0 1
  1 1 1
  • (1 3 3 1+/#:33) Create a numeric matrix representing the ascii "cell":

    2 1 1 1 1 2
    4 3 3 3 3 4
    4 3 3 3 3 4
    2 1 1 1 1 2
    
  • *&$~{.[ Multiply dimensions of that times dimensions of input, ie, 4 6 * 3 3, giving 12 18, and extend our cell to those dimensions, which will always be slightly bigger than we need:

    2 1 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0
    4 3 3 3 3 4 0 0 0 0 0 0 0 0 0 0 0 0
    4 3 3 3 3 4 0 0 0 0 0 0 0 0 0 0 0 0
    2 1 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    
  • Our strategy will be to rotate the above matrix in 2 dimensions, one time for each 1, moving the cell into each require position.

    • $...#:I.@, Convert the positions of the ones into 2d coordinates:

       0 1
       1 2
       2 0
       2 1
       2 2
      
    • _3 _5&*@ Multiply row-wise by "dimensions of cell, minus 1, negated". The negation is needed because we want to rotate right rather than left.

       0  _5
      _3 _10
      _6   0
      _6  _5
      _6 _10
      
    • |. Create multiple copies of our "extended" cell, rotating by those amounts:

      0 0 0 0 0 2 1 1 1 1 2 0 0 0 0 0 0 0
      0 0 0 0 0 4 3 3 3 3 4 0 0 0 0 0 0 0
      0 0 0 0 0 4 3 3 3 3 4 0 0 0 0 0 0 0
      0 0 0 0 0 2 1 1 1 1 2 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 2 0 0
      0 0 0 0 0 0 0 0 0 0 4 3 3 3 3 4 0 0
      0 0 0 0 0 0 0 0 0 0 4 3 3 3 3 4 0 0
      0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 2 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      2 1 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0
      4 3 3 3 3 4 0 0 0 0 0 0 0 0 0 0 0 0
      4 3 3 3 3 4 0 0 0 0 0 0 0 0 0 0 0 0
      2 1 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 2 1 1 1 1 2 0 0 0 0 0 0 0
      0 0 0 0 0 4 3 3 3 3 4 0 0 0 0 0 0 0
      0 0 0 0 0 4 3 3 3 3 4 0 0 0 0 0 0 0
      0 0 0 0 0 2 1 1 1 1 2 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 2 0 0
      0 0 0 0 0 0 0 0 0 0 4 3 3 3 3 4 0 0
      0 0 0 0 0 0 0 0 0 0 4 3 3 3 3 4 0 0
      0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 2 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      
  • >./@ Max reduce these "planes" to create a single matrix, which handles the overlapping corners:

    0 0 0 0 0 2 1 1 1 1 2 0 0 0 0 0 0 0
    0 0 0 0 0 4 3 3 3 3 4 0 0 0 0 0 0 0
    0 0 0 0 0 4 3 3 3 3 4 0 0 0 0 0 0 0
    0 0 0 0 0 2 1 1 1 1 2 1 1 1 1 2 0 0
    0 0 0 0 0 0 0 0 0 0 4 3 3 3 3 4 0 0
    0 0 0 0 0 0 0 0 0 0 4 3 3 3 3 4 0 0
    2 1 1 1 1 2 1 1 1 1 2 1 1 1 1 2 0 0
    4 3 3 3 3 4 3 3 3 3 4 3 3 3 3 4 0 0
    4 3 3 3 3 4 3 3 3 3 4 3 3 3 3 4 0 0
    2 1 1 1 1 2 1 1 1 1 2 1 1 1 1 2 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    
  • ' -o/|'{~ Convert to ascii:

    o----o       
    |////|       
    |////|       
    o----o----o  
         |////|  
         |////|  
    o----o----o----o  
    |////|////|////|  
    |////|////|////|  
    o----o----o----o
    
\$\endgroup\$
2
\$\begingroup\$

Perl 5 + -pl, 77 bytes

$"="..[6D";s!.!@{[$&?qw(o----o |////|)[0,1,1,0]:(".[6C")x4]}.[3A.!g;$\=".[3E"

Try it online!

Contains unprintable characters and uses ANSI escape codes to reposition the cursor and output the required ASCII art. Long arrays may not display correctly in the browser (as the terminal is a fixed height and the cursor cannot move out of bounds). Happy to delete if this is not to spec!

Explanation

First, we set the list separator variable ($" - this is automatically added to string when a list is interpolated into it) to a string that will move the cursor down 1 line (form feed - \x0c) and back 6 characters (\x1b[6D). Then s///ubstitute each char (.) in (the implicit, stored in $_, via -p) input with an inline interpolated array (@{[...]}) that contains either the four parts of the box (qw(o----o |////|)[0,1,1,0]) or four repetitions of moving the cursor forward six characters (("\x1b[6C")x4), depending on whether or not the currently matched character ($&) is truthy. At the end of the string the cursor is moved back up three lines (\x1b[3A) and a literal backspace moves the cursor back one character (\x08). Finally, the output record separator ($\) is set to a string that moves the cursor to the beginning of the line three lines down (\x1b[3E), which is automatically printed (along with the modified input).

\$\endgroup\$
1
  • \$\begingroup\$ Works!!!!!!!!!! \$\endgroup\$ Commented May 11, 2022 at 0:28
2
\$\begingroup\$

JavaScript, 182 bytes

m=>m.map(g=r=>((p=(L=(` |`[r[0]]+r.map((d,x)=>d?`////|`:`    `+` |`[r[x+1]|0]).join``+`
`))[R='replace'](/\//g,'-')[R](/\|/g,'o'))[R](/ /g,(c,i)=>P[i]||' '))+(P=p,L)+L,P='').join``+P

Can probably be golfed a lot more.

f=
m=>m.map(g=r=>((p=(L=(` |`[r[0]]+r.map((d,x)=>d?`////|`:`    `+` |`[r[x+1]|0]).join``+`
`))[R='replace'](/\//g,'-')[R](/\|/g,'o'))[R](/ /g,(c,i)=>P[i]||' '))+(P=p,L)+L,P='').join``+P
;

console.log(f([
  [1,1,1],
  [0,0,0]
]));
console.log(f([
  [0,1,0],
  [1,0,1]
]));
console.log(f([
  [1,0,1,0],
  [0,0,0,0],
  [1,1,1,0]
]));
console.log(f([
  [1]
]));
console.log(f([
  [1,0,1,0],
  [1,0,0,0],
  [0,0,0,1],
  [1,1,1,0]
]));

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

C (clang), 198 197 bytes

-1 byte thanks to @ceilingcat.


Based on @Matteo C.'s Python answer.

#define F(_,t)for(_=t;_--;)
i;j;I;J;f(*a,X,Y){char*s[3*X+1];F(i,4*X)asprintf(s+i,"%*c",Y*5,0);F(i,X)F(j,Y)if(a[i*Y+j])F(I,4)F(J,6)s[I+3*i][J+j*5]="/|-o"[2*!(I%3)+!(J%5)];F(i,j=3*X+1)puts(s[j+~i]);}

Try it online! Takes input as the matrix as a flattened array, the number of rows in the matrix, and the number of elements in each row.

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

PowerShell, 186 bytes

$args|%{$l=$m=' '
$_|%{if($_){$l=($l-replace'.$')+'o----o';$m=($m-replace'.$')+'|////|'}else{$l+=' '*5;$m+=' '*5}}
$p+=$l*!$p
&{-join($l|% t*y|%{($_,$p[$i++])[$_-eq32]})}
$m;$m;$p=$l}
$p

Try it online!

Less golfed:

$args|%{
    $line=$midl=' '

    $_|%{                               # for each row element
        if($_){
            $line=($line-replace'.$')+'o----o'
            $midl=($midl-replace'.$')+'|////|'
        }else{
            $line+=' '*5
            $midl+=' '*5
        }
    }

    $prev+=$line*!$prev                 # use $line as previous if $prev is empty

    &{                                  # run in new context to reset the local variable $i.
        -join($line|% toCharArray|%{    # output a new line, where
            ($_,$prev[$i++])[$_-eq32]   # each space char from $line
        })                              # replaced by related char from $prev
    }

    $midl                               # implicit output
    $midl                               # implicit output

    $prev=$line
}
$prev                                   # implicit output
\$\endgroup\$

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