Clarence the Slow Typist


35

introduzione

Clarence è un impiegato di immissione dati che lavora presso un fornitore di servizi Internet. Il suo compito è inserire manualmente gli indirizzi IP di tutti i clienti dell'ISP nel database. Lo fa usando una tastiera che ha il seguente layout:

123
456
789
.0

La distanza tra il centro dei tasti adiacenti orizzontalmente o verticalmente è esattamente di un centimetro. Ad esempio, la distanza tra i centri di 3e 9sarebbe di due centimetri. La distanza tra i centri di 3e 5sarebbe √2cm. Il teorema di Pitagora è sufficiente per calcolare la distanza tra due tasti qualsiasi.

Clarence, come ci si potrebbe aspettare da chi lavora in un ISP, utilizza un sistema di digitazione molto lento e inefficiente. Usa un solo dito e cerca il tasto, quindi sposta il dito sul tasto, poi lo preme e si ripete per tutte le cifre del numero. Potresti conoscere questo stile come il "sistema di ricerca dell'aquila" poiché il dito cerca sopra la tastiera il tasto corretto prima di immergersi per premere il tasto, come un'aquila che si abbassa per uccidere.

Ad esempio, ecco come Clarence digiterebbe il numero 7851:

  1. Mette il dito verso 7e preme la chiave.
  2. Muove il dito verso destra di 1 cm 8e preme la chiave.
  3. Muove il dito verso l'alto di 1 cm 5e preme la chiave.
  4. Muove il dito in diagonale verso l'alto e ha lasciato √2cm verso 1e preme la chiave.

Pertanto la distanza totale che Clarence mosso un dito per digitare 7851a dire 1 + 1 + √2che è di circa 3,41 centimetri.

Il tuo compito è scrivere un programma che calcoli la distanza che Clarence deve muovere con il dito per digitare indirizzi IP arbitrari.

Descrizione dell'input

L'input è una stringa che sarà nel modulo

().().().()

dove ognuno ()è un numero intero nell'intervallo 0- 999. Questo rappresenta l'indirizzo IP che Clarence deve digitare. Un esempio di input potrebbe essere:

219.45.143.143

Vorrei anche sottolineare che input come 0.42.42.42o 999.999.999.999sono ancora input validi, nonostante siano indirizzi IP non validi. Quindi non è necessario includere alcun codice di verifica dell'indirizzo IP nel programma.

Descrizione dell'uscita

Emetti la distanza che Clarence deve muovere con il dito per digitare l'indirizzo IP specificato. Round risponde a due cifre decimali ove necessario e usa l' cmunità nel tuo output. L'uscita per l'ingresso di esempio è 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).


29
Amico, gli ISP hanno strane tastiere ...
Dennis,

1
@RetoKoradi Mi aspetto un programma, sì. sono accettabili stdin, argomenti della riga di comando o funzioni di input dell'utente.
assenzio

2
@dacapoaria - 'ricerca dell'aquila' è anche conosciuta come 'caccia e becca' o 'cerca e distruggi' per i dattilografi più pesanti.

12
@ArtofCode Clarence lavora su un ISP, e talvolta l'ISP gli invia i dati non validi per digitare nel database. Clarence digita comunque i dati. Questa è la ragione canonica comunque. Il vero motivo è che l'ho trascurato quando ho scritto le specifiche.
assenzio

3
Considerando solo gli indirizzi IP dell'intervallo valido (0-255), quale dovrebbe essere la disposizione ottimale della tastiera per digitare tutti gli indirizzi nel percorso più breve?
Israel Morales,

Risposte:


16

CJam, 46 44 43 38 37 34 byte

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

Grazie a @ user23013 per il suggerimento mh, che ha permesso di salvare 5 byte.

Provalo online nell'interprete CJam .

Come funziona

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: Grazie. Non avevo nemmeno idea che mhesistesse.
Dennis,

16

Pyth, 38 35 34 byte

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

Dimostrazione.

Indicizzazione nella stringa di un'idea float grazie a @Dennis.

Spiegazione, sull'input falso 15.0:

  • Innanzitutto, prendiamo l'input. È implicitamente memorizzato in z. '15 .0'
  • Abbiamo Visualizza la lista come segue: m.jF.Dx`ciUTT1k3z.

    • UT: Generiamo l'elenco [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Successivamente, trattiamo questo elenco come un numero di base 10 che ci fornisce 123456789.
    • ciUTT1: Successivamente, convertiamo questo numero in un galleggiante in virgola mobile dividendolo per 1, dando 123456789.0.
    • `: Converti in una stringa. '123456789.0'
    • x k: Prende l'indice del carattere di input in quella stringa. [0, 4, 9, 10].
    • .D 3: .Dè la funzione divmod, emette il suo primo input diviso e modulo dal secondo input. Il secondo input è 3, qui. Ciò fornisce la posizione fisica del personaggio sul tastierino numerico. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jè il costruttore di numeri complessi. Flo applica alla tupla. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Ora prendiamo le sottostringhe di 2 voci di questo elenco in modo da poter trovare le distanze a coppie. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Rileva la differenza tra i due numeri complessi. [(-1-1j), (-2+1j), -1j].
  • .aM: Accetta il valore assoluto del risultato. Questa è la distanza tra le posizioni della tastiera.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Somma le distanze. 4.650281539872885.
  • .R 2: Arrotondare al secondo decimale. 4.65.
  • + "cm: Aggiungi 'cm'alla fine e stampa. 4.65cm.

7

PHP - 108 byte

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

L'input è preso dallo stdin. L' -.987654321invio alla strposfunzione viene valutato '-0.987654321'in un contesto di stringa.


Esempio di utilizzo:

$ echo 219.45.143.143 | php isp.php
27.38cm

5

C, 192 177 159 byte

Versione aggiornata, ora completa il programma usando l'argomento della riga di comando. Allo stesso tempo, migliorato per essere ancora più breve rispetto alla versione precedente:

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

La versione golfizzata utilizza un preprocessore #defineper abbreviare parte del codice ripetuto nella versione completa.


2
1. Alla tua versione golfata manca un punto e virgola alla fine. 2. La tua versione golfizzata sta producendo risultati errati, poiché aumenti sprima di verificare che *ssia diverso da zero. 3. L'OP ha detto programma nel suo posto. Non sono sicuro che una funzione sia accettata. 4. Con GCC, non è necessario includere. 5. sqrtè più corto di sqrtf. 6. pow(u-p,2)è più corto di (u-p)*(u-p). 7. Non ne sono sicuro, ma penso che memorizzare entrambe le coordinate in un'unica stringa e l'impostazione u=x[c]/3e v=x[c]%3dovrebbe essere più breve.
Dennis,

Risolto il problema di correttezza. Si scopre che ho continuato a compilare una versione precedente durante la messa a punto. Mi dispiace per quello. 1, 2. Risolto. Sono stato davvero sorpreso di poterli lasciare via. Il test interrotto lo spiegherebbe ... 3. Sulla base di ciò che ho visto su wiki / meta, sembrava che prendere l'input come argomenti di funzione sia un'opzione consentita se l'input non è specificato esplicitamente. Lo cambierò se la mia interpretazione non è corretta. 4. Ho sempre pensato che solo le funzioni che restituivano intpotevano essere utilizzate non dichiarate. Ma in effetti, anche clang lo accetta con un avvertimento, quindi me ne sono liberato.
Reto Koradi,

Il wiki afferma che le funzioni sono consentite per impostazione predefinita, sì, ma l'OP ha scritto che il tuo compito è quello di scrivere un programma ... Non hai bisogno delle parentesi che hai introdotto se scrivi il ciclo come p=u,q=v,G,r+=....
Dennis,

Ho chiesto al PO un chiarimento sui requisiti di input. Sul codice, l'ho riportato a una versione leggermente più vecchia prima di ottimizzarlo in modo errato. Daremo un'altra possibilità di sintonizzarlo domani, ma non volevo lasciare una versione rotta troppo a lungo. Grazie per i suggerimenti.
Reto Koradi,

@Dennis Ok, la versione aggiornata dovrebbe essere migliore in ogni modo. Ora un programma completo e ancora più breve grazie ad alcune ottimizzazioni. Grazie ancora per avermi informato dei problemi con la versione iniziale.
Reto Koradi,

3

JavaScript ( ES6 ), 132

I / O tramite popup. Esegui lo snippet per testare (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')


3

Python 3, 108 byte

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, non molto bene il golf, ma almeno si lega al PHP.



2

Python 199171 166 166

C'è un codice Python più breve (108) per questo da 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

Esempio di utilizzo:

$ python isp.py 219.45.143.143
27.38cm

Esegui online: http://codepad.org/h9CWCBNO

Codice commentato

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

1
È possibile salvare alcuni byte definendo ifclausole su una riga, ad esempioif i<1:c=3,1
Zgarb,

1
Puoi aggiungere l'evidenziazione della sintassi inserendo questo commento nella parte superiore del tuo post:<!-- language: lang-python -->
Martin Ender,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.