Clarence el mecanógrafo lento

35

Introducción

Clarence es un empleado de entrada de datos que trabaja en un proveedor de servicios de internet. Su trabajo es ingresar manualmente las direcciones IP de todos los clientes del ISP en la base de datos. Lo hace usando un teclado que tiene el siguiente diseño:

123
456
789
.0

La distancia entre el centro de las teclas adyacentes horizontal o verticalmente es exactamente un centímetro. Por ejemplo, la distancia entre los centros de 3y 9sería dos centímetros. La distancia entre los centros de 3y 5sería √2cm. El teorema de Pitágoras es suficiente para calcular la distancia entre dos claves.

Clarence, como es de esperar de alguien que trabaja en un ISP, utiliza un sistema de escritura muy lento e ineficiente. Utiliza un solo dedo y busca la tecla, luego mueve el dedo hacia la tecla, luego la presiona y repite todos los dígitos del número. Es posible que conozca este estilo como el "sistema de búsqueda de águilas", ya que el dedo busca por encima del teclado la tecla correcta antes de presionar la tecla, como un águila que cae para matar.

Por ejemplo, así es como Clarence escribiría el número 7851:

  1. Empieza su dedo 7y empuja la llave.
  2. Mueve su dedo hacia la derecha 1 cm 8y empuja la tecla.
  3. Mueve su dedo hacia arriba 1 cm 5y empuja la tecla.
  4. Mueve su dedo diagonalmente hacia arriba y hacia la izquierda √2cm 1y empuja la tecla.

Por lo tanto la distancia total que Clarence movió su dedo para escribir 7851es 1 + 1 + √2que es aproximadamente 3.41cm.

Su tarea es escribir un programa que calcule la distancia que Clarence debe mover su dedo para escribir direcciones IP arbitrarias.

Descripción de entrada

La entrada es una cadena que tendrá el formato

().().().()

donde cada uno ()es un entero en el rango 0- 999. Esto representa la dirección IP que Clarence debe escribir. Una entrada de ejemplo podría ser:

219.45.143.143

También me gustaría señalar que las entradas como 0.42.42.42o 999.999.999.999son entradas válidas, a pesar de que son direcciones IP no válidas. Por lo tanto, no necesita incluir ningún código de verificación de dirección IP en su programa.

Descripción de salida

Muestra la distancia que Clarence debe mover su dedo para escribir la dirección IP especificada. Redondea las respuestas a dos decimales cuando sea necesario, y usa la cmunidad en tu salida. La salida para la entrada de ejemplo es 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).

Ajenjo
fuente
29
Hombre, los ISP tienen teclados extraños ...
Dennis
1
@RetoKoradi Espero un programa, sí. stdin, argumentos de línea de comando o funciones de entrada del usuario son aceptables.
ajenjo
2
@dacapoaria - 'búsqueda de águila' también se conoce como 'cazar y picotear' o 'buscar y destruir' para los mecanógrafos más duros.
12
@ArtofCode Clarence trabaja en un ISP y, a veces, el ISP le envía los datos no válidos para escribir en la base de datos. Clarence escribe los datos de todos modos. Esa es la razón canónica de todos modos. La razón real es porque pasé por alto eso al escribir la especificación.
absenta
3
Considerando solo las direcciones IP de rango válido (0-255), ¿cuál debería ser la disposición óptima del teclado para escribir todas esas direcciones en la ruta más corta?
Israel Morales

Respuestas:

16

CJam, 46 44 43 38 37 34 bytes

rA,sd`f#3fmd2/2ew::.-::mh:+2mO"cm"

Gracias a @ user23013 por sugerir mh, lo que hizo posible guardar 5 bytes.

Pruébelo en línea en el intérprete de CJam .

Cómo funciona

r     e# Read a token from STDIN.
A,    e# Push [0 1 2 3 4 5 6 7 8 9].
s     e# Stringify: [0 1 2 3 4 5 6 7 8 9] -> "0123456789"
d     e# Cast to Double: "0123456789" -> 123456789.0
`     e# Inspect: 123456789.0 -> "123456789.0"
f#    e# Push the index of each character from the input in "123456789.0".
3fmd  e# Push the quotient and residue of each index divided by 3.
2/    e# Split the resulting array into pairs.
2ew   e# Convert the array of pairs in the array of all overlapping pairs of pair.
::.-  e# Reduce each pair using vectorized difference: [[a b][c d]] -> [a-b c-d]
::mh  e# Reduce each reduced pair to its 2-norm distance: [a b] -> sqrt(aa + bb)
:+    e# Sum all distances.
2mO   e# Round to two decimal places.
"cm"  e# Push "cm".
Dennis
fuente
2
{3fmd~@-@@-mh}%.
jimmy23013
@ user23013: Gracias. Ni mhsiquiera tenía idea de que existía.
Dennis
16

Pyth, 38 35 34 bytes

+.Rs.aM-M.:m.jF.Dx`ciUTT1b3z2 2"cm

Demostración.

Indexación en la cadena de una idea flotante gracias a @Dennis.

Explicación, en la entrada falsa 15.0:

  • Primero, tomamos la entrada. Está implícitamente almacenado en z. '15 .0 '
  • Estamos mapa esta lista de la siguiente manera: m.jF.Dx`ciUTT1k3z.

    • UT: Generamos la lista [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Luego, tratamos esta lista como un número base 10 que nos da 123456789.
    • ciUTT1: Luego, convertimos este número en un flotador por coma flotante dividiéndolo por 1, dando 123456789.0.
    • `: Convertir a una cadena. '123456789.0'
    • x k: Tome el índice del carácter de entrada en esa cadena. [0, 4, 9, 10].
    • .D 3: .Des la función divmod, que genera su primera entrada dividida y modulada por la segunda entrada. La segunda entrada es 3, aquí. Esto proporciona la ubicación física del personaje en el teclado numérico. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jes el constructor de números complejos. Flo aplica a la tupla. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Ahora, tomamos las 2 subcadenas de entrada de esta lista para que podamos encontrar las distancias por pares. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Toma la diferencia de los dos números complejos. [(-1-1j), (-2+1j), -1j].
  • .aM: Toma el valor absoluto del resultado. Esta es la distancia entre las ubicaciones del teclado.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Suma las distancias. 4.650281539872885.
  • .R 2: Redondear a 2 decimales. 4.65.
  • + "cm: Agregar 'cm'al final e imprimir. 4.65cm.
isaacg
fuente
7

PHP - 108 bytes

<?for(;$v=strpos(-.987654321,fgetc(STDIN));$l=$v)$l&&$t+=hypot($l/3%4-$v/3%4,$l%3-$v%3);printf('%.2fcm',$t);

La entrada se toma de stdin. El -.987654321enviado a la strposfunción se evalúa '-0.987654321'en un contexto de cadena.


Uso de la muestra:

$ echo 219.45.143.143 | php isp.php
27.38cm
primo
fuente
5

C, 192 177 159 bytes

Versión actualizada, ahora complete el programa usando el argumento de la línea de comando. Al mismo tiempo, mejorado para ser aún más corto que la versión anterior:

#define G c=*a[1]++,c=c>48?c-49:c/2-14,u=c%3,v=c/3
float r;c,u,v,p,q;main(int n,char**a){for(G;*a[1];)p=u,q=v,G,p-=u,q-=v,r+=sqrt(p*p+q*q);printf("%.2fcm",r);}

Sin golf:

#include <stdio.h>
#include <math.h>

float r;
int c, u, v, p, q;

int main(int n, char** a) {
    c = *a[1]++;
    c = c > 48 ? c - 49 : c / 2 - 14;
    u = c % 3;
    v = c / 3;
    for ( ; *a[1]; ) {
        p = u;
        q = v;
        c = *a[1]++;
        c = c > 48 ? c - 49 : c / 2 - 14;
        u = c % 3;
        v = c / 3;
        p -= u;
        q -= v;
        r += sqrt(p * p + q * q);
    }

    printf("%.2fcm",r);

    return 0;
}

La versión de golf utiliza un preprocesador #definepara acortar parte del código repetido en la versión completa.

Reto Koradi
fuente
2
1. A su versión de golf le falta un punto y coma al final. 2. Su versión de golf está produciendo resultados incorrectos, ya que incrementa santes de verificar que *sno es cero. 3. El OP dicho programa en su post. No estoy seguro de si se acepta una función. 4. Con GCC, no necesita incluir. 5. sqrtes más corto que sqrtf. 6. pow(u-p,2)es más corto que (u-p)*(u-p). 7. No estoy seguro, pero creo que almacenar ambas coordenadas en una sola cadena y configuración u=x[c]/3y v=x[c]%3debería ser más corto.
Dennis
Se corrigió el problema de corrección. Resulta que seguí compilando una versión anterior mientras hacía ajustes. Lo siento por eso. 1, 2. Fijo. De hecho, me sorprendió poder dejarlos lejos. Las pruebas rotas lo explicarían ... 3. Basado en lo que vi en wiki / meta, sonó como que tomar la entrada como argumentos de función es una opción permitida si la entrada no se especifica explícitamente. Lo cambiaré si mi interpretación es incorrecta. 4. Siempre pensé que solo las funciones que retornaban intpodían usarse sin declarar. Pero, de hecho, el sonido metálico también lo acepta con una advertencia, así que me deshice de él.
Reto Koradi
El wiki establece que las funciones están permitidas por defecto, sí, pero el OP escribió que su tarea es escribir un programa ... No necesita los corchetes que introdujo si escribe el bucle como p=u,q=v,G,r+=....
Dennis
Le pedí al OP una aclaración sobre los requisitos de entrada. En el código, volví a una versión un poco más antigua antes de optimizarlo en incorrección. Haré otra oportunidad para ajustarlo mañana, pero no quería dejar una versión rota por mucho tiempo. Gracias por los consejos.
Reto Koradi
@ Dennis Ok, la versión actualizada debería ser mejor en todos los sentidos. Ahora un programa completo, y aún más corto gracias a algunas optimizaciones. Gracias nuevamente por informarme sobre los problemas con la versión inicial.
Reto Koradi
3

JavaScript ( ES6 ), 132

E / S a través de una ventana emergente. Ejecute el fragmento para probar (solo Firefox)

[for(a of prompt(d=''))[p,q,d]=[x=(a=a<'0'?9:-a?a-1:10)%3,y=a/3|0,d!==''?d+Math.sqrt((p-=x)*p+(q-=y)*q):0]],alert(d.toFixed(2)+'cm')

edc65
fuente
3

Python 3, 108 bytes

L=[x//3*1j+x%3for x in map("123456789.0".find,input())]
print("%.2fcm"%sum(abs(a-b)for a,b in zip(L,L[1:])))

Es cierto que no está muy bien golfizado, pero al menos está vinculado con PHP.

Sp3000
fuente
2

Rubí 135 139

s=0
gets.chars.each_cons(2).map{|a|i,j=a.map{|e|'123456789.0'.index e}
i&&j&&s+=((i%3-j%3)**2+(i/3-j/3)**2)**0.5}
print s.round(2),'cm'

Pruébelo en línea: http://ideone.com/2CIQa5

Cristian Lupascu
fuente
2

Python 199 171 166

Hay un código Python más corto (108) para esto por SP3000:

https://codegolf.stackexchange.com/a/50854/41163

import sys
p=r=0
for i in sys.argv[1]:
 c=3,0
 if i!=".":c=divmod(int(i)-1,3)
 if i<1:c=3,1
 if p:r+=((p[1]-c[1])**2+(p[0]-c[0])**2)**0.5
 p=c
print"%.2fcm"%r

Uso de la muestra:

$ python isp.py 219.45.143.143
27.38cm

Ejecutar en línea: http://codepad.org/h9CWCBNO

Código comentado

import sys

# p - last position as (y,x) tuple - initialized with 0, because "if 0" -> equals to "False"
p = 0
# r - result of adding all distances - ini with 0, because not moved any distances on start
r = 0

# Loop over chars
for char in sys.argv[1]:
   # c - current position of typist as (y,x) tuple

   # Always set c to position of "." key 
   c = 3,0 # lazy for c=(3,0)

   # Check if char is not the "." key
   if char !=".":

      # Get position of char on keypad
      c=divmod(int(char)-1,3)

      if char<1:
         c=3,1  

   # If this is the first char, 
   # then STORE_OPERATION has not been executed, 
   # so p is still p=0 from original initialization 
   # calling "if 0" evaluates to False,
   # so we jump this code block, for the first char
   if p:                           
      # calculate delta of x, y from current and last position, 
      # then add both deltas squared (**2),
      # then get square root of it (**0.5 = **1/2)
      # add to r (+=)
      r+=( (p[1]-c[1])**2 + (p[0]-c[0])**2 )**0.5

   # STORE_OPERATION - Store current position as last position
   p = c

# .2f returns r with 2 trailing digits
print"%.2fcm"%r
AddingColor
fuente
1
Puede guardar algunos bytes definiendo ifcláusulas en una línea, comoif i<1:c=3,1
Zgarb
1
Puede agregar resaltado de sintaxis colocando este comentario en la parte superior de su publicación:<!-- language: lang-python -->
Martin Ender