48
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ Is a leading newline allowed? Especially interesting for N=0. \$\endgroup\$
    – Jakube
    Commented May 7, 2015 at 23:10
  • \$\begingroup\$ @Jakube No. Trailing only. \$\endgroup\$ Commented May 7, 2015 at 23:12

47 Answers 47

27
\$\begingroup\$

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'
    );
}
\$\endgroup\$
3
  • 7
    \$\begingroup\$ "c++" in C ... heh! \$\endgroup\$
    – bjb568
    Commented May 10, 2015 at 0:54
  • \$\begingroup\$ I'm glad you ungolfed it. Those ternary ifs are insane! \$\endgroup\$
    – ldam
    Commented May 15, 2015 at 7:54
  • \$\begingroup\$ 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);} \$\endgroup\$
    – jdt
    Commented May 8, 2017 at 10:57
24
\$\begingroup\$

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---
   /|\  
  / | \ 
 /  |  \
 $
\$\endgroup\$
1
  • \$\begingroup\$ also, you actually can make that first bit a lot better using y: if we replace 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 with s/0//g;:w;y/987654321/87654321 /;s/[1-9]/& /g;tw it does the same thing \$\endgroup\$
    – guest4308
    Commented Apr 9 at 3:28
17
\$\begingroup\$

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.

\$\endgroup\$
4
  • 5
    \$\begingroup\$ This 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. \$\endgroup\$
    – JustSid
    Commented May 7, 2015 at 22:56
  • \$\begingroup\$ @JustSid Well, the text wasn't up to date with the code but technically I never wrote that the code is ungolfed. :) \$\endgroup\$
    – randomra
    Commented May 8, 2015 at 9:54
  • \$\begingroup\$ It's still mighty impressive either way \$\endgroup\$
    – JustSid
    Commented May 8, 2015 at 10:05
  • 3
    \$\begingroup\$ @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 :) \$\endgroup\$ Commented May 8, 2015 at 12:46
12
\$\begingroup\$

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
\$\endgroup\$
12
\$\begingroup\$

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

\$\endgroup\$
13
  • 3
    \$\begingroup\$ 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. \$\endgroup\$
    – r3mainer
    Commented May 7, 2015 at 23:57
  • \$\begingroup\$ ternary operators is a good tip \$\endgroup\$
    – nick
    Commented May 8, 2015 at 2:33
  • \$\begingroup\$ 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":"";}} \$\endgroup\$
    – royhowie
    Commented May 8, 2015 at 8:30
  • \$\begingroup\$ 1. 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. \$\endgroup\$
    – royhowie
    Commented May 8, 2015 at 8:32
  • \$\begingroup\$ @squeamishossifrage I never thought of that. Thanks for the tips! \$\endgroup\$ Commented May 8, 2015 at 16:45
9
\$\begingroup\$

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

\$\endgroup\$
9
+100
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ I think you can use R instead of .5 to save 1 byte. \$\endgroup\$
    – randomra
    Commented May 9, 2015 at 21:46
  • \$\begingroup\$ @randomra That's clever, thanks. Down to two digits! \$\endgroup\$
    – xnor
    Commented May 10, 2015 at 0:04
8
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ An anonymous user suggested to change "-": NEXT y: PRINT AT s,s;"O" to "-";AT s,s;"O": NEXT y to save two bytes. \$\endgroup\$ Commented Jun 12, 2015 at 13:45
8
\$\begingroup\$

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>

\$\endgroup\$
2
  • \$\begingroup\$ Beautiful. I should have thought of a closure to use normal for loops. \$\endgroup\$
    – nderscore
    Commented May 8, 2015 at 16:18
  • \$\begingroup\$ I like this one. I had tried writing one using a string and accessing a specific index, but yours is much shorter. \$\endgroup\$
    – royhowie
    Commented May 9, 2015 at 8:46
8
\$\begingroup\$

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--
 /|\ 
/ | \
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$
    – nimi
    Commented May 9, 2015 at 0:05
  • \$\begingroup\$ Maybe map(i#)[-n..n] to save two bytes. \$\endgroup\$
    – lynn
    Commented May 11, 2015 at 17:17
7
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ For your cheater version: if the filename of a program is not arbitrary, it has to be included in the byte count. \$\endgroup\$ Commented May 9, 2015 at 9:51
  • \$\begingroup\$ 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. \$\endgroup\$
    – lisa
    Commented May 9, 2015 at 14:38
  • \$\begingroup\$ @lisa except that its not novel at all ;) . Also, it would break the leaderboard script if used in this challenge. \$\endgroup\$
    – Optimizer
    Commented May 10, 2015 at 10:55
6
\$\begingroup\$

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
\$\endgroup\$
5
\$\begingroup\$

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.

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

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!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Sorry 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. \$\endgroup\$
    – MickyT
    Commented May 7, 2015 at 23:44
  • \$\begingroup\$ @MickyT: That's fantastic. Thank you so much for noticing my mistake and proving a much better solution! I edited the answer. \$\endgroup\$
    – Alex A.
    Commented May 8, 2015 at 1:05
4
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – Alex A.
    Commented May 8, 2015 at 14:57
  • \$\begingroup\$ nice, may steal your string building method. it annoys me that linq is longer than for loops :( \$\endgroup\$
    – Ewan
    Commented May 8, 2015 at 15:17
  • \$\begingroup\$ I've added the ungolfed version :) \$\endgroup\$ Commented May 8, 2015 at 15:59
4
\$\begingroup\$

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,'']
\$\endgroup\$
1
  • \$\begingroup\$ 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! \$\endgroup\$
    – Oebele
    Commented May 11, 2015 at 11:41
4
\$\begingroup\$

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----
   /|\   
  / | \  
 /  |  \ 
/   |   \
\$\endgroup\$
2
  • \$\begingroup\$ "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." \$\endgroup\$ Commented May 8, 2015 at 14:55
  • \$\begingroup\$ hahaha no worries :) \$\endgroup\$ Commented May 8, 2015 at 15:07
3
\$\begingroup\$

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 '']
\$\endgroup\$
2
  • \$\begingroup\$ 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=) \$\endgroup\$
    – flawr
    Commented May 8, 2015 at 21:15
  • \$\begingroup\$ I actually had the input line first, but for some reason I mistakenly thought it wasn't allowed... Thanks for the other tip though! \$\endgroup\$
    – Oebele
    Commented May 11, 2015 at 11:36
3
\$\begingroup\$

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).
\$\endgroup\$
3
\$\begingroup\$

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 />');

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

Haskell, 80 bytes

a#b=2*a+0^b^2
f n|r<-[-n..n]=[[" /\\x-xOx|"!!mod(0#x#y#(x-y)#(x+y))9|x<-r]|y<-r]

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Vyxal, 20 bytes

`|/-\\`d•\Op8ʁ8j?›ø∧

Try it Online!

                  ø∧ # Draw on the canvas with
            8ʁ8j     # Directions [0, 8, 1, 8, 2, 8 ... 6, 8, 7]
                     # - ↑, center, ⇗, center ... ⇐, center, ⇖
`|/-\\`d             # Text: "|/-\|/-\"
        •            # Each char repeated by the input
         \Op         # With an O prepended
                ?›   # Line length: Input + 1
\$\endgroup\$
3
\$\begingroup\$

Uiua, 46 44 … 35 34 bytes

crossed out 44 is still regular 44 :(

⊏↧5/◇+\+{⇌,¤,⊞=.⟜=}⇡+1×2.:$  -\|/O

Try it! I submitted this on the day of the 2024 solar eclipse, which is fitting for a challenge about the sun. (Edit - the eclipse was beautiful! I saw it at around 85%-90% coverage)

Certainly my most well-golfed Uiua submission to-date. I have had a lot of different ideas and methods to save bytes and frequently switched much of the approach around a lot, but finally I have this at a state where I'd be happy if I don't find anything more.

Omnikar's very clever idea in the Uiua discord to use /+\+ instead of multiplying each term by a different factor helped me save 3 bytes! 38 → 35

Explanation:

Note: This explanation is very slightly outdated, but the strategy is the same, just a few things shifted around.

Consider the input 3. We double this and add 1 to get the side length 7, and take the range from 0 up to it.

[0 1 2 3 4 5 6]

Underneath this we push a copy with a mask of where the original input appears, and a "fixed" (wrapped in an array) copy of that.

[0 0 0 1 0 0 0]    [[0 0 0 1 0 0 0]]    [0 1 2 3 4 5 6]

Using the range at the top of the stack, push the identity matrix and a reversed copy.

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

Take their cumulative sums:

[[0 0 0 0 0 0 1]   [[1 0 0 0 0 0 1]   [[1 0 0 0 0 0 1]   [[1 0 0 1 0 0 1]
 [0 0 0 0 0 1 0]    [0 1 0 0 0 1 0]    [0 1 0 0 0 1 0]    [0 1 0 1 0 1 0]
 [0 0 0 0 1 0 0]    [0 0 1 0 1 0 0]    [0 0 1 0 1 0 0]    [0 0 1 1 1 0 0]
 [0 0 0 1 0 0 0]    [0 0 0 2 0 0 0]    [1 1 1 3 1 1 1]    [1 1 1 4 1 1 1]
 [0 0 1 0 0 0 0]    [0 0 1 0 1 0 0]    [0 0 1 0 1 0 0]    [0 0 1 1 1 0 0]
 [0 1 0 0 0 0 0]    [0 1 0 0 0 1 0]    [0 1 0 0 0 1 0]    [0 1 0 1 0 1 0]
 [1 0 0 0 0 0 0]]   [1 0 0 0 0 0 1]]   [1 0 0 0 0 0 1]]   [1 0 0 1 0 0 1]]

Notice that adding the fixed version of the list adds to each column, while the non-fixed version adds to each row.

Now, we sum the cumulative sums:

[[3 0 0 1 0 0 4]
 [0 3 0 1 0 4 0]
 [0 0 3 1 4 0 0]
 [2 2 2 10 2 2 2]
 [0 0 4 1 3 0 0]
 [0 4 0 1 0 3 0]
 [4 0 0 1 0 0 3]]

We’re going to index these numbers into a string to get each character, and that 10 is going to get in the way, so take the minimum of the results and 5:

[[3 0 0 1 0 0 4]
 [0 3 0 1 0 4 0]
 [0 0 3 1 4 0 0]
 [2 2 2 5 2 2 2]
 [0 0 4 1 3 0 0]
 [0 4 0 1 0 3 0]
 [4 0 0 1 0 0 3]]

Finally index these into a string so that 0 becomes a space, 1 becomes |, 2 becomes -, 3 becomes \, 4 becomes /, and 5 becomes O:

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

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.

\$\endgroup\$
2
\$\begingroup\$

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());}}
\$\endgroup\$
1
  • \$\begingroup\$ working on it!! \$\endgroup\$
    – Ewan
    Commented May 8, 2015 at 14:58
2
\$\begingroup\$

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
\$\endgroup\$
2
  • 2
    \$\begingroup\$ 5? \$\endgroup\$
    – ASCII-only
    Commented Jan 26, 2019 at 23:44
  • \$\begingroup\$ @ASCII-only Thanks! Didn't even knew there was a :* builtin for this. \$\endgroup\$ Commented Jan 27, 2019 at 12:01
2
\$\begingroup\$

05AB1E, 25 23 bytes

>"|-/\"SI4*×J…+8×Λ1'O0Λ

Try it online.

Explanation:

Step 1: Draw the ASCII sun without its center:

>                  # Increase the (implicit) input-integer by 1
 "|-/\"S          "# Push list ["|","-","/","\"]
        I4*        # Push the input-integer, and multiply it by 4
           ×       # Repeat each character that many times
            J      # Join it together to a single string
             …+8×  # Push string "+8×"
                 Λ # Use the Canvas builtin with these three arguments

Try just step 1 online.
See this 05AB1E tip of mine to understand how the Canvas builtin and its arguments works.

Step 2: Fix the center:

1'O0              '# # Push 1,"O",0
    Λ              # Use the Canvas of step 1 as background, and overwrite it
                   # with the result of this Canvas
                   # (after which the result is output immediately as result)

Old 25 bytes approach using mirrors:

>I…-\|×{1ú68780.Λ¨'O«.º.∊

Try it online.

Explanation:

Step 1: Draw the top-right corner:

>                  # Increase the (implicit) input-integer by 1
 …-\|              # Push string "-\|"
     I×            # Repeat it the input amount of times
       {           # Sort it, so it's in the order "--\\||" again
        1ú         # Pad a leading space
          68780    # Push 68780
               .Λ  # Use the modifiable Canvas builtin with these three arguments

Try just step 1 online.
See this 05AB1E tip of mine to understand how the Canvas builtin and its arguments works.

Step 2: Fix the center O:

¨                 # Remove the trailing character
 'O«             '# Append an "O" instead

Try just the first two steps online.

Step 3: Mirror it in both directions, and output the result:

.º                # Intersected mirror it horizontally
  .∊              # Intersected mirror it vertically
                  # (after which the result is output implicitly)
\$\endgroup\$
5
  • \$\begingroup\$ Might be shorter to use 0,8,1,8,2,8...6,8,7 for the canvas (see my vyxal). Not sure if 05AB1E's 8 replaces the origin character \$\endgroup\$
    – emanresu A
    Commented Oct 17 at 21:33
  • \$\begingroup\$ @emanresuA I'm afraid 8 indeed overwrites it, but only if another direction comes after it. Not sure if intentional or a bug, but that's how it works right now. Here is the output for your Vyxal approach halfway through and here the output for 05AB1E with those same inputs. Don't ask me where that fourth - is coming from when we use the 8s, because I honestly don't know. \$\endgroup\$ Commented Oct 18 at 7:14
  • 1
    \$\begingroup\$ Ah, unfortunate. When I implemented the Vyxal canvas builtin I tried to make it identical to 05AB1E's, but evidently one or two things slipped through the cracks. At least it's more useful this way. \$\endgroup\$
    – emanresu A
    Commented Oct 18 at 7:17
  • \$\begingroup\$ @emanresuA Yeah, I think your Canvas builtin is better this way. It isn't the first time the 8 screws me over in a challenge and I have to drop the Canvas idea entirely. \$\endgroup\$ Commented Oct 18 at 7:18
  • \$\begingroup\$ @emanresuA I did find an alternative approach that saved 2 bytes, using +8× without mirrors. :) \$\endgroup\$ Commented Oct 18 at 7:37
2
\$\begingroup\$

TinyAPL, 51 47 44 bytes*

{" -|\/O"⊇⍨5⌊+⍆+⍆↟(⊖⊸,=⊞⍨a)⍪⍉⊸,⊣⊞⍨⍵=a←⍳⧺2×⍵}

Try it: TinyAPL REPL


*Encoded with 1 byte per character using (⎕Import"std:sbcs")→Encode.

\$\endgroup\$
2
  • \$\begingroup\$ haven't looked at what the code is doing yet, but in 0.10.0 you can remove 1+ before From and replace 0 Catenate Index Generator with Index Generator Increment for a total of -3 (sorry, no keyboard with glyphs) \$\endgroup\$
    – RubenVerg
    Commented Oct 27 at 18:32
  • \$\begingroup\$ @RubenVerg Edited in, thanks. \$\endgroup\$ Commented Oct 28 at 3:28
1
\$\begingroup\$

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

\$\endgroup\$
1
  • 1
    \$\begingroup\$ 88B: 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=<>). \$\endgroup\$
    – alyx-brett
    Commented May 8, 2015 at 10:09
1
\$\begingroup\$

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");
}
\$\endgroup\$
5
  • 2
    \$\begingroup\$ You appear to be missing two rays. \$\endgroup\$
    – user12166
    Commented May 8, 2015 at 2:31
  • \$\begingroup\$ Oh, darn, I forgot to add that back in… \$\endgroup\$
    – royhowie
    Commented May 8, 2015 at 2:32
  • \$\begingroup\$ (A=Array).from(A(m)) \$\endgroup\$
    – Shmiddty
    Commented May 8, 2015 at 2:42
  • \$\begingroup\$ @MichaelT I fixed it, but I think I can golf it some more \$\endgroup\$
    – royhowie
    Commented May 8, 2015 at 3:17
  • \$\begingroup\$ @Shmiddty thanks for the suggestion! that saved a lot of characters \$\endgroup\$
    – royhowie
    Commented May 8, 2015 at 3:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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