24
\$\begingroup\$

Our classic snake has developed an inbalance of growth hormones. To make matters worse, his tail is frozen in place! Given directional input as specified in Figure 1, write a program to determine where he will grow.

wasd

Figure 1. Directional input.

Program specifications

  • Read the input character by character on STDIN.
  • After reading a character, output the snake to STDOUT. Please include a blank line in between each time you print a snake.
  • The snake consists of <>v^ and a head. The head of the snake may be any round character of your choosing, such as o, 0, O, or .
  • Any combination of wasd is valid for input.
  • Your program should not assume the input is within a certain length.
  • The snake can pile on top of itself, overwriting <>v^. See examples for snake growing mechanics.
  • Trailing whitespace is okay, but your snake must look correct.

Scoring

This is . Your score is the number of characters in your program. Lowest score wins!

Example snakes:

Input: ddddssaassdddddww

Output:

>>>>v
    v
  v<<  ☺
  v    ^
  >>>>>^

Input: dddsssaaawww

Output:

☺>>v
^  v
^  v
^<<<

Input: dddsssdddddasddddwww

Output:

>>>v
   v       ☺
   v       ^
   >>>>v<  ^
       >>>>^

Input: dddwwdddssssaaaaaaaaawww

Output:

      >>>v
☺     ^  v
^  >>>^  v
^        v
^<<<<<<<<<

Input: ddddssssaawwddddd

Output:

>>>>v
    v
  >>>>>☺
  ^ v
  ^<<

Input: dddddssaawwwwddddd

Output:

   >>>>>☺
   ^
>>>^>v
   ^ v
   ^<<

Input:

ddddaaaasssssdddddddddddwwwwwaaaasssssdddddddddddwwwwwwwwwwsssssaaaasssssdddddddwwwwwddddssaaaasssddddaaaassssssssssdddwwwwwwwddddswaaaassssddaasssaaaaaaaaaawwwwddddssssaaaaaaaaaaawwwwddddsssssssssaaaa

Output:

                  v
                  v
                  v
                  v
                  v
v<<<<  v<<<<  v<<<<  >>>>v
v      v   ^  v   ^  ^   v
v      v   ^  v   ^  v<<<<
v      v   ^  v   ^  v
v      v   ^  v   ^  v
>>>>>>>>>>>>>>>>>>>>>v<<<<
                     v
                     v
                     v  v<<<<
                     v  v   ^
                     v  v
       >>>>v  >>>>v  v  v
       ^   v  ^   v  v  v<<
       ^   v  ^   v  v  v
       ^   v  ^   v  v  v
       ^<<<v<<<<<<<<<<<<<
           v
           v
           v
           v
       O<<<<
\$\endgroup\$
27
  • 9
    \$\begingroup\$ Very nice. But... WTH is a "code gofl"? \$\endgroup\$ Commented Aug 30, 2014 at 14:14
  • 2
    \$\begingroup\$ I'd get rid of the bonus as it is way too easy to create your own snake and input string. \$\endgroup\$
    – Beta Decay
    Commented Aug 30, 2014 at 14:14
  • 1
    \$\begingroup\$ @JanDvorak rotfl my bad. \$\endgroup\$
    – hmatt1
    Commented Aug 30, 2014 at 14:16
  • 1
    \$\begingroup\$ @BetaDecay the plane scales. In the code golf example it started at the top left of the c, but since the d is taller it moves down. \$\endgroup\$
    – hmatt1
    Commented Aug 30, 2014 at 14:55
  • 2
    \$\begingroup\$ @chilemagic Thanks! If both are acceptable you should probably clarify this in the question. \$\endgroup\$
    – Ingo Bürk
    Commented Aug 30, 2014 at 23:36

11 Answers 11

11
\$\begingroup\$

ECMAScript 6 Javascript (399 401 431)

Has to be run in a browser supporting ECMAScript 6 due to the arrow functions.

Here are fiddles which have been altered to run in any (common) browser by not using arrow functions. They also print to a textarea instead:

Golfed Version

i=prompt(),v=[],c=0,x=[0],y=[0],s='unshift',k='slice',t='sort',h=[0,-1,0,1,0]
while(c<i.length){m='wasd'.indexOf(i[c++]);v[s]('^<v>'[m]);x[s](x[0]+h[m]);y[s](y[0]+h[m+1])}f=(a,b)=>a-b
q=x[k]()[t](f)[0],e=x[k]()[t]((a,b)=>b-a)[0],w=y[k]()[t](f)[0],o=[]
while((i=y.pop())!=null){i-=w;j=x.pop()-q;t=(o[i]||Array(e+1-q).join(" ")).split("");t.splice(j,1,v.pop()||"@");o[i]=t.join("")}alert(o.join("\n"))

Animated GIF:

One of the OP's examples:

enter image description here

The example from Stretch Maniac:

enter image description here

Ungolfed

Here is a (slightly) ungolfed version from sometime before I started really golfing it down:

var input = prompt(),
    values = [],
    c = 0,
    x = [0],
    y = [0],
    s = 'unshift';
while (c < input.length) {
    var mapped = 'wasd'.indexOf(input[c++]);
    values[s]('^<v>'[mapped]);
    x[s](x[0]+[0, -1, 0, 1][mapped]);
    y[s](y[0]+[-1, 0, 1, 0][mapped]);
}

var minX = x.slice().sort(function (a,b){return a-b})[0];
var maxX = x.slice().sort(function (a,b){return b-a})[0];
var minY = y.slice().sort(function (a,b){return a-b})[0];

var output = [];
while((i=y.pop())!=null) {
    i-=minY;
    j=x.pop()-minX;
    t=(output[i]||Array(maxX+1-minX).join(" ")).split("");
    t.splice(j,1,values.pop()||"@");
    output[i]=t.join("");    
}

console.log(output.join("\n"));
\$\endgroup\$
3
  • \$\begingroup\$ The gifs are very cool. Are they made automatically, by a script you've written? \$\endgroup\$
    – AndoDaan
    Commented Aug 31, 2014 at 20:25
  • 1
    \$\begingroup\$ Thanks! With the power of Google I just looked up how to make a gift from a screen recording in Ubuntu. It just uses a screen recorder and convert. Pretty easy :) \$\endgroup\$
    – Ingo Bürk
    Commented Aug 31, 2014 at 20:29
  • 3
    \$\begingroup\$ (gif, not gift) \$\endgroup\$
    – Ingo Bürk
    Commented Aug 31, 2014 at 20:52
8
\$\begingroup\$

sed, 71

s/w/\^\x1B[D\x1B[A/g
s/a/<\x1B[2D/g
s/s/v\x1B[B\x1B[D/g
s/d/>/g
s/$/@/

Golfscript, 165 126

' '*"\33[":e{e'D'}:-{[e'C'+'<'--]]}:a{[-+'>']]}:d{[e'B'+'^'-e'A']]}:w{[e'A'+'v'-e'B']]}:s{][\[}:+7{;}*''\~[e'H'e'J']\'@'e'20H'

Same approach as my previous answer, but correctly positioning the cursor before and afterwards. I'm pretty proud of the approach to cursor positioning -- basically, it first runs the snake in reverse, without printing out characters.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Can you add an example call? echo "dddddssaawwwwddddd" | sed -e 's/w/\^\x1B[D\x1B[A/g' -e 's/a/<\x1B[2D/g' -e 's/s/v\x1B[S\x1B[D/g' -e 's/d/>/g' -e 's/$/@/' doesn't give the correct output for me. \$\endgroup\$
    – Ingo Bürk
    Commented Aug 31, 2014 at 9:53
  • \$\begingroup\$ Your prompt after executing is probably overwriting part of the snake. Paste the snake directly into stdin instead of piping, or add a few \ns after the @ so your prompt goes elsewhere. \$\endgroup\$
    – Sneftel
    Commented Aug 31, 2014 at 9:57
  • 1
    \$\begingroup\$ This might fail if the snake goes up or left of the board. \$\endgroup\$
    – tomsmeding
    Commented Aug 31, 2014 at 12:31
  • \$\begingroup\$ @tomsmeding Yeah, I might expand it to deal with that. Language aside, though, I really think ANSI control sequences are the way to go for shorter code. \$\endgroup\$
    – Sneftel
    Commented Aug 31, 2014 at 21:47
5
\$\begingroup\$

Ruby, 207 characters

b=[];x=y=0;gets.chars{|c|b[y]||=[];b[y][x]={?\n=>->{?0},?w=>->{y>0?y-=1:b=[[]]+b;?^},?a=>->{x>0?x-=1:b.map!{|r|[' ']+r};b[y][1]=?<},?s=>->{y+=1;?v},?d=>->{x+=1;?>}}[c][]};puts b.map{|r|r.map{|c|c||' '}.join}

Ungolfed:

b=[]  #board
x=y=0 #position
gets.each_char{|c|
  b[y] ||= []
  b[y][x] = {
    "\n" => lambda{0},
    "w"  => lambda{if y>0 then y-=1 else b=[[]]+b; "^"},
    "a"  => lambda{if x>0 then x-=1 else b.map!{|r|[' ']+r}; b[y][1]="<"},
    "s"  => lambda{y+=1; "v"},
    "d"  => lambda{x+=1; ">"}
  }[c].call}
puts b.map{|r|r.map{|c|c||' '}.join}

(the lambda for a writes back because the row the assignment above writes to is no longer on the board)

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

Java - 646

Might as well be the first one!

I bet you all can beat this.

un(sort of)golfed

import java.util.*;
public class Snake{
    public static void main(String[]a) {
        int x,y,minX,minY,maxX,maxY;
        x=y=minX=maxX=minY=maxY=0;
        List<Integer>xs,ys=new ArrayList<Integer>();
        xs=new ArrayList<Integer>();
        List<Character>p=new ArrayList<Character>();
        for(int b=0;b<a[0].length();b++){
            int newX=x,newY=y;
            switch(a[0].charAt(b)){
            case'a':newX--;p.add('<');break;
            case's':newY++;p.add('v');break;
            case'd':newX++;p.add('>');break;
            case'w':newY--;p.add('^');break;
            }
            xs.add(x);ys.add(y);
            x=newX;y=newY;
            if(x<minX){minX=x;}
            if(x>maxX){maxX=x;}
            if(y<minY){minY=y;}
            if(y>maxY){maxY=y;}
        }
        char[][]c=new char[maxY-minY+1][maxX-minX+1];
        for(int i=0;i<xs.size();i++)c[ys.get(i)-minY][xs.get(i)-minX]=p.get(i);
        c[y-minY][x-minX]='@';
        for(char[]k:c){for(char l:k){System.out.print(l);}System.out.println();}
    }
}

Smaller -

import java.util.*;class S{public static void main(String[]a){int x,y,o,z,s,u;x=y=o=s=z=u=0;List<Integer>j,t=new ArrayList<Integer>();j=new ArrayList<Integer>();List<Character>p=new ArrayList<Character>();for(int b=0;b<a[0].length();b++){int e=x,r=y;switch(a[0].charAt(b)){case'a':e--;p.add('<');break;case's':r++;p.add('v');break;case'd':e++;p.add('>');break;case'w':r--;p.add('^');break;}j.add(x);t.add(y);x=e;y=r;if(x<o)o=x;if(x>s)s=x;if(y<z)z=y;if(y>u)u=y;}char[][]c=new char[u-z+1][s-o+1];for(int i=0;i<j.size();i++)c[t.get(i)-z][j.get(i)-o]=p.get(i);c[y-z][x-o]='@';for(char[]k:c){for(char l:k){System.out.print(l);}System.out.println();}}}

input - dddsssdddwwwwaaaaaaaassssssssssddddddddddddddddd

v<<<<<<<<         
v >>>v  ^         
v    v  ^         
v    v  ^         
v    >>>^         
v                 
v                 
v                 
v                 
v                 
>>>>>>>>>>>>>>>>>@

input - dddsssdddddasddddwww

>>>v        
   v       @
   v       ^
   >>>>v<  ^
       >>>>^

my personal favorite - dwdwdwddaasassdddddwdwdwddsdswawaasassdddddddwdwdwddsdswawaasassddddwwwwwwwssssssdsdddwwwwddaassddaassddddsssdddwdwdwddaasasassddddwwwwssssssssasasaaawdwwdwddwwdddddddwdwdwddsdswawaasassddddddddddwwdwwwwaasssassdsdddddddwdwdwwwwasasssssssssssdwwwwwwwddd

                    v                                          
                    v                                          
                    v                                          
                    v   v<<                                    
   v<<   v<<     v<<v   v                                      
  v<    v< ^<   v< ^v   v<<                        v<<     v<  
 >v    >v   ^  >v   >v  v                          v ^    v<^  
>^>>>>>^>>>>>>>^>>>>^>>>>>>>v    v<v               v ^    v ^  
                            v   v< v       v<<    v< ^    v ^  
                            v  v<  v      v< ^<   v >^    v>^  
                            >>>v   v     >v   ^   >v^     v>>>@
                               >>>>>>>>>>^>>>>>>>>>>>>>>>>v^   
                                  ^v                      v^   
                                >>^v                      v^   
                               >^  v                      v^   
                               ^  v<                      v^   
                              >^ v<                       v^   
                              ^<<<                        >^  
\$\endgroup\$
1
2
\$\begingroup\$

C# 607

namespace System{using B=Text.StringBuilder;class P{static void Main(){var f=new Collections.Generic.List<B>(){new B("O")};int w=1,r=0,c=0;for(Action R=()=>f[r].Append(' ',w-f[r].Length+1);1>0;){var key=Console.ReadKey(1>0).KeyChar;if(key=='w'){f[r][c]='^';if(--r<0)f.Insert(r=0,new B());R();f[r][c]='O';}if(key=='a'){f[r][c]='<';if(--c<0){foreach(var s in f)s.Insert(c=0,' ');w++;}R();f[r][c]='O';}if(key=='s'){f[r][c]='v';if(++r>f.Count-1)f.Add(new B());R();f[r][c]='O';}if(key=='d'){f[r][c]='>';if(++c>w++)foreach(var s in f)s.Append(' ');R();f[r][c]='O';}Console.WriteLine(string.Join("\n",f)+"\n");}}}}

"Ungolfed" with whitespace (this will not be kept in sync with the golfed version):

namespace System
{
    using B = Text.StringBuilder;
    class P
    {
        static void Main()
        {
            var f = new Collections.Generic.List<B>() { new B("O") };
            int w = 1, r = 0, c = 0;
            Action R = () => f[r].Append(' ', w - f[r].Length + 1);
            while (true)
            {
                char key = Console.ReadKey(1>0).KeyChar;
                if (key == 'w')
                {
                    f[r][c] = '^';
                    if (--r < 0) { f.Insert(0, new B()); r = 0; }
                    R();
                    f[r][c] = 'O';
                }
                if (key == 'a')
                {
                    f[r][c] = '<';
                    if (--c < 0)
                    {
                        foreach (var s in f)
                            s.Insert(0, ' ');
                        w++;
                        c = 0;
                    }
                    R();
                    f[r][c] = 'O';
                }
                if (key == 's')
                {
                    f[r][c] = 'v';
                    if (++r > f.Count - 1) f.Add(new B());
                    R();
                    f[r][c] = 'O';
                }
                if (key == 'd')
                {
                    f[r][c] = '>';
                    if (++c > w++)
                    {
                        foreach (var s in f)
                            s.Append(' ');
                    }
                    R();
                    f[r][c] = 'O';
                }

                Console.WriteLine(string.Join("\n", f) + "\n");
            }
        }
    }
}
\$\endgroup\$
2
\$\begingroup\$

Python 3: 259 Bytes

x=y=0
b,p,r={},(0,-1,0,1),range
while 1:
 d='wasd'.index(input());b[(x,y)]='^<v>'[d];x+=p[d];y-=p[~d];b[(x,y)]='☺';l,m=([k[i]for k in b]for i in(0,1))
 for j in r(min(m),max(m)+1):print(''.join(b[(i,j)]if(i,j)in b else' 'for i in r(min(l),max(l)+1)))
 print()

I decided to store the snake in a dict, with coordinates for the keys. Then find and iterate over the output range, substituting blank spaces.

x = y = 0
board = {}
while 1:
    d = 'wasd'.index(input())
    board[(x, y)] = '^<v>'[d] # body
    x += (0, -1, 0, 1)[d]
    y -= list(reversed((0, -1, 0, 1)))[d]
    board[(x,y)] = '☺' # head

    xs, ys= ([coord[dim] for coord in board] for dim in(0, 1))
    for j in range(min(ys), max(ys)+1):
        print(''.join(board[(i,j)] if (i,j) in board else ' '
                      for i in range(min(xs), max(xs)+1)))
    print()

PS. My first Golf :) Let me know if my answer is inappropriate

\$\endgroup\$
7
  • \$\begingroup\$ Using O instead of saves you 2 bytes. is a red herring. \$\endgroup\$ Commented Jul 31, 2016 at 18:20
  • \$\begingroup\$ @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ wasn't actually counted as 3 bytes. \$\endgroup\$ Commented Jul 31, 2016 at 18:30
  • \$\begingroup\$ @MartinEnder It must be, the default encoding is UTF-8. I had a feeling it wasn't counted. I have a feeling it was accidental and must be immediately fixed by Gilly. \$\endgroup\$ Commented Jul 31, 2016 at 18:39
  • \$\begingroup\$ @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Well technically, the answerer is free to use any encoding supported by their interpreter (and I'm pretty sure some ASCII-compatible code page contains that character) but that's beside the point. I'm saying the byte count is already the same as that of using O, so I wouldn't worry about it. It's clear from the code that it would still work for any other character but using lets you conveniently run the test cases from the challenge without changes. \$\endgroup\$ Commented Jul 31, 2016 at 18:43
  • \$\begingroup\$ @MartinEnder Python uses UTF-8, proved by its ability to support unicode strings. To enable this functionality, the first or second line must be #coding=utf-8. Note that #coding=utf-16 does not work. Hence must be counted as 3. \$\endgroup\$ Commented Jul 31, 2016 at 18:45
2
\$\begingroup\$

Python 2.7 - 274 bytes

x,y,m,d,r=0,0,{},(0,-1,0,1),range
for c in raw_input():b='wasd'.index(c);m[(x,y)]='^<v>'[b];x+=d[b];y-=d[~b];m[(x,y)]='@';l,n=([k[h] for k in m] for h in (0, 1))
for j in range(min(n),max(n)+1):print(''.join(m[(i,j)] if (i,j) in m else ' 'for i in range(min(l),max(l)+1)))

Ungolfed version

x,y,matrix,delta = 0,0,{},(0, -1, 0, 1)    
for c in raw_input('Command: '):
    d = 'wasd'.index(c)
    matrix[(x, y)] = '^<v>'[d]
    x += delta[d]
    y -= list(reversed(delta))[d]
    matrix[(x, y)] = '@'    
xs, ys = ([xy[i] for xy in matrix] for i in (0, 1))
for j in range(min(ys), max(ys)+1):
    print(''.join(matrix[(i, j)] if (i, j) in matrix else ' '
                  for i in range(min(xs), max(xs)+1)))
\$\endgroup\$
6
  • 2
    \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! According to the rules outlined in our help center, all solutions to challenges should be a serious contender for the winning criteria in use. For example, an entry to a code golf contest needs to be golfed. \$\endgroup\$
    – Dennis
    Commented Mar 19, 2016 at 17:09
  • 1
    \$\begingroup\$ I'm added the byte count for you, but there's quite a lot of unnecessary spaces in there which you might want to remove. \$\endgroup\$ Commented Mar 19, 2016 at 18:38
  • \$\begingroup\$ Thanks guys, I made the necessary changes to my first entry. Any extra advice will be greatly appreciated. \$\endgroup\$ Commented Mar 20, 2016 at 7:20
  • \$\begingroup\$ I really golfed it. \$\endgroup\$ Commented Jul 31, 2016 at 19:04
  • \$\begingroup\$ @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ That just prints SyntaxError: invalid syntax. \$\endgroup\$
    – Dennis
    Commented Jul 31, 2016 at 19:34
2
\$\begingroup\$

05AB1E, 35 34 30 28 bytes

.•₃º•"<>v^"©‡0ªÐUĀ>sŽO^®XkèΛ

Uses 0 as head of the snake.

-4 bytes thanks to @Grimy.

Try it online (no test suite for all test cases at once, because there is no way to reset the Canvas, so outputs would overlap..).

Explanation:

.•₃º•          # Push compressed string "adsw"
     "<>v^"    # Push string "<>v^"
           ©   # Save it in variable `r` (without popping)
            ‡  # Transliterate the (implicit) input-string,
               # replacing all "adsw" with "<>v^" respectively
               #  i.e. "ddddssaassdddddww" → ">>>>vv<<vv>>>>>^^"
0ª             # Convert the string to a list of characters, and append a 0 (for the head)
               #  → [">",">",">",">","v","v","<","<","v","v",">",">",">",">",">","^","^","0"]
  Ð            # Triplicate this list of characters
   U           # Pop and store one of the three lists in variable `X`
   Ā           # Trutify each character ("0" remains 0; everything else becomes 1)
    >          # And then increase each integer by 1
               #  → [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1]
  s            # Swap the two lists on the stack
      ®Xk      # Get the index of each character of variable `X` in variable `r` ("<>v^")
               #  i.e. [">",">",">",">","v","v","<","<","v","v",">",">",">",">",">","^","^","0"]
               #   → [1,1,1,1,2,2,0,0,2,2,1,1,1,1,1,3,3,-1]
   ŽO^   è     # And use those to index into the compressed number 6240
               #  → [2,2,2,2,4,4,6,6,4,4,2,2,2,2,2,0,0,0]
Λ              # Use the Canvas builtin with these three lists

See this 05AB1E tip of mine (sections How to compress strings not part of the dictionary? and How to compress large integers?) to understand why .•₃º• is "adsw" and ŽO^ is 6240.

As for a brief explanation of the Canvas builtin Λ and its three arguments:

First argument: length(s): the sizes of the lines we want to draw. Since we have to keep in mind overlapping, we use size 2 for every character, and an additional 1 for the head of the snake.
Second argument: string(s): the characters we want to display. Which are the characters in this case, appended with the head-character of the snake.
Third argument: direction(s): the directions these character-lines of the given length should be drawn in. In general we have the directions [0,7] which map to these directions:

7   0   1
  ↖ ↑ ↗
6 ← X → 2
  ↙ ↓ ↘
5   4   3

Which is why we have the integer 6240 for the directions \$[←,→,↓,↑]\$ respectively.

See this 05AB1E tip of mine for a more detailed explanation about the Canvas builtin Λ.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ I might have missed something, but I don't think γ is needed at all. This seem to work just fine. \$\endgroup\$
    – Grimmy
    Commented Jun 4, 2019 at 10:37
  • \$\begingroup\$ @Grimy Thanks, it indeed does; nice alternative approach with the list of 2s and 1 for the head! And I've been able to save 2 more bytes based off your program. \$\endgroup\$ Commented Jun 4, 2019 at 12:02
  • \$\begingroup\$ Thanks! I am currently at 23, though that's a significantly different approach, so I might make it its own answer if that's fine by you. \$\endgroup\$
    – Grimmy
    Commented Jun 4, 2019 at 12:22
  • \$\begingroup\$ @Grimy That indeed is quite a different approach than mine, so feel free to post it. I was indeed kinda expecting some unicode conversion and modulo might make this shorter than the transliterate, but I'm quite honestly pretty bad with those kind of magic integer/string conversions. :) \$\endgroup\$ Commented Jun 4, 2019 at 12:24
1
\$\begingroup\$

Perl - 394

Not the shortest, but it beats Javascript, C# and Java at least.

use List::Util qw(min max);sub c{()=$_[0]=~/$_[1]/g}%l=(a,['<',-1,0],d,['>',1,0],w,['^',0,-1],s=>['v',0,1]);($s,$x,$y,$w,$h)=($ARGV[0],0,0,max(c($s,a),c($s,d)),max(c($s,w),c($s,'s')));@s=split'',$s;map$x=min($x,$i+=$l{$_}[1]),@s;$i=0;map$y=min($y,$i+=$l{$_}[2]),@s;$x=abs $x;$y=abs $y;map{$m[$y][$x]=$l{$_}[0];$x+=$l{$_}[1];$y+=$l{$_}[2]}@s;$m[$y][$x]='o';map{map{print$_||' '}@$_;print"\n"}@m 

Some tricks:

  • Warnings and strict not turned on to allow barewords and not declaring variables before using them
  • Thin commas instead of fat commas to save a few characters
  • Not setting initial values for variables when not necessary
  • Leaving out semi-colons when possible
  • Defining arrays and hashes not as references to avoid having to use ->
  • Allowing width, height to be larger than necessary to avoid having to calculate them accurately (which would take extra code)

Things that hurt:

  • No built-in way to count number of characters in a string (might have been longer anyway)
  • No built-in min/max functions, thus need to waste 27 characters to import library that does it (less than defining our own)
\$\endgroup\$
1
\$\begingroup\$

C - 273 bytes - with Interactive Input!

#define F for(i=w*w
*g,*G,x,i,j,w,W,u;main(w){putch(1);F;j=-~getch();g=G){if(!(x%w&&~-~x%w&&x/w&&x/w^~-w)){W=w+6;G=calloc(W*W,4);F-1;u=i%w+i/w*W-~W*3,i==x?x=u:8,i;)G[u]=g[i--];free(g);w=W;}G[x]="<^X>v"[j%=7];G[x+=1-G[x]%3+W*(!!j-j/2)]=1;F;i;)putch(i--%W?G[i]?G[i]:32:10);}}

The field is printed each time a character is entered and grows if the snake's head nears the edge. I don't know how portable it is--someone on the Internet said getch() doesn't work on non-Windows platforms. Hard to say whether ASCII 1 will look like a smiley face either.

The golfed version is quite annoying as there is no way to gracefully exit the program. Control-C doesn't work for me. On the other hand, the ungolfed version terminates if a character other than 'w', 'a', 's', or 'd' is entered.

So-called "ungolfed":

#define SMILEYFACE 1
int main()
{
    int o;
    int w = 1;
    int *g = 0, *g2;
    int c, n;
    int x = 0;
    for( putch(SMILEYFACE);c = getch(); ) {
        if(c!='w'&&c!='a'&&c!='s'&&c!='d')
            return 1;
        if(!(x%w) | !(~-~x%w) | !(x/w)  | !(x/w-~-w) ) {
            int wnew = w + 4;
            int off = 2;
            g2 = calloc(wnew*wnew,sizeof(int));
            for(n = w*w; --n; )
                g2[ n%w+off + (n/w+off)*wnew ] = g[n];
            free(g);
            g = g2;
            x = (x/w+off)*wnew + x%w + off;
            w = wnew;
        }
        int i = -~c%7;
        g[x] = "<^X>v"[i];
        int dx = 1-g[x]%3 + w * (!!i-i/2);
        x += dx;
        g[x] = SMILEYFACE;
        for(o = w*w; o; )
            putch(o--%w?g[o]?g[o]:32:10);


    }
    return 0;
}
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 23 bytes

Ç7%DÉ+D"^>>v"ºsè0ªDĀ>rΛ

Try it online!

Explanation:

                      # implicit input (eg: "wasd")
Ç                     # codepoints (eg: [119, 97, 115, 100])
 7%                   # modulo 7 (eg: [0, 6, 3, 2])
   DÉ+                # plus itself modulo 2 (eg: [0, 6, 4, 2])
# This is the list of directions that will be passed to 05AB1E's canvas function, Λ.
# 0 means up, 6 left, 4 right, 2 down.

 "^>>v"º              # "^>>v", horizontally mirrored (namely "^>>vv<<^")
D       sè            # index into this with a copy of the list of directions
          0ª          # append "0"
# This is the list of strings that will be drawn.

D                     # duplicate the list of strings
 Ā                    # truthify (maps letters to 1, 0 stays 0)
  >                   # increment each
# This is the list of lengths to draw.

r                     # reverse the stack because Λ takes arguments in the opposite order
 Λ                    # draw!

\$\endgroup\$

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.