The Speed of Letters

Given a string as input, print a new string with each letter pushed to the right by its respective alphabet index.

We all know that A is a slow and Z is a fast letter. This means that Z gets shifted to the right by 25 spaces, A doesn't get shifted at all and B gets shifted by 1 space.

Your program only has to handle uppercase letters from A-Z, and no other characters, no whitespaces, no punctuation.

Note that if 2 or more letters fall onto the same space after shifting, the latest character will be used. (Example: BA ->  A)

Examples

"AZ" -> "A                         Z"

"ABC" -> "A B C"

"ACE" -> "A  C  E"

"CBA" -> "  A"

"HELLOWORLD" -> "     E H    DLL   OLO   R  W"

Rules

• This is , so the shortest code in any language bytes wins.
• Standard loopholes are forbidden.

• Input must be received as a string.

• You may print the result to stdout or return a string.
• A single trailing whitespace and/or newline is allowed.
• You may also use lowercase letters as input or output, but only use either case.
• Trailing whitespace okay?
– Okx
Oct 13 '17 at 13:56
• @Okx Yes, note my previous comment. Oct 13 '17 at 13:58
• What about a lot of trailing spaces?
– Okx
Oct 13 '17 at 13:59
• @Okx Forbidden, one is all you get. Oct 13 '17 at 13:59
• I assume we can use lowercase letters instead, right? Oct 13 '17 at 15:53

Python 2, 81 bytes

t=[]
i=65
for c in input():t+=[' ']*26;t[ord(c)-i]=c;i-=1
printt[2::5].rstrip()

Try it online!

MATL, 11 bytes

''jtfy65-+(

Explanation

MATL indexing is 1-based. This golfing trick is used here. This other one cannot be used because we need an empty string, not an empty numeric array.

Consider input 'ACE' as an example. Stack contents are shown bottom to top.

''     % Push empty string
%   Stack: ''
j      % Input string
%   Stack: '', 'ACE'
t      % Duplicate
%   Stack: '', 'ACE', 'ACE'
f      % Indices of nonzero entries. Gives [1 2 ... n] where n is input length
%   Stack: '', 'ACE', [1 2 3]
y      % Duplicate from below
%   Stack: '', 'ACE', [1 2 3], 'ACE'
65     % Push 65
%   Stack: '', 'ACE', [1 2 3], 'ACE', 65
-      % Subtract, element-wise. Characters are converted to codepoints
%   Stack: '', 'ACE', [1 2 3], [0 2 4]
%   Stack: '', 'ACE', [1 4 7]
(      % Fill string '' with values 'ACE' at positions [1 4 7]. The original
% empty string is extended. Non-existing values are filled with char 0,
% which is displayed as space. Implicitly display
%   Stack: 'A  C  E'
• (: nice builtin Oct 13 '17 at 14:39
• @EriktheOutgolfer I think it's similar to 05AB1E's ǝ? Ah, but that doesn't seem to vectorize over the second/third inputs Oct 13 '17 at 14:46
• Exactly why it's unique :p and also how MATL auto-fills with 0s and displays 0 as space. Oct 13 '17 at 14:50
• @LuisMendo Nice answer. Out of curiosity, and this question is probably applicable to most stack based langs, when you write in MATL do you need to keep track of the stack (eg, in a line above the code, or a piece of paper, etc) as you compose code? Or has it become natural enough to you that you don't? Oct 14 '17 at 1:20
• Heh - learned something new today; you can index into the same position twice without any problem in MATL(AB). I already started writing a complicated loop-based answer because I assumed it would give an error otherwise. Oct 15 '17 at 12:07

R, 140133129 74 bytes

Saved a ton of bytes porting an ASCII value approach like everyone else. Sad I didn't think of it before :(

function(s){F[X-65+1:sum(X|1)]=X=utf8ToInt(s)
F[is.na(F)]=32
intToUtf8(F)}

Try it online!

function(s){o=rep(' ',(n=nchar(s))+25)
for(i in 1:n){k=substr(s,i,i)
o[x<-i+match(k,LETTERS)-1]=k
F=max(F,x)}
cat(o[1:F],sep='')}

Try it online!

generates a too-long list o of spaces, then iterates through s, replacing the values in o with the correct value and updating F, the position of the rightmost character. Then prints out the first F elements of o with no separators between them.

05AB1E, 20 16 bytes

-4 bytes thanks to Emigna

ð₄×svyAuykN+ǝ}ðÜ

Try it online!

• I think you can shorten to ð₄×svyAuykN+ǝ}ðÜ at least. Also, is there a guarantee that the input string shifted isn't larger than 1000 chars? If not, g₂+ð× should work. Oct 13 '17 at 14:10

JavaScript (ES6), 81 bytes

s=>[...s].map((c,i)=>a[i+parseInt(c,36)-10]=c,a=[])&&[...a].map(c=>c||" ").join

Somewhat builds off of Rick Hitchcock's incomplete answer but ended up rather different.

Places the characters into their respective index of an empty array, then uses array spread ([...a]) to turn the missing elements into undefined, allowing map to replace empty elements with a space.

Test Cases

let f=
s=>[...s].map((c,i)=>a[i+parseInt(c,36)-10]=c,a=[])&&[...a].map(c=>c||" ").join

;["AZ", "ABC", "ACE", "CBA", "HELLOWORLD"]
.forEach(t=>console.log("${t}", "=>", "${f(t)}"))

• Very nice! I was about to post an 88-byte solution, but yours is much better. Oct 13 '17 at 19:45

Perl 5, 42 bytes

41 bytes code + 1 for -p. The \x1bs in the code are literal escape characters.

Relies on ANSI escape sequences to position the cursor and therefore doesn't work on TIO.

s/./($-=-65+ord$&)?"\x1b[$-C$&\x1b[--$-D":$&/ge

Usage

perl -pe 's/./($-=-65+ord$&)?"\x1b[$-C$&\x1b[--$-D":$&/ge' <<< 'HELLOWORLD'
E H    DLL   OLO   R  W
• Here's one that works on TIO but comes in at one byte more (41 bytes of code + 2 for -F): Try it online! Oct 13 '17 at 18:03
• @Xcali You should post that so I can upvote it :)
– Lynn
Oct 13 '17 at 18:46
• @Xcali Agree with Lynn too more posts are great. I like language competition too! Oct 13 '17 at 21:08

Java (OpenJDK 8), 207191189183178174173 170 bytes

s->{char i=0,l,c[]=new char[s.chars().map(j->j+s.lastIndexOf(j)).max().getAsInt()-64];for(;i<s.length();c[i+l-66]=l)l=s.charAt(i++);return"".valueOf(c).replace('',' ');}

Try it online!

Perl 5, 41 + (-F) = 43 bytes

map$r[$i++-65+ord]=$_,@F;print$_||$"for@r Try it online! Just for @lynn brainfuck, 127 bytes ,[[-<+<+>>]----[----<<->>]<<-[[>]>++++>[-<[-]<+>>]<[-<++++++++>]<[<]>-]>[>]<[-]+[<]>-[[>]<+[<]>-]>.[-]>[>]<[[->>+<<]<]>,]>>[.>] Try it online! Explanation ,[ Take input and start main loop [-<+<+>>] Make two copies of input byte ----[----<<->>]<<- Subtract 64 from one of them to get position in alphabet There are two zero cells between the input and the remaining output cells; we wish to move these zeroes to indicate where the letter is to be moved [ A number of times equal to the position in the alphabet: [>] Go to current position in output string >++++> Create 4 (as part of creating a space if needed) [-<[-]<+>>] Move output byte back two cells; zero the previous 4 if output existed <[-<++++++++>] Otherwise move a space (32) into that position <[<]>- Move back to counter and decrement ] >[>]<[-] Delete last moved byte to make room for input byte +[<]>- Initialize slot at 1 so it is always nonzero in this loop [[>]<+[<]>-] Move input byte into slot >.[-] Output next output byte and clear >[>]< Move to space vacated in preparation to remove gap (Moves to end instead if input was A; this causes no problems) [[->>+<<]<] Move values two cells right until zero reached >, Get into position and take another byte of input ] >>[.>] Output characters beyond end of input Proton, 78 bytes x=>{t=[' ']*26*(q=len(x))for i:0..q{t[i+ord(k=x[i])-65]=k}"".join(t).rstrip()} Try it online! 69 bytes by porting Lynn's solution: x=>{t=[]i=65for k:x{t+=[' ']*26t[ord(k)-i]=k;i--}"".join(t).rstrip()} Jelly, 20 bytes ØAiÐ€+JṬ€a"⁸Zḟ€0Ṫ€o⁶ Try it online! Haskell, 90 88 bytes d=drop 1 [a]#s|s<"A"=a:d s|0<1=s b#s=(s++" ")!!0:d b#d s f(c:t)=['A'..c]#(' ':f t) f s=s Try it online! • @Laikoni Oh dang, I misread that. Will fix... Oct 13 '17 at 21:04 • Well, it's no longer shorter. :/ Oct 13 '17 at 21:13 Japt, 23 bytes ;iB ç Ng £=hX10nY+XnG U Test it online! First attempt, may be improvable... • It looks like you should be able to save a byte by assigning the initial string to V instead of U: ethproductions.github.io/japt/… Oct 13 '17 at 21:02 Wolfram Language (Mathematica), 76 bytes SparseArray[Reverse@MapIndexed[#&@@#2+LetterNumber@#-1->#&,#]]<>""/. 0->" "& Takes a list of characters as input. This generates some error messages that are safe to ignore. I included Print and Character command in the footer of the TIO link for ease of use. (Character command simply converts a string to a list of characters) Try it online! • LetterNumber is a built-in for finding the position of a letter in the alphabet? Holy crap, that's ridiculous. Oct 14 '17 at 6:40 J, 37 31 bytes [](' '#~(1+>./)@])}(i.@#+65-~a.&i.) [](' '#~(1+>./)@])}#\-66-3&u: -6 bytes thanks to FrownyFrog explanation The entire thing is a hook: [](' '#~(1+>./)@])} #\-66-3&u: The right side calculates the new indexes for all the letters. The left side uses the gerund form of Amend } first to create a string of the necessary number of spaces: (' '#~(1+>./)@]) . And then to place each letter of the original string into its appropriate index within the all-space string. Try it online! • (i.@#+65-~a.&i.) -> (i.@#+65-~3&u:) -> (i.@#-65-3&u:) -> (#\-66-3&u:) Oct 13 '17 at 17:13 • You can drop the parentheses too. Oct 13 '17 at 17:18 • @FrownyFrog tyvm. i'd forgotten about both those golf tricks. Oct 13 '17 at 17:52 • You can save 3 bytes with (]' '#~1+>./) Oct 14 '17 at 1:28 • @miles. Nice. I need to make dyadic hooks part of my regular toolbox, I noticed you used them in that revision from this morning as well. Oct 14 '17 at 1:49 Haskell, 88 bytes foldr(\c->(((['B'..c]>>" ")++[c])#).(' ':))[] (x:r)#(y:t)|y>' '=y:r#t|1<3=x:r#t r#t=r++t Try it online! Haskell, 88 bytes f s|q<-zipWith((+).fromEnum)s[0..]=[last$' ':[c|(c,i)<-zip s q,i==p]|p<-[65..maximum q]]

Try it online!

q is the list of the final indices of the letters of the input string (with an offset of 65). Loop through all indices (starting at 65) and find all letters for it, prepending a space. Take the last.

• Yet another 88 byte Haskell solution, see here and here.
– nimi
Oct 14 '17 at 17:51

C# (.NET Core), 117110 84 bytes

Saved 7 bytes thanks to Ayb4tu.

Changed return type from string to char[] to save 26 bytes.

n=>{int i=0,l=n.Length;var t=new char[l+26];for(;i<l;)t[i+n[i]-65]=n[i++];return t;}

Try it online!

• You can save 7 bytes by changing t[i+((int)n[i]-65)] to t[i+n[i]-65]. Oct 14 '17 at 9:28
• @Ayb4btu Thanks forgot that char -> int conversions are implicit. Oct 14 '17 at 9:37

C# .NET, 89 Bytes 87 Bytes

-2 bytes thanks to Lan H.

f=>{var s=new char[f.Length+26];for(int i=0;i<f.Length;i++)s[f[i]+i-65]=f[i];return s;}

Try it Online!

• Welcome to the site! :) Oct 16 '17 at 15:44
• Thanks! I hope it's ok to post multiple answer in the same language Oct 16 '17 at 16:07
• You can omit the curly brackets in your for-loop for -2 bytes. Oct 16 '17 at 20:50

Kotlin, 207 bytes189 bytes187 bytes 177 bytes

fun main(){val i=(readLine()+" ".repeat(26)).toCharArray();for(x in(i.size-1) downTo 0){if(i[x]!=' '){i[x+i[x].toInt()-65]=i[x];i[x]=' '}};print(i.joinToString("").trim())}

If the leading blank should remain I would just call trimEnd() instead of trim().

Unminified:

fun main() {
val m = (readLine() + " ".repeat(26)).toCharArray()
for (x in (m.size - 1) downTo 0) {
if(m[x] != ' ') {
m[x + m[x].toInt() - 65] = m[x]
m[x] = ' '
}
}

print(m.joinToString("").trim())
}

Maybe Kotlin is not the best language for code golfing but I liked the challenge and I wanted to make myself more familiar with Kotlin's standard library.

q/kdb+, 37 bytes

Solution:

@[max[1+m]#" ";m:!:[x#:]+.Q.A?x;:;]x:

Examples:

q)@[max[1+m]#" ";m:!:[x#:]+.Q.A?x;:;]x:"AZ"
"A                         Z"
q)@[max[1+m]#" ";m:!:[x#:]+.Q.A?x;:;]x:"ABC"
"A B C"
q)@[max[1+m]#" ";m:!:[x#:]+.Q.A?x;:;]x:"ACE"
"A  C  E"
q)@[max[1+m]#" ";m:!:[x#:]+.Q.A?x;:;]x:"CBA"
"  A"
q)@[max[1+m]#" ";m:!:[x#:]+.Q.A?x;:;]x:"HELLOWORLD"
"     E H    DLL   OLO   R  W"

Explanation:

I think this is the same idea as the J solution, calculate the correct indices for the input array and then assign them to an empty string of correct length:

@[max[1+m]#" ";m:til[count x]+.Q.A?x;:;]x: / ungolfed solution
x: / save input as x
@[            ;                     ; ;]   / apply[variable;indices;function;parameters]
:     / assignment
.Q.A?x       / location of x in uppercase alphabet
count x               / length of input
til[       ]              / range, 0..n
m:                          / save as m
max[   ]                                 / maximum of list
1+m                                  / m + 1
#" "                             / take " ", creates empty character list

Jq 1.5, 91 bytes

reduce(explode|[.,keys]|transpose[]|.+=.-65)as[$c,$p]([];.[$p]=$c)|map(.//32)|implode

Expanded

reduce(  explode         # convert string to array of ordinals
| [.,keys]        # [ [v0,v1,...], [0,1,2,...] ]
| transpose[]     # [ [v0,0], [v1,1], [v2,2]...]
| .+=.-65   # adjust position of each value
) as[$c,$p] (
[]
; .[$p]=$c               # store each value at its position
)
| map(.//32)               # map null values to spaces
| implode                  # convert back to string

Try it online!

Charcoal, 16 bytes

Ｐ ＦＳ«Ｍ⌕αι→ιＭ⌕αι←

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

Ｐ                   Output a space to force the indent
Ｓ                Input string
Ｆ «               Loop over each letter
α            Uppercase letters predefined variable
⌕ ι           Find index of current letter
Ｍ   →          Move that many characters right
ι         Implicitly print the current letter
Ｍ⌕αι←    Move the same number of characters left

APL (Dyalog), 26 bytes

Anonymous prefix lambda which takes the input string as argument and returns the output string. Assumes ⎕IO (Index Origin) 0, which is default on many systems.

{⍵@i⊢''↑⍨1+⌈/i←(⎕A⍳⍵)+⍳≢⍵}

Try it online!

{} anonymous lambda; represents the argument

≢⍵ tally of the argument

than many ɩntegers (0…LengthOfArgument-1)

()+ plus:

⎕A⍳⍵ the indices of the argument in the uppercase Alphabet

i← strore in i (for indices)

⌈/ maximum (reduction)

''↑⍨ take that many characters from the empty string, padding with spaces as needed

yield that (serves to separate i from '')

⍵@i amend that with the argument letters at the i indices

SOGL V0.12, 10 bytes

ā,{ZFWē+1ž

Try it Here!

Explanation:

ā           push an empty array
,{         for each char in the input
ZFW        get its index in the uppercase alphabet
ē+      add to that the 0-indexed counter
1ž    at [pop; 1] insert in the array the current character

Pyth, 44 38 bytes

Striked out 44 is still 44 :(

Bloody Pyth beginner.

Saved 6 bytes thanks to @Mr. Xcoder.

K*d+lz26Vlz K=XK-C@zN-65N@zN;.WqeHdPZK

Try it online!

How?

K*d+lz26Vlz K=XK-C@zN-65N@zN;.WqeHdPZK          Full program

K*d+lz26                                        Assign a string consisting of
(26 + input.length) whitespaces to K
Vlz                                     For-loop from 0 to input.length
-C@zN-65N                       Calculate the index for the current letter
@zN                    The current letter
K=XK                                Insert the current letter into K at
position i
;                   End statement
.WqeHdPZK          While the last character of H is not a
whitespace, pop the last character off K
• 38 bytes: K*d+lz26Vlz K=XK-C@zN-65N@zN;.WqeHdPZK. WqeKd K=PK;K is replaced by .W (functional while) and its arguments of course, and FNrZlz can be replaced VrZlz, but rZ... means U..., and U is generated automatically by V. So FNrZlz becomes Vlz Oct 17 '17 at 10:55

Batch, 418 331 bytes

Works with uppercase letters only and will take some seconds for longer strings.

Learned new tricks here, the character to ASCII value conversion using %=exitcodeAscii%. Also, if defined and "array" access using call. Also, golfing by almost 100 bytes was good batch code golf training.

Note the trailing space in set z=set.

@echo off
setlocal EnableDelayedExpansion
set z=set
%z%a=%1
:a
%z%v=64
:b
%z%/Av+=1
cmd/Cexit %v%
if %=exitcodeAscii% neq %a:~0,1% goto b
%z%/Ao=v+c
%z%a%o%=%a:~0,1%
if %o%. geq %m%. %z%m=%o%
%z%/Ac+=1
%z%a=%a:~1%
if %a%. neq . goto a
for /l %%n in (65,1,%m%)do (
if defined a%%n (call %z%r=%%r%%%%a%%n%%
)else %z%r=!r! )
echo %r%

Ruby, 68 bytes

->s{r,w="",-66;s.bytes{|b|r[(b+w+=1).times{|a|r[a]||=" "}]=b.chr};r}

Try it online!

IBM PC DOS8088 Assembly, 34 33 bytes

b403 cd10 be80 00ad 8bc8 32ed ac8b de02 d880 ebc4 8ad3 b402 cd10 b40e cd10 e2ec c3

Ungolfed (unassembled):

MOV  AH, 03H        ; get current cursor position row into DH
INT  10H
MOV  SI, 80H        ; point SI to PSP
LODSW               ; fetch length into AL, increment SI to 82H
MOV  CX, AX         ; move to CX
XOR  CH, CH         ; clear CH
OUTPUT:
LODSB               ; load DS:SI into AL
MOV  BX, SI         ; input string offset into BX (so doesn't overwrite DH)
SUB  BL, 'A'+83H    ; convert to numeric val (A=0, Z=25)
MOV  DL, BL         ; DL is column number
MOV  AH, 02H        ; BIOS set cursor position function
INT  10H            ; move to column
MOV  AH, 0EH        ; BIOS display char function in AL
INT  10H            ; write to screen
LOOP OUTPUT

This is a complete PC DOS executable that takes the input string from the command line and prints the new "faster" version to the screen. Requires a minimum of DOS 1.0... hopefully you've got at least that.

Output

A>SPEED.COM ABC
A B C
A>SPEED.COM AZ
A                         Z
A>SPEED.COM CBA
A
A>SPEED.COM HELLOWORLD
E H    DLL   OLO   R  W

PHP, 127 123 bytes

function b($i){for($q=0;$q<strlen($i);$q++){$n[ord($i[$q])-65]=$i[$q];}while($x++<26){$m.=$n[$x-1]?$n[$x-1]:" ";}return\$m;}

Try it online

Had to fix a bug that wouldn't output 'A'...

• To who-ever downvoted: You probably mis-clicked the up-button. Please correct, or drop me a line on why the downvote... Tnx Oct 13 '17 at 21:47