Distancia de cadena


28

Reto

Dada una entrada de una cadena en minúsculas [a-z], genera la distancia total entre las letras.

Ejemplo

Input: golf

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

Output: 17

Reglas

  • Lagunas estándar prohibidas
  • Este es el : la respuesta más corta en bytes gana.
  • El alfabeto se puede atravesar desde cualquier dirección. Siempre debes usar el camino más corto. (es decir, la distancia entre xy ces 5).

1

Casos de prueba

Input: aa
Output: 0

Input: stack
Output: 18

Input: zaza
Output: 3

Input: valleys
Output: 35

Respuestas:


11

Jalea , 11 8 bytes

OIæ%13AS

Guardado 3 bytes gracias a @ Martin Ender .

Pruébalo en línea! o Verificar todos los casos de prueba.

Explicación

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

66
Me encontré æ%mientras leía los complementos el otro día, y estaba hecho para este (tipo de) problema:OIæ%13AS
Martin Ender

Creo que esto es de 9 bytes ( æson dos).
Aleksei Zabrodskii

1
@elmigranto Jelly tiene una página de códigos que codifica cada uno de sus caracteres en un byte: github.com/DennisMitchell/jelly/wiki/Code-page
ruds

10

Haskell, 57 56 bytes

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

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

Cómo funciona:

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

Editar: @Damien guardó un byte. ¡Gracias!


gracias por el truco de la distancia de rotación ( q.q)
Leif Willerts

Wow agradable! Puede agregar mapen la definición de qun byte menos
Damien

@Damien: bien visto. ¡Gracias!
nimi

8

MATL , 14 , 10 bytes

dt_v26\X<s

Pruébalo en línea!

¡Gracias @Suever por guardar 4 bytes!

Explicación:

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ón previa:

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

Descompostura:

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

1
Puedes perder un byte eliminando el espacio anteriorfor
Daniel

@Dopapp ¡Oh sí, gracias!
busukxuan

2
Puede tomar la entrada como una lista de caracteres y usar la recursión para guardar 3 bytes: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;}

Gracias a @KevinCruijssen por señalar un error en la versión original y sugerir que se vacíe el bucle for.

El uso de (26 + z[i] - z[i - 1]) % 26)está inspirado en un comentario de @Neil sobre otra respuesta. (26 + ...)%26tiene el mismo propósito que Math.abs(...)por ...? e : 26 - e.

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

Bienvenido al sitio! ¿Qué lenguaje es este? ¿Cuántos caracteres / bytes tiene? Deberías [edit] those details into the top of your post, with this markdown: #Idioma, n bytes`
DJMcMayhem

Okay. Gracias. Lo he editado ¿Cualquier mejora? :)
todeale

1
Te estás perdiendo un -antes de un een tu versión sin golf.
Neil

2
Bienvenido a PPCG! Hmm, obtengo un error de "No coincidencia de tipos: no se puede convertir de int a byte" en e=z[i]-z[i-1];Entonces necesitas un reparto (byte)o cambiar el ea int. También, puede quitar los soportes de bucle mediante la colocación de todo dentro del ciclo for, así: 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;}(PD: La invirtió la for-loop es por desgracia la misma longitud: 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
Muchas gracias @KevinCruijssen: D. Tu sugerencia ha ayudado mucho.
todeale

3

JavaScript (ES6), 84 82 79 bytes

Guardado 3 bytes gracias a 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

Explicación:

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

Ejemplo:
Llamada: f('golf')
Salida:17


Soluciones anteriores:

82 bytes gracias a 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
En lugar de Math.abs(...)usted puede usar (26+...)%26; esto funciona porque está volcando valores superiores a 13 de todos modos. (Creo que así es como funciona la respuesta MATL.)
Neil

1
Guarde algunos bytes al anteponer el código p=parseInt;y luego usarlo en p()lugar deparseInt()
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

Explicación

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

Pruébalo en línea!


Son 12 símbolos, no bytes. La longitud del byte sería 16 para UTF-8.
Aleksei Zabrodskii

@elmigranto: De hecho. En UTF-8 ese sería el caso, pero 05AB1E usa CP-1252 donde esto es 12 bytes.
Emigna

2

Perl, 46 bytes

Incluye +3 para -p(el código contiene ')

Dar entrada en STDIN sin nueva línea final:

echo -n zaza | stringd.pl

stringd.pl:

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

2

Raqueta 119 bytes

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

Pruebas:

(f "golf")

Salida:

17

Versión detallada:

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

Puede reemplazar (define(f s)con (lambda(s)2 bytes más cortos (las funciones anónimas están bien).
fede s.

1
Espera, Racket debería tomar (λ(s)también, que si en utf8 es de 6 bytes, creo
fede s.

Hecho eso Gracias.
rnso

2

DO#, 87 85 bytes

Solución mejorada : se reemplazó Math.Abs ​​() con el truco add & modulo para guardar 2 bytes:

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

Solución inicial :

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

Pruébalo en línea!

Fuente completa, incluidos los casos de prueba:

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

En realidad, 21 bytes

Basado parcialmente en la respuesta de Rubia de cia_rana .

Hubo un error con O(en este caso, map ord () sobre una cadena) donde no funcionaría con d(quitar el elemento inferior) y p(pop primer elemento) sin convertir primero el mapa en una lista con #. Este error se ha solucionado, pero como esa solución es más nueva que este desafío, me he mantenido #.

Editar: Y el recuento de bytes ha estado mal desde septiembre. Whoops

Sugerencias de golf bienvenidas. Pruébalo en línea!

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

No golfista

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

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

1

Pyth, 20 bytes

Lm-13.adbsyy-M.:CMQ2

Un programa que toma la entrada de una cadena entre comillas en STDIN e imprime el resultado.

Pruébalo en línea

Cómo funciona

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'

Explicación:

Como en DC no puedes acceder a los caracteres de una cadena, usé od para obtener los valores ASCII. Estos se procesarán en orden inverso desde la pila (contenedor LIFO) de la siguiente manera:

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

Correr:

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

Salida:

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

Asume que la cadena de entrada tiene al menos un carácter de longitud. Esto no requiere#include<stdlib.h>

Editar: Argh, puntos de secuencia!

Pruébalo en Ideone


en Ideone compilador la cadena "nwlrbb" y toda la cadena del rand trato 6 len devolver todo el 0 pero parece que no es 0 el resultado ....
RosLuP

Sí, ahora parece estar bien ...
RosLuP


1

Scala, 68 bytes

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

La crítica es bienvenida.


1

C #, 217 bytes

Golfizado:

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

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

Salida:

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

'a' es 97 cuando se convierte a bytes, por lo que 97 se resta de cada uno. Si la diferencia es mayor que 13 (es decir, la mitad del alfabeto), reste las diferencias entre cada carácter (valor de byte) de 26. ¡Una adición de último minuto de "retorno de rendimiento" me ahorró algunos bytes!


1
Dos espacios en blanco inútiles: ambos antes de 's'.
Yytsi

0

Python 3, 126 bytes

Con lista en comprensión.

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

Buena respuesta. Se podría sustituir abs(x-y)por y-xya que el llamado a sortedhacer 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;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.