弦距


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

规则

  • 禁止标准漏洞
  • 这是 -最短的答案以字节为单位。
  • 可以从任一方向遍历字母。您必须始终使用最短路径。(即,距离之间xc为5)。

1个

测试用例

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35

Answers:


11

果冻11 8字节

OIæ%13AS

由于@ Martin Ender节省了3个字节。

在线尝试!验证所有测试用例。

说明

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
Martin Ender

我认为这是9个字节(æ是两个)。
Aleksei Zabrodskii

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
Leif Willerts

哇,真好!您可以添加少一个字节map的定义q
Damien 16'9

@Damien:发现得很好。谢谢!
nimi 2016年

8

MATL14,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
Daniel

@Dopapp哦,是的,谢谢!
busukxuan

2
您可以将输入作为字符列表,并使用递归保存3个字节:f=lambda a,b,*s:13-abs(13-abs(ord(a)-ord(b)))+(s and f(b,*s)or 0)
Jonathan Allan

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: #Language,n bytes`
DJMcMayhem

好。谢谢。我已经编辑了 有什么改善吗?:)
todeale

1
-在未e高尔夫版本中,您缺少前一个。
尼尔

2
欢迎来到PPCG!嗯,我收到“类型不匹配:无法从int转换为字节”错误,e=z[i]-z[i-1];因此您需要强制转换为(byte)或将更e改为int。:另外,您可以通过将所有for循环,这样内部取出的环支架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:颠倒的for循环是不幸的是,同样的长度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。您的建议很有帮助。
todeale

3

JavaScript(ES6),84 82 79字节

由于Cyoce,节省了3个字节:

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答案的工作方式。)
Neil

1
通过在代码前添加p=parseInt;,然后使用p()代替,以节省一些字节parseInt()
Cyoce 16'9

3

Ruby,73个字节

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

2

PHP,93字节

for(;++$i<strlen($s=$argv[1]);)$r+=13<($a=abs(ord($s[$i-1])-ord($s[$i])))?$a=26-$a:$a;echo$r;

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个符号,而不是字节。对于UTF-8,字节长度为16。
Aleksei Zabrodskii

@elmigranto:的确如此。在UTF-8中会是这种情况,但是05AB1E使用CP-1252(这是12个字节)。
Emigna '16

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个字节(可以使用匿名函数)。
fede s。

1
等一下,球拍应该(λ(s)也是如此,这如果UTF8是6个字节,我认为
FEDE秒。

做到了。谢谢。
rnso

2

C#,87 85字节

改进的解决方案- 用add&modulo技巧替换了Math.Abs​​()以节省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个位元组

部分基于cia_rana的Ruby答案

O(在这种情况下,将map ord()映射到字符串上)存在一个错误,该错误在未先使用将地图转换为列表的情况下无法与d(出队底部元素)和p(弹出第一个元素)一起使用#。该错误已得到修复,但由于此修复程序比此挑战要新,所以我一直坚持#

编辑:字节计数自9月以来是错误的。哎呀

欢迎打高尔夫球。在线尝试!

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

开球

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

不打高尔夫球

 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>

编辑:啊,序列点!

在Ideone上尝试


在ideone编译字符串“nwlrbb”和所有的字符串兰特我尝试6 LEN返回所有0,但它似乎不为0的结果....
RosLuP

是的现在看起来还不错...
RosLuP

1

C,70字节76字节

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

1

Scala,68个字节

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

欢迎批评。


1

C#,217个字节

打高尔夫球:

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

取消高尔夫:

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中减去每个字符之间的差异(字节值)。最后一刻添加的“ yield 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自调用sortedx < 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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.