Guide the Alphabet
JavaScript (ES6), 108 107 94 87 bytes
Saved a whopping 13 bytes, thanks to Titus!
Saved 7 more bytes, thanks to edc65!
let f =
a=>[i=9,...a].map(d=>r[p+=(d+=d>3)*9-d%3*8-28]=(++i).toString(36),r=[],p=646)&&r.join``
console.log(f([4,7,1,6,6,6,0,3,1]));
How it works
The formula (d += d > 3) * 9 - d % 3 * 8 - 28
translates the directions 0..7
into the following offsets:
0 1 2 -28 -27 -26
3 x 4 --> -1 x +1
5 6 7 +26 +27 +28
We use these offsets to move the pointer p
into the one-dimensional array r
and write the letters at the resulting positions.
We iterate on [i = 9, ...a]
rather than just a
in order to insert the starting letter 'a'. Because we initialize i
to 9
at the same time, we introduce a special offset of 54 (the result of the above formula for d = 9
). After the first iteration, p
equals 646 + 54 = 700
, which leaves just enough space to support up to 25 moves to North-West: 25 * -28 = -700
. That's why p
is initialized to 646
.
Then we just have to join the array to get our final string. Undefined values in between letters are simply ignored by join()
.
MATL, 64 58 57 50 46 40 37 36 35 30 bytes
O'!":<TUV '59-G)hYsIH$6#u64+c!
Try it at MATL Online
Explanation
O % Push the number 0 to the stack
'!":<TUV ' % String literal
59- % Converts this string literal into [-26 -25 -1 1 25 26 27 -27]. These
% are deltas for the linear indexes into the matrix corresponding to each
% of the directions. Note that the -27 is at the end since a 0 index wraps
% around to the end
i) % Grab the input and use it to index into the delta array
h % Horizontally concatenate this with the 0 (our starting point)
Ys % Take the cumulative sum to get the absolute linear index (location) of
% each successive letter
IH$6#u % Find the index of the last (sorted) occurrence of each location
64+ % Add 64 to this index to create ASCII codes
c! % Convert to character, transpose, and display
Octave, 145 138 131 123 105 103 90 87 85 bytes
@(a){[~,k]=unique(cumsum([1 fix((z=a+(a>3))/3);1 mod(z,3)]'-1),'rows');[k'+64 '']}{2}
Try It Online
Thanks to Suever 2 bytes saved!
Previous answer 103 bytes:
@(a)[nonzeros(accumarray(cumsum([1 fix((z=a+(a>3))/3);1 mod(z,3)]'-1)+30,65:nnz(++a)+65,[],@max)')' '']
Try It Online!
First try 145 byts
@(a){[x y]=find(~impad(1,1,1));c=cumsum([0 0;([y x]-2)(++a,:)]);c=c-min(c)+1;n=nnz(a);[nonzeros(sparse(c(:,1),c(:,2),65:n+65,'unique')')' '']}{5}
Some Explanations
@(a){
[x y]=find([1 0 1]|[1;0;1]); %generate 2d coordinates corresponding to 1d input indices
XY = [y x]-2;
c=cumsum([0 0;XY(++a,:)]); %cumulative sum of coordinates to find position of characters
c=c-min(c)+1;n=nnz(a);
[nonzeros(sparse(c(:,1),c(:,2),65:n+65,'unique')')' ''] %using sparse matrix to place characters at specified positions
}{5}