Take a break to make a snake!
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:
- Normal
- Animated
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:
The example from Stretch Maniac:
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"));
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.
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)