String Abstand


28

Herausforderung

Geben Sie bei Eingabe einer Zeichenfolge in Kleinbuchstaben [a-z]den Gesamtabstand zwischen den Buchstaben aus.

Beispiel

Input: golf

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

Output: 17

Regeln

  • Standardlücken verboten
  • Dies ist - kürzeste Antwort in Bytes gewinnt.
  • Das Alphabet kann aus beiden Richtungen durchlaufen werden. Sie müssen immer den kürzesten Weg verwenden. (dh der Abstand zwischen xund cist 5).

1

Testfälle

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35

Antworten:


11

Jelly , 11 8 Bytes

OIæ%13AS

3 Bytes gespart dank @ Martin Ender .

Probieren Sie es online! oder Überprüfen Sie alle Testfälle.

Erläuterung

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
Ich bin neulich æ%beim Durchlesen der Einbauten OIæ%13AS
Martin Ender,

Ich denke, das sind 9 Bytes ( æsind zwei).
Aleksei Zabrodskii

1
@elmigranto Jelly hat eine Codepage, die jedes seiner Zeichen in einem Byte codiert: github.com/DennisMitchell/jelly/wiki/Code-page
ruds

10

Haskell, 57 56 Bytes

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

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

Wie es funktioniert:

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

Edit: @Damien hat ein Byte gespeichert. Vielen Dank!


danke für den Rotationsdistanz-Trick ( q.q)
Leif Willerts

Wow schön! Sie können mapin der Definition von qfür ein Byte weniger hinzufügen
Damien

@ Damien: gut gesehen. Vielen Dank!
nimi

8

MATL , 14 , 10 Bytes

dt_v26\X<s

Probieren Sie es online!

Vielen Dank an @Suever für das Speichern von 4 Bytes!

Erläuterung:

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

Vorherige Version:

d26\t13>26*-|s

6

Python 3, 69 68 Bytes

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

Nervenzusammenbruch:

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

1
Sie können ein Byte verlieren, indem Sie vorher das Leerzeichen entfernenfor
Daniel

@ Dopapp Oh ja, danke!
Busukxuan

2
Sie können die Eingabe als Liste von Zeichen verwenden und mithilfe der Rekursion 3 Bytes speichern: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 Bytes

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

Vielen Dank an @KevinCruijssen für den Hinweis auf einen Fehler in der Originalversion und den Vorschlag, die for-Schleife leer zu machen.

Die Verwendung von (26 + z[i] - z[i - 1]) % 26)basiert auf einem Kommentar von @Neil zu einer anderen Antwort. (26 + ...)%26dient dem gleichen Zweck wie Math.abs(...)wegen ...? 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;
}

Willkommen auf der Seite! Welche Sprache ist das? Wie viele Zeichen / Bytes sind das? Du solltest [edit] those details into the top of your post, with this markdown: #Language, n bytes`
DJMcMayhem

Okay. Vielen Dank. Ich habe es bearbeitet. Irgendeine Verbesserung? :)
todeale

1
In Ihrer ungolften Version fehlt ein -vor einem e.
Neil

2
Willkommen bei PPCG! Hmm, ich bin immer einen „Typenkonflikt: kann nicht von int konvertieren Byte“ bei Fehlern e=z[i]-z[i-1];So benötigen Sie entweder eine Besetzung zu (byte)ändern oder das ezu int. Außerdem können Sie die for-Schleife Klammern entfernen , indem sie alles in dem for-Schleife platzieren, wie folgt aus : 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: Die umgekehrten die for-Schleife ist leider die gleiche Länge: 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
Vielen Dank @ KevinCruijssen: D. Ihr Vorschlag hat sehr geholfen.
Todeale

3

JavaScript (ES6), 84 82 79 Byte

3 Bytes gespart dank 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

Erläuterung:

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

Beispiel:
Aufruf: f('golf')
Ausgabe:17


Bisherige Lösungen:

82 Bytes dank 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 Bytes:

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

1
Anstelle von Math.abs(...)Ihnen können verwenden (26+...)%26; Das funktioniert, weil Sie sowieso Werte über 13 spiegeln. (Ich denke, so funktioniert die MATL-Antwort.)
Neil

1
Speichern Sie einige Bytes durch das Voranstellen des Codes mit p=parseInt;und dann unter Verwendung p()anstelle vonparseInt()
Cyoce

3

Ruby, 73 Bytes

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

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;

2

05AB1E , 12 Bytes

SÇ¥YFÄ5Ø-}(O

Erläuterung

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

Probieren Sie es online!


Es sind 12 Symbole, keine Bytes. Die Bytelänge wäre 16 für UTF-8.
Aleksei Zabrodskii

@elmigranto: In der Tat. In UTF-8 wäre dies der Fall, aber 05AB1E verwendet CP-1252, wo dies 12 Bytes sind.
Emigna

2

Perl, 46 Bytes

Beinhaltet +3 für -p(Code enthält ')

Geben Sie eine Eingabe in STDIN ohne letzte Zeile ein:

echo -n zaza | stringd.pl

stringd.pl:

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

2

Schläger 119 Bytes

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

Testen:

(f "golf")

Ausgabe:

17

Ausführliche Version:

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

Sie könnten (define(f s)mit (lambda(s), 2 Bytes kürzer ersetzen (anonyme Funktionen sind in Ordnung).
fede s.

1
Warten Sie, Schläger sollte auch nehmen (λ(s), was, wenn in utf8 6 Bytes ich denke
fede s ist.

Habe das gemacht. Vielen Dank.
RNSO

2

C #, 87-85 Bytes

Verbesserte Lösung - Math.Abs ​​() wurde durch den Add & Modulo-Trick ersetzt, um 2 Bytes zu sparen:

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

Anfangslösung :

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

Probieren Sie es online!

Vollständige Quelle, einschließlich Testfällen:

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

Eigentlich 21 Bytes

Basiert teilweise auf der Ruby-Antwort von cia_rana .

Es gab einen Fehler mit O(in diesem Fall map ord () über einer Zeichenfolge), bei dem es nicht funktioniert hat d(unteres Element aus der Warteschlange entfernen) und p(erstes Element einblenden ), ohne die Karte zuerst in eine Liste mit zu konvertieren #. Dieser Fehler wurde behoben, aber da dieses Update neuer als diese Herausforderung ist, habe ich mich daran gehalten #.

Edit: Und die Byteanzahl ist seit September falsch. Hoppla.

Golfvorschläge sind willkommen. Probieren Sie es online!

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 Bytes

 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 Bytes

Lm-13.adbsyy-M.:CMQ2

Ein Programm, das eine in Anführungszeichen gesetzte Zeichenfolge in STDIN eingibt und das Ergebnis ausgibt.

Probieren Sie es online aus

Wie es funktioniert

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 bytes

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

Erläuterung:

Da Sie in dc nicht auf die Zeichen eines Strings zugreifen können, habe ich od verwendet , um die ASCII-Werte abzurufen. Diese werden vom Stapel (LIFO-Container) in umgekehrter Reihenfolge wie folgt verarbeitet:

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

Lauf:

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

Ausgabe:

17

1

C, 82 86 83 76 Bytes

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

Es wird davon ausgegangen, dass die Eingabezeichenfolge mindestens ein Zeichen lang ist. Dies ist nicht erforderlich#include<stdlib.h>

Edit: Argh, Sequenzpunkte!

Probieren Sie es auf Ideone


Im Ideone-Compiler geben der String "nwlrbb" und der gesamte Rand-String, den ich ausprobiere, alle 0 zurück, aber es scheint nicht 0 zu sein.
RosLuP

Ja, jetzt scheint es
RosLuP

1

C 70 Bytes 76 Bytes

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

1

Scala, 68 Bytes

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

Kritik ist willkommen.


1

C #, 217 Bytes

Golf gespielt:

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

Ausgabe:

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

'a' ist 97, wenn es in Bytes konvertiert wird, also wird 97 von jedem abgezogen. Wenn die Differenz größer als 13 ist (dh die Hälfte des Alphabets), dann subtrahieren Sie die Unterschiede zwischen den einzelnen Zeichen (Bytewert) von 26. Eine Last-Minute-Addition von "yield return" hat mir ein paar Bytes erspart!


1
Zwei nutzlose Leerzeichen: beide vor 's'.
Yytsi

0

Python 3, 126 Bytes

Mit Liste im Verständnis.

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

Gute Antwort. Sie könnten ersetzen abs(x-y)durch , y-xda der Anruf zu sortedmachen x < y.
Todeale

0

PHP, 79 Bytes

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

0

Java, 109 Bytes

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;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.