ระยะทางสตริง


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 ไบต์ด้วย @มาร์ตินเอนเดอร์

ลองออนไลน์!หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย

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 วุ้นมีเพจที่เข้ารหัสตัวละครแต่ละตัวในหนึ่งไบต์: 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: ด่างดี ขอบคุณ!
nimi

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
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-loop ว่างเปล่า

การใช้(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ในเวอร์ชันที่ไม่ได้รับการอวดของคุณ
Neil

2
ยินดีต้อนรับสู่ PPCG! อืมฉันได้รับ "ชนิดไม่ตรงกัน: ไม่สามารถแปลงจาก int เพื่อไบต์" ข้อผิดพลาดที่e=z[i]-z[i-1];ดังนั้นคุณอาจต้องโยนไป(byte)หรือเปลี่ยนไปe intนอกจากนี้คุณสามารถลบวงเล็บสำหรับห่วงโดยวางทุกอย่างไว้ใน for-loop เช่นนี้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-loop นั้นน่าเสียดายที่มีความยาวเท่ากัน: 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
ขอบคุณมาก @KevinCruijssen: D ข้อเสนอแนะของคุณช่วยได้มาก
todeale

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 ไบต์ขอบคุณ 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 ไบต์:

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



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
Aleksei Zabrodskii

@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 ไบต์สั้นลง (ฟังก์ชั่นที่ไม่ระบุชื่อเป็นเรื่องปกติ)
fede s

1
รอแร็กเก็ตควรใช้(λ(s)ด้วยซึ่งถ้าใน utf8 คือ 6 ไบต์ฉันคิดว่า
fede s

เสร็จแล้ว ขอบคุณ
rnso

2

C #, 87 85 ไบต์

วิธีแก้ปัญหาที่ดีขึ้น - แทนที่ Math.Abs ​​() ด้วยเคล็ดลับการเพิ่ม & 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(ในกรณีนี้แมอ๊อด () มากกว่าสตริง) ซึ่งมันจะไม่ทำงานกับd(dequeue องค์ประกอบด้านล่าง) และp(pop องค์ประกอบแรก) #โดยแปลงแรกแผนที่ไปยังรายการที่มี ข้อผิดพลาดนี้ได้รับการแก้ไข แต่การแก้ไขที่ใหม่กว่าความท้าทายนี้ดังนั้นฉันได้เก็บไว้#ใน

แก้ไข:และนับไบต์ผิดตั้งแต่เดือนกันยายน อ๊ะ

ยินดีต้อนรับคำแนะนำการเล่นกอล์ฟ ลองออนไลน์!

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


ใน ideone คอมไพเลอร์สตริง "nwlrbb" และสตริงแรนด์ทั้งหมดที่ฉันลอง 6 len ส่งคืนทั้งหมด 0 แต่ดูเหมือนว่าจะไม่ใช่ 0 ผลลัพธ์ ....
RosLuP

ใช่ตอนนี้ดูเหมือนว่าจะเป็น ...
RosLuP



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

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 การเพิ่ม "ผลตอบแทนคืน" ในนาทีสุดท้ายของการบันทึก "!


1
ช่องว่างสองช่องที่ไร้ประโยชน์: ทั้งคู่ก่อนหน้า
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


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.