Строка Расстояние


28

Вызов

Учитывая ввод строчной буквы [a-z], выведите общее расстояние между буквами.

пример

Input: golf

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

Output: 17

правила

  • Стандартные лазейки запрещены
  • Это - самый короткий ответ в байтах выигрывает.
  • Алфавит может быть пройден в любом направлении. Вы всегда должны использовать кратчайший путь. (т.е. расстояние между xи cсоставляет 5).

1

Контрольные примеры

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35

Ответы:


11

Желе , 11 8 байт

OIæ%13AS

Сохранено 3 байта благодаря @ Martin Ender .

Попробуйте онлайн! или Проверьте все контрольные примеры.

объяснение

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

6
Я сталкивался æ%, читая встроенные модули на днях, и это было в значительной степени сделано для этой (типа) проблемы:OIæ%13AS
Мартин Эндер

Я думаю, что это 9 байтов ( æэто два).
Алексей Забродский

1
@elmigranto Jelly имеет кодовую страницу, которая кодирует каждый из его символов в один байт: github.com/DennisMitchell/jelly/wiki/Code-page
ruds

10

Haskell, 57 56 байт

q=map$(-)13.abs
sum.q.q.(zipWith(-)=<<tail).map fromEnum

Пример использования: sum.q.q.(zipWith(-)=<<tail).map fromEnum $ "valleys"-> 35.

Как это работает:

q=map$(-)13.abs                -- helper function.
                               -- Non-pointfree: q l = map (\e -> 13 - abs e) l
                               -- foreach element e in list l: subtract the
                               -- absolute value of e from 13

               map fromEnum    -- convert to ascii values
      zipWith(-)=<<tail        -- build differences of neighbor elements
  q.q                          -- apply q twice on every element
sum                            -- sum it up

Изменить: @Damien сохранил один байт. Благодарность!


спасибо за трюк с вращательным расстоянием ( q.q)
Лейф Виллертс

Ух ты хороший! Вы можете добавить mapв определение qна один байт меньше
Дэмиен

@Damien: хорошо заметили. Благодарность!
Ними

8

MATL , 14 , 10 байт

dt_v26\X<s

Попробуйте онлайн!

Спасибо @Suever за сохранение 4 байта!

Объяснение:

d           % Take the difference between consecutive characters
 t_         % Make a copy of this array, and take the negative of each element
   v        % Join these two arrays together into a matrix with height 2
    26\     % Mod 26 of each element
       X<   % Grab the minimum of each column
         s  % Sum these. Implicitly print

Предыдущая версия:

d26\t13>26*-|s

6

Python 3, 69 68 байт

lambda s:sum([13-abs(13-abs(ord(a)-ord(b)))for a,b in zip(s,s[1:])])

Сломать:

lambda s:
         sum(                                                      )
             [                             for a,b in zip(s,s[1:])]
              13-abs(13-abs(ord(a)-ord(b)))

1
Вы можете потерять один байт, удалив пробел раньшеfor
Даниэль

@ Dopapp О да, спасибо!
Busukxuan

2
Вы можете взять входные данные в виде списка символов и использовать рекурсию, чтобы сохранить 3 байта:f=lambda a,b,*s:13-abs(13-abs(ord(a)-ord(b)))+(s and f(b,*s)or 0)
Джонатан Аллан

5

Java, 126 120 117 байт

int f(String s){byte[]z=s.getBytes();int r=0,i=0,e;for(;++i<z.length;r+=(e=(26+z[i]-z[i-1])%26)<14?e:26-e);return r;}

Спасибо @KevinCruijssen за указание на ошибку в оригинальной версии и предложение сделать цикл for пустым.

Использование (26 + z[i] - z[i - 1]) % 26)вдохновлено комментарием @Neil к другому ответу. (26 + ...)%26служит той же цели, что и Math.abs(...)из-за ...? e : 26 - e.

Ungolfed :

int f(String s) {
    byte[]z = s.getBytes();
    int r = 0, i = 0, e;
    for (; ++i < z.length; r += (e = (26 + z[i] - z[i - 1]) % 26) < 14 ? e : 26 - e);
    return r;
}

Добро пожаловать на сайт! Что это за язык? Сколько это символов / байтов? Вы должны # [edit] those details into the top of your post, with this markdown: Язык, n байтов`
DJMcMayhem

Хорошо. Спасибо. Я редактировал это. Есть ли улучшения? :)
todeale

1
Вы пропускаете -раньше, чем eв вашей версии без золота.
Нил

2
Добро пожаловать в PPCG! Хм, я получаю «Несоответствие типа: не удается преобразовать из междунар в байт» ошибка в e=z[i]-z[i-1];Таким образом , вам необходимо либо бросок , чтобы (byte)или изменить eк int. Кроме того , вы можете удалить для петли-скобки, помещая все внутри для цикла, как это: int f(String s){byte[]z=s.getBytes();int r=0,i=0,e;for(;++i<z.length;r+=(e=z[i]-z[i-1])>0?e<14?e:26-e:-e<14?-e:e+26);return r;}(PS: Перевернутая для-петли , к сожалению , такая же длина: int f(String s){byte[]z=s.getBytes();int r=0,i=z.length-1,e;for(;i>0;r+=(e=z[i]-z[--i])>0?e<14?e:26-e:-e<14?-e:e+26);return r;}.
Кевин Cruijssen

1
Большое спасибо @KevinCruijssen: D. Ваше предложение очень помогло.
августа

3

JavaScript (ES6), 84 82 79 байтов

Сохранено 3 байта благодаря Cyoce:

f=([d,...s],p=parseInt,v=(26+p(s[0],36)-p(d,36))%26)=>s[0]?f(s)+(v>13?26-v:v):0

Объяснение:

f=(
  [d,...s],                    //Destructured input, separates first char from the rest
  p=parseInt,                  //p used as parseInt
  v=(26+p(s[0],36)-p(d,36))%26 //v is the absolute value of the difference using base 36 to get number from char
  )
)=>
  s[0]?                        //If there is at least two char in the input
    f(s)                       //sum recursive call
    +                          //added to
    (v>13?26-v:v)              //the current shortest path
  :                            //else
    0                          //ends the recursion, returns 0

Пример:
Вызов: f('golf')
Выход:17


Предыдущие решения:

82 байта благодаря Нейлу:

f=([d,...s],v=(26+parseInt(s[0],36)-parseInt(d,36))%26)=>s[0]?f(s)+(v>13?26-v:v):0

84 байта:

f=([d,...s],v=Math.abs(parseInt(s[0],36)-parseInt(d,36)))=>s[0]?f(s)+(v>13?26-v:v):0

1
Вместо Math.abs(...)тебя можно использовать (26+...)%26; это работает, потому что вы переворачиваете значения выше 13 в любом случае. (Я думаю, что так работает ответ MATL.)
Нил

1
Сохраните несколько байтов, добавив код p=parseInt;p()parseInt()
вперед,

3

Рубин, 73 байта

->x{eval x.chars.each_cons(2).map{|a,b|13-(13-(a.ord-b.ord).abs).abs}*?+}


2

05AB1E , 12 байтов

SÇ¥YFÄ5Ø-}(O

объяснение

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

Попробуйте онлайн!


Это 12 символов, а не байты. Длина байта будет 16 для UTF-8.
Алексей Забродский

@elmigranto: Действительно. В UTF-8 это было бы так, но 05AB1E использует CP-1252, где это 12 байтов.
Emigna

2

Perl, 46 байт

Включает +3 для -p(код содержит ')

Дайте ввод на STDIN без заключительного перевода строки:

echo -n zaza | stringd.pl

stringd.pl:

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

2

Ракетка 119 байт

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

Тестирование:

(f "golf")

Выход:

17

Подробная версия:

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

Вы можете заменить (define(f s)на (lambda(s)2 байта короче (анонимные функции в порядке).
Федерация с.

1
Подождите, Racket (λ(s)тоже должен взять , что если в utf8 6 байт, я думаю
fede s.

Сделано это. Спасибо.
rnso

2

C #, 87 85 байт

Улучшенное решение - заменил Math.Abs ​​() на трюк add & modulo, чтобы сохранить 2 байта:

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;};

Начальное решение:

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;};

Попробуйте онлайн!

Полный исходный код, включая контрольные примеры:

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
        }
    }
}

2

На самом деле, 21 байт

Основано частично на ответе Ruby cia_rana .

Была ошибка с O(в данном случае map ord () над строкой), из-за которой она не работала d(с удалением нижнего элемента) и p( с выталкиванием первого элемента) без предварительного преобразования карты в список с помощью #. Эта ошибка была исправлена, но, поскольку это исправление является более новым, чем эта проблема, я продолжил #.

Редактировать: И количество байтов было неправильным с сентября. Упс.

Предложения по игре в гольф приветствуются. Попробуйте онлайн!

O#;dX@pX♀-`A;úl-km`MΣ

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.

1

Java 7,128 байт

 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;
 }

1

Pyth, 20 байтов

Lm-13.adbsyy-M.:CMQ2

Программа, которая принимает ввод строки в кавычках в STDIN и печатает результат.

Попробуйте онлайн

Как это работает

Lm-13.adbsyy-M.:CMQ2  Program. Input: Q
L                     def y(b) ->
 m      b              Map over b with variable d:
  -13                   13-
     .ad                abs(d)
                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

1

dc + od, 65 байт

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

Объяснение:

Поскольку в dc вы не можете получить доступ к символам строки, я использовал od для получения значений ASCII. Они будут обработаны в обратном порядке из стека (LIFO-контейнер) следующим образом:

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

Бег:

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

Выход:

17

1

C 82 86 83 76 байтов

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;}

Предполагается, что длина входной строки не менее одного символа. Это не требует#include<stdlib.h>

Изменить: Argh, последовательность точек!

Попробуйте это на Ideone


в идеальном компиляторе строка "nwlrbb" и вся строка ранда, которую я пробую 6 len, возвращают все 0, но, кажется, не 0 результат ....
RosLuP

да, теперь кажется, что все в порядке ...
РосЛюП


1

Скала, 68 байт

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

Критика приветствуется.


1

C #, 217 байт

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;
  }
}

Выход:

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

«a» равно 97 при преобразовании в байты, поэтому 97 вычитается из каждого. Если разница больше 13 (т. Е. Половина алфавита), то вычтите различия между каждым символом (байтовым значением) из 26. Последнее добавление «return return» сэкономило мне несколько байтов!


1
Два бесполезных пробела: оба перед 's'.
Yytsi

0

Python 3, 126 байт

Со списком в понимании.

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]]))

Хороший ответ. Вы можете заменить abs(x-y), y-xтак как вызов sortedсделать x < y.
todeale

0

PHP, 79 байт

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

0

Java, 109 байт

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;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.