# Challenge

Given an input of an all-lowercase string [a-z], output the total distance between the letters.

## Example

Input: golf

Distance from g to o : 8
Distance from o to l : 3
Distance from l to f : 6

Output: 17

## Rules

• Standard loopholes forbidden
• This is - shortest answer in bytes wins.
• The alphabet can be traversed from either direction. You must always use the shortest path. (i.e the distance between x and c is 5).

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35

# Jelly, 11 8 bytes

OIæ%13AS

Saved 3 bytes thanks to @Martin Ender.

## Explanation

OIæ%13AS  Input: string Z
O         Ordinal. Convert each char in Z to its ASCII value
I        Increments. Find the difference between each pair of values
æ%13    Symmetric mod. Maps each to the interval (-13, 13]
A   Absolute value of each
S  Sum
Return implicitly
• I came across æ% while reading through the built-ins the other day, and it was pretty much made for this (type of) problem: OIæ%13AS – Martin Ender Sep 17 '16 at 15:44
• I think this is 9 bytes (æ is two). – Aleksei Zabrodskii Sep 18 '16 at 9:48
• @elmigranto Jelly has a codepage that encodes each of its characters in one byte: github.com/DennisMitchell/jelly/wiki/Code-page – ruds Sep 18 '16 at 15:54

q=map$(-)13.abs sum.q.q.(zipWith(-)=<<tail).map fromEnum Usage example: sum.q.q.(zipWith(-)=<<tail).map fromEnum$ "valleys" -> 35.

How it works:

# 05AB1E, 12 bytes

SÇ¥YFÄ5Ø-}(O

Explanation

SÇ                   # convert to list of ascii values
¥                  # take delta's
YF    }           # 2 times do
Ä5Ø-            # for x in list: abs(x) - 13
(O         # negate and sum

Try it online!

• It's 12 symbols, not bytes. Byte-length would be 16 for UTF-8. – Aleksei Zabrodskii Sep 18 '16 at 9:49
• @elmigranto: Indeed. In UTF-8 that would be the case, but 05AB1E uses CP-1252 where this is 12 bytes. – Emigna Sep 18 '16 at 10:06

# Perl, 46 bytes

Includes +3 for -p (code contains ')

Give input on STDIN without final newline:

echo -n zaza | stringd.pl

stringd.pl:

#!/usr/bin/perl -p
s%.%$\+=13-abs 13-abs ord($&)-ord$'.$&%eg}{

## Racket 119 bytes

(λ(s)(for/sum((i(sub1(string-length s))))(abs(-(char->integer
(string-ref s i))(char->integer(string-ref s(+ 1 i)))))))

Testing:

(f "golf")

Output:

17

Detailed version:

(define(f s)
(for/sum((i(sub1(string-length s))))
(abs(-(char->integer(string-ref s i))
(char->integer(string-ref s(+ 1 i)))))))
• You could replace (define(f s) with (lambda(s), 2 bytes shorter (anonymous functions are fine). – fede s. Sep 17 '16 at 21:15
• Wait, Racket should take (λ(s) too, which if in utf8 is 6 bytes i think – fede s. Sep 17 '16 at 21:17
• Done that. Thanks. – rnso Sep 17 '16 at 23:27

# C#, 87 85 bytes

Improved solution - replaced Math.Abs() with the add & modulo trick to save 2 bytes:

s=>{int l=0,d,i=0;for(;i<s.Length-1;)l+=(d=(s[i]-s[++i]+26)%26)>13?26-d:d;return l;};

Initial solution:

s=>{int l=0,d,i=0;for(;i<s.Length-1;)l+=(d=Math.Abs(s[i]-s[++i]))>13?26-d:d;return l;};

Try it online!

Full source, including test cases:

using System;

namespace StringDistance
{
class Program
{
static void Main(string[] args)
{
Func<string,int>f= s=>{int l=0,d,i=0;for(;i<s.Length-1;)l+=(d=Math.Abs(s[i]-s[++i]))>13?26-d:d;return l;};

Console.WriteLine(f("golf"));   //17
Console.WriteLine(f("aa"));     //0
Console.WriteLine(f("stack"));  //18
Console.WriteLine(f("zaza"));   //3
Console.WriteLine(f("valleys"));//35
}
}
}

# Actually, 21 bytes

Based partially on cia_rana's Ruby answer.

There was a bug with O (in this case, map ord() over a string) where it would not work with d (dequeue bottom element) and p (pop first element) without first converting the map to a list with #. This bug has been fixed, but as that fix is newer than this challenge, so I've kept # in.

Edit: And the byte count has been wrong since September. Whoops.

Golfing suggestions welcome. Try it online!

O#;dX@pX♀-A;úl-kmMΣ

Ungolfing

Implicit input string.
The string should already be enclosed in quotation marks.
O#       Map ord() over the string and convert the map to a list. Call it ords.
;        Duplicate ords.
dX       Dequeue the last element and discard it.
@        Swap the with the duplicate ords.
pX       Pop the last element and discard it. Stack: ords[:-1], ords[1:]
♀-       Subtract each element of the second list from each element of the first list.
This subtraction is equivalent to getting the first differences of ords.
...`M   Map the following function over the first differences. Variable i.
A;       abs(i) and duplicate.
úl       Push the lowercase alphabet and get its length. A golfy way to push 26.
-        26-i
k        Pop all elements from stack and convert to list. Stack: [i, 26-i]
m        min([i, 26-i])
Σ        Sum the result of the map.
Implicit return.

# Java 7,128 bytes

int f(String s){char[]c=s.toCharArray();int t=0;for(int i=1,a;i<c.length;a=Math.abs(c[i]-c[i++-1]),t+=26-a<a?26-a:a);return t;}

# Ungolfed

int f(String s){
char[]c=s.toCharArray();
int t=0;
for(int i=1,a;
i<c.length;
a=Math.abs(c[i]-c[i++-1]),t+=26-a<a?26-a:a);
return t;
}

# Pyth, 20 bytes

A program that takes input of a quoted string on STDIN and prints the result.

Try it online

How it works

L                     def y(b) ->
m      b              Map over b with variable d:
-13                   13-
CMQ   Map code-point over Q
.:   2  All length 2 sublists of that
-M        Map subtraction over that
yy          y(y(that))
s            Sum of that
Implicitly print

## dc + od, 65 bytes

od -tuC|dc -e'?dsN0sT[lNrdsNr-d*vdD[26-]sS<Sd*vlT+sTd0<R]dsRxlTp'

Explanation:

Because in dc you can't access a string's characters, I used od to get the ASCII values. These will be processed in reverse order from the stack (LIFO container) like so:

dsN0sT             # initialize N (neighbor) = top ASCII value, and T (total) = 0
[lNrdsNr-          # loop 'R': calculate difference between current value and N,
#updating N (on the first iteration the difference is 0)
d*vdD[26-]sS<S  # get absolute value (d*v), push 13 (D) and call 'S' to subtract
#26 if the difference is greater than 13
d*vlT+sT        # get absolute value again and add it to T
d0<R]dsR           # repeat loop for the rest of the ASCII values
xlTp               # the main: call 'R' and print T at the end

Run:

echo -n "golf" | ./string_distance.sh

Output:

17

# C, 82 86 83 76 bytes

t,u;f(char*s){for(t=0;*++s;u=*s-s[-1],t+=(u=u<0?-u:u)>13?26-u:u);return t;}

Assumes input string is at least one character long. This doesn't require #include<stdlib.h>

Edit: Argh, sequence points!

Try it on Ideone

• in ideone compiler the string "nwlrbb" and all the rand string i try 6 len return all 0 but it seems not 0 the result.... – user58988 Sep 23 '16 at 8:56
• yes now it seems ok... – user58988 Sep 23 '16 at 23:02

# C, 70 bytes 76 bytes

k,i;f(char *s){for(i=0;*++s;i+=(k=abs(*s-s[-1]))>13?26-k:k);return i;}

# Scala, 68 bytes

def f(s:String)=(for(i<-0 to s.length-2)yield (s(i)-s(i+1)).abs).sum

Criticism is welcome.

# C#, 217 bytes

Golfed:

IEnumerable<int>g(string k){Func<Char,int>x=(c)=>int.Parse(""+Convert.ToByte(c))-97;for(int i=0;i<k.Length-1;i++){var f=x(k[i]);var s=x(k[i+1]);var d=Math.Abs(f-s);yield return d>13?26-Math.Max(f,s)+Math.Min(f,s):d;}}

Ungolfed:

IEnumerable<int> g(string k)
{
Func<Char, int> x = (c) => int.Parse("" + Convert.ToByte(c)) - 97;
for (int i = 0; i < k.Length - 1; i++)
{
var f = x(k[i]);
var s = x(k[i + 1]);
var d = Math.Abs(f - s);
yield return d > 13 ? 26 - Math.Max(f, s) + Math.Min(f, s) : d;
}
}

Output:

aa: 0
stack: 18
zaza: 3
valleys: 35

'a' is 97 when converted to bytes, so 97 is subtracted from each one. If the difference is greater than 13 (ie, half of the alphabet), then subtract the differences between each character (byte value) from 26. A last minute addition of "yield return" saved me a few bytes!

• Two useless whitespaces: both before 's'. – Yytsi Oct 27 '16 at 17:03

# Python 3, 126 bytes

With list incomprehension.

d=input()
print(sum([min(abs(x-y),x+26-y)for x,y in[map(lambda x:(ord(x)-97),sorted(d[i:i+2]))for i in range(len(d))][:-1]]))
• Nice answer. You could replace abs(x-y) by y-x since the call to sorted make x < y. – todeale Sep 24 '16 at 7:58

# PHP, 79 bytes

for($w=$argv[1];$w[++$i];)$s+=13-abs(13-abs(ord($w[$i-1])-ord($w[$i])));echo$s;

# Java, 109 bytes

int f(String s){int x=0,t,a=0;for(byte b:s.getBytes()){t=a>0?(a-b+26)%26:0;t=t>13?26-t:t;x+=t;a=b;}return x;