Jarak Tali

28

Tantangan

Diberikan input dari string semua-huruf kecil [a-z], output jarak total antara huruf.

Contoh

Input: golf

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

Output: 17

Aturan

  • Celah standar dilarang
  • Ini adalah - jawaban terpendek dalam byte yang menang.
  • Alfabet dapat dilintasi dari kedua arah. Anda harus selalu menggunakan jalur terpendek. (Yaitu jarak antara xdan c5).

1

Uji kasus

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35
Daniel
sumber

Jawaban:

11

Jelly , 11 8 byte

OIæ%13AS

Disimpan 3 byte berkat @ Martin Ender .

Cobalah online! atau Verifikasi semua kasus uji.

Penjelasan

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
mil
sumber
6
Saya menemukan æ%saat membaca built-in hari yang lain, dan itu cukup banyak dibuat untuk masalah (jenis) ini:OIæ%13AS
Martin Ender
Saya pikir ini adalah 9 byte ( ædua).
Aleksei Zabrodskii
1
@elmigranto Jelly memiliki codepage yang menyandikan setiap karakternya dalam satu 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

Contoh penggunaan: sum.q.q.(zipWith(-)=<<tail).map fromEnum $ "valleys"-> 35.

Bagaimana itu bekerja:

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

Sunting: @Damien menyimpan satu byte. Terima kasih!

nimi
sumber
terima kasih untuk trik jarak rotasi ( q.q)
Leif Willerts
Wow, bagus! Anda dapat menambahkan mapdefinisi kurang dari qsatu byte
Damien
@ Damen: terlihat dengan baik. Terima kasih!
nimi
8

MATL , 14 , 10 byte

dt_v26\X<s

Cobalah online!

Terima kasih @Suever karena telah menghemat 4 byte!

Penjelasan:

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

Versi sebelumnya:

d26\t13>26*-|s
DJMcMayhem
sumber
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:])])

Kerusakan:

lambda s:
         sum(                                                      )
             [                             for a,b in zip(s,s[1:])]
              13-abs(13-abs(ord(a)-ord(b)))
busukxuan
sumber
1
Anda dapat kehilangan satu byte dengan menghapus spasi sebelumnyafor
Daniel
@Dappapp Oh ya, terima kasih!
busukxuan
2
Anda dapat mengambil input sebagai daftar karakter dan menggunakan rekursi untuk menghemat 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;}

Terima kasih kepada @KevinCruijssen karena menunjukkan bug dalam versi asli dan menyarankan untuk membuat for-loop kosong.

Penggunaan (26 + z[i] - z[i - 1]) % 26)terinspirasi dari komentar oleh @Neil pada jawaban lain. (26 + ...)%26melayani tujuan yang sama Math.abs(...)karena ...? e : 26 - e.

Tidak Terkumpul :

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;
}
Todeale
sumber
Selamat datang di situs ini! Bahasa apa ini? Berapa banyak karakter / byte? Anda harus [edit] those details into the top of your post, with this markdown: #Language, n bytes`
DJMcMayhem
Baik. Terima kasih. Saya sudah mengeditnya. Adakah perbaikan? :)
todeale
1
Anda kehilangan tanda -sebelum edalam versi yang tidak dikoleksi.
Neil
2
Selamat datang di PPCG! Hmm, saya mendapatkan "Ketidakcocokan tipe: tidak dapat mengkonversi dari int ke byte" di e=z[i]-z[i-1];Jadi Anda juga perlu pemain untuk (byte)atau mengubah eke int. Juga, Anda dapat menghapus untuk loop kurung dengan menempatkan segala sesuatu di dalam untuk loop, seperti ini: 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: The terbalik untuk loop sayangnya sama panjang: 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
Terima kasih banyak @KevinCruijssen: D. Saran Anda telah banyak membantu.
todeale
3

JavaScript (ES6), 84 82 79 byte

Disimpan 3 byte berkat 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

Penjelasan:

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

Contoh:
Panggilan: f('golf')
Keluaran:17


Solusi sebelumnya:

82 byte berkat 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
Hedi
sumber
1
Alih-alih Math.abs(...)Anda bisa menggunakan (26+...)%26; ini berhasil karena Anda membalik nilai di atas 13. (Saya pikir ini adalah bagaimana jawaban MATL bekerja.)
Neil
1
Simpan beberapa byte dengan mengawali kode dengan p=parseInt;dan kemudian menggunakan p()alih-alihparseInt()
Cyoce
3

Ruby, 73 byte

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

PHP, 93 Bytes

for(;++$i<strlen($s=$argv[1]);)$r+=13<($a=abs(ord($s[$i-1])-ord($s[$i])))?$a=26-$a:$a;echo$r;
Jörg Hülsermann
sumber
2

05AB1E , 12 byte

SÇ¥YFÄ5Ø-}(O

Penjelasan

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

Cobalah online!

Emigna
sumber
Ini 12 simbol, bukan byte. Panjang Byte adalah 16 untuk UTF-8.
Aleksei Zabrodskii
@elmigranto: Memang. Dalam UTF-8 itu akan terjadi, tetapi 05AB1E menggunakan CP-1252 di mana ini adalah 12 byte.
Emigna
2

Perl, 46 byte

Termasuk +3 untuk -p(kode berisi ')

Berikan masukan pada STDIN tanpa baris akhir final:

echo -n zaza | stringd.pl

stringd.pl:

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

Racket 119 byte

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

Pengujian:

(f "golf")

Keluaran:

17

Versi detail:

(define(f s)
  (for/sum((i(sub1(string-length s))))
    (abs(-(char->integer(string-ref s i))
          (char->integer(string-ref s(+ 1 i)))))))
juga
sumber
Anda dapat mengganti (define(f s)dengan (lambda(s), 2 byte lebih pendek (fungsi anonim baik-baik saja).
fede s.
1
Tunggu, Racket juga harus mengambil (λ(s), yang jika di utf8 adalah 6 byte saya pikir
fede s.
Selesai itu. Terima kasih.
rnso
2

C #, 87 85 byte

Solusi yang ditingkatkan - menggantikan Math.Abs ​​() dengan trik add & modulo untuk menghemat 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;};

Solusi awal :

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

Cobalah online!

Sumber lengkap, termasuk uji kasus:

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
        }
    }
}
adrianmp
sumber
2

Sebenarnya, 21 byte

Didasarkan sebagian pada jawaban Ruby cia_rana .

Ada bug dengan O(dalam hal ini, peta ord () di atas string) di mana ia tidak akan bekerja dengan d(elemen bawah dequeue) dan p(elemen pertama pop) tanpa terlebih dahulu mengubah peta ke daftar #. Bug ini telah diperbaiki, tetapi karena perbaikannya lebih baru daripada tantangan ini, maka saya tetap menyimpannya #.

Sunting: Dan jumlah byte sudah salah sejak September. Aduh.

Saran bermain golf diterima. Cobalah online!

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

Tidak melakukanolf

         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.
Sherlock9
sumber
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;}

Tidak disatukan

 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;
 }
Numberknot
sumber
1

Pyth, 20 byte

Lm-13.adbsyy-M.:CMQ2

Program yang mengambil input dari string yang dikutip pada STDIN dan mencetak hasilnya.

Cobalah online

Bagaimana itu bekerja

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
TheBikingViking
sumber
1

dc + od, 65 byte

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

Penjelasan:

Karena di dc Anda tidak dapat mengakses karakter string, saya menggunakan od untuk mendapatkan nilai ASCII. Ini akan diproses dalam urutan terbalik dari tumpukan (wadah LIFO) seperti:

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

Menjalankan:

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

Keluaran:

17
seshoumara
sumber
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;}

Mengasumsikan string input setidaknya satu karakter. Ini tidak perlu#include<stdlib.h>

Sunting: Argh, titik urutan!

Cobalah di Ideone

plafon
sumber
dalam ideone compiler string "nwlrbb" dan semua string rand saya coba 6 len kembalikan semua 0 tetapi tampaknya bukan 0 hasilnya ....
RosLuP
ya sekarang sepertinya ok ...
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;}
NoSeatbelts
sumber
1

Scala, 68 byte

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

Kritik dipersilahkan.

Himself12794
sumber
1

C #, 217 byte

Golf:

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

Tidak Terkumpul:

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

Keluaran:

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

'a' adalah 97 ketika dikonversi ke byte, jadi 97 dikurangkan dari masing-masing. Jika perbedaannya lebih besar dari 13 (yaitu, setengah dari alfabet), maka kurangi perbedaan antara masing-masing karakter (nilai byte) dari 26. Tambahan menit terakhir "hasil pengembalian" menyelamatkan saya beberapa byte!

Pete Arden
sumber
1
Dua ruang putih yang tidak berguna: keduanya sebelum 's'.
Yytsi
0

Python 3, 126 byte

Dengan daftar di pemahaman.

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]]))
edelbitter
sumber
Jawaban bagus. Anda dapat mengganti abs(x-y)dengan y-xsejak panggilan sorteddibuat 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;
Titus
sumber
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;
Ekeko
sumber