Extendify the ASCII Sun

43

7

Write a program that takes in (via STDIN/command line) a non-negative integer N.

When N is 0, your program should print O (that's capital Oh, not zero).

When N is 1, your program should print

\|/
-O-
/|\

When N is 2 your program should print

\ | /
 \|/
--O--
 /|\
/ | \

When N is 3 your program should print

\  |  /
 \ | /
  \|/
---O---
  /|\
 / | \
/  |  \

For larger N, this pattern continues on in the same exact fashion. Each of the eight rays of the "sun" should be made of N of the appropriate -, |, /, or \ characters.

Details

  • Instead of a program, you may write a function that takes an integer. The function should print the sun design normally or return it as a string.
  • You must either

    • have no trailing spaces at all, or
    • only have enough trailing spaces so the pattern is a perfect (2N+1)*(2N+1) rectangle.
  • The output for any or all N may optionally have a trailing newline.

Scoring

The shortest code in bytes wins.

Calvin's Hobbies

Posted 2015-05-07T20:36:04.593

Reputation: 84 000

Is a leading newline allowed? Especially interesting for N=0. – Jakube – 2015-05-07T23:10:49.310

@Jakube No. Trailing only. – Calvin's Hobbies – 2015-05-07T23:12:20.617

Answers

12

Pyth, 39 38 36 bytes

jbXmXXj\|m*\ Q2d\\_hd\/JhyQQX*\-JQ\O

Try it online: Pyth Compiler/Executor

Explanation

jbXmXXj\|m*\ Q2d\\_hd\/JhyQQX*\-JQ\O   implicit: Q = input
                       JhyQ            J = 1 + 2*Q
    m                  J               map each d of [0,1,...,2*Q] to:
          *\ Q                           " "*input
         m    2                          list with twice " "*input
      j\|                                join this list by "|"
     X         d\\                       replace the value at d to "\"
    X             _hd\/                  replace the value at -(d+1) to "/"
  X                        Q           replace line Q by:
                             *\-J        "-"*J
                            X    Q\O     replace element at Q with "O"
jb                                     join by "newlines"

Another 36 bytes solution would be:

jbmXXj\|m*?\-KqdQ\ Q2d\\_hd?\OK\/hyQ

Jakube

Posted 2015-05-07T20:36:04.593

Reputation: 21 462

26

C: 116 102 99 95 92 90

s(n){for(int c=-n,r=c;r<=n;c++)putchar(c>n?c=-c,r++,10:c?r?c-r?c+r?32:47:92:45:r?124:79);}

I think that I am getting fairly close to a minimal solution using this approach, but I can't stop feeling that there is a much better approach in C. Ungolfed:

void s(int n) {
  for(
    int c = -n, r = c;
    r <= n;
    c++
  )
    putchar(
      c > n
        ? c = -c, r++, '\n'
        : c
          ? r
            ? c - r
              ? c + r
                ? ' '
                : '/'
              : '\\'
            : '-'
          : r
            ? '|'
            : 'O'
    );
}

Fors

Posted 2015-05-07T20:36:04.593

Reputation: 3 020

7"c++" in C ... heh! – bjb568 – 2015-05-10T00:54:19.957

I'm glad you ungolfed it. Those ternary ifs are insane! – ldam – 2015-05-15T07:54:50.237

You can save 2 more bytes and make it vc 2012 compliant ;) c,r;s(n){for(r=c=-n;r<=n;c++)putchar(c>n?c=-c,r++,10:c?r?c-r?c+r?32:47:92:45:r?124:79);} – Johan du Toit – 2017-05-08T10:57:19.497

21

GNU sed, 252 + 1

Phew - I beat the php answer!

Score + 1 for using the -r parameter.

Because of sed limitations, we have to burn nearly 100 bytes just convert N to a string of N spaces. The rest is the fun stuff.

/^0/{y/0/O/;q}
s/./<&/g
s/9/8 /g
s/8/7 /g
s/7/6 /g
s/6/5 /g
s/5/4 /g
s/4/3 /g
s/3/2 /g
s/2/1 /g
s/1/ /g
s/0//g
:t
s/ </<          /g
tt
s/<//g
:
s/ //
s^.*^\\&|&/^;ta
:a
/\\$/q
p
s^\\\|/^-O-^;tn
s^(\\)? (/)?^\2 \1^g;ta
:n
y/ /-/
p
s^-O-^/|\\^
y/-/ /
ta

Explanation

  • The first line is an early exit for the N=0 case.
  • The next 15 lines (up to the :) convert N to a string of N spaces
  • s/ // removes one space
  • s^.*^\\&|&/^;ta converts N-1 spaces to: \ + N-1 spaces + | + N-1 spaces + /
  • Iterate, printing each iteration, and moving \ one space to the right and / one space to the left...
  • ...until we match \|/, which is replaced with -O- and jump to the n label
  • replace with - and print
  • replace -0- with /|\, and replace with - and jump back into the main loop
  • Iterate, printing each iteration, and moving \ one space to the right and / one space to the left...
  • ...until we match \$ which indicates were finished, and quit.

Output

 $ for i in {0..3}; do sed -rf asciisun.sed <<< $i ; done
 O
 \|/
 -O-
 /|\
 \ | /
  \|/ 
 --O--
  /|\ 
 / | \
 \  |  /
  \ | / 
   \|/  
 ---O---
   /|\  
  / | \ 
 /  |  \
 $

Digital Trauma

Posted 2015-05-07T20:36:04.593

Reputation: 64 644

16

J, 37 34 40 bytes

1:echo('O\/-|'{.@#~0=+&|,-,+,[,])"*/~@i:

Usage:

   (1:echo('O\/-|'{.@#~0=+&|,-,+,[,])"*/~@i:) 2  NB. prints to stdout:
\ | /
 \|/ 
--O--
 /|\ 
/ | \

Explanation (from left to right):

  • i: generates list -n, -(n-1), ..., n-1, n
  • ( )"*/~@i: creates the Descartes product of i: with itself in a matrix arrangement, e.g. for n = 1 creates the following 3-by-3 matrix

    ┌─────┬────┬────┐
    │-1 -1│-1 0│-1 1│
    ├─────┼────┼────┤
    │0 -1 │0 0 │0 1 │
    ├─────┼────┼────┤
    │1 -1 │1 0 │1 1 │
    └─────┴────┴────┘
    
  • for every matrix-element with integers x y we do the following

  • +&|,-,+,[,] calculate a list of properties

    • +&| abs(x)+abs(y), equals 0 iff (if and only if) x=0 and y=0
    • - x-y, equals 0 iff x=y i.e. we are on the diagonal
    • + x+y, equals 0 iff x=-y i.e. we are on the anti-diagonal
    • [ x, equals 0 iff x=0 i.e. we are on the middle row
    • ] y, equals 0 iff y=0 i.e. we are on the middle column
  • 'O\/-|'#~0= compare these above property values to 0 and take the ith character from the string 'O\/-|' if the ith property is true.

  • the first character in the resulting string will always be the one we need, if there string is empty we need a space
  • {. takes the first character of a string and if there is no one it returns a space character as padding just as we need
  • we now have the exact matrix we need so we print it to stdout once with 1:echo

Try it online here.

randomra

Posted 2015-05-07T20:36:04.593

Reputation: 19 909

5This is the ungolfed version?! I feel like a pretty average programmer at times, and then for some reason I end up on codegolf and see the stuff you guys pull off and can't help but feel like an idiot. – JustSid – 2015-05-07T22:56:31.607

@JustSid Well, the text wasn't up to date with the code but technically I never wrote that the code is ungolfed. :) – randomra – 2015-05-08T09:54:59.600

It's still mighty impressive either way – JustSid – 2015-05-08T10:05:43.520

2@JustSid Not that it's any less impressive but J code pretty much just looks like that, and this seems like a challenge that it would be a good language for. It's a very impressive answer, but so is everything else in J :) – undergroundmonorail – 2015-05-08T12:46:43.107

11

PHP, 182 bytes

This seemed like a fun activity for my first answer. Comments on my code are welcome.

<?php function s($n){$e=2*$n+1;for($i=0;$i<$e*$e;$i++){$x=$i%$e;$y=floor($i/$e);echo$y==$x?($x==$n?"O":"\\"):($e-1==$x+$y?"/":($y==$n?"-":($x==$n?"|":" ")));echo$x==$e-1?"\n":"";}}?>

Here is the un-golfed code with comments:

<?php
function s($n) {
    $e=2*$n+1; //edge length
    for($i=0;$i<$e*$e;$i++) {
        $x = $i%$e; // current x coordinate
        $y = floor($i/$e); // current y coordinate

        if ($y==$n&&$x==$n) {
            // center of square
            echo'O';
        }
        else if ($y==$n) {
            // horizontal line
            echo'-';
        }
        else if ($x==$n) {
            // vertical line
            echo'|';
        }
        else if ($y==$x) {
            // diagonal line from top-left to bottom right
            echo'\\';
        }
        else if (($y-$n)==($n-$x)) {
            // diagonal line from bottom-left to top-right
            echo'/';
        }
        else {
            // empty space
            echo' ';
        }
        if ($x==$e-1) {
            // add new line for the end of the row
            echo"\n";
        }
    }
}?>
<pre>
<?php s(10); ?>
</pre>

Edited with code by royhowie

Kodos Johnson

Posted 2015-05-07T20:36:04.593

Reputation: 776

3

Hi :-) Good first effort. You can shrink your code in quite a few places though. For example if(($y-$h)==($x-$h)) does the same as if(($y==$x). You can save another character by replacing if($x==y$)foo();else bar(); with if($x^$y)bar();else foo();. You should also try using ternary operators instead of if .. else statements.

– r3mainer – 2015-05-07T23:57:26.297

ternary operators is a good tip – nick – 2015-05-08T02:33:32.787

174 bytes: function s($n){$e=2*$n+1;for($i=0;$i<$e*$e;$i++){$x=$i%$e;$y=floor($i/$e);echo$y==$x?($x==$n?"O":"\\"):($e-1==$x+$y?"/":($y==$n?"-":($x==$n?"|":" ")));echo$x==$e-1?"\n":"";}} – royhowie – 2015-05-08T08:30:08.627

>

  • there's no need for $r; just use echo ($r.= is the same amount of bytes as echo). 2. used ternary operator (saves a lot of characters). 3. $h was useless since it equaled $n. 4. You didn't need to use floor for $x = floor($i%$e);, since a modulus on an integer won't need to be rounded down.
  • < – royhowie – 2015-05-08T08:32:01.843

    @squeamishossifrage I never thought of that. Thanks for the tips! – Kodos Johnson – 2015-05-08T16:45:42.220

    @royhowie Thanks! Is it ok if I update my answer with your solution? – Kodos Johnson – 2015-05-08T16:46:21.513

    @user2518200 of course – royhowie – 2015-05-08T20:32:38.693

    With or without the floor() calls the $x and $y calculation still seems longer than using 2 fors. And when possible, combine calculation and first use – for example calculate $e inside the for where it is first used. Based on @royhowie's version, 161 characters: function s($n){for($y=0;$y<$e=2*$n+1;$y++)for($x=0;$x<$e;){echo$y==$x?($x==$n?"O":"\\"):($e-1==$x+$y?"/":($y==$n?"-":($x==$n?"|":" ")));echo$x++==$e-1?"\n":"";}} – manatwork – 2015-05-09T09:49:54.623

    Replace floor($e/2); with $e>>1; and you will save a few bytes. – Ismael Miguel – 2015-05-09T14:43:59.373

    for(;$i<$c=1+2*$argn;$o.="$t\n"){$t=str_pad("|O"[$b=$i++==$argn],$c," -"[$b],2);$b?:$t[$i-1]="\\".!$t[$c-$i]="/";}echo$o; 121 Bytes – Jörg Hülsermann – 2017-05-08T11:57:08.753

    @JörgHülsermann Wow that is nice. Feel free to make a new answer. I'll upvote it. – Kodos Johnson – 2017-06-06T00:56:54.420

    Feel free to take it as as your improvement. – Jörg Hülsermann – 2017-06-06T01:36:25.007

    I have reuse my idea in an other challenge so you can use it here – Jörg Hülsermann – 2017-06-08T20:35:29.313

    9

    Python 2, 99

    n=input()
    R=range(-n,n+1)
    for i in R:print''.join("O\|/ -"[[R,i,0,-i,j].index(j)^(i==0)]for j in R)
    

    Prints line by line, creating each line by checking whether the coordinate (i,j) (centered at (0,0)) satisfies j==-i, j==0, j==i, or none, with a hack to make the center line work.

    xnor

    Posted 2015-05-07T20:36:04.593

    Reputation: 115 687

    I think you can use R instead of .5 to save 1 byte. – randomra – 2015-05-09T21:46:09.403

    @randomra That's clever, thanks. Down to two digits! – xnor – 2015-05-10T00:04:36.453

    8

    CJam, 48 45 43 41 38 bytes

    This is still too long and I am still doing some redundant things, but here goes:

    ri:R{_S*"\|/"@R-~S**1$N}%'-R*'O1$W$sW%
    

    Try it online here

    Optimizer

    Posted 2015-05-07T20:36:04.593

    Reputation: 25 836

    7

    SpecBAS - 117 bytes

    1 INPUT s: LET t=s*2: FOR y=0 TO t: PRINT AT y,y;"\";AT y,t/2;"|";AT t-y,y;"/";AT t/2,y;"-": NEXT y: PRINT AT s,s;"O"
    

    This prints the slashes and dashes in one loop, and then plonks the "O" in the middle.

    Output using 1, 2 and 9

    enter image description here

    Brian

    Posted 2015-05-07T20:36:04.593

    Reputation: 1 209

    An anonymous user suggested to change "-": NEXT y: PRINT AT s,s;"O" to "-";AT s,s;"O": NEXT y to save two bytes. – Martin Ender – 2015-06-12T13:45:21.243

    7

    JavaScript (ES6) 97 98

    This seems different enough ...

    // GOLFED
    f=n=>(y=>{for(t='';++y<n;t+='\n')for(x=-n;++x<n;)t+='-O /\\|'[y?x?x-y?x+y?2:3:4:5:+!x]})(-++n)||t
    
    // Ungolfed
    
    F=n=>{
      ++n;
      t = '';
      for (y = -n; ++y < n; t += '\n')
        for (x = -n; ++x < n; )
          if (y != 0)
            if (x != 0)
              if (x != y)
                if (x != -y)
                  t += ' '
                else
                  t += '/'
              else
                t += '\\'
            else
              t += '|'
          else
            if (x != 0)
              t += '-'
            else 
              t += 'O'
      return t;
    }
        
    // TEST
    function test(){ OUT.innerHTML = f(N.value|0); }
    test()
    input { width: 4em }
    N: <input id=N value=5><button onclick="test()">Go</button>
    <pre id="OUT"></pre>

    edc65

    Posted 2015-05-07T20:36:04.593

    Reputation: 31 086

    Beautiful. I should have thought of a closure to use normal for loops. – nderscore – 2015-05-08T16:18:57.170

    I like this one. I had tried writing one using a string and accessing a specific index, but yours is much shorter. – royhowie – 2015-05-09T08:46:40.337

    6

    Haskell, 109 98 96 bytes

    Thanks to nimi and Mauris for their help!

    0#0='O'
    0#_='-'
    _#0='|'
    i#j|i==j='\\'|i== -j='/'|1<2=' '
    f n=unlines[map(i#)[-n..n]|i<-[-n..n]]
    

    Explanation:

    The operator # specifies which character appears at coordinates (i,j), with the sun centered at (0,0). Function f builds the result String by mapping # over all pairs of coordinates ranging from -n to n.

    Usage:

    ghci> putStr $ f 2
    \ | /
     \|/ 
    --O--
     /|\ 
    / | \
    

    user40671

    Posted 2015-05-07T20:36:04.593

    Reputation: 71

    You can save a few bytes by using an infix operator instead of s, e.g. 0#0='O', 0#_='-', etc. and 1<2 instead of True. – nimi – 2015-05-09T00:05:58.890

    Maybe map(i#)[-n..n] to save two bytes. – Lynn – 2015-05-11T17:17:25.713

    6

    OS/2 Classic Rexx, 102... or 14 for "cheater's version"

    Take out the linefeeds to "golf" it.

    w='%1'
    o=center('O',w,'-')
    m='center(space("\|/",w),%1)'
    do w
      w=w-1
      interpret "o="m"|o|"m
    end l
    say o
    

    Cheater's version, name the script whatever source code you want under 255 characters (requires HPFS disk):

    interpret '%0'
    

    EDIT: Just to be clear, cheater's version isn't intended to count! It's just to be silly and show an old dog can still do tricks. :)

    e.g. For real fun and games, an implementation of Java-8/C11 style "lambda" expressions on a list iterator. Not tested, but ought to run on a circa 1979 IBM mainframe. ;)

    ForEachInList( 'Months.January.Days', 'Day' -> 'SAY "You have an appointment with" Day.Appointment.Name "on" Day.Appointment.Date' )
    EXIT
    
    ForEachInList: 
        SIGNAL ON SYNTAX
        PARSE ARG MyList "," MyVar "->" MyCommand
        INTERPRET ' MyListCount = ' || MyList || '.Count'
        DO ListIndex = 1 TO MyListCount
           INTERPRET MyVar || ' = ' || MyList || '.' || ListIndex
           INTERPRET MyCommand
        END
        RETURN
    SYNTAX:
        SAY MyCommand ' is not a valid expression. '
        EXIT
    

    -- Calling code assumes you already made a stem (array), naturally.

    lisa

    Posted 2015-05-07T20:36:04.593

    Reputation: 161

    For your cheater version: if the filename of a program is not arbitrary, it has to be included in the byte count.

    – Martin Ender – 2015-05-09T09:51:59.470

    Fair enough. Cheater's version wasn't intended as at all serious! :) ...which is why I posted the "real" answer at 102. It was just for novelty's sake. – lisa – 2015-05-09T14:38:30.393

    @lisa except that its not novel at all ;) . Also, it would break the leaderboard script if used in this challenge. – Optimizer – 2015-05-10T10:55:21.930

    4

    R, 177 149 bytes

    Mickey T. is the man! He helped me fix my originally incorrect solution and save 28 bytes. Thanks, Mickey!

    m=matrix(" ",(w=2*(n=scan()+1)-1),w);m[row(m)==rev(col(m))]="/";diag(m)="\\";m[,n]="|";m[n,]="-";m[n,n]="O";m[,w]=paste0(m[,w],"\n");cat(t(m),sep="")
    

    Ungolfed + explanation:

    # Create a matrix of spaces, read n from stdin, assign w=2n+1
    m <- matrix(" ", (w <- 2*(n <- scan() + 1) - 1), w)
    
    # Replace the opposite diagonal with forward slashes
    m[row(m) == rev(col(m))] <- "/"
    
    # Replace the diagonal with backslashes
    diag(m) <- "\\"
    
    # Replace the vertical center line with pipes
    m[, n] <- "|"
    
    # Replace the horizontal center line with dashes
    m[n, ] <- "-"
    
    # Put an O in the middle
    m[n, n] <- "O"
    
    # Collapse the columns into single strings
    m[, w] <- paste0(m[, w], "\n")
    
    # Print the transposed matrix
    cat(t(m), sep = "")
    

    Any further suggestions are welcome!

    Alex A.

    Posted 2015-05-07T20:36:04.593

    Reputation: 23 761

    1Sorry Alex, you missed the vertical rays. There is a few things that could be changed to shorten this without changing the general process. The scan doesn't really need the w=. It can also be shifted deeper into the commands. The if can be ditched if you change the way the matrix is handled in a couple of instances. Applying these I get m=matrix(" ",(w=2*(n=scan()+1)-1),w);m[row(m)-rev(col(m))==0]='/';diag(m)="\\";m[,n]='|';m[n,]="-";m[n,n]="O";m[,w]=paste0(m[,w],'\n');cat(t(m),sep=''). Further golfing possible I think. – MickyT – 2015-05-07T23:44:12.770

    @MickyT: That's fantastic. Thank you so much for noticing my mistake and proving a much better solution! I edited the answer. – Alex A. – 2015-05-08T01:05:03.253

    4

    Rust, 215 characters

    fn a(n:usize){for i in 0..n{println!("{}\\{}|{1}/{0}",s(i),s(n-i-1))}println!("{}O{0}",vec!["-";n].concat());for i in(0..n).rev(){println!("{}/{}|{1}\\{0}",s(i),s(n-i-1))}}fn s(n:usize)->String{vec![" ";n].concat()}
    

    I tried to use a string slicing method (by creating a string of n-1 spaces and slicing to and from an index) like so:

    fn a(n:usize){let s=vec![" ";n-(n>0)as usize].concat();for i in 0..n{println!("{}\\{}|{1}/{0}",&s[..i],&s[i..])}println!("{}O{0}",vec!["-";n].concat());for i in(0..n).rev(){println!("{}/{}|{1}\\{0}",&s[..i],&s[i..])}}
    

    But that's actually 3 chars longer.

    Ungolfed code:

    fn asciisun_ungolfed(n: usize) {
        for i in 0..n {
            println!("{0}\\{1}|{1}/{0}", spaces(i), spaces(n-i-1))
        }
        println!("{0}O{0}", vec!["-"; n].concat());
        for i in (0..n).rev() {
            println!("{0}/{1}|{1}\\{0}", spaces(i), spaces(n-i-1))
        }
    }
    fn spaces(n: usize) -> String { vec![" "; n].concat() }
    

    The part I like is how I shave a few chars off on the formatting strings. For example,

    f{0}o{1}o{1}b{0}ar
    

    is equivalent to

    f{}o{}o{1}b{0}ar
    

    because the "auto-incrementer" for the format string argument position is not affected by manually specifying the number, and acts completely independently.

    Doorknob

    Posted 2015-05-07T20:36:04.593

    Reputation: 68 138

    4

    IDL 8.3, 135 bytes

    Dunno if this can be golfed more... It's very straightforward. First we create a m x m array (m=2n+1) of empty strings; then, we draw the characters in lines (y=x, y=-x, y=n, and x=n). Then we drop the O in at point (n, n), and print the whole thing, formatted as m strings of length 1 on each line so that there's no extra spacing from printing the array natively.

    pro s,n
    m=2*n+1
    v=strarr(m,m)
    x=[0:m-1]
    v[x,x]='\'
    v[x,m-x-1]='/'
    v[n,x]='|'
    v[x,n]='-'
    v[n,n]='O'
    print,v,f='('+strtrim(m,2)+'A1)'
    end
    

    Test:

    IDL> s,4
    \   |   /
     \  |  / 
      \ | /  
       \|/   
    ----O----
       /|\   
      / | \  
     /  |  \ 
    /   |   \
    

    sirpercival

    Posted 2015-05-07T20:36:04.593

    Reputation: 1 824

    "Instead of a program, you may write a function that takes an integer. The function should print the sun design normally or return it as a string." – sirpercival – 2015-05-08T14:55:25.867

    hahaha no worries :) – sirpercival – 2015-05-08T15:07:54.657

    4

    C#, 230 226 bytes

    string g(int n){string r="";int s=n*2+1;for(int h=0;h<s;h++){for(int w=0;w<s;w++){if(h==w){if(w==n){r+="O";}else{r+="\\";}}else if(w==s-h-1){r+="/";}else if(w==n){r+="|";}else if(h==n){r+="-";}else{r+=" ";}}r+="\n";}return r;}
    

    As requested, the ungolfed version: string ug(int n) {

            // The sting we'll be returning
            string ret = ""; 
    
            // The width and height of the output
            int s = n * 2 + 1; 
    
            // for loop for width and height
            for (int height = 0; height < s; height++) 
            {
                for (int width = 0; width < s; width++) 
                {
                    // Matches on top-left to bottom-right diagonal line
                    if (height == width) 
                    {
                        // If this is the center, write the 'sun'
                        if (width == n) 
                        {
                            ret += "O"; 
                        }
                        // If this is not the center, add the diagonal line character
                        else 
                        {
                            ret += "\\"; 
                        }
                    }
                    // Matches on top-right to bottom-left diagonal line
                    else if (width == s - height - 1) 
                    { 
                        ret += "/";
                    }
                    // Matches to add the center line
                    else if (width == n) 
                    { 
                        ret += "|";
                    }
                    // Matches to add the horizontal line
                    else if (height == n) 
                    { 
                        ret += "-";
                    }
                    // Matches all others
                    else 
                    { 
                        ret += " "; 
                    } 
                } 
                // Add a newline to separate each line
                ret += "\n"; 
            } 
            return ret; 
        }
    

    This is my first post so apologies if I've done something wrong. Any comments and corrections are very welcome.

    Transmission

    Posted 2015-05-07T20:36:04.593

    Reputation: 71

    Also, s=2*n+1 rather than s=(n*2)+1 and w==s-h-1 rather than w==(s-h)-1 will make this a little shorter. – Alex A. – 2015-05-08T14:57:29.343

    nice, may steal your string building method. it annoys me that linq is longer than for loops :( – Ewan – 2015-05-08T15:17:44.150

    I've added the ungolfed version :) – Transmission – 2015-05-08T15:59:49.413

    4

    Ruby: 98 92 characters

    Proc that returns a string with the Sun.

    f=->n{x=(0..m=n*2).map{|i|s=?|.center m+1
    s[i]=?\\
    s[m-i]=?/
    s}
    x[n]=?O.center m+1,?-
    x*?\n}
    

    Sample run:

    irb(main):001:0> f=->n{x=(0..m=n*2).map{|i|s=?|.center m+1;s[i]=?\\;s[m-i]=?/;s};x[n]=?O.center m+1,?-;x*?\n}
    => #<Proc:0x000000020dea60@(irb):1 (lambda)>
    irb(main):002:0> (0..3).each {|i| puts f[i]}
    O
    \|/
    -O-
    /|\
    \ | /
     \|/ 
    --O--
     /|\ 
    / | \
    \  |  /
     \ | / 
      \|/  
    ---O---
      /|\  
     / | \ 
    /  |  \
    => 0..3
    

    manatwork

    Posted 2015-05-07T20:36:04.593

    Reputation: 17 865

    4

    Octave 85

    Bulding matrices as always=) eye produces an identity matrix, the rest is self explanatory I think.

    m=(e=eye(2*(k=input('')+1)-1))*92+rot90(e)*47;m(:,k)='|';m(k,:)=45;m(k,k)='o';[m,'']
    

    flawr

    Posted 2015-05-07T20:36:04.593

    Reputation: 40 560

    Still two bytes better than mine :( I actually tried something similar to this initially, but couldn't get it small enough - I didn't realize I could do "m(:,k)='|'". Nice submission! – Oebele – 2015-05-11T11:41:51.630

    3

    Javascript (ES7 Draft) 115

    f=l=>[['O |/\\-'[y^x?z+~x^y?y^l?x^l?1:2:5:3:x^l&&4]for(x in _)].join('')for(y in _=[...Array(z=2*l+1)])].join('\n')
    
    
    // Snippet demo: (Firefox only)
    for(var X of [0,1,2,3,4,5])
        document.write('<pre>' + f(X) + '</pre><br />');

    nderscore

    Posted 2015-05-07T20:36:04.593

    Reputation: 4 912

    3

    Matlab, 93 87 bytes

    Sadly the function header has to be so big... Apart from that I think it is golfed pretty well. I wonder if it could be done better with some of the syntax differences in Octave.

    N=input('');E=eye(N)*92;D=rot90(E)*.52;H=ones(1,N)*45;V=H'*2.76;[E V D;H 79 H;D V E '']
    

    Oebele

    Posted 2015-05-07T20:36:04.593

    Reputation: 311

    You can just make a program with N=input('') to save 2 characters. Other than that you can just write [E V D;H 79 H;D V E ''] for converting the whole matrix into a char array, which will save you another byte or two. ( I just submitted an Octave program with a slightly different approach, but before I found yours=) – flawr – 2015-05-08T21:15:09.203

    I actually had the input line first, but for some reason I mistakenly thought it wasn't allowed... Thanks for the other tip though! – Oebele – 2015-05-11T11:36:31.283

    2

    Pyth - 52 bytes

    The hard part was figuring out how to switch the slashes for each side. I settled for defining a lambda that takes the symbols to use.

    KdMms[*Kt-QdG*Kd\|*KdH)_UQjbg\\\/p\O*Q\-*\-Qjb_g\/\\
    

    Can likely be golfed more, explanation coming soon.

    Try it online here.

    Maltysen

    Posted 2015-05-07T20:36:04.593

    Reputation: 25 023

    2

    Perl, 94

    There are a lot of nested ternary operators in here, but I think the code is reasonably straightforward.

    $n=<>;for$x(-$n..$n){for$y(-$n..$n){print$x^$y?$x+$y?$x?$y?$":'|':'-':'/':$x?'\\':'O'}print$/}
    

    Try it out here: ideone.com/E8MC1d

    r3mainer

    Posted 2015-05-07T20:36:04.593

    Reputation: 19 135

    188B: for$x(-($n=<>)..$n){map{print$x^$_?$x+$_?$x?$_?$":'|':'-':'/':$x?'\\':O}-$n..$n;print$/} - A couple of tweaks: convert inner for to map and change $y to $_; inline ($n=<>). – alexander-brett – 2015-05-08T10:09:00.273

    2

    C# - 291 (full program)

    using System;using System.Linq;class P{static void Main(string[] a){Func<int,int,int,char>C=(s,x,i)=>x==(2*s+1)?'\n':i==s?x==s?'O':'-':x==s?'|':x==i?'\\':x==2*s-i?'/':' ';int S=int.Parse(a[0])*2;Console.Write(Enumerable.Range(0,(S+1)*(S+1)+S).Select(z=>C(S/2,z%(S+2),z/(S+2))).ToArray());}}
    

    Ewan

    Posted 2015-05-07T20:36:04.593

    Reputation: 151

    working on it!! – Ewan – 2015-05-08T14:58:36.690

    1

    JavaScript (ES6), 142 140 134 117 bytes

    n=>(g=x=>x?`${t=` `[r=`repeat`](n-x--)}\\${s=` `[r](x)}|${s}/${t}
    `+g(x):`-`[r](n))(n)+`O`+[...g(n)].reverse().join``
    

    Try It

    f=
    n=>(g=x=>x?`${t=` `[r=`repeat`](n-x--)}\\${s=` `[r](x)}|${s}/${t}
    `+g(x):`-`[r](n))(n)+`O`+[...g(n)].reverse().join``
    i.addEventListener("input",_=>o.innerText=f(+i.value))
    o.innerText=f(i.value=1)
    <input id=i type=number><pre id=o>

    Shaggy

    Posted 2015-05-07T20:36:04.593

    Reputation: 24 623

    1

    Powershell, 108 97 93 bytes

    filter f{try{$s=' '*--$_
    "\$s|$s/"
    $_|f|%{(" $_ ","-$_-")[$_-match'O']}
    "/$s|$s\"}catch{'O'}}
    

    Explanation:

    • the recursive algorithm throws an exception on $s=' '*--$_ when current number less then 1;
    • the output is a perfect rectangle with trailing spaces.

    Less golfed test script:

    filter f{
        try{
            $s=' '*--$_
            "\$s|$s/"
            $_|f|%{(" $_ ","-$_-")[$_-match'O']}
            "/$s|$s\"
        }catch{
            'O'
        }
    }
    
    @(
    
    ,(0,"O")
    ,(1,"\|/",
        "-O-",
        "/|\")
    ,(2,"\ | /",
        " \|/ ",
        "--O--",
        " /|\ ",
        "/ | \")
    ,(3,"\  |  /",
        " \ | / ",
        "  \|/  ",
        "---O---",
        "  /|\  ",
        " / | \ ",
        "/  |  \")
    
    ) | % {
        $n,$expected = $_
        $result = $n|f
        "$result"-eq"$expected"
        $result
    }
    

    Output:

    True
    O
    True
    \|/
    -O-
    /|\
    True
    \ | /
     \|/ 
    --O--
     /|\ 
    / | \
    True
    \  |  /
     \ | / 
      \|/  
    ---O---
      /|\  
     / | \ 
    /  |  \
    

    mazzy

    Posted 2015-05-07T20:36:04.593

    Reputation: 4 832

    1

    Charcoal, 12 5 bytes

    P*⊕θO
    

    -7 bytes thanks to @ASCII-only, by using the builtin :*.

    Try it online (verbose) or try it online (pure).

    Explanation:

    Print the 8-armed lines with a length of the input+1 (the +1 is because the center is included), without moving the cursor position:

    MultiPrint(:*, Incremented(q));
    P*⊕θ
    

    Then print the "O" at the current location (still in the center, because we haven't moved due to the MultiPrint):

    Print("O");
    O
    

    Kevin Cruijssen

    Posted 2015-05-07T20:36:04.593

    Reputation: 67 575

    25? – ASCII-only – 2019-01-26T23:44:10.337

    @ASCII-only Thanks! Didn't even knew there was a :* builtin for this. – Kevin Cruijssen – 2019-01-27T12:01:48.787

    1

    JavaScript (ES6), 139 135 140 + 1 bytes

    (+1 is for -p flag with node in the console)

    fixed:

    t=(n,m)=>(m=2*n+1,(A=Array).from(A(m),(d,i)=>A.from(A(m),(e,j)=>i==j?j==n?"O":"\\":m-1==j+i?"/":i==n?"-":j==n?"|":" ").join("")).join("\n"))
    

    usage:

    t(3)
    /*
    \  |  /
     \ | / 
      \|/  
    ---O---
      /|\  
     / | \ 
    /  |  \
    */
    

    ungolfed:

    var makeSun = function (n, m) {
        m = 2 * n + 1;    // there are 2*n+1 in each row/column
        return Array.from(Array(m), function (d, i) {
            return Array.from(Array(m), function (e, j) {
                // if i is j, we want to return a \
                // unless we're at the middle element
                // in which case we return the sun ("O")
                if (i == j) {
                    return j == n ? "O" : "\\";
                // the other diagonal is when m-1 is j+i
                // so return a forward slash, /
                } else if (m - 1 == j + i) {
                    return "/";
                // the middle row is all dashes
                } else if (i == n) {
                    return "-";
                // the middle column is all pipes
                } else if (j == n) {
                    return "|";
                // everything else is a space
                } else {
                    return " ";
                }
            }).join("");
        }).join("\n");
    }
    

    royhowie

    Posted 2015-05-07T20:36:04.593

    Reputation: 151

    2You appear to be missing two rays. – None – 2015-05-08T02:31:09.517

    Oh, darn, I forgot to add that back in… – royhowie – 2015-05-08T02:32:01.423

    (A=Array).from(A(m)) – Shmiddty – 2015-05-08T02:42:55.140

    @MichaelT I fixed it, but I think I can golf it some more – royhowie – 2015-05-08T03:17:35.920

    @Shmiddty thanks for the suggestion! that saved a lot of characters – royhowie – 2015-05-08T03:27:48.547

    1

    Ruby - 130 bytes

    def f(n);a=(0...n).map{|i|' '*i+"\\"+' '*(n-1-i)+'|'+' '*(n-1-i)+'/'+' '*i};puts(a+['-'*n+'O'+'-'*n]+a.reverse.map(&:reverse));end
    

    usage:

    irb(main):002:0> f(3)
    \  |  /
     \ | /
      \|/
    ---O---
      /|\
     / | \
    /  |  \
    

    Tomáš Dundáček

    Posted 2015-05-07T20:36:04.593

    Reputation: 121

    1

    Applied a couple of old trick: f=->n{a=(0...n).map{|i|(s=' ')*i+?\\+s*(m=n-1-i)+?|+s*(m)+?/+s*i};puts(a+[?-*n+'O'+?-*n]+a.reverse.map(&:reverse))} (See Tips for golfing in Ruby for some more.)

    – manatwork – 2015-05-08T16:22:06.283

    1

    Perl 85 91 90 89 86B

    map{$_=$r||O;s/^|$/ /mg;s/ (-*O-*) /-$1-/;$r="\\$s|$s/
    $_
    /$s|$s\\";$s.=$"}1..<>;say$r
    

    Ungolfed:

    # usage: echo 1|perl sun.pl
    
    map {
        $_ = $r || O;  # no strict: o is "o". On the first run $r is not defined
        s/^|$/ /mg;    # overwriting $_ saves characters on these regexes
        s/ (-*O-*) /-$1-/;
        $r = "\\$s|$s/
    $_
    /$s|$s\\";         # Embedded newlines save 1B vs \n. On the first run $s is not defined.
        $s .= $"
    } 1..<>;
    say $r
    

    alexander-brett

    Posted 2015-05-07T20:36:04.593

    Reputation: 1 485

    1

    Python, 175 129 127 125 Bytes

    s,q,x=' ','',int(input())
    for i in range(x):d=(x-i-1);q+=(s*i+'\\'+s*d+'|'+s*d+'/'+s*i+'\n')
    print(q+'-'*x+'O'+'-'*x+q[::-1])
    

    Try it online here.

    Tim

    Posted 2015-05-07T20:36:04.593

    Reputation: 2 789

    1

    Python 3, 193 186 bytes

    Golfed

    def f(n):
     s,b,e,d,g=' \\/|-';p,r,i='',int(n),0
     while r:print(s*i+b+s*(r-1)+d+s*(r-1)+e);r-=1;i+=1
     print(g*n+'O'+g*n);r+=1;i=n-1
     while r<n+1:print(s*i+e+s*(r-1)+d+s*(r-1)+b);r+=1;i-=1
    

    Output

    >>> f(3)
    \  |  /
     \ | /
      \|/
    ---O---
      /|\
     / | \
    /  |  \
    
    >>> f(5)
    \    |    /
     \   |   /
      \  |  /
       \ | /
        \|/
    -----O-----
        /|\
       / | \
      /  |  \
     /   |   \
    /    |    \
    

    Ungolfed

    def f(n):
        s, b, e, d, g = ' \\/|-'
        p, r, i = '', int(n), 0
        while r:
            print(s*i + b + s*(r-1) + d + s*(r-1) + e)
            r -= 1
            i += 1
        print(g*n + 'O' + g*n)
        r += 1
        i = n-1
        while r < n+1:
            print(s*i + e + s*(r-1) + d + s*(r-1) + b)
            r += 1
            i -= 1
    

    Zach Gates

    Posted 2015-05-07T20:36:04.593

    Reputation: 6 152

    1There's a few things to be golfed here, but the biggest one is your default arguments. s=' ',b='\\',f='/',d='|',g='-' is very long, so you'd be better off moving it by adding s,b,f,d,g=" \/|-" to the second line. – Sp3000 – 2015-05-08T18:28:26.477

    I meant " \/|-" as a single string, rather than splitting it up into individual chars. You can unpack from a string like x,y,z="123", which makes x="1", y="2" and z="3". – Sp3000 – 2015-05-08T18:34:09.287

    Edited again. Thanks @Sp3000 – Zach Gates – 2015-05-08T18:39:40.577

    1

    CJam, 59 55 bytes

    ri:A,W%{_S*"\|/"\*\A\-(S*_@@++}%_Wf%W%['-A*_'O\++]\++N*
    

    This won't win any awards as-is but I was happy enough it worked!

    Thanks to Sp3000 for golfing tips.

    Claudiu

    Posted 2015-05-07T20:36:04.593

    Reputation: 3 870

    1Nice work! Here's a few tips: 1) You can use S instead of the ' version for space and 2) For '-A*'O'-A you can do '-A*_'O\ instead because generating it twice is long – Sp3000 – 2015-05-08T19:46:18.367

    1

    Prolog, 219 bytes

    No, it's not much of a golfing language. But I think this site needs more Prolog.

    s(N,N,N,79).
    s(R,R,_,92).
    s(R,C,N,47):-R+C=:=2*N.
    s(N,_,N,45).
    s(_,N,N,124).
    s(_,_,_,32).
    c(_,C,N):-C>2*N,nl.
    c(R,C,N):-s(R,C,N,S),put(S),X is C+1,c(R,X,N).
    r(R,N):-R>2*N.
    r(R,N):-c(R,0,N),X is R+1,r(X,N).
    g(N):-r(0,N).
    

    Tested with swipl on Linux. Invoke like so: swipl -s asciiSun.prolog; then query for your desired size of sun:

    ?- g(3).
    \  |  /
     \ | /
      \|/
    ---O---
      /|\
     / | \
    /  |  \
    true .
    

    Ungolfed:

     % Args to sym/4 are row, column, N and the character code to be output at that location.
    sym(N,N,N,79).
    sym(R,R,_,'\\').
    sym(R,C,N,'/') :- R+C =:= 2*N.
    sym(N,_,N,'-').
    sym(_,N,N,'|').
    sym(_,_,_,' ').
    
     % Args to putCols/3 are row, column, and N.
     % Recursively outputs the characters in row from col onward.
    putCols(_,C,N) :- C > 2*N, nl.
    putCols(R,C,N) :- sym(R,C,N,S), put_code(S), NextC is C+1, putCols(R,NextC,N).
    
     % Args to putRows/2 are row and N.
     % Recursively outputs the grid from row downward.
    putRows(R,N) :- R > 2*N.
    putRows(R,N) :- putCols(R,0,N), NextR is R+1, putRows(NextR,N).
    
    putGrid(N) :- putRows(0,N).
    

    DLosc

    Posted 2015-05-07T20:36:04.593

    Reputation: 21 213

    0

    SmileBASIC, 87 bytes

    INPUT N
    FOR Y=-N TO N
    FOR X=-N TO N?" \/|-     O"[(X==Y)+!(X+Y)*2+!X*3+!Y*4];
    NEXT?NEXT
    

    12Me21

    Posted 2015-05-07T20:36:04.593

    Reputation: 6 110

    0

    Japt, 26 bytes

    Pub golfing so, as usual, could probably be shorter.

    Æ'\+'/i|û´NÑÄÃp'Oi-pU¹·ê û
    

    Try it

    Æ'\+'/i|û´NÑÄÃp'Oi-pU¹·ê û     :Implicit input of integer U
    Æ                              :Map the range [0,U)
     '\+                           :  Append to "\"
        '/i                        :    "/" prepended with
           |û                      :      "|" centre padded with spaces to length
             ´N                    :        Decrement the (singleton) array of inputs, casting it to an integer on the first iteration
               Ñ                   :        Multiply by 2
                Ä                  :        Add 1
                 Ã                 :End map
                  p                :Push
                   'Oi             :  "O" prepended with
                      -pU          :    "-" repeated U times
                         ¹         :End push
                          ·        :Join with newlines
                           ê       :Palindromise (Mirror around the "O")
                             û     :Centre pad each line with spaces to the length of the longest
    

    Shaggy

    Posted 2015-05-07T20:36:04.593

    Reputation: 24 623

    0

    Canvas, 14 bytes

    ╵⌐|*⁸/+↔ω↶n┼O╋
    

    Try it here!

    dzaima

    Posted 2015-05-07T20:36:04.593

    Reputation: 19 048

    0

    Retina 0.8.2, 99 bytes

    .+
    $* X$&$*-
     ( *)X(-+)
    $1\|/¶$2X$2¶$1/|\
    +`^ ( *.)( *)
    $1$2 | $2/¶$&
    +` ( */)( *).+$
    $&¶$1$2 | $2\
    

    Try it online! Explanation:

    .+
    $* X$&$*-
    

    Place the X and draw n -s to its right. This completes the output for n=0.

     ( *)X(-+)
    $1\|/¶$2X$2¶$1/|\
    

    If n>0 then copy the -s to the left, and add the first level of \|/ and /|\ around the X. This completes the output for n=1.

    +`^ ( *.)( *)
    $1$2 | $2/¶$&
    

    Extend the \|/ upwards, removing a space of indent each time, adding it back on each side of the |.

    +` ( */)( *).+$
    $&¶$1$2 | $2\
    

    Extend the /|\ downwards, removing a space of indent each time, adding it back on each side of the |.

    Neil

    Posted 2015-05-07T20:36:04.593

    Reputation: 95 035

    0

    Groovy - 113

    f={n->s=2*n+1;(1..s).each{r->(1..s+1).each{c->print c==r?n+1==r?"O":"\\":c==s-r+1?"/":c==n+1?"|":c>s?"\n":" "}}}
    

    I think the ternary logic could probably be cleaned up to give a shorter answer...

    dbramwell

    Posted 2015-05-07T20:36:04.593

    Reputation: 201