Clarence die langsame Schreibkraft

35

Einführung

Clarence ist ein Dateneingabe-Angestellter, der bei einem Internetdienstanbieter arbeitet. Seine Aufgabe ist es, die IP-Adressen aller ISP-Kunden manuell in die Datenbank einzugeben. Er tut dies mit einer Tastatur, die das folgende Layout hat:

123
456
789
.0

Der Abstand zwischen der Mitte horizontal oder vertikal benachbarter Tasten beträgt genau einen Zentimeter. Beispielsweise würde der Abstand zwischen den Mitten von 3und 9zwei Zentimeter betragen. Der Abstand zwischen den Mitten von 3und 5wäre √2cm. Der Satz von Pythagoras reicht aus, um den Abstand zwischen zwei beliebigen Schlüsseln zu berechnen.

Clarence verwendet, wie Sie es von einem Internetdienstanbieter erwarten können, ein sehr langsames und ineffizientes Tippsystem. Er benutzt einen einzelnen Finger und sucht nach der Taste, bewegt dann seinen Finger zur Taste, drückt sie dann und wiederholt sie für alle Ziffern in der Nummer. Sie kennen diesen Stil vielleicht als das "Adlersuchsystem", da der Finger über der Tastatur nach der richtigen Taste sucht, bevor er nach dem Tastendruck abtaucht, wie ein Adler, der nach einem Kill abtaucht.

So würde Clarence beispielsweise die Zahl eingeben 7851:

  1. Er beginnt mit dem Finger 7und drückt den Schlüssel.
  2. Er bewegt seinen Finger 1 cm nach rechts 8und drückt die Taste.
  3. Er bewegt seinen Finger 1 cm nach oben 5und drückt die Taste.
  4. Er bewegt seinen Finger diagonal nach oben und um √2 cm nach links 1und drückt die Taste.

Daher ist die Gesamtdistanz , dass Clarence seinen Finger bewegt , in den Typ 7851IS , 1 + 1 + √2die etwa 3.41cm ist.

Ihre Aufgabe ist es, ein Programm zu schreiben, das die Entfernung berechnet, die Clarence zum Eingeben beliebiger IP-Adressen benötigt.

Eingabebeschreibung

Die Eingabe ist eine Zeichenfolge, die im Formular enthalten sein wird

().().().()

wobei jedes ()eine ganze Zahl im Bereich ist 0- 999. Dies stellt die IP-Adresse dar, die Clarence eingeben muss. Eine Beispieleingabe könnte sein:

219.45.143.143

Ich möchte auch darauf hinweisen, dass Eingaben wie 0.42.42.42oder 999.999.999.999immer noch gültige Eingaben sind, obwohl es sich um ungültige IP-Adressen handelt. Sie müssen also keinen IP-Adressverifizierungscode in Ihr Programm aufnehmen.

Ausgabebeschreibung

Geben Sie die Entfernung ein, um die Clarence seinen Finger bewegen muss, um die angegebene IP-Adresse einzugeben. Runden Sie die Antworten nach Bedarf auf zwei Dezimalstellen und verwenden Sie die cmEinheit in Ihrer Ausgabe. Die Ausgabe für die Beispieleingabe ist 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).

Absinth
quelle
29
Mann, ISPs haben seltsame Tastaturen ...
Dennis
1
@RetoKoradi Ich erwarte ein Programm, ja. Standardeingabe, Befehlszeilenargumente oder Benutzereingabefunktionen sind zulässig.
Absinth
2
@dacapoaria - "Adlersuche" ist auch als "Jagen und Picken" oder "Suchen und Zerstören" für die hartnäckigeren Schreibkräfte bekannt.
12
@ArtofCode Clarence arbeitet bei einem ISP, und manchmal sendet der ISP ihm die ungültigen Daten, um sie in die Datenbank einzugeben. Clarence gibt die Daten trotzdem ein. Das ist sowieso der kanonische Grund. Der eigentliche Grund ist, dass ich das beim Schreiben der Spezifikation übersehen habe.
Absinth
3
Berücksichtigt man nur den gültigen Bereich (0-255) der IP-Adressen, sollte dies die optimale Anordnung der Tastatur sein, um all diese Adressen auf dem kürzesten Weg einzugeben?
Israel Morales

Antworten:

16

CJam, 46 44 43 38 37 34 Bytes

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

Vielen Dank an @ user23013 für den Vorschlag mh, mit dem 5 Bytes eingespart werden konnten .

Probieren Sie es online im CJam-Interpreter aus .

Wie es funktioniert

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
quelle
2
{3fmd~@-@@-mh}%.
Jimmy23013
@ user23013: Danke. Ich hatte keine Ahnung, dass es mhüberhaupt existiert.
Dennis
16

Pyth, 38 35 34 Bytes

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

Demonstration.

Indizierung in die Zeichenfolge einer Float-Idee dank @Dennis.

Erklärung zum falschen Eingang 15.0:

  • Zuerst nehmen wir die Eingabe. Es ist implizit in gespeichert z. '15 .0 '
  • Wir bilden diese Liste wie folgt: m.jF.Dx`ciUTT1k3z.

    • UT: Wir erstellen die Liste [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Als nächstes behandeln wir diese Liste als Basis 10, die uns eine Zahl gibt 123456789.
    • ciUTT1: Als nächstes konvertieren wir diese Zahl in einen Gleitkommawert, indem wir sie durch 1 teilen und geben 123456789.0.
    • `: In einen String konvertieren. '123456789.0'
    • x k: Nimm den Index des eingegebenen Zeichens in diese Zeichenkette. [0, 4, 9, 10].
    • .D 3: .Dist die DivMod-Funktion, die ihren ersten Eingang geteilt und durch den zweiten Eingang moduliert ausgibt. Die zweite Eingabe ist hier 3. Dies gibt die physische Position des Zeichens auf dem Nummernblock an. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jist der Konstruktor für komplexe Zahlen. Fwendet es auf das Tupel an. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Nun nehmen wir die 2 Eintragssubstrings dieser Liste, um die paarweisen Abstände zu finden. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Nimmt die Differenz der beiden komplexen Zahlen. [(-1-1j), (-2+1j), -1j].
  • .aM: Nimmt den absoluten Wert des Ergebnisses. Dies ist der Abstand zwischen den Positionen der Tastatur.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Summiere die Entfernungen. 4.650281539872885.
  • .R 2: Auf 2 Dezimalstellen runden. 4.65.
  • + "cm: 'cm'Zum Ende hinzufügen und ausdrucken. 4.65cm.
isaacg
quelle
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);

Die Eingabe erfolgt aus stdin. Die -.987654321an die strposFunktion gesendete wird '-0.987654321'in einem String-Kontext ausgewertet .


Beispielnutzung:

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

C 192 177 159 Bytes

Aktualisierte Version, jetzt Programm mit Kommandozeilenargument abschließen. Gleichzeitig verbessert, um noch kürzer als die Vorgängerversion zu sein:

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

Die Golf-Version verwendet einen Präprozessor #define, um einen Teil des wiederholten Codes in der Vollversion zu verkürzen.

Reto Koradi
quelle
2
1. In Ihrer Golfversion fehlt am Ende ein Semikolon. 2. Ihre Golf-Version führt zu falschen Ergebnissen, da Sie svor dem Überprüfen, ob der Wert *sungleich Null ist, eine Erhöhung durchführen . 3. Das OP sagte Programm in seinem Beitrag. Ich bin nicht sicher, ob eine Funktion akzeptiert wird. 4. Bei GCC benötigen Sie das Include nicht. 5. sqrtist kürzer als sqrtf. 6. pow(u-p,2)ist kürzer als (u-p)*(u-p). 7. Ich bin nicht sicher, aber ich denke, beide Koordinaten in einer einzigen Zeichenfolge und Einstellung zu speichern u=x[c]/3und v=x[c]%3sollte kürzer sein.
Dennis
Das Problem mit der Richtigkeit wurde behoben. Es stellte sich heraus, dass ich während der Feinabstimmung eine frühere Version kompiliert habe. Das tut mir leid. 1, 2. behoben. Ich war tatsächlich überrascht, dass ich sie weglassen konnte. Das kaputte Testen würde es erklären ... 3. Basierend auf dem, was ich in Wiki / Meta gesehen habe, hat es sich angehört, als ob die Eingabe als Funktionsargumente akzeptiert würde, wenn die Eingabe nicht explizit angegeben wird. Ich werde es ändern, wenn meine Interpretation falsch ist. 4. Ich dachte immer, dass nur Funktionen, die zurückgeben, intnicht deklariert werden könnten. Aber in der Tat akzeptiert Clang es auch mit einer Warnung, also habe ich es losgeworden.
Reto Koradi
Das Wiki besagt, dass Funktionen standardmäßig erlaubt sind, ja, aber das OP hat Ihre Aufgabe darin bestanden, ein Programm zu schreiben ... Sie brauchen die eingeführten Klammern nicht, wenn Sie die Schleife als schreiben p=u,q=v,G,r+=....
Dennis
Ich bat das OP um Klärung der Eingangsanforderungen. Im Code habe ich es auf eine etwas ältere Version zurückgesetzt, bevor ich es auf Unkorrektheit optimiert habe. Ich werde morgen noch einmal versuchen, es zu tunen, aber ich wollte eine kaputte Version nicht zu lange stehen lassen. Danke für die Hinweise.
Reto Koradi
@Dennis Ok, die aktualisierte Version sollte in jeder Hinsicht besser sein. Jetzt ein vollständiges Programm und dank einiger Optimierungen noch kürzer. Nochmals vielen Dank, dass Sie mich über die Probleme mit der ursprünglichen Version informiert haben.
Reto Koradi
3

JavaScript ( ES6 ), 132

I / O über Popup. Führen Sie das zu testende Snippet aus (nur 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
quelle
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:])))

Zugegebenermaßen nicht sehr gut golfen, aber es hängt zumindest mit PHP zusammen.

Sp3000
quelle
2

Ruby 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'

Testen Sie es online: http://ideone.com/2CIQa5

Cristian Lupascu
quelle
2

Python 199 171 166

Es gibt einen kürzeren Python-Code (108) von 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

Beispielnutzung:

$ python isp.py 219.45.143.143
27.38cm

Online ausführen : http://codepad.org/h9CWCBNO

Kommentierter Code

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
quelle
1
Sie können einige Bytes einsparen, indem Sie ifKlauseln in einer Zeile definieren, z. B.if i<1:c=3,1
Zgarb
1
Sie können Syntaxhervorhebungen hinzufügen, indem Sie diesen Kommentar oben in Ihren Beitrag <!-- language: lang-python -->
Martin Ender