# Operator ASCII art

### Challenge

Given an ASCII operator from the list below and a number n, draw an ASCII representation of the operator using that operator as the character with the line segments of the operator having length n.

### Input

An ASCII character from the list = + - x / and an integer n where n >= 1. (I'm using x instead of * and / instead of ÷, but you could use either one, whichever is easier). For + and x, you only have to handle odd numbers to avoid issues with alignment.

### Output

An ASCII drawing of the operator composed of the character with segments of length n. Horizontal portions should have spaces between the characters to offset vertical/horizontal distance differences.

### Rules

This is , so shortest code in bytes wins. Standard loopholes are forbidden.

### Examples

Input: + 3

  +
+ + +
+


Input: = 4

= = = =
= = = =


Input: = 10

= = = = = = = = = =
= = = = = = = = = =


Input: - 2

- -


Input: / 10

         /
/
/
/
/
/
/
/
/
/


Input: x 7

x     x
x   x
x x
x
x x
x   x
x     x

• can you add the test case for = 10?
– Rod
Nov 7, 2016 at 16:40
• I assume "x" and "+" imply odd numbers? (I just saw DrMcMoylex asked nearly the same question.) Nov 7, 2016 at 16:48
• @MartinRosenau Yes, from the Input section: "For + and x, you only have to handle odd numbers to avoid issues with alignment." Nov 7, 2016 at 17:01
• Why are X and / not spaced out?
Nov 8, 2016 at 11:37
Nov 8, 2016 at 12:15

# V, 78, 72, 71, 68, 65, 63, 62, 61 bytes

Ç=ü-/Àé X
ç^Ó/é Àä$ç+/ÀÄM|ÀR+ ç=/Ä ç¯/lòhYpX çx/rxòl3Äjxlrx  Try it online! As always, the neck-and-neck battle with 05AB1E is really fun! Since this contains non-ASCII characters, here is a hexdump: 0000000: c73d fc2d 2fc0 e920 580a e75e d32f e920 .=.-/.. X..^./. 0000010: c0e4 240a e72b 2fc0 c44d 7cc0 522b 200a ..$..+/..M|.R+ .
0000020: e73d 2fc4 0ae7 af2f 6cf2 6859 7058 0ae7  .=/..../l.hYpX..
0000030: 782f 7278 f26c 33c4 6a78 6c72 78         x/rx.l3.jxlrx


This does create leading spaces in the output for = and -, but this seems to be allowed. If this is not allowed, feel free to comment and I'll roll it back.

# Explanation

The "global command" (e.g. ç) applies a certain set of commands to every line that matches a certain regex. The syntax is

ç<compressed regex>/<commands>


This is the easiest way of simulating a conditional/switch statement. In my original answer, I simply created the entire ASCII-art on the right-hand side for each different character we need to search for. However, a lot of these outputs require similar commands. So I combined them. The first command ('Ç') is actually the inverse of the global command, it applies the command to every line not matching the regex. So the first command is:

Ç=ü-        " On every line not containing an '=' or an '-' (e.g. inputs '/', '+', and 'x'):
/Àé     "   Insert *n* spaces
X   "   Delete one of them


The following command is for inputs '=' and '-'. These two are conveniently easy and similar. After this command, we need no more processing for -.

ç^Ó         " On every line that starts with non-whitespace (e.g. every line not affected by our previous command):
/é       "   Insert one space
"   Move back a character
À     "   Make *n* copies
ä$" Of every character on this line  From here we just do some extra commands for each individual possible input. For +: ç+/ " On every line containing a '+': ÀÄ " Make *n* copies of this line M| " Move to the first character of the middle line À " *n* times: R+ " Replace the next two characters with '+ '  The command for equals is very straightforward. We just duplicate it with Ä. For /: ç¯ " On every line containing a '/': /l " Move one character to the right ò " Recursively: h " Move one character to the left Yp " Make a copy of this line X " Delete one character ò " End loop (implicit)  The last one is the most complicated. It is basically a port of this answer. çx " On every line containing a 'x': /rx " Replace the first character with an 'x' ò " Recursively: l " Move one char to the right 3Ä " Make 3 copies of this line j " Move down one line x " Delete one char l " Move one char to the right rx " Replace this char with an 'x'  • so is that what multiple lines are used for? Nov 8, 2016 at 12:48 • @Conorobrien Yes. The ç command (as well as search and replace, / and ?) all simulate part of vim's command line, where you have to hit enter to actually run the command Nov 8, 2016 at 14:09 # 05AB1E, 81767473706968656462605957 56 bytes Currently in war with the V answer. I'm coming for you Dr. McMoylex :p. Also in war with the Pip answer. I'll be watching you Mr. DLosc. Code: Ç6&"¹s<ú.s.Bívy¹'xQiÂðñ}, ¹×S)»¹'=Qƒ= ;ƒ¹})D¦»»Rû.c"#è.V  Or in a more readable form:  Ç6& "¹s<ú.s.Bívy¹'xQiÂðñ}, ¹×S)»¹'=Qƒ= ;ƒ¹})D¦»»Rû.c" #è.V  Uses the CP-1252 encoding. Try it online! • Here we go again... :P Nov 7, 2016 at 17:53 • @DrMcMoylex Hahaha, good old times :). Nov 7, 2016 at 17:53 • More readable... totally... Nov 7, 2016 at 17:56 • For a given definition of "readable". Nov 8, 2016 at 22:23 • Nov 10, 2016 at 16:01 # Python 3, 304283 278 bytes Simple enough, just makes a matrix of chars and applies the different operations based on which one it is. The = and - have trailing spaces if that's not too bad. EDIT: Thanks to @Shebang and @Rod for their suggestions which ended up saving 21 bytes! EDIT2: Thanks to @Artyer for saving 5 bytes! t,s=input().split() s=int(s) r=range(s) b=[[' ']*s for x in r] exec(['for x in r:b[s//2][x]=b[x][s//2]=t','b=[t*s]'+'*2'*(t=='='),'for x in r:b[x][s-x-1]='+'b[x][x]='*(t=='x')+'t'][(t>'+')+(t in'x/')]) if t in'-=+':b=[[x+' 'for x in l]for l in b] print(*map(''.join,b),sep='\n')  • You can save 8 bytes by removing the if'-'==t condition line and replacing the one above it with if t in'=-':b=[[t+' ']*s]*(2*(t>'-')) (I think). – Kade Nov 7, 2016 at 17:25 • you can wrap the functions inside a list and run using exec: exec(['+ block','/ block','x block','= block','- block']['+/x=-'.find(t)]) to save ~18 bytes – Rod Nov 7, 2016 at 17:31 • Yes, trailing spaces/newlines are acceptable. Nov 7, 2016 at 17:41 • For the first line, do .split() (No args splits on whitespace). On line 6, you missed a space (b=[[x+' 'for). You can make the last line print(*map(''.join,b),sep='\n') for 1 less bytes. Nov 7, 2016 at 22:34 # JavaScript (ES6), 238225215202 196 bytes (c,n)=>[...Array(i=n*(c=="="?4:c+1-1?2:c<"-"?n+n:n+1))].map(_=>--i%(n+(c=='/'|c>'w'||n))?c>'w'?i%n&&~-i%(n+2)?" ":c:c<'-'?i%(n*2)-n&&(~i&1|(n/2^i/n/2))?" ":c:c=="/"?i%n?" ":c:i%2?c:" ": ).join  Could probably be golfed, but it's a start. # Scala, 275 bytes (i,c)=>if(c<44){val b=(" "*(i-1)+"+\n")*((i-1)/2) b+"+ "*i+"\n"+b}else if(c<46)"- "*i else if(c<48)i-1 to(0,-1)map(" "*_+"/\n")mkString else if(c<62)"= "*i+"\n"+"= "*i else{val a=0 to i/2-1 map(x=>" "*x+"x"+" "*((i/2-x)*2-1)+"x"+" "*x+"\n")mkString;a+" "*(i/2)+"x"+a.reverse}  Usage: val f:((Int,Char)=>String)=... print(f(10, '/'))  Explanation: The code tests for the ascii value of the char to choose the right way of generating the image. The ascii values of the operators in question are: ('+' -> 43), ('-' ->45), ('/' -> 47), ('=' -> 61), ('x' -> 120) (i,c)=> //define a function if(c<44){ //if c is a plus val b=(" "*(i-1)+"+\n")*((i-1)/2) //define the top/bottom part b as (i-1)/2 times (i-1) spaces, a plus sign and a newlineine b+"+ "*i+"\n"+b //return b, i times a plus and a space, a newline and b }else if(c<46) //if c is a '-' "- "*i //return "- " repeated i times else if(c<48) //if c is a '/' i-1 to(0,-1) //create a range from i-1 to 0 in steps of -1 map(" "*_+"/\n") //map each number to that number of spaces plus a "/" and a newline mkString //join them together else if(c<62) //if c is '=' "= "*i+"\n"+"= "*i //return "= " repeated i times, a newline and "= " repeated i times again else{ //if c if 'x' val a= //define a, which will be the top part, as... 0 to i/2-1 //a range from 0 to i/2-1 map(n=> //map each number n to " "*n //n spaces +"x" //plus an "x" +" "*((i/2-n)*2-1) //plus ((i/2)-n)*2-1 spaces +"x" //plus an "x" +" "*n //plus n spaces +"\n" //and a newline )mkString; //join them a+" "*(i/2)+"x"+a.reverse //return a, i/2 spaces, "x" and the reverse of a }  ## Pip, 6259 56 bytes 55 bytes of code, +1 for -S flag. [sXbRA_AEv-_aM,b(Y^aWR_Xb/2s)MyRVsX,b.aYaXbJsxyRL2x]@Aa  Note that this solution works with input of ÷ for division and * for multiplication, though it uses those characters to draw ASCII-art / and x, respectively. OP has clarified that this is okay. Try it online! ### How? Here's a partially spaced and commented version. Note that a and b are the command-line args, i.e. the operator and the size respectively. The -S flag controls how lists are output: it joins on newlines first, but joins any nested lists on spaces. [ Build a list of all possible figures: sXbRA_AEv-_aM,b 0 - Multiplication (Y^aWR_Xb/2s)My 1 - Addition RVsX,b.a 2 - Division YaXbJs 3 - Subtraction x 4 - Empty yRL2 5 - Equals x 6 - Empty ] @ Aa Index, mod 7, with ASCII value of a  And here are the individual sections: Multiplication For each row in the figure, we generate a string of spaces and then replace two of them with the input character. For row i, we want to replace the spaces at index i and b-1-i; but note that the latter can use the negative index -1-i. (It's even shorter because the variable v is preinitialized to negative 1.) sXbRA_AEv-_aM,b M,b Map this function to range(b): sXb Space, repeated b times _ Function arg AE (Implicitly) convert to list and append element... v-_ -1 minus function arg RA Replace the characters at those indices... a ... with input character The resulting list is output with one item per line  Addition Using the strategy from my Draw a hollow square answer, we define a function that wraps a + in b/2 copies of its argument and returns the result as a list of characters. (Integer division // isn't necessary because the string repetition operator X automatically truncates to integer.) First, we call this function on a space, giving [" ";" ";"+";" ";" "]; then, we map the same function to that result, giving [" ";" ";"+";" ";" "] on most lines but ["+";"+";"+";"+";"+"] on the center line. This nested list is then output, because of the -S flag, with spaces between all characters on a row and newlines between rows. (Y^aWR_Xb/2s)My Anonymous function: _Xb/2 Function arg, repeated b/2 times (implicitly rounded down) aWR Wrap a in two copies of the above ^ Split resulting string into list of chars Y Yank that function into y ( s) Apply function y to space My Map y to that result  Division Each row has between b-1 and 0 spaces, followed by the input character a. RVsX,b.a ,b Range(b) sX Space, repeated that many times (works itemwise) .a Concatenate a (itemwise) RV Reverse (puts the larger number of spaces at the beginning) Outputs newline-separated  Subtraction Make a space-separated row of the input character. Save a copy for later. YaXbJs aXb b copies of a Js Join on space Y Yank into y (overwrites the function from earlier, but we're done using it anyway) This is a string, so it just gets output  Equals The subtraction step stored half of what we need in y--just double it. yRL2 (Implicitly) convert y to list and repeat it twice Outputs newline-separated  The dummy x values are there to pad the main list so that the modular indexing gives a unique index for each input character in +-*÷=. ## JavaScript (ES6), 156 bytes (c,n)=>[...Array(n--)].map((_,i,a)=>a.map((_,j)=>({'/':a=i+j-n,x:a&&i-j,'-':a=i+i-n,'+':a&&j+j-n,'=':a+2&&a-2}[c]?' ':c)).join(c=='='|c<'/'?' ':'')).join\n  Where \n represents the literal newline character. • In Firefox 49, I get SyntaxError: invalid property id as it's currently written, but changing the backticks around the slash to apostrophes fixed that. (Why do you have backticks there instead of apostrophes?) Nov 8, 2016 at 14:33 • Also, the outputs for +, - and = look different than the challenge calls for: "Horizontal portions should have spaces between the characters to offset vertical/horizontal distance differences." Nov 8, 2016 at 14:35 • @ETHproductions a) typo b) sorry, I overlooked that, will fix later. – Neil Nov 8, 2016 at 14:39 • This is ridiculously short though. I hope fixing it doesn't add too many bytes. Nov 8, 2016 at 14:41 • @ETHproductions Thanks. I think this does at a cost of 19 bytes. – Neil Nov 8, 2016 at 15:06 # Dyalog APL, 91 86 bytes Needs ⎕IO←0, which is default on many systems. Takes n as left argument, and one of + - × ÷ = as right argument. {s←⌈⍎⍕3⍵2 t←' '⍵ d←⌽∘.=⍨⍺ s∊2 6:t[d∨⌽d∧6=s] 5=s:t[↑,/2↑¨∨/¨(⌊⍺÷2)=⍳⍺ ⍺] (2-s)(2×⍺)⍴t}  ### Explanation { s ← ⌈ ⍎ ⍕ 3 ⍵ 2 ⍝ calculate ceil(3 f 2), where f is the given symbol t ← ' '⍵ ⍝ create a string with a space before the symbol d ← ⌽ ∘.=⍨ ⍺ ⍝ Boolean \ diagonal s ∊ 2 6: t[d ∨ ⌽ d ∧ 6 = s] ⍝ if ÷ or × index t with one or both diagonals ⍝ find coordinates that are in the middle of at least one dimension ⍝ pad with zeros for spacing ⍝ use that to index into t 5 = s: t[ ↑ ,/ 2↑¨ ∨/¨ (⌊ ⍺ ÷ 2) = ⍳ ⍺ ⍺] ⍝ - or =: (2 - s) (2 × ⍺) ⍴ t ⍝ one or two rows of double-spaced symbols }  # Mathematica, 191 bytes e=#~Mod~2==1&;StringRiffle[Normal@SparseArray[{a_,b_}/;(a+b==d+1||a==b)[e@b&&a<3,,e@b&&(a==⌈d/2⌉||b==d),,e@b&&a<2,,a+b==d+1][[Last@ToCharacterCode@#~Mod~10]]:>#,{d=#2,2d-1}," "]," "," "]&  Anonymous function. Takes a string and a number as input, and returns a string as output. Not the shortest by far, but still fun to write. # C, 396 bytes #define p(x) printf(x); i,j,k,m;f(char s,int n){i=k=0;if(s==45)for(;i<n;++i)p("- ")m=n/2;if(s==43)for(;i<n;++i)for(j=0;j<=m;++j)if(i-m)p(j-m?" ":"+\n")else{for(;k<n;++k)p("+ ")p("\n")j+=m;}if(s==61)for(;i<2;++i){for(k=0;k<n;++k)p("= ")p("\n")}j=n;if(s==47)for(;i<n;++i){--j;for(k=0;k<j;++k)p(" ")p("/\n")}if(s==120)for(;i<n;++i){k=m-abs(m-i);for(j=0;j<n-k;++j)p(j-k?" ":"x")p(i-m?"\bx\n":"\n")}}  Call with: int main() { f('x', 5); return 0; }  # SOML, 104 100 bytes (non-competing)  Cd³³b»E +=?ce*d+e{t}bd*Oe{t}} ==?b*tt} -=?b*t} /=?bc*b{j:d+p}} x=?"”cb*e{jj⁴⁴d;d+++tGG;c+;}XOdoe{O  This is kind-of competing as I'm pretty sure that everything I used here has docs on github before this questions posting date but the parser doesn't have support for some functions I used so idk. # PHP, 306292281282281275 270 bytes $r=str_pad("",2*$n=$argv[2],($c=$argv[1])." ")."\n";if(",">$c)$r=($m=str_repeat(str_pad($c,$n," ",0)."\n",$n/2))."$r$m";if(9<$c)$r.=$r;if(w<$c)for($r=$c;$i<$n;$r[$i*(2+$n)]=$r[++$i*$n-1]=x)$r[$i*$n+$i+$n]="\n";if("/"==$c)for($r=$s="";$i++<$n;$s.=" ")$r="$s/\n$r";echo\$r;


Ooh this is bulky ... needs further golfing.
I could save 4 bytes with physical linebreaks or one byte with putting "\n" into a variable.

• Nice.for the "+", I think you need to match the height and not always 3. Also you should be able golf more to use if() instead of case/break; Nov 9, 2016 at 7:50

# C#, 744 Bytes

It's like 1 million characters long, I think, but I don't care, I am just so happy that I solved this...

Golfed:

string A(string s,int n){string O="";Func<string,int,string>R=(a,b)=>{return string.Join("",Enumerable.Repeat(a,b))+"\r\n";};switch(s){case"+":for(int i=0;i<n;i++){if(i==n/2){O+=R("+",n);}else{O+="+".PadLeft(n-n/2,' ').PadRight(n-n/2,' ')+"\r\n";}}return O;case"=":return R("=",n)+R("=",n);case "-":return R("-",n);case "/":for(int i=n;i>0;i--){O+="/".PadLeft(i)+"\r\n";}return O;case "x":int x=0;string[]r=new string[n];for(int i=n;i>0;i--){if(n-x-x<0){O+="x".PadLeft(x+1)+"\r\n";break;}string row=string.Join("",Enumerable.Repeat(" ",x))+"x"+string.Join("",Enumerable.Repeat(" ",n-x-x))+"x"+"\r\n";O+=row;x++;r[x]=row;if(i==n/2)break;}for(int i=r.Length-1;i>0;i--){if(string.IsNullOrEmpty(r[i]))continue;O+=r[i];}return O;default:return "";}}


Ungolfed:

public string A(string s, int n)
{
string O = "";

Func<string, int, string> R = (a, b) =>
{
return string.Join("", Enumerable.Repeat(a, b)) + "\r\n";
};

switch (s)
{
case "+":
for (int i = 0; i < n; i++)
{
if (i == n / 2)
{
O += R("+", n);
}
else
{
O += "+".PadLeft(n - n / 2, ' ').PadRight(n - n / 2, ' ') + "\r\n";
}
}
return O;
case "=":
return R("=", n) + R("=", n);
case "-":
return R("-", n);
case "/":
for (int i = n; i > 0; i--)
{
}
return O;
case "x":
int x = 0;
string[] r = new string[n];
for (int i = n; i > 0; i--)
{
if (n - x - x < 0)
{
O += "x".PadLeft(x + 1) + "\r\n";
break;
}
string row = string.Join("", Enumerable.Repeat(" ", x))
+ "x"
+ string.Join("", Enumerable.Repeat(" ", n - x - x)) + "x" + "\r\n";
O += row;
x++;
r[x] = row;
if (i == n / 2)
break;
}
for (int i = r.Length - 1; i > 0; i--)
{
if (string.IsNullOrEmpty(r[i]))
continue;
O += r[i];
}
return O;
default:
return "";
}
}


Testing:

+: 3, 5, 7, 9, 11
/: 7, 8, 9, 10
-: 3, 4, 5, 6
=: 3, 4, 5, 6, 7
x: 5, 7, 9, 11


Too much to paste and format here, I created a pastebin:

Pastebin

• Please golf it and provide a byte count. Nov 10, 2016 at 19:29

## C, 331 Bytes

i,j;f(o,n){if(47==o)for(i=n;i;puts("")){for(j=i--;j--;putchar(j?32:o)){}}
if(43==o)for(i=n;i--;puts("")){for(j=n;j--;printf(i==n/2||!j?"+ ":" ")){}}
if(45==o)for(i=n;i--;putchar(o)){}
if(61==o)for(i=3;i--;puts("")){for(j=n;j--;putchar(i&1?32:o)){}}
if(120==o)for(i=n;i;puts("")){for(j=0;j++<n;putchar(j==i||j==n-i+1?o:32)){}i--;}}


The operator is passed as ASCII code into o and the character count into n. I only added spaces between horizontally consecutive characters into the plus sign, since this was the only one where the output would have been distorted if I hadn't and in the task it only said "should". I use two nested loops counting down (except for - where I only need one line).

= Three Lines, one of them empty, straight forward

+ using printf because of the spaces

- straight forward

/ have the inner loop print at zero and start at the outer loop's counter

x have the inner loop print at the outer loop's counter and its "inverse" n-i. Still need to look at why I'am off-by-one here.

Sample call:

#include <stdio.h>
/*  =       61
+       43
-       45
/       47
Space   32
x       120
*/
int main(int argc, char **argv){
printf("%s\n%s\n",argv[1], argv[2]);
f(*argv[1],strtol(argv[2],NULL,10));
}


# Lua, 402344 312 bytes

312:

r,p,b,x=string.rep,print,' ','x'function d(s,n)h,l=(n+1)/2,s..b;e=r(l,n)if s=='-'then p(e)elseif s=='='then p(e)p(e)else for f=1,n do p(s=='/'and(r(b,n-f)..s)or s=='+'and(f~=h and r(' ',n-1)..'+'or r('+ ',n))or f<h and r(b,f-1)..x..r(b,n-2*f)..x or f>h and r(b,n-f)..x..r(b,2*f-2-n)..x or r(b,f-1)..x)end end end


344:

r,p,b,x=string.rep,print,' ','x'function d(s,n)h,l=(n+1)/2,s..b;e=r(l,n)if s=='-'then p(e)elseif s=='='then p(e)p(e)else for f=1,n do if s=='/'then p(r(b,n-f)..s)elseif s=='+'then p(f~=h and r(' ',n-1)..'+'or r('+ ',n))elseif s=='x'then p(f<h and r(b,f-1)..x..r(b,n-2*f)..x or f>h and r(b,n-f)..x..r(b,2*f-2-n)..x or r(b,f-1)..x)end end end end


402:

r,p,b,x=string.rep,print,' ','x'function d(s,n)h=(n+1)/2;if s=='-'then p(r(s..b,n))end;if s=='='then p(r(s..b,n))p(r(s..b,n))end;if s=='/'then for i=1,n do p(r(b,n-i)..s)end end;if s=='+'then for i=1,n do p(i~=h and r(' ',n-1)..'+'or r('+ ',n))end end;if s=='x'then for i=1,n do if i<h then p(r(b,i-1)..x..r(b,n-2*i)..x)elseif i>h then p(r(b,n-i)..x..r(b,-n+2*i-2)..x)else p(r(b,i-1)..x)end end end end


90 characters reduced and it's now painful to look at even when expanded. :|