# Spelling on a Grid

(based on this deleted question)

Take the English alphabet a b c d e f g h i j k l m n o p q r s t u v w x y z (spaces added for clarity), and split it into chunks of X width, padding any leftover lines with spaces if necessary for your language. For example, splitting it into width 4 results in

a b c d
e f g h
i j k l
m n o p
q r s t
u v w x
y z


Now, given a word composed of [a-z]+, output the path taken to spell that word when starting from a and using ! to specify selecting that letter, with D U R L for Down, Up, Right, Left, respectively.

For the above X=4 example, and the word dog, the output would be R R R ! L D D D ! U U ! (spaces added for clarity and not required in output).

If X=3, you get a different picture of the alphabet:

a b c
d e f
g h i
j k l
m n o
p q r
s t u
v w x
y z


And a different solution for the word dog -- D ! D D D R R ! L L U U !.

## Examples

"dog" 4 --> R R R ! L D D D ! U U !
"dog" 3 --> D ! D D D R R ! L L U U !
"hello" 6 --> R D ! R R R U ! R D ! ! D L L L !
"codegolf" 10 --> R R ! R R D ! L U ! R ! R R ! L L D ! L L L ! U R R R R !
"acegikmoqsuwy" 2 --> ! D ! D ! D ! D ! D ! D ! D ! D ! D ! D ! D ! D !


## Rules

• Note that the grid doesn't wrap, so to get from the leftmost column to the rightmost column requires traversing the entire X distance.
• The output must be a shortest possible path, but doesn't necessarily need to be in a particular order. For example, for the first dog example you could instead produce R R R ! D D D L ! U U !, swapping the order of the Downs and the Left, because that's the same length path and achieves the same character.
• Similarly, please output only one path (because there will likely be multiple), but that doesn't need to be deterministic (i.e., multiple runs of your program may produce different paths, provided they're all the shortest).
• The output doesn't have to have delimiters (like I do here with spaces), that's up to your aesthetic choice.
• You can choose input as all-lowercase or all-uppercase, but it must be consistent.
• The input number is guaranteed to be in the range 1 to 26 (i.e., a single column to a single row of letters).
• Input words are guaranteed to be at least one character long, and match [a-z]+ with no other punctuation, spaces, etc., (i.e., you'll never receive empty string "" as input), but it may not be an actual English word.
• Instead of D U R L !, you can choose five characters/numbers/arrows/etc. to represent the direction and selection. For example, you could choose 1 2 3 4 x. This output choice must be consistent across all runs of your code, and please specify in your submission what the output is.
• Input and output can be given by any convenient method.
• You can print it to STDOUT or return it as a function result.
• Either a full program or a function are acceptable.
• Standard loopholes are forbidden.
• This is so all usual golfing rules apply, and the shortest code (in bytes) wins.
• Can we take the input as a list of integers from 0 to 25 rather than lowercase letters? My Jelly answer spends 4 bytes converting the letters into integers, and in general IO is less interesting for codegolf. – Nick Kennedy Oct 25 at 19:47
• @NickKennedy No, that would radically change the input from "a string and a width." – AdmBorkBork Oct 25 at 20:13
• not really. A list of integers from 0 to 25 where there is a one-to-one correspondence to the letters A to Z and a width as the second input isn’t really any different. I.e. rather than "codegolf" and 10, you would have [2,14,3,4,6,14,11,5] and 10. Anyway, it’s your challenge, so happy to go with whatever you prefer; my current answer takes a word of lower case letters as its first argument as per the spec. – Nick Kennedy Oct 25 at 20:30
• Is there a unique output for the inputs "zy" and 5? – Neil Oct 25 at 22:58
• @Neil Not necessarily, because you can optionally pad the z line with spaces. – AdmBorkBork Oct 28 at 12:30

# K (ngn/k), 41 32 bytes

{,/(|4,&0|,/-:\)'-':+(0,y)\x-97}


Try it online!

output: 0=D 1=R 2=U 3=L 4=!

{ } function with arguments x and y

x-97 convert "a".."z" to 0..25

(0,y)\ divmod by y, returns a pair of lists - one with the quotients and one with the remainders

+ flip - make it a list of pairs

-': deltas - subtract each pair from the previous one; use 0 0 as an implicit pair before the first

( )' for each pair (let's call it (Δi;Δj)) do:

• -:\ self and own negation: (Δi;Δj) -> ((Δi;Δj);(-Δi;-Δj))

• ,/ concatenate: -> (Δi;Δj;-Δi;-Δj)

• 0| max with 0

• & "where" - for instance it would turn the list a:1 5 0 2 into 0 1 1 1 1 1 3 3, i.e. each index i is repeated a[i] times

• 4, prepend a 4

• | reverse

,/ concatenate

• that cat with the negative trick is quite nice. quite nice indeed. – Jonah Oct 26 at 4:23
• @Jonah thanks­­ – ngn Oct 26 at 8:10

# JavaScript (Node.js),  112 ... 104  102 bytes

Takes input as (width)(word), where word is expected in lowercase. Returns 01234 for RLDU!.

n=>w=>Buffer(w).map(g=c=>v-(c%=97)?g(c,v-=[-1,1,-n,n][d=(v-c)%n?v%n>c%n&1:v>c|2],o+=d):o+=4,o=v='')&&o


Try it online!

# J, 44 41 bytes

;@(2<@(_,~[:I.0>.-,-~)/\0,]#:~_,[)97|3&u:


Try it online!

All credit to ngn for the best part: the self-append of the negative delta and max with 0, as a way of creating unique markers for each direction.

Separately, -3 bytes thanks to ngn for some line edits

2 = D, 3 = R, 0 = U, 1 = L, _ = select

• 97|3&u: turns the letters into numbers, with a = 0.
• ]#:~_,[ use a mixed base of infinity and the left arg as a way of calculating divmod
• 0, append 0 so we'll have a delta to the first letter
• 2<@(_,~[:I.0>.-,-~)/\ calculates the deltas, then append their negative, use J's "indices" (like k's "where" -- see ngn's answer), append an infinity _,~, and box the result <@.
• ;@ remove all the boxing
• 97-~ -> 97| – ngn Oct 26 at 8:29
• _&,@[#:] -> ]#:~_,[ – ngn Oct 26 at 8:37
• ([:; -> ;@( – ngn Oct 26 at 8:39
• @ngn Tyvm, I was hoping you'd have a look. – Jonah Oct 26 at 12:26

# Jelly, 24 20 bytes

O_97ŻdZIb1Ḥ2¦Z;€3Fḟ0


Try it online!

A dyadic link taking the word as the left argument and the width as the right. Returns a list of integers where:

-2 = L
-1 = U
1 = R
2 = D
3 = Select


# Python 3, 126 bytes

lambda s,n:[abs(x//n-y//n)*'UD'[y>x]+abs(x%n-y%n)*'LR'[y%n>x%n]+'!'for x,y in zip(map(O,'a'+s),map(O,s))]
O=lambda c:ord(c)-97


Try it online!

# C (gcc), 165164140138137 135 bytes

#define W(b,c);for(;X b;putchar(c))
x,y,X;f(s,w)char*s;{x=y=0 W(=*s++,33){X-=97 W(%w<x,76)x--W(%w>x,82)x++W(/w<y,85)y--W(/w>y,68)y++;}}


Try it online!

1 25 27 28 byte shaved off thanks to ceilingcat! Ungolfed:

int x, y, X, Y;

f(char *s, int w) {
x = 0;                                 // Starting position is (0, 0)
y = 0;

while (*s) {                          // For each character
X = (*s - 'a') % w;               // Get its x coordinate
Y = (*s - 'a') / w;               // Get its y coordinate
s++;

while (X > x) putchar('R'), x++;  // Print R for each step we need to move right
while (X < x) putchar('L'), x--;  // ...et cetera...
while (Y > y) putchar('D'), y++;
while (Y < y) putchar('U'), y--;

putchar('!');                     // We are there, print !
}
}


# 05AB1E, 20 bytes

AIk0šI‰ü-εεdDNOyÄ×]»


Try it online!

Uses 0 for D, 1 for R, 2 for U, 3 for L, and newline for !. Space is used as an optional separator.

# Charcoal, 52 48 bytes

Ｎθ≔⁰δＦＥＳ⌕βι«≔⁻﹪ιθ﹪δθη≔⁻÷ιθ÷δθζＦ±ηLＦ±ζUＦηRＦζD≔ιδ!


Try it online! Link is to verbose version of code. Edit: Saved 4 bytes by only tracking the alphabet index rather than the row and column separately. Takes input as X first, then the word. Explanation:

Ｎθ


Input X.

≔⁰δ


Start the path at the a with index 0.

ＦＥＳ⌕βι«


Input the word, convert its letters to their alphabet index and loop over them.

≔⁻﹪ιθ﹪δθη


Calculate the horizontal difference.

≔⁻÷ιθ÷δθζ


Calculate the vertical difference.

Ｆ±ηLＦ±ζUＦηRＦζD


Turn those differences into a path.

≔ιδ


Update the current index.

!


Select the current letter.

The reverse program is only 23 bytes:

ＮθＰ⪫⪪βθ¶ＦＳ≡ι!⊞υＫＫＭ✳ι⎚↑υ


Try it online! Link is to verbose version of code. Explanation:

Ｎθ


Input X.

Ｐ⪫⪪βθ¶


Split the lowercase alphabet into substrings of length X and print them on separate lines without moving the cursor.

ＦＳ


Loop over the command characters.

≡ι!


If the next character is a !...

⊞υＫＫ


... then save the letter under the cursor in a list...

Ｍ✳ι


... otherwise move in the direction given by that character.

⎚↑υ


Remove the alphabet and output the saved letters.