Clarence, o datilógrafo lento


35

Introdução

Clarence é um funcionário de entrada de dados que trabalha em um provedor de serviços de Internet. Seu trabalho é inserir manualmente os endereços IP de todos os clientes do ISP no banco de dados. Ele faz isso usando um teclado com o seguinte layout:

123
456
789
.0

A distância entre o centro das teclas adjacentes na horizontal ou na vertical é exatamente de um centímetro. Por exemplo, a distância entre os centros de 3e 9seria de dois centímetros. A distância entre os centros de 3e 5seria √2cm. O teorema de Pitágoras é suficiente para calcular a distância entre duas chaves.

Clarence, como você pode esperar de quem trabalha em um ISP, usa um sistema de digitação muito lento e ineficiente. Ele usa um único dedo e procura a tecla, depois move o dedo para a tecla, pressiona e repete para todos os dígitos do número. Você pode conhecer esse estilo como o "sistema de pesquisa de águia", já que o dedo procura acima do teclado a tecla correta antes de mergulhar no pressionamento de tecla, como uma águia mergulhando para matar.

Por exemplo, aqui está como o Clarence digitaria o número 7851:

  1. Ele começa o dedo 7e aperta a tecla.
  2. Ele move o dedo para a direita 1cm 8e pressiona a tecla.
  3. Ele move o dedo para cima 1cm 5e pressiona a tecla.
  4. Ele move o dedo na diagonal para cima e deixa √2cm 1e pressiona a tecla.

Portanto, a distância total que Clarence moveu seu dedo para digitar 7851é 1 + 1 + √2que é cerca de 3,41 centímetros.

Sua tarefa é escrever um programa que calcule a distância que Clarence deve mover o dedo para digitar endereços IP arbitrários.

Descrição da entrada

Entrada é uma sequência que estará no formato

().().().()

onde cada ()um é um número inteiro no intervalo 0- 999. Isso representa o endereço IP que o Clarence deve digitar. Um exemplo de entrada pode ser:

219.45.143.143

Também gostaria de salientar que entradas como 0.42.42.42ou 999.999.999.999ainda são válidas, apesar de serem endereços IP inválidos. Portanto, você não precisa incluir nenhum código de verificação de endereço IP no seu programa.

Descrição da saída

Saída a distância que Clarence deve mover o dedo para digitar o endereço IP especificado. Arredonde as respostas para duas casas decimais, quando necessário, e use a cmunidade em sua saída. A saída para a entrada de exemplo é 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).


29
Man, ISPs têm teclados estranhas ...
Dennis

11
@RetoKoradi Espero um programa, sim. stdin, argumentos de linha de comando ou funções de entrada do usuário são aceitáveis.
absinto

2
@dacapoaria - 'busca da águia' também é conhecido como 'caçar e beijar' ou 'procurar e destruir' para os digitadores mais pesados.

12
O @ArtofCode Clarence trabalha em um ISP e, às vezes, o ISP envia a ele os dados inválidos para digitar no banco de dados. O Clarence digita os dados de qualquer maneira. Essa é a razão canônica de qualquer maneira. O motivo real é que eu ignorei isso ao escrever as especificações.
absinto

3
Considerando apenas os endereços IP do intervalo válido (0-255), qual deve ser o arranjo ideal do teclado para digitar todos os endereços no caminho mais curto?
Israel Morales

Respostas:


16

CJam, 46 44 43 38 37 34 bytes

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

Obrigado a @ user23013 por sugerir mh, o que possibilitou salvar 5 bytes.

Experimente online no intérprete CJam .

Como 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".

2
{3fmd~@-@@-mh}%.
Jimmy23013

@ user23013: Obrigado. Eu nem imaginava que mhexistisse.
Dennis

16

Pitão, 38 35 34 bytes

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

Demonstração.

Indexando a sequência de uma ideia de flutuação graças a @Dennis.

Explicação, na entrada falsa 15.0:

  • Primeiro, pegamos a entrada. Está implicitamente armazenado em z. '15 .0 '
  • Mapeamos esta lista da seguinte forma: m.jF.Dx`ciUTT1k3z.

    • UT: Geramos a lista [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Em seguida, tratamos esta lista como um número base 10, fornecendo-nos 123456789.
    • ciUTT1: Em seguida, convertemos esse número em um ponto flutuante pelo ponto flutuante, dividindo-o por 1, dando 123456789.0.
    • `: Converte em uma sequência. '123456789.0'
    • x k: Pegue o índice do caractere de entrada nessa sequência. [0, 4, 9, 10].
    • .D 3: .Dé a função divmod, emitindo sua primeira entrada dividida e modulada pela segunda entrada. A segunda entrada é 3, aqui. Isso fornece a localização física do personagem no teclado numérico. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jé o construtor de números complexos. Faplica-o à tupla. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Agora, pegamos as 2 substrings de entrada desta lista para encontrar as distâncias aos pares. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Toma a diferença dos dois números complexos. [(-1-1j), (-2+1j), -1j].
  • .aM: Pega o valor absoluto do resultado. Esta é a distância entre os locais do teclado.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Soma as distâncias. 4.650281539872885.
  • .R 2: Arredonde para 2 casas decimais. 4.65.
  • + "cm: Adicione 'cm'no final e imprima. 4.65cm.

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

A entrada é retirada do stdin. O -.987654321enviado para a strposfunção é avaliado '-0.987654321'em um contexto de sequência.


Uso da amostra:

$ echo 219.45.143.143 | php isp.php
27.38cm

5

C, 192 177 159 bytes

Versão atualizada, agora complete o programa usando o argumento de linha de comando. Ao mesmo tempo, aprimorado para ainda ser menor que a versão 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);}

Ungolfed:

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

A versão golfed usa um pré #define- processador para encurtar parte do código repetido na versão completa.


2
1. Falta um ponto e vírgula na sua versão do golfe no final. 2. Sua versão golfada está produzindo resultados incorretos, pois você incrementa santes de verificar que *snão é zero. 3. O OP disse programa em seu post. Não tenho certeza se uma função é aceita. 4. Com o GCC, você não precisa da inclusão. 5. sqrté menor do que sqrtf. 6. pow(u-p,2)é menor do que (u-p)*(u-p). 7. Não tenho certeza, mas acho que armazenar as duas coordenadas em uma única string e configuração u=x[c]/3e v=x[c]%3deve ser mais curta.
Dennis

Corrigido o problema de correção. Acontece que eu continuei compilando uma versão anterior enquanto fazia o ajuste fino. Me desculpe por isso. 1, 2. Fixo. Fiquei realmente surpreso por poder deixá-los longe. O teste quebrado explicaria isso ... 3. Com base no que vi no wiki / meta, parecia que pegar a entrada como argumentos de função é uma opção permitida se a entrada não for especificada explicitamente. Vou mudar se minha interpretação estiver incorreta. 4. Eu sempre pensei que apenas as funções que retornam intpoderiam ser usadas não declaradas. Mas, de fato, o clang também aceita isso com um aviso, então me livrei dele.
Reto Koradi 25/05

O wiki afirma que as funções são permitidas por padrão, sim, mas o OP escreveu sua tarefa é escrever um programa ... Você não precisa dos colchetes que introduziu se escrever o loop como p=u,q=v,G,r+=....
Dennis

Pedi ao OP esclarecimentos sobre os requisitos de entrada. No código, eu o revirei para uma versão um pouco mais antiga antes de otimizá-la para incorreta. Vou tentar outra vez amanhã, mas não queria deixar uma versão quebrada por muito tempo. Obrigado pelas indicações.
Reto Koradi 25/05

@ Dennis Ok, a versão atualizada deve ser melhor em todos os aspectos. Agora, um programa completo e ainda mais curto, graças a algumas otimizações. Mais uma vez obrigado por me informar sobre os problemas com a versão inicial.
Reto Koradi 25/05

3

JavaScript ( ES6 ), 132

E / S via pop-up. Execute o trecho para testar (apenas 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')


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

É certo que não muito bem jogado, mas pelo menos ele se relaciona com o PHP.



2

Python 199 171 166

Existe um código Python mais curto (108) para isso no 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 da amostra:

$ python isp.py 219.45.143.143
27.38cm

Execute on-line: 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

11
Você pode salvar alguns bytes definindo ifcláusulas em uma linha, comoif i<1:c=3,1
Zgarb 27/05

11
Você pode adicionar realce de sintaxe colocando este comentário na parte superior da sua postagem:<!-- language: lang-python -->
Martin Ender
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.