# Alphabet Position Finder

Inspired by the Codewars Kata.

Your goal is to take an input string such as this one:

"'Twas a dark and stormy night..."

and return a string containing the position of each character in the alphabet, separated by spaces and ignoring non-alphabetical characters, like this:

"20 23 1 19 1 4 1 18 11 1 14 4 19 20 15 18 13 25 14 9 7 8 20"

For an additional challenge, you can replace any numerical characters in the original string with themselves + 27. For example, "25" would become "29, 32". This is completely optional.

You must use 1-indexing ('a'==1, 'b'==2, etc)

• You must return a string, not an array.

• Trailing whitespace is OK.

The winner has the lowest byte count.

Good luck!

• closely related – Giuseppe May 31 '18 at 9:14
• @TheoC Why? The general consensus is that answers should be able to output in any reasonable format, as it may add too much bloat and make it unfair to languages who can join by spaces in a shorter way. – Okx May 31 '18 at 9:42
• @TheoC Why don't you just allow both? – Okx May 31 '18 at 9:54
• Welcome to PPCG! This is a decent challenge overall, but for next time you post a challenge, here are some things to keep in mind. 1) This challenge is pretty simple. I think it would be more interesting if the optional part was mandatory (note, don't change that part now, it's too late). 2) You're pretty restrictive about some arbitrary parts. Why not allow an array? It's our standards than an array of characters is a string. I would recommend reading through this thread for ideas. – James May 31 '18 at 16:37
• Future notes: 1 and 0 indexing are usually one and the same, and both are usually allowed. Also, constraining output formats is frowned upon. If it's a list of values let the language decide the format. The challenge isn't about formatting output nor is it about shifting indices. Therefore, it shouldn't be a constraint when you could just allow languages to do what they'd do naturally and focus on the challenge intent. – Magic Octopus Urn May 31 '18 at 21:17

# PHP, 61 bytes

works in any PHP version from 4.0.4 to 7.2 (but might cease to work in 7.3)

while(~$c=$argn[$i++])ctype_alpha($c)&&print(ord(\$c)&31)." ";

Run as pipe with -nr or try it online.

## ABAP, 228 bytes, letters only

I wrote a FORM subroutine for an ABAP report. i is input, o is output.

FORM h USING i o.TRANSLATE i TO UPPER CASE.DO strlen( i ) TIMES.data c(2).c = sy-index - 1.FIND i+c(1) IN 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' RESULTS data(r).CHECK sy-subrc = 0.c = r-offset + 1.CONCATENATE o c   INTO o.ENDDO.ENDFORM.

Verbose code:
Look at it on Pastebin.com for syntax highlighting. (Not that it looks much better)

"This stuff is used to actually run the program, call the form and output the results.
REPORT z.
PARAMETERS se_input TYPE string.
START-OF-SELECTION.
DATA ret type string.
PERFORM h USING se_input ret.
WRITE ret.

"---- CODE STARTS HERE ----
FORM f USING i o.              "Two parameters: i for input, o for output.
TRANSLATE i TO UPPER CASE. "All to uppercase
DO strlen( i ) TIMES.      "Do for each character
data c(2).             "A char field, length of 2
c = sy-index - 1.      "Current loop index - 1 = index in string. Loop index starts at 1.
FIND i+c(1)            "Find substring: input at position index, length 1...
IN 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' RESULTS data(r). "...in the alphabet, save to "r"
CHECK sy-subrc = 0.    "sy-subrc <> 0 => not in the alphabet, skips the rest of this loop (same as CONTINUE)
c = r-offset + 1.      "r-offset is the index in the string, add one for alphabet position
CONCATENATE o c   INTO o. "Concatenate it all into the output chars, including the literal space.
"      ^- had I used ' ' here, CONCATENATE would remove blank space, but   stays untouched.
ENDDO. "Loop end
ENDFORM.   "FORM end

### Notes, thoughts, background stuff

First of all, no, I did not miss spaces in my code. ABAP wants them and will not run without them...

The USING parameters i and o are of unknown type, so the program calling the FORM must use a string (or char field with at least length of input * 3: 2 characters + space per letter) for o, otherwise results can be cut off or it all just dumps right away if it's a numeric value for example.

I saved a few bytes here by re-using the same character field over and over again, abusing the fact that ABAP implicitly converts numbers to chars and vice versa without any issues. This is especially better than using the CONDENSE <var> statement, which was initially necessary to not have my integers padded to 26 characters width.

Getting substrings in ABAP is super quick and easy once you get used to it:
substring = string+offset(length).
Thanks to the implicit conversion, offset can be even a character field. Nasty, but great for us in this case. But be careful: While string+5 gives you the substring starting from index 5, string + 5 will try to cast your string to a number and add 5. Spaces matter!

There's also an easy way to convert the character to a byte value, giving me the ASCII code and removing the need to do the lengthy FIND IN ... stuff, but on a Unicode SAP system there's no quick and dirty way to convert that byte value into a "readable" number that I know of, so it's kind of a red herring.

By the way: TRANSLATE i TO UPPER CASE. is exactly 26 bytes long, so at first glance it looks like we don't even need it and can just add the lowercase letters to the alphabet string instead. But you probably realized right away why we can't do that. ;-)

## ABAP, 238 bytes, alphanumeric

For the alphanumeric version we just add 0123456789 to the alphabet string, hence increasing the length of the code by 10 bytes. Not very interesting, but any other approach would just be longer thanks to the very, uhm, verbose language that ABAP is.

FORM h USING i o.TRANSLATE i TO UPPER CASE.DO strlen( i ) TIMES.data c(2).c = sy-index - 1.FIND i+c(1) IN 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' RESULTS data(r).CHECK sy-subrc = 0.c = r-offset + 1.CONCATENATE o c   INTO o.ENDDO.ENDFORM.

I hope my explanation is somewhat interesting. Thanks for the challenge!

# [C (gcc)], 57 56 bytes (printing), 70 69 bytes (printing w/optional), 146 bytes (string)

Thanks to ceilingcat for the && optimization.

f(char*s){for(;*s;s++)isalpha(*s)&&printf("%d ",*s&31);}

Try it online!

This version takes alphanumeric text per the additional challenge:

f(char*s){for(;*s;s++)isalnum(*s)&&printf("%d ",(*s<65)*10+(*s&31));}

Try it online!

If returning a string is required for this challenge:

char*f(s,t,u,i)char*s,*t,*u;{for(i=strlen(s)*4,t=calloc(i,2),u=t+i;*s;s++)isalnum(*s)?sprintf(u,"%d ",(*s<65)*10+(*s&31)),strcat(t,u):0;return t;}

Try it online!

import Data.Char
unwords.map(show.(mod32).ord).filter isAlpha

Try it online!

• Currently this only converts uppercase letters, you need isAlpha instead of isUpper. – Laikoni Jun 22 '18 at 11:01
• @Laikoni I don't know how I failed to notice that... – Esolanging Fruit Jun 22 '18 at 16:10
• 62 bytes and a less insane header: Try it online! – Laikoni Jun 22 '18 at 19:51

# Ruby, 41 bytes

->s{s.scan(/\p{L}/).map{|i|i.ord%32}*' '}

Try it online!

• [A-z] is too wide, it includes underscores and other stuff. – G B Jun 22 '18 at 6:54
• @GB fixed at no extra cost – Asone Tuhid Jun 23 '18 at 12:01

# Ruby, 97 bytes

n=[];gets.chomp.gsub(/[^a-zA-Z]/,'').upcase.bytes.each{|i|n.push i-64};puts n.map(&:to_i).join" "

Try it online!

# Lua (5.3), 94 bytes

x=...y=""for i=1,#x do z=x:sub(i,i)y=y..(z:find"%a"and(z:byte()&~32)-64 .." "or"")end print(y)

Try it online!

# CJam, 23 15 bytes

qel_eu-{i32%S}/

Try it online!

Saved 8 bytes thanks to Esolanging Fruit

• q{el_eu-},{i32%S}/ works. – Esolanging Fruit Jun 22 '18 at 6:53
• Nice solution! I managed to golf it down a bit more – maxb Jun 25 '18 at 6:08