Distance de chaîne

28

Défi

Étant donné l'entrée d'une chaîne entièrement en minuscules [a-z], affichez la distance totale entre les lettres.

Exemple

Input: golf

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

Output: 17

Règles

  • Failles standard interdites
  • C'est le - la réponse la plus courte en octets gagne.
  • L'alphabet peut être parcouru dans les deux sens. Vous devez toujours utiliser le chemin le plus court. (ie la distance entre xet cest 5).

1

Cas de test

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35
Daniel
la source

Réponses:

11

Gelée , 11 8 octets

OIæ%13AS

Enregistré 3 octets grâce à @ Martin Ender .

Essayez-le en ligne! ou Vérifiez tous les cas de test.

Explication

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
miles
la source
6
Je suis tombé sur æ%l'autre jour en lisant les modules intégrés, et c'était à peu près fait pour ce (type de) problème:OIæ%13AS
Martin Ender
Je pense que cela fait 9 octets ( æsoit deux).
Aleksei Zabrodskii
1
@elmigranto Jelly a une page de code qui encode chacun de ses caractères dans un octet: github.com/DennisMitchell/jelly/wiki/Code-page
ruds
10

Haskell, 57 56 octets

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

Exemple d'utilisation: sum.q.q.(zipWith(-)=<<tail).map fromEnum $ "valleys"-> 35.

Comment ça marche:

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

Modifier: @Damien a enregistré un octet. Merci!

nimi
la source
merci pour le tour de distance de rotation ( q.q)
Leif Willerts
Wow chouette! Vous pouvez ajouter mapla définition de qpour un octet de moins
Damien
@Damien: bien repéré. Merci!
nimi
8

MATL , 14 , 10 octets

dt_v26\X<s

Essayez-le en ligne!

Merci @Suever d' avoir économisé 4 octets!

Explication:

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

La version précédente:

d26\t13>26*-|s
DJMcMayhem
la source
6

Python 3, 69 68 octets

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

Panne:

lambda s:
         sum(                                                      )
             [                             for a,b in zip(s,s[1:])]
              13-abs(13-abs(ord(a)-ord(b)))
busukxuan
la source
1
Vous pouvez perdre un octet en supprimant l'espace avantfor
Daniel
@Dopapp Oh oui, merci!
busukxuan
2
Vous pouvez prendre l'entrée comme une liste de caractères et utiliser la récursivité pour enregistrer 3 octets: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 octets

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

Merci à @KevinCruijssen d'avoir signalé un bug dans la version originale et suggéré de rendre la boucle for vide.

L'utilisation de (26 + z[i] - z[i - 1]) % 26)est inspirée d'un commentaire de @Neil sur une autre réponse. (26 + ...)%26sert le même but qu'en Math.abs(...)raison de ...? e : 26 - e.

Non golfé :

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
la source
Bienvenue sur le site! Quelle langue est-ce? Combien de caractères / octets est-ce? Vous devez [edit] those details into the top of your post, with this markdown: #Langue, n octets`
DJMcMayhem
D'accord. Merci. Je l'ai édité. Une amélioration? :)
todeale
1
Vous manquez un -avant un edans votre version non golfée.
Neil
2
Bienvenue chez PPCG! Hmm, j'obtiens une erreur "Non-correspondance de type: impossible de convertir de int en octet" à e=z[i]-z[i-1];Donc, vous avez besoin d'un transtypage en (byte)ou changez le een int. En outre, vous pouvez supprimer les en plaçant tout à l' intérieur de la boucle for, entre parenthèses pour boucle comme ceci: 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: Le inversé la boucle for est malheureusement la même longueur: 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
Merci beaucoup @KevinCruijssen: D. Votre suggestion a beaucoup aidé.
todeale
3

JavaScript (ES6), 84 82 79 octets

3 octets enregistrés grâce à 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

Explication:

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

Exemple:
Appel: f('golf')
Sortie:17


Solutions précédentes:

82 octets grâce à 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 octets:

f=([d,...s],v=Math.abs(parseInt(s[0],36)-parseInt(d,36)))=>s[0]?f(s)+(v>13?26-v:v):0
Hedi
la source
1
Au lieu de Math.abs(...)vous pouvez utiliser (26+...)%26; cela fonctionne parce que vous inversez les valeurs supérieures à 13 de toute façon. (Je pense que c'est ainsi que fonctionne la réponse MATL.)
Neil
1
Économisez quelques octets en ajoutant le code avec p=parseInt;puis en utilisant à la p()place deparseInt()
Cyoce
3

Rubis, 73 octets

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

PHP, 93 octets

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
la source
2

05AB1E , 12 octets

SÇ¥YFÄ5Ø-}(O

Explication

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

Essayez-le en ligne!

Emigna
la source
C'est 12 symboles, pas des octets. La longueur en octets serait de 16 pour UTF-8.
Aleksei Zabrodskii
@elmigranto: En effet. En UTF-8, ce serait le cas, mais 05AB1E utilise CP-1252 où cela fait 12 octets.
Emigna
2

Perl, 46 octets

Comprend +3 pour -p(le code contient ')

Donnez votre avis sur STDIN sans nouvelle ligne finale:

echo -n zaza | stringd.pl

stringd.pl:

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

Raquette 119 octets

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

Essai:

(f "golf")

Sortie:

17

Version détaillée:

(define(f s)
  (for/sum((i(sub1(string-length s))))
    (abs(-(char->integer(string-ref s i))
          (char->integer(string-ref s(+ 1 i)))))))
rnso
la source
Vous pouvez remplacer (define(f s)par (lambda(s), 2 octets plus court (les fonctions anonymes sont très bien).
fede s.
1
Attendez, Racket devrait prendre (λ(s)aussi, ce qui si dans utf8 est de 6 octets je pense
fede s.
C'est fait. Merci.
rnso
2

C #, 87 85 octets

Solution améliorée - remplacé Math.Abs ​​() par l'astuce add & modulo pour économiser 2 octets:

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

Solution initiale :

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

Essayez-le en ligne!

Source complète, y compris les cas de test:

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
la source
2

En fait, 21 octets

Basé en partie sur la réponse Ruby de cia_rana .

Il y avait un bogue avec O(dans ce cas, map ord () sur une chaîne) où cela ne fonctionnerait pas avec d(retirer l'élément du bas) et p(pop premier élément) sans d'abord convertir la carte en une liste avec #. Ce bug a été corrigé, mais comme ce correctif est plus récent que ce défi, j'ai donc continué #.

Edit: Et le nombre d'octets est erroné depuis septembre. Oups.

Suggestions de golf bienvenues. Essayez-le en ligne!

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.
Sherlock9
la source
1

Java 7,128 octets

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

Non golfé

 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
la source
1

Pyth, 20 octets

Lm-13.adbsyy-M.:CMQ2

Un programme qui prend l'entrée d'une chaîne entre guillemets sur STDIN et imprime le résultat.

Essayez-le en ligne

Comment ça marche

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
la source
1

dc + od, 65 octets

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

Explication:

Parce qu'en DC, vous ne pouvez pas accéder aux caractères d'une chaîne, j'ai utilisé od pour obtenir les valeurs ASCII. Celles-ci seront traitées dans l'ordre inverse de la pile (conteneur LIFO) comme suit:

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

Courir:

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

Sortie:

17
seshoumara
la source
1

C, 82 86 83 76 octets

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

Suppose que la chaîne d'entrée comporte au moins un caractère. Cela ne nécessite pas#include<stdlib.h>

Edit: Argh, séquence de points!

Essayez-le sur Ideone

plafond
la source
dans le compilateur ideone, la chaîne "nwlrbb" et toute la chaîne rand j'essaye 6 len renvoie tous les 0 mais il ne semble pas 0 le résultat ....
RosLuP
oui maintenant ça semble ok ...
RosLuP
1

C, 70 octets 76 octets

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

Scala, 68 octets

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

La critique est la bienvenue.

Lui-meme12794
la source
1

C #, 217 octets

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

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

Sortie:

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

'a' vaut 97 lorsqu'il est converti en octets, donc 97 est soustrait de chacun. Si la différence est supérieure à 13 (c.-à-d. La moitié de l'alphabet), soustrayez les différences entre chaque caractère (valeur d'octet) de 26. Un ajout de dernière minute de "rendement de retour" m'a fait économiser quelques octets!

Pete Arden
la source
1
Deux espaces blancs inutiles: les deux avant 's'.
Yytsi
0

Python 3, 126 octets

Avec liste en compréhension.

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
la source
Bonne réponse. Vous pouvez remplacer abs(x-y)par y-xdepuis l'appel à sortedeffectuer x < y.
todeale
0

PHP, 79 octets

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

Java, 109 octets

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
la source