Chuỗi khoảng cách


28

Thử thách

Đưa ra một đầu vào của một chuỗi chữ thường [a-z], xuất tổng khoảng cách giữa các chữ cái.

Thí dụ

Input: golf

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

Output: 17

Quy tắc

  • Sơ hở tiêu chuẩn bị cấm
  • Đây là - câu trả lời ngắn nhất trong byte thắng.
  • Bảng chữ cái có thể được đi qua từ một trong hai hướng. Bạn phải luôn luôn sử dụng con đường ngắn nhất. (tức là khoảng cách giữa xclà 5).

1

Các trường hợp thử nghiệm

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35

Câu trả lời:


11

Thạch , 11 8 byte

OIæ%13AS

Đã lưu 3 byte nhờ @ Martin Ender .

Hãy thử trực tuyến! hoặc Xác minh tất cả các trường hợp thử nghiệm.

Giải trình

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
Tôi đã đi qua æ%trong khi đọc qua các bản dựng sẵn vào một ngày khác, và nó đã được thực hiện khá nhiều cho vấn đề (loại) này:OIæ%13AS
Martin Ender

Tôi nghĩ rằng đây là 9 byte ( ælà hai).
Aleksei Zabrodskii

1
@elmigranto Jelly có một bảng mã mã hóa từng ký tự của nó trong một byte: github.com/DennisMitchell/jelly/wiki/Code-page
ruds

10

Haskell, 57 56 byte

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

Ví dụ sử dụng: sum.q.q.(zipWith(-)=<<tail).map fromEnum $ "valleys"-> 35.

Làm thế nào nó hoạt động:

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

Chỉnh sửa: @Damien lưu một byte. Cảm ơn!


cảm ơn về thủ thuật khoảng cách quay ( q.q)
Leif Willerts

Wow một cái tốt đẹp! Bạn có thể thêm mapvào định nghĩa qcho ít hơn một byte
Damien

@Damien: phát hiện tốt. Cảm ơn!
nimi

8

MATL , 14 , 10 byte

dt_v26\X<s

Hãy thử trực tuyến!

Cảm ơn @Suever đã lưu 4 byte!

Giải trình:

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

Phiên bản trước:

d26\t13>26*-|s

6

Python 3, 69 68 byte

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

Phá vỡ:

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

1
Bạn có thể mất một byte bằng cách xóa khoảng trắng trướcfor
Daniel

@Dopapp ơi, cảm ơn!
busukxuan

2
Bạn có thể lấy đầu vào làm danh sách các ký tự và sử dụng đệ quy để lưu 3 byte: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 byte

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

Cảm ơn @KevinCruijssen đã chỉ ra một lỗi trong phiên bản gốc và đề nghị làm cho vòng lặp for trống.

Việc sử dụng (26 + z[i] - z[i - 1]) % 26)được lấy cảm hứng từ một bình luận của @Neil về một câu trả lời khác. (26 + ...)%26phục vụ cùng một mục đích Math.abs(...)...? e : 26 - e.

Ung dung :

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

Chào mừng đến với trang web! Ngôn ngữ này là gì? Có bao nhiêu ký tự / byte? Bạn nên [edit] those details into the top of your post, with this markdown: # Ngôn ngữ, n byte`
DJMcMayhem

Được. Cảm ơn. Tôi đã chỉnh sửa nó. Có cải thiện gì không? :)
todeale

1
Bạn đang thiếu một -trước một etrong phiên bản vô danh của bạn.
Neil

2
Chào mừng đến với PPCG! Hmm, tôi đang gặp lỗi "Loại không khớp: không thể chuyển đổi từ int sang byte" tại e=z[i]-z[i-1];Vì vậy, bạn cần phải truyền (byte)hoặc thay đổi ethành int. Ngoài ra, bạn có thể xóa dấu ngoặc cho vòng lặp bằng cách đặt mọi thứ bên trong vòng lặp for, như thế này: 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: Vòng lặp for không may có cùng độ dài : 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;}.
Kevin Cruijssen

1
Cảm ơn rất nhiều @KevinCruijssen: D. Đề nghị của bạn đã giúp rất nhiều.
todeale

3

JavaScript (ES6), 84 82 79 byte

Đã lưu 3 byte nhờ 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

Giải trình:

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

Ví dụ:
Gọi: f('golf')
Đầu ra:17


Giải pháp trước đây:

82 byte nhờ Neil:

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

84 byte:

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

1
Thay vì Math.abs(...)bạn có thể sử dụng (26+...)%26; điều này hoạt động vì dù sao bạn cũng lật các giá trị trên 13. (Tôi nghĩ rằng đây là cách câu trả lời MATL hoạt động.)
Neil

1
Lưu một số byte bằng cách thêm mã vào p=parseInt;và sau đó sử dụng p()thay vìparseInt()
Cyoce

3

Ruby, 73 byte

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

2

PHP, 93 byte

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 byte

SÇ¥YFÄ5Ø-}(O

Giải trình

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

Hãy thử trực tuyến!


Đó là 12 ký hiệu, không phải byte. Độ dài byte sẽ là 16 đối với UTF-8.
Aleksei Zabrodskii

@elmigranto: Thật vậy. Trong UTF-8 đó là trường hợp, nhưng 05AB1E sử dụng CP-1252 trong đó đây là 12 byte.
Emigna

2

Perl, 46 byte

Bao gồm +3 cho -p(mã chứa' )

Cung cấp đầu vào trên STDIN mà không có dòng mới:

echo -n zaza | stringd.pl

stringd.pl:

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

2

Vợt 119 byte

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

Kiểm tra:

(f "golf")

Đầu ra:

17

Phiên bản chi tiết:

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

Bạn có thể thay thế (define(f s)bằng (lambda(s), ngắn hơn 2 byte (các hàm ẩn danh vẫn ổn).
fede s.

1
Đợi đã, vợt cũng nên mất (λ(s), mà nếu trong utf8 là 6 byte tôi nghĩ
fede s.

Làm xong mà. Cảm ơn.
rnso

2

C #, 87 85 byte

Giải pháp cải tiến - đã thay thế Math.Abs ​​() bằng thủ thuật add & modulo để lưu 2 byte:

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

Giải pháp ban đầu :

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

Hãy thử trực tuyến!

Nguồn đầy đủ, bao gồm các trường hợp thử nghiệm:

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

Trên thực tế, 21 byte

Dựa một phần vào câu trả lời Ruby của cia_rana .

Có một lỗi với O(trong trường hợp này là map ord () trên một chuỗi) trong đó nó không hoạt động với d(phần tử dưới cùng dequeue) và p(phần tử đầu tiên pop) mà không chuyển đổi bản đồ thành danh sách trước #. Lỗi này đã được sửa, nhưng vì sửa lỗi đó mới hơn thử thách này, nên tôi đã tiếp tục #.

Chỉnh sửa: Và số byte đã sai từ tháng Chín. Rất tiếc.

Gợi ý chơi golf chào mừng. Hãy thử trực tuyến!

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 byte

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

Bị đánh cắp

 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

Bình thường, 20 byte

Lm-13.adbsyy-M.:CMQ2

Một chương trình lấy đầu vào của một chuỗi được trích dẫn trên STDIN và in kết quả.

Dùng thử trực tuyến

Làm thế nào nó hoạt động

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 byte

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

Giải trình:

Bởi vì trong dc bạn không thể truy cập các ký tự của chuỗi, tôi đã sử dụng od để nhận các giá trị ASCII. Chúng sẽ được xử lý theo thứ tự ngược từ ngăn xếp (thùng chứa LIFO) như sau:

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

Chạy:

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

Đầu ra:

17

1

C, 82 86 83 76 byte

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

Giả sử chuỗi đầu vào dài ít nhất một ký tự. Điều này không cần#include<stdlib.h>

Chỉnh sửa: Argh, điểm thứ tự!

Hãy thử nó trên Ideone


trong trình biên dịch ideone, chuỗi "nwlrbb" và tất cả chuỗi rand tôi thử 6 len trả về tất cả 0 nhưng có vẻ như không phải là 0 kết quả ....
RosLuP

vâng, bây giờ có vẻ ổn ...
RosLuP

1

C, 70 byte 76 byte

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

1

Scala, 68 byte

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

Phê bình được chào đón.


1

C #, 217 byte

Chơi gôn

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

Ung dung:

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

Đầu ra:

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

'a' là 97 khi được chuyển đổi thành byte, do đó 97 bị trừ đi từ mỗi byte. Nếu chênh lệch lớn hơn 13 (tức là một nửa của bảng chữ cái), thì trừ đi sự khác biệt giữa mỗi ký tự (giá trị byte) từ 26. Một lần thêm vào "lợi nhuận cuối cùng" đã tiết kiệm cho tôi một vài byte!


1
Hai khoảng trắng vô dụng: cả trước 's'.
Yytsi

0

Python 3, 126 byte

Với danh sách trong hiểu.

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

Câu trả lời tốt đẹp. Bạn có thể thay thế abs(x-y)bởi y-xvì cuộc gọi để sortedthực hiện x < y.
todeale

0

PHP, 79 byte

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

0

Java, 109 byte

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.