Clarence the Slow Typist

Introduction

Clarence is a data entry clerk who works at an internet service provider. His job is to manually enter the IP addresses of all of the ISP's customers into the database. He does this using a keypad which has the following layout:

123
456
789
.0

The distance between the centre of horizontally or vertically adjacent keys is exactly one centimetre. For instance, the distance between the centres of 3 and 9 would be two centimetres. The distance between the centres of 3 and 5 would be √2cm. The Pythagoras theorem is sufficient to calculate the distance between any two keys.

Clarence, as you might expect from one who works in an ISP, uses a very slow and inefficient system of typing. He uses a single finger and searches for the key, and then moves his finger to the key, then presses it, and repeats for all of the digits in the number. You might know of this style as the "eagle search system" since the finger searches above the keyboard for the correct key before plunging down for the keypress, like an eagle plunging down for a kill.

For example, here is how Clarence would type out the number 7851:

1. He starts his finger at 7 and pushes the key.
2. He moves his finger to the right 1cm to 8 and pushes the key.
3. He moves his finger upwards 1cm to 5 and pushes the key.
4. He moves his finger diagonally upwards and left √2cm to 1 and pushes the key.

Therefore the total distance that Clarence moved his finger to type in 7851 is 1 + 1 + √2 which is about 3.41cm.

Your task is to write a program that calculates the distance Clarence must move his finger to type in arbitrary IP addresses.

Input Description

Input is a string that will be in the form

().().().()

where each () is an integer in the range 0 - 999. This represents the IP address that Clarence must type in. An example input might be:

219.45.143.143

I would also like to point out that inputs such as 0.42.42.42 or 999.999.999.999 are still valid inputs, despite the fact that they are invalid IP addresses. So you don't need to include any IP address verification code in your program.

Output Description

Output the distance that Clarence must move his finger in order to type in the specified IP address. Round answers to two decimal places where needed, and use the cm unit in your output. The output for the example input is 27.38cm (1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).

• Man, ISPs have weird keyboards... May 25, 2015 at 2:15
• @dacapoaria - 'eagle search' is also known as 'hunt and peck' or 'search and destroy' for the more heavy-handed typists.
– user31556
May 25, 2015 at 9:51
• @ArtofCode Clarence works at an ISP, and sometimes the ISP sends him the invalid data to type into the database. Clarence types the data in anyway. That's the canonical reason anyway. The actual reason is because I overlooked that when writing the spec. May 25, 2015 at 11:59
• Considering only the valid range (0-255) IP Addresses, which should be the optimum arrangement of the keyboard to type all that addresses in the shortest path? May 25, 2015 at 17:18
• @IsraelMorales Hmmm... my hunch would be that you'd have the . in the middle, 2, 5, 1, and 3 adjacent, 9 and 8 outside of the square and the remaining ones in the corners. That's just my guess though. May 26, 2015 at 0:25

CJam, 4644433837 34 bytes

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

Thanks to @user23013 for suggesting mh, which made it possible to save 5 bytes.

Try it online in the CJam interpreter.

How it works

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".
• {3fmd~@-@@-mh}%. May 25, 2015 at 3:57
• @user23013: Thanks. I had no idea mh even existed. May 25, 2015 at 4:16

Pyth, 3835 34 bytes

+.Rs.aM-M.:m.jF.DxciUTT1b3z2 2"cm

Demonstration.

Indexing into the string of a float idea thanks to @Dennis.

Explanation, on the phony input 15.0:

• First, we take the input. It is implicitly stored in z. '15.0'
• We map this list as follows: m.jF.DxciUTT1k3z.

• UT: We generate the list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
• iUTT: Next, we treat this list as a base 10 number giving us 123456789.
• ciUTT1: Next, we convert this number to a float by floating point dividing it by 1, giving 123456789.0.
• `: Convert to a string. '123456789.0'
• x k: Take the index of the input character in that string. [0, 4, 9, 10].
• .D 3: .D is the divmod function, outputing its first input divided and modulo'd by the second input. The second input is 3, here. This gives the physical location of the character on the numpad. [(0, 0), (1, 1), (3, 0), (3, 1)].
• .jF: .j is the complex number constructor. F applies it to the tuple. [0j, (1+1j), (3+0j), (3+1j)].
• .: 2: Now, we take the 2 entry substrings of this list so we can find the pairwise distances. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
• -M: Takes the difference of the two complex numbers. [(-1-1j), (-2+1j), -1j].
• .aM: Takes the absolute value of the result. This is the distance between the keypad locations. [1.4142135623730951, 2.23606797749979, 1.0]
• s: Sum the distances. 4.650281539872885.
• .R 2: Round to 2 decimal places. 4.65.
• + "cm: Add 'cm' to the end and print. 4.65cm.

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

Input is taken from stdin. The -.987654321 sent to the strpos function evaluates to '-0.987654321' in a string context.

Sample usage:

27.38cm

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