Square root of ASCII art

30

1

You are working as an intern for a mathematician who really hates TeX, LaTeX, etc. So much so that he has decided to abandon all typesetting whatsoever and make you do all the formatting in ASCII. You got tired of this after a while and decided to start automating parts of it, starting with square roots.

Here's how a square root is made:

###  this is the input
###
###

_____  put a row of underscores stretching one character off either side on top
 ### 
 ### 
 ### 

   _____  put a diagonal of slashes in front going the height of the input
  / ### 
 /  ### 
/   ### 

      _____ put a diagonal of backslashes in front of that, going up half of the input's height rounded up
     / ###
 \  /  ###
  \/   ###

And that's it!

Rules

You are to make a program or function that takes in a string, list of strings (i.e. lines), or array of characters, and outputs the input transformed according to the description above (not necessarily by the exact same order or process)

You may assume that the input is rectangular if preferred. Trailing whitespace is neither required nor disallowed.

This is , so the shortest answer in bytes wins.

Examples:

Input:
40
Output:
  ____
\/ 40

Input:
  ____
\/ 40
Output:
   ________
  /   ____
\/  \/ 40 

Input:
/| 
 | 
 | 
_|_
Output:
      _____
     / /|
    /   |
\  /    |
 \/    _|_

Input:
#  # 
#  # 
#####
   # 
   # 
Output:
        _______
       / #  #  
      /  #  #  
\    /   ##### 
 \  /       #  
  \/        #  

DanTheMan

Posted 2017-07-25T20:55:41.687

Reputation: 3 140

3V is gonna do well in this one – caird coinheringaahing – 2017-07-25T21:09:12.610

16a mathematician who really hates TeX, LaTeX etc I almost quit reading right there – Luis Mendo – 2017-07-25T23:04:34.287

5You are working I almost quit reading right there – Arnauld – 2017-07-26T17:46:20.597

Answers

7

Python 2, 196 bytes

x=Q=input()
l=len(x)
k=(l+1)/2
q=l+k
x=[[' ']*(q+1)+list(y)for y in x]
for i in range(k):x[i+l/2][i]='\\'
for j in range(l):x[j][q-j-1]='/'
print'\n'.join([' '*q+'_'*(2+len(Q[0]))]+map(''.join,x))

Try it online!

-2 bytes thanks to Step Hen

-13 bytes thanks to Jonathan Allan

HyperNeutrino

Posted 2017-07-25T20:55:41.687

Reputation: 26 575

@StepHen Hm. It works but / would work too. Thanks. – HyperNeutrino – 2017-07-25T21:29:45.483

Same for i+l//2 – Stephen – 2017-07-25T21:31:28.383

The underscores need to stretch one character extra on either side. – Neil – 2017-07-26T00:15:46.680

You can take input as a list of strings (Python 2's input() evaluates the raw input). Also '_'*len(Q[0])+'__' is '_'*(2+len(Q[0])). – Jonathan Allan – 2017-07-26T02:14:38.003

6

SOGL V0.12, 27 bytes

1w⁄2+╔*00žl»╚;lH╚@Κ№↕h┼№↕;┼

Try it Here! ( added for ease-of-use; the program expects the input on stack)

dzaima

Posted 2017-07-25T20:55:41.687

Reputation: 19 048

5

Charcoal, 32 bytes

WS⊞υιP⪫υ¶↖P×_⁺²⌈EυLι↙↙Lυ↑↖÷⁺¹Lυ²

Try it online! Link is to verbose version of code. 29-byte version that assumes rectangular input:

WS⊞υιP⪫υ¶↖P×_⁺²Lθ↙↙Lυ↑↖÷⁺¹Lυ²

Neil

Posted 2017-07-25T20:55:41.687

Reputation: 95 035

3@LuisMendo Charcoal is getting old... – Erik the Outgolfer – 2017-07-26T10:29:15.173

@EriktheOutgolfer D: old how – ASCII-only – 2017-08-10T10:34:31.873

@ASCII-only Well SOGL is newer and better, so...no offense to Charcoal though it still wins a lot. – Erik the Outgolfer – 2017-08-10T10:38:39.283

@EriktheOutgolfer but how is it better :( – ASCII-only – 2017-08-10T10:54:12.803

IMO it's kinda like saying Haskell is newer and better so Haskell > C# although it still wins a lot – ASCII-only – 2017-08-10T10:55:11.670

@ASCII-only Well you can't just design the perfect language for everything :p basically that's a problem with many languages, and there's also evolution, and of course being able to recognize when somebody means something literally or not ;) – Erik the Outgolfer – 2017-08-10T10:57:23.110

i know but old :||||||||||||||||||||||||||||| do you know how offensive that is to charcoal it's one of the younger ones (less old than cjam etc, including v and jelly) :P – ASCII-only – 2017-08-10T11:02:55.330

5

Python 3, 138 147 Bytes

def f(l):h=len(l);w=len(l[0]);c=int(h/2);print('\n'.join([(h*2-c)*' '+w*'_']+[(i*' '+'\\'+(h-i-1)*2*' '+'/'+i*' ')[c:]+s for(i,s)in enumerate(l)]))

Variable 'l' is a list of strings, each string a line. Readable Version:

def f(l):
  height = len(l)
  width = len(l[0])
  half_height_floor = int(height / 2)

  print((height * 2 - half_height_floor) * ' ' + width * '_')

  for (index, line) in enumerate(l):
    #build a V based on the location of the line
    #surrounding V whitespace
    outer_space = index * ' '

    #inner V whitespace
    inner_space = (height - index - 1) * 2 * ' ' #inner v space

    #complete V
    v = outer_space + '\\' + inner_space + '/' + outer_space

    #left half_height_floor chars removed
    v_chopped = v[half_height_floor:]

    print(v_chopped + line)

Forms a square root symbol with a complete V then shaves off the left accordingly.

Try it Online!

Conner Johnston

Posted 2017-07-25T20:55:41.687

Reputation: 146

2Hi, Welcome to PPCG. Nice first answer, but this is a snippet, since it is assuming the variable l as input. You must also include the part where l is input, either as a function parameter or input() function, etc. (P.S. your answer also seems to be lacking a few white-space-padding.) – officialaimm – 2017-07-26T06:20:33.210

2@officialaimm, thank you for the welcome! To practice for future problems I have updated and included TIO link – Conner Johnston – 2017-08-09T00:10:40.370

3

Python 2,  131  130 bytes

x=input()
n=len(x)
s=" "
for v in[s*2*n+"_"*(2+len(x[0]))]+[s*i+"\\"+s*2*(n+~i)+"/"+s*-~i+r for i,r in enumerate(x)]:print v[n/2:]

A full program taking a list of lines as input with the rectangular-only allowance (actually that the first line is one of the longest).

Try it online!

Jonathan Allan

Posted 2017-07-25T20:55:41.687

Reputation: 67 804

2

Java 8, 244 bytes

A very long solution, but probably close to the shortest for Java. This lambda takes lines of input as a String[] and returns a String. All lines must have the same length.

Based on the example outputs, I assumed that there's no need to append a space to each line in the input, so the program doesn't.

Thanks to Jonathan Allan for reminding me about the ~ operator.

l->{int h=l.length,w=l[0].length(),a=h/2,i=w+3,x=h+a+h%2;String s="",t=s;for(;--i>0;)t+="_";for(;i++<x;)s+=" ";t=s+t;for(i=0;i<h;)t+="\n"+s.substring(0,i<a?x+~i:i-a)+(i<a?"":"\\"+s.substring(0,(h+~i)*2))+"/"+s.substring(0,i+1)+l[i++];return t;}

Try It Online

Ungolfed

l -> {
    int
        h = l.length,
        w = l[0].length(),
        a = h / 2,
        i = w + 3,
        x = h + a + h % 2
    ;
    String
        s = "",
        t = s
    ;
    for (; --i > 0; )
        t += "_";
    for (; i++ < x; )
        s += " ";
    t = s + t;
    for (i = 0; i < h; )
        t +=
            "\n"
            + s.substring(0, i < a ? x + ~i : i - a)
            + (i < a ? "" : "\\" + s.substring(0, (h + ~i) * 2))
            + "/"
            + s.substring(0, i + 1)
            + l[i++]
        ;
    return t;
}

Acknowledgments

  • -2 bytes thanks to Kevin Cruijssen

Jakob

Posted 2017-07-25T20:55:41.687

Reputation: 2 428

1

Nice answer +1. You can golf 2 bytes by creating a variable for h+a+h%2 which you use two times in your code: l->{int h=l.length,w=l[0].length(),a=h/2,i=w+3,x=h+a+h%2;String s="",t=s;for(;--i>0;)t+="_";for(;i++<x;)s+=" ";t=s+t;for(i=0;i<h;)t+="\n"+s.substring(0,i<a?x+~i:i-a)+(i<a?"":"\\"+s.substring(0,(h+~i)*2))+"/"+s.substring(0,i+1)+l[i++];return t;}. (I also used the header & footer in the TIO link, so you can isolate your actual golfed code from the test code.)

– Kevin Cruijssen – 2017-08-10T11:24:28.823

1

Japt, 46 bytes


l *2
£Vç hY'\ h~Y'/ +S+XÃuVç +'_p2+Ug l¹msV/4

Leading newline is part of the program. Input and output is an array of strings representing lines.

Try it online! using the -R flag to join the resulting array with newlines.

Justin Mariner

Posted 2017-07-25T20:55:41.687

Reputation: 4 746

@ETHproductions Sadly that won't work since U is an array and not a string. – Justin Mariner – 2017-07-26T01:05:31.193

Ah, darn it.... – ETHproductions – 2017-07-26T01:06:54.497

1

Perl 5, 177 185 160 bytes

$s=$f=int((@t=<>)*1.5+.5);print" "x$f;print"_"x length$t[0];print"_
";$b=-int(@t/2);for(0..$#t){--$s;print$_==$s?"/":$_==$b?"\\":" " for 0..$f;print$t[$_];++$b}

Try it online!

Changelog:

  • needed more bytes to fix a bug (it assumed a square input first)
  • fixed another bug and used some tips from comments (thanks Dada!)

Felix Palmen

Posted 2017-07-25T20:55:41.687

Reputation: 3 866

Shortened to 132 bytes. I let you have a look at what I did. The big lines: <> instead of <STDIN>, print" "x$f instead of for(1..$f){print" "}, using xxx for yyy instead of for(yyy){xxx}, using $_ in the for loop instead of explicit variables (for$i(..){..})...

– Dada – 2017-07-27T11:31:19.237

Long time since I used perl, thanks! But I tried with x$f and couldn't get it to work :o trying again now... – Felix Palmen – 2017-07-27T11:34:40.027

Uh and I just found a bug in both versions ... give me some time to fix this ;) – Felix Palmen – 2017-07-27T11:44:50.427

1

JavaScript (ES6), 140 bytes

Takes input as an array of strings / returns an array of strings.

a=>[a[0].replace(/./g,'_'),...a].map((r,y)=>[...a,...a].map((_,x)=>x-y+1|y-.5<l/2?l*2-x-y?' ':'/':'\\',c=y?' ':'_').join``+c+r+c,l=a.length)

Test cases

let f =

a=>[a[0].replace(/./g,'_'),...a].map((r,y)=>[...a,...a].map((_,x)=>x-y+1|y-.5<l/2?l*2-x-y?' ':'/':'\\',c=y?' ':'_').join``+c+r+c,l=a.length)

console.log(
  f([
    '40'
  ]).join`\n`
)

console.log(
  f([
    '  ____',
    '\\/ 40 '
  ]).join`\n`
)

console.log(
  f([
    '/| ',
    ' | ',
    ' | ',
    '_|_'
  ]).join`\n`
)

console.log(
  f([
    '#  # ',
    '#  # ',
    '#####',
    '   # ',
    '   # '
  ]).join`\n`
)

Arnauld

Posted 2017-07-25T20:55:41.687

Reputation: 111 334

0

C++, 291 bytes

The function assumes that all the strings in the vector passed as parameter have the same length

#include<vector>
#include<string>
#define S std::string
#define T size()
void f(std::vector<S>&c){c.insert(c.begin(),S(c[0].T+1,'_'));int i,j=0;for(i=1;i<c.T;++i){c[i]='/'+S(i,' ')+c[i];if(i>=c.T/2)c[i]='\\'+S((c.T-i-1)*2,' ')+c[i];}for(auto&a:c)j=j>a.T?j:a.T;for(auto&a:c)a=S(j-a.T,' ')+a;}

HatsuPointerKun

Posted 2017-07-25T20:55:41.687

Reputation: 1 891

0

Dyalog APL, 95 bytes

{((' '/⍨y+x),'_'/⍨2+⊃⌽⍴⍵)⍪⍉(x-y)↓⍉(⊖(x(-x)↑⌽y y⍴'\',' '\⍨y←⌈x÷2),x x⍴'/',' '\⍨x←⊃⍴⍵),' ',⍵,' '}

Try it online!

Uriel

Posted 2017-07-25T20:55:41.687

Reputation: 11 708

0

C, 485 bytes

This program takes up to 999 characters from standard input and reads them into an array. It prints them 1 at a time to standard output with the changes your challenge indicated. It assumes the input is rectangular.

#include<stdio.h>
#define p(a)putc(a,stdout);
#define P j+j/2+1
a[999],i,j,k,l,m,n,q;char c;pad(a){m=P;if(a&&!k){m-=1;}for(n=0;n!=m;n++){q=32;if((!a||k)&&n==c){c--;q=47;}else if((P-c+1)>j/2+1&&(P)/2-n==c-2){q=92;}p(q);}}int main(){k=i=j=0;x:if(read(0,&c,1)){if('\n'==(a[i++]=c)){if(!j){l=i;}j++;}goto x;}i--;if('\n'==a[i-1]){i--;}else{j++;}c=P-2;for(;k!=i;k++){if(!k||a[k]==10){if(a[k]==10){p(10);}pad(1);if(!k){l++;while(l-->0){p(95);}p(10);pad(0);}if(a[k]==10){continue;}}p(a[k]);}}

Eric Urban

Posted 2017-07-25T20:55:41.687

Reputation: 101

0

Perl 5, 159 bytes

@a=map{$m=(y///c)>$m?y///c:$m;$_}<>;$_=$"x($l=@a/2-.5).'\\/'.$"x@a;for$i(1..@a){$a[-$i]=$_.$a[-$i];s| \\|\\ |;s|/ | /|;$i>$l&&y/\\/ /}chop;say$_.'_'x++$m,$/,@a

Try it online!

Xcali

Posted 2017-07-25T20:55:41.687

Reputation: 7 671