74
\$\begingroup\$

Write a program or function that takes in a positive integer and prints or returns a stack of that many ASCII-art turtles, where each turtle is larger than the one above it.

Specifically, if the input is 1, the output should be:

 __
/,,\o

If the input is 2:

  __
o/,,\
 ____
/,__,\o

If the input is 3:

   __
  /,,\o
  ____
o/,__,\
 ______
/,____,\o

If the input is 4:

    __
  o/,,\
   ____
  /,__,\o
  ______
o/,____,\
 ________
/,______,\o

If the input is 5:

     __
    /,,\o
    ____
  o/,__,\
   ______
  /,____,\o
  ________
o/,______,\
 __________
/,________,\o

And so on in the same pattern for larger inputs.

Note that:

  • The head (the o) of the bottom turtle is always on the right. The heads of the turtles above then alternate back and forth.
  • No lines may have trailing spaces.
  • Superfluous leading spaces are not allowed. (i.e. the back of the bottom turtle should be at the start of the line.)
  • A single optional trailing newline is allowed.

The shortest code in bytes wins.

\$\endgroup\$
  • 11
    \$\begingroup\$ trichoplax, I'm expecting an answer that uses recursion. \$\endgroup\$ – El'endia Starman Aug 3 '16 at 23:40
  • 15
    \$\begingroup\$ ,________, When someone says something that makes no sense. \$\endgroup\$ – R. Kap Aug 4 '16 at 0:43
  • 8
    \$\begingroup\$ Flipping sides to make sure that every turtle looking up or down sees an ass? \$\endgroup\$ – Basic Aug 4 '16 at 16:06
  • 15
    \$\begingroup\$ I'm glad you specified ASCII turtles. Otherwise, I was going to finally submit a Logo answer where I didn't have to waste 3 bytes to hide the turtle. \$\endgroup\$ – GuitarPicker Aug 4 '16 at 21:47
  • 4
    \$\begingroup\$ I like turtles! \$\endgroup\$ – Scotty.NET Aug 5 '16 at 10:59

22 Answers 22

31
\$\begingroup\$

Batch, 256 bytes

@set i=echo 
@%i%off
set u=
for /l %%j in (2,2,%1)do call set i=%%i%%  
set/af=%1^&1
if %f%==1 %i% __&%i%/,,\o&set u=__
for /l %%j in (2,2,%1)do call:l
exit/b
:l
set i=%i:~0,-2%
%i%  _%u%_
%i%o/,%u%,\
%i% __%u%__
%i%/,_%u%_,\o
set u=__%u%__

Note that line 1 has a trailing space and line 4 has two trailing spaces. i therefore contains an echo command with the appropriate amount of indentation for each turtle. Meanwhile u contains the number of underscores in alternate turtles. A leading odd turtle is special-cased and then the rest of the turtles are output in pairs.

\$\endgroup\$
  • 25
    \$\begingroup\$ +1 for being exactly 256 bytes. Do not golf it unless u can exactly half its length! \$\endgroup\$ – Rohan Jhunjhunwala Aug 4 '16 at 2:03
  • \$\begingroup\$ Originally I missed the note about trailing spaces, most of my editors are set to chop those off and I couldn't figure out why it wasn't working! Always happy to see Batch on PPCG. :) \$\endgroup\$ – Captain Man Aug 4 '16 at 14:14
24
\$\begingroup\$

C, 131 bytes

i,j;f(n){char _[3*n];memset(_,95,3*n);for(i=n;i--;printf("%*.*s\n%*s/,%.*s,\\%s\n",j+n+1,j+j,_,i,"o"+1-i%2,j+j-2,_,"o"+i%2))j=n-i;}

Try it online.

Defines a function that prints the turtles.

Heavily abuses printf's width and precision specifiers to get the spacing and repeating the underscores. Each turtle is printed using a single printf call:

printf("%*.*s\n%*s/,%.*s,\\%s\n",j+n+1,j+j,_,i,"o"+1-i%2,j+j-2,_,"o"+i%2)

I also have a different version that's 144 bytes with whitespace removed:

c,i;f(n){for(i=n;i--;){
    char*p=" _\n o/,_,\\o\n";
    int C[]={i+1,c=n+n-i-i,1,i&~1,i%2,1,1,c-2,1,1,1-i%2,1};
    for(c=0;p[c];)C[c]--?putchar(p[c]):++c;
}}
\$\endgroup\$
  • \$\begingroup\$ Damn, I was about to add a C++ one \$\endgroup\$ – user54200 Aug 4 '16 at 8:51
  • 4
    \$\begingroup\$ +1 for having ,_, in your code. \$\endgroup\$ – R. Kap Aug 4 '16 at 19:27
14
\$\begingroup\$

Ruby, 100 bytes

Recursive solution. Try it online!

f=->n,i=1{f[n-1,i+1]if n>1;puts' '*i+?_*n*2,"%#{i-1}s/,#{?_*2*~-n},\\"%(i<2?'':'o '[i%2])+' o'[i%2]}
\$\endgroup\$
12
\$\begingroup\$

05AB1E, 45 bytes

Lvð¹y-©>ׄ__y×UXJ,„/,X¨¨„,\J'o®ÉiìëJ}ð®®É-×ì,

Try it online

\$\endgroup\$
  • 3
    \$\begingroup\$ Gets my vote for being so short. \$\endgroup\$ – jseals Aug 4 '16 at 17:05
  • \$\begingroup\$ Not sure if the G-loop was already in the August 2016 version, but if it was, Lv can be G and both y can be N for -1 byte. \$\endgroup\$ – Kevin Cruijssen Sep 24 '18 at 13:21
12
\$\begingroup\$

V, 57, 53 49 bytes

i ³_
/,_,\oÀñHyjí_/___
ëPhjI ñdjí___
òkk$x^PXkk

Since this contains unprintable characters, here is a hexdump:

00000000: 6920 b35f 0a2f 2c5f 2c5c 6f1b c0f1 4879  i ._./,_,\o...Hy
00000010: 6aed 5f2f 5f5f 5f0a eb50 1668 6a49 20f1  j._/___..P.hjI .
00000020: 646a ed5f 5f5f 0af2 6b6b 2478 5e50 586b  dj.___..kk$x^PXk
00000030: 6b                                       k

Try it online!

Explanation:

i ³_\n/,_,\o<esc>       "Insert the original turtle with one extra underscore

Àñ                      "Arg1 times:
  Hyj                   "  Go the the beginning of the file, and yank a turtle
     í_/___             "  Extend the lenght of every turtle by two
ëP                      "  Move to the beginning of the file again, and paste the turtle we yanked
  <C-v>hjI              "  Move this turtle one to the right
           ñ            "Stop looping.

dj                      "Delete a turtle (since we have one too many)
  í___                  "Make every turtle shorter (since they are all too long)

ò                       "Recursively:
 kk                     "  Move up two lines
   $x                   "  Delete the last character on this line (an 'o')
     ^P                 "  And paste this 'o' at the beginning of the line
       X                "  Remove one space
        kk              "  Move up two lines again
\$\endgroup\$
  • \$\begingroup\$ Interesting outputs for inputs 0 and below. \$\endgroup\$ – R. Kap Aug 4 '16 at 2:40
  • \$\begingroup\$ This code also doesn't work for input > 10. On a side note, I accidentally broke it completely with the input 0 41c14. Not sure if I broke the code, or the runner. \$\endgroup\$ – Brandon Anzaldi Aug 4 '16 at 2:41
  • 1
    \$\begingroup\$ @R.Kap Yeah, I think I know why it does that. V is barely able to comprehend integers, so it just sees -1 as a string that it can't pretend is a number. Thankfully, I don't have to handle those. \$\endgroup\$ – DJMcMayhem Aug 4 '16 at 2:47
  • 1
    \$\begingroup\$ @BrandonAnzaldi Ah, I see why that doesn't work. I'll fix that in a minute. Also, doing anything other than decimal number is bound to cause some weird problems. \$\endgroup\$ – DJMcMayhem Aug 4 '16 at 2:50
  • 1
    \$\begingroup\$ Yup! Cool solution. Figured it'd probably be somewhat simple to fix. I was just very, very fascinated with the output of the aforementioned accidental keyboard mash. Leading spaces also produce some fun output. Seems like you wrangled V quite nicely! \$\endgroup\$ – Brandon Anzaldi Aug 4 '16 at 2:57
11
\$\begingroup\$

Perl, 92 bytes

91 bytes code +1 for -n.

Requires -E at no extra cost.

for$i(1..$_){say$"x$_._,$v=_ x(--$i*2),_.$/.$"x(--$_-1),$_%2?o:$"x!!$_,"/,$v,\\",$_%2?"":o}

Usage

perl -nE 'for$i(1..$_){say$"x$_._,$v=_ x(--$i*2),_.$/.$"x(--$_-1),$_%2?o:$"x!!$_,"/,$v,\\",$_%2?"":o}' <<< 3
   __
  /,,\o
  ____
o/,__,\
 ______
/,____,\o

Thanks to @Dada for -9 bytes with his re-work!

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice one. Another version, same bytecount : perl -nE 'for$i(1..$_){say$"x$_._.($v=_ x(($i-1)*2))._.$/.$"x(--$_-1).($_%2?o:$_?$":"")."/,$v,\\".($_%2?"":o)}'. I tried to get under 100 too but coudln't... \$\endgroup\$ – Dada Aug 4 '16 at 14:29
  • \$\begingroup\$ @Dada Thanks! Updated, much appreciated! \$\endgroup\$ – Dom Hastings Aug 4 '16 at 15:57
10
\$\begingroup\$

Cheddar, 105 bytes

n->(|>n).map(i->(1-i%2)*"o"+"\\,"+(n-i-1)*"__"+",/"+i%2*"o"+i/2*"  "+"\n"+(n-i)*"__"+(i+1)*" ").vfuse.rev
\$\endgroup\$
  • 2
    \$\begingroup\$ +1 for using cheese. You can use literal newline to save bytes \$\endgroup\$ – Downgoat Aug 4 '16 at 3:37
10
\$\begingroup\$

Retina, 97 91 88 bytes

Byte count assumes ISO 8859-1 encoding.

.+
  $&$*_$&$*_o
+`^( *?)(.)__(_+)(.)
$1 $4$3$2¶$&
 (.)__(_*) ?
  __$2¶$%`$1/,$2,\
Rm`^ 

Try it online!

\$\endgroup\$
6
\$\begingroup\$

Python 2, 116 Bytes

m=input()
for i in range(m):r=m-i;b=r%2;h='o';a='__';u=i*a;s=' '*r;print s+u+a+'\n'+s[:b-2]+h*-~-b+"/,"+u+",\\"+b*h
\$\endgroup\$
  • \$\begingroup\$ I get your count at 115 bytes and you can save one byte by using lambda m:for i in r... instead of input() \$\endgroup\$ – wnnmaw Aug 8 '16 at 12:35
6
\$\begingroup\$

R, 150 bytes

a=function(x,y=1){d=x-y;t=d%%2;cat(rep(" ",d+1),rep("_",2*y),"\n",rep(" ",d-t),"o"[t],"/,",rep("_",2*y-2),",\\","o"[!t],"\n",sep="");if(y<x)a(x,y+1)}

more cleanly (adds a byte)

a=function(x,y=1){
     d=x-y
     t=d%%2
     cat(rep(" ",d+1),rep("_",2*y),"\n",rep(" ",d-t),"o"[t],"/,",rep("_",2*y-2),",\\","o"[!t],"\n",sep="")
     if(y<x)a(x,y+1)
}

Basic structure recursively calls itself --telling itself both the final number to be called and the current level. Starts with a default for y=1, so it only needs one variable for initial call. Quickly defines two values that are frequently used. Then it just repeats everything the necessary number of times.

"o"[t],"o"[!t]

Each of these implicitly test whether to add the head to right or left and place it appropriately.

\$\endgroup\$
  • \$\begingroup\$ Use # before the title in the markdown editor to format it like the other answers. \$\endgroup\$ – TheBikingViking Aug 4 '16 at 21:07
  • \$\begingroup\$ apologies -- so edited \$\endgroup\$ – user5957401 Aug 4 '16 at 21:30
6
\$\begingroup\$

TSQL, 189 bytes

Now with input acceptance - thanks to @PatrickRoberts

DECLARE @i INT=##i##,@ INT=0a:PRINT SPACE(@i-@)+REPLICATE('__',@+1)+'
'+SPACE((@i-@-1)/2*2)+IIF((@i-@-1)%2=1,'o/,','/,')+REPLICATE('__',@)+IIF((@i-@-1)%2=0,',\o',',\')SET
@+=1IF @i>@ GOTO a

Fiddle

\$\endgroup\$
  • 1
    \$\begingroup\$ Here's a version that lets you specify i at the cost of 4 bytes \$\endgroup\$ – Patrick Roberts Aug 5 '16 at 0:17
  • \$\begingroup\$ @PatrickRoberts thanks, didn't know that one, is that sql server 2016 ? \$\endgroup\$ – t-clausen.dk Aug 5 '16 at 7:25
  • \$\begingroup\$ @t-clausen.dk That input mechanism is specific to the data.SE site, it's not a standard feature of any version of SQL. \$\endgroup\$ – BradC Aug 15 at 16:54
  • \$\begingroup\$ @BradC you are absolutely right, it is some sort of programming language, and very nice to finally be able to add a parameter input. I forgot all about this, and I will consider using it in the future paying the extra bytes \$\endgroup\$ – t-clausen.dk Aug 21 at 7:48
6
\$\begingroup\$

C, 328 238 234 215 bytes:

B;M(w,j,R){j=w;if(j<=B){char b[j*2-1],k[j*2+1];b[j*2-2]=k[j*2]=0;memset(b,95,j*2-2);memset(k,95,j*2);R=(B+1-j)%2;printf("%*s\n%*s/,%s,\\%s\n",j*2+B+1-j,k,B-j,R?"":"o",b,R?"o":"");j++;M(j);}}main(){scanf("%d",&B);M(1);}

A recursive implementation using a lot of string formatting and the builtin memset function. Will try and golf this more over time as much as I can.

C It Online! (Ideone)

\$\endgroup\$
  • \$\begingroup\$ Strangely enough, the third and fourth turtles appear broken on Ideone... \$\endgroup\$ – Quentin Aug 4 '16 at 7:24
  • \$\begingroup\$ @Quentin Actually, that is not Ideone. That is my program's fault. For some reason, the minute input approaches 17 and beyond, the logic breaks for some reason, and therefore, so do the turtles. I'm currently trying to figure out what is wrong. \$\endgroup\$ – R. Kap Aug 4 '16 at 7:26
  • \$\begingroup\$ Nice ! Note that you can replace most character literals ('c') by their ASCII code to spare one character each :) \$\endgroup\$ – Quentin Aug 4 '16 at 8:52
  • \$\begingroup\$ @Quentin Nice?... It doesn't work very well. How is that nice? \$\endgroup\$ – R. Kap Aug 4 '16 at 8:54
  • \$\begingroup\$ Oh! I checked back on Ideone and it looked fixed, but that's because there are less turtles of course... Hazy morning. \$\endgroup\$ – Quentin Aug 4 '16 at 8:57
4
\$\begingroup\$

Java 1.7, 238 bytes

A set of two functions: first iterates over input (# of turtles), second facilitates in constructing a sequence of repeated characters recursively (i.e. the leading spaces, the back and belly of the turtles).

String f(int n){String s="";for(int i=-1,x=-2;++i<n;){int m=(i+n)%2;s+=r(' ',n-i)+r('_',i*2+2)+"\n"+r(' ',n-i-(m==1?1:2))+(m==0?"o":"")+"/,"+r('_',x+=2)+",\\"+(m==1?"o":"")+"\n";}return s;}String r(char c,int n){return n>0?c+r(c,--n):"";}

Ungolfed:

class C {
    public static void main(String[] a) {
        System.out.println(new T().f(1));
        System.out.println(new T().f(2));
        System.out.println(new T().f(3));
        System.out.println(new T().f(4));
        System.out.println(new T().f(5));
    }

    static class T {

        String f(int n) {
            String s = "";
            for (int i = -1, x = 0; ++i < n; x+=2) {
                int m = (i + n) % 2;
                s += r(' ', n - i) + r('_', i * 2 + 2) + "\n" + r(' ', n - i - (m == 1 ? 1 : 2)) + (m == 0 ? "o" : "") + "/," + r('_', x) + ",\\" + (m == 1 ? "o" : "") + "\n";
            }
            return s;
        }

        String r(char c, int n) {
            return n > 0 ? c + r(c, --n) : "";
        }

    }

}

Run it! (Ideone)

I've assumed it's okay to exclude the class definition from the byte count.

I may be able to golf this a little further by reversing the iteration order of the loop (build from bottom turtle up) and/or by going fully recursive like some of the other answers.

Note to self: Java really lacks a built-in shorthand to repeat n characters...

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

Python, 137 120 113 110 bytes

m=input()
for i in range(m):p=m-i;b=p%2;print' '*p+'__'*-~i+'\n'+' '*(p-2+b)+'o'*-~-b+'/,'+'__'*i+',\\'+'o'*b

Ungolfed:

m=input()
for i in range(m):
  p=m-i                              // Abstract m-i for a few bytes
  b=p%2                              // Determines every other turtle from bottom

  print' '*p + '__'*-~i + '\n' +    // The top of the turtle
       ' '*(p-2+b) +                // Leading spaces (-1 for every other turtle)
       '0'*-~-b +                   // Add a leading head to every other turtle
       '/,'+'__'*i +                // Body of the turtle
       ',\\'+'0'*b                  // Add a trailing head to every other turtle

The heads were hard.

\$\endgroup\$
  • \$\begingroup\$ Instead of ('o','')[b], you can do 'o'*(1-b) (and 'o'*b for ('o','')[1-b]). \$\endgroup\$ – Mego Aug 4 '16 at 21:56
  • \$\begingroup\$ @mego oh right, i changed that to an empty char, that works. thanks! \$\endgroup\$ – greyShift Aug 5 '16 at 14:07
  • \$\begingroup\$ '0'*-~-1 is shorter than '0'*(1-b) \$\endgroup\$ – Destructible Lemon Aug 8 '16 at 10:09
  • \$\begingroup\$ and -~i is shorter than (i+1) \$\endgroup\$ – Destructible Lemon Aug 8 '16 at 10:13
3
\$\begingroup\$

F#, 218 207 202 196 187 bytes.

Shaved most of these bytes by inlining variables

let R=String.replicate
let t n=let rec L i r k=if i<n then L(i+1)(R(k+i%2+1)" "+R((n-i)*2)"_"+"\n"+R k" "+R(i%2)"o"+"/,"+R(n*2-i*2-2)"_"+",\\"+R(1-i%2)"o"+"\n"+r)(k+i%2*2)else r in L 0""0

The logic is shamelessly stolen from this Python answer

Try it online.

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

CJam, 88 bytes

ri_[S\_'_*_+N+\O\"/,"\('_*_++','\+'o]\({_[(S+\(2>\(S\+)'O^c+\(-2<\(\('o\{;O}&\;]}*]-1%N*

Makes the biggest turtle first (because otherwise what would every other turtle stand on?), then gradually reduces the size until the smallest one is made. Works for any integer larger than 0.

Try it online!

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

Python 2.7, 255 238 236 bytes

Even though this loses to both of the other Python 2 solutions, I liked my recursive approach:

def r(s,p):
 for(a,b)in p:s=a.join(s.split(b))
 return s
def t(w):
 i='_'*2*w;s='\n __%s\n/,%s,\o'%(i,i)
 if w:s=r(t(w-1),[('\n ','\n'),('Z/',' /'),('\\Z\n','\\\n'),(' /','o/'),('\\','\\o'),('o','Z')])+s
 return s
print t(input()-1)[1:]

edit1: dropped a few bytes by eliminating some replacements

edit2: shaved 2 bytes by saving the underscores as a variable

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

Python 2, 147 bytes

n=input()
s=' ';r=[];i=k=0
while i<n:a=i%2;r=[s*k+s*a+s+'_'*(n-i)*2+s,s*k+'o'*a+'/,'+'_'*(n-i-1)*2+',\\'+'o'*(1-a)]+r;k+=a*2;i+=1
print'\n'.join(r)

Try it online

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

Python 2.7, 139 114 113 130 bytes

I also liked Iguanodon's recursive approach so here's a slightly shorter attempt.

def t(n):
 if n>1:t(n-1)
 a=i-n;b=(a+1)%2;print' '*(a+1)+'__'*n+'\n'+' '*(a-1+b)+'o'*(not b)+'/,'+'__'*(n-1)+',\\'+'o'*b
i=input()
t(i)

EDIT

A mighty 25 26 9 bytes golfed due to some fantastic tips from Destructible Watermelon. Many thanks! Think it may be the shortest Python answer now :-)

def t(n):
 if n>1:t(n-1)
 a=i-n;b=-~a%2;print' '*-~a+'__'*n+'\n'+' '*(a-1+b)+'o'*-~-b+'/,'+'__'*~-n+',\\'+'o'*b
i=input()
t(i)
\$\endgroup\$
  • \$\begingroup\$ (a+1) can be shortened to -~a, and n-1 can be shortened to ~-n, and b is always 0 or 1, so not b can be shortened to -~-b, and you can eliminate the i=input();t(i) part, because you are allowed to just have a function. \$\endgroup\$ – Destructible Lemon Aug 9 '16 at 0:48
  • \$\begingroup\$ Man thanks for some great hints @Destructible . Also spotted that as b is always 1 or 0 then 1-b works and loses 1 more byte. \$\endgroup\$ – ElPedro Aug 9 '16 at 7:05
  • \$\begingroup\$ except that that would require parens, because * has higher priority than binary -, but unary - and ~ have higher priority than * \$\endgroup\$ – Destructible Lemon Aug 9 '16 at 7:10
  • \$\begingroup\$ Now that i think about it, if n is always >0, then if n>1 can be shortened to ~-n (n-1), which chops off the leading space. Also, again, (1-b) can be shortened to -~-b with no parens \$\endgroup\$ – Destructible Lemon Aug 9 '16 at 7:14
  • \$\begingroup\$ This just gets better and better! I'm pretty new to this and more used to writing readable code so your hints are greatly appreciated :) \$\endgroup\$ – ElPedro Aug 9 '16 at 7:16
1
\$\begingroup\$

PowerShell, 105 100 97 87 85 84 bytes

-21 bytes thanks to mazzy, the mad man

"$args"..1|%{' '*$_--+($m='__'*$i++)+'__'
' '*($_-$_%2)+("/,$m,\o","o/,$m,\")[$_%2]}

Try it online!

Cleverly shifts variables using $_-- to avoid using repeated ($_+1) blocks to save several bytes. It also converts the single argument to a string which is then cast to an int when used in a range to iterate over through the number of turtles. Biggest trick is now having the 2nd level of a turtle's spacing only increase every other row by subtracting $_%2 (i.e. 0 if even, 1 if odd) from the current row_count.

Otherwise, it's a lot of index math to get proper _ and counts, including a lag counter in the form of $i++, and now only a single list index to put the head on the correct side.

\$\endgroup\$
  • \$\begingroup\$ @mazzy Can't have trailing spaces but I did modify it for 5 bytes, thanks \$\endgroup\$ – Veskah Apr 10 at 14:44
  • 1
    \$\begingroup\$ I'm sorry :) 85 bytes \$\endgroup\$ – mazzy Apr 10 at 19:06
  • \$\begingroup\$ @mazzy Double dang, putting in even more work. Good stuff \$\endgroup\$ – Veskah Apr 10 at 19:12
  • 1
    \$\begingroup\$ That's all :) 84 bytes \$\endgroup\$ – mazzy Apr 10 at 19:22
0
\$\begingroup\$

ES6 (JavaScript), 140 bytes

Code

T=(i,h=0,p=1,R="repeat")=>(i>1?T(i-1,~h,p+1)+"\n":"")+" "[R](p)+'--'[R](i)+"\n"+" "[R](p-1+h)+(h?"o":"")+"/,"+'__'[R](i-1)+",\\"+(!h?"o":"")

Test

console.log(T(5));

     --
    /,,\o
    ----
  o/,__,\
   ------
  /,____,\o
  --------
o/,______,\
 ----------
/,________,\o
\$\endgroup\$
0
\$\begingroup\$

Canvas, 26 bytes

╷_×,×l_×∔/×║o×⇵↔⁸¹-[  ×↔}]

Try it here!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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