Calculate the Numpad Taxicab

Credit goes where credit is due

Given two digits, x, and y, calculate the shortest number of horizontal or vertical jumps to get from x to y on a standard numpad, e.g.

789
456
123
00

You can safely assume that all inputs will be 0-9, and you do not have to handle invalid inputs. The input may be the same number twice, which has a distance of 0.

IO can be in any reasonable format, and standard loopholes are forbidden. Shortest answer in bytes wins!

Sample IO:

1, 4: 1
1, 8: 3
3, 7: 4
8, 2: 2
6, 1: 3
0, 9: 4
4, 4: 0
0, 4: 2
• Related. – Dennis May 22 '16 at 4:57

Jelly, 11 bytes

o-1.’d3ạ/ḞS

How it works

o-1.’d3ạ/ḞS  Main link. Argument: [a, b] (list of integers)

-1.         Yield -1.5.
o            Take the logical OR of a and b with -1.5.
This maps 0 to -1.5, and all other integers to themselves.
’        Decrement the results.
d3      Divmod; compute quotient and remainder of each result divided by 3.
ạ/    Reduce by absolute difference across columns.
Ḟ   Floor; round all differences down to the nearest integer.
S  Sum; add the rounded absolute differences.
• Nice comeback . – Leaky Nun May 22 '16 at 5:45

Python, 140 114 bytes

I am a first timer, so please help. Here's my code.

def f(x,y):x,y,k=x-1,y-1,abs;return x!=-1 and y!=-1 and k(y//3-x//3)+k(y%3-x%3) or k(y//3-x//3)+int(max(x,y)%3==2)
• Some tips: 1) use single spaces for indents, 2) drop the parentheses around the if condition, 3) get rid of the space in the argument list, 4) divmod may help you, 5) instead of if cond:return A\nelse:return B, do return cond and A or B. – Mego May 22 '16 at 9:00
• @Mego How does divmod help? I don't think I've ever saved bytes with that – Sp3000 May 22 '16 at 10:22
• @Sp3000 Perhaps Mego means that by defining (for example) p,q=divmod(x,3);r,s=divmod(y,3), Dhruv could save bytes in k(y//3-x//3)+k(y%3-x%3 by changing to k(r-p)+k(s-q). In addition, I think you can remove int and just have (max(x,y)%3==2) – Sherlock9 May 22 '16 at 11:39
• @Sherlock9 The thing is, p,q=x//3,x%3 is always better than p,q=divmod(x,3), even in Python 3 – Sp3000 May 22 '16 at 11:47
• @DrGreenEggsandHamDJ Python lambdas don't support multiple assignment. He'd lose a lot of bytes without those definitions. – Sherlock9 May 23 '16 at 11:14

Jelly, 13 bytes

+2\$.¹?€d3ạ/SḞ

Try it online!

Port of my Pyth answer.

Test suite.

JavaScript (ES6), 59

Unfortunately, no divmod in javascript. In fact, no integer div, and no mod either: the % is not exactly mod. But for once, the weird behaviour of % with negative numbers is useful.

(a,b,A=Math.abs)=>A(~(--a/3)-~(--b/3))+A(a%3-b%3)-(a*b%3<0)

Test

f=(a,b,A=Math.abs)=>A(~(--a/3)-~(--b/3))+A(a%3-b%3)-(a*b%3<0)

for(i=0;i<10;console.log(r),i++)
for(r='',j=0;j<10;j++)
r+=[i,j,f(i,j)]+' '

• So, this ends up calculating as if 0 is to the left of 1 instead of below it, and then the (a*b%3<0) is the sneaky adjustment for the second 0. Nice! – Neil May 22 '16 at 8:54

Pyth, 2221 19 bytes

FGITW.

L.D?b+2b.5 3ssaMCyM

Test suite.

Conversion table:

0: [0.0, 0.5]
1: [1, 0]
2: [1, 1]
3: [1, 2]
4: [2, 0]
5: [2, 1]
6: [2, 2]
7: [3, 0]
8: [3, 1]
9: [3, 2]

Julia, 56 bytes

x->sum(abs(-([[divrem(t>0?t+2:.5,3)...]for t=x]...)))÷1

Try it online!

Python 2, 61 bytes

lambda x,y:abs(x/-3-y/-3)+abs((x or 1.5)%-3-(y or 1.5)%-3)//1

Test it on Ideone.

How it works

• Vertical distance

Integer division always round down to the nearest integer in Python, yielding the following results for the 10 possible dividends divided by -3.

0  1  2  3  4  5  6  7  8  9
0 -1 -1 -1 -2 -2 -2 -3 -3 -3

Thus, we can compute the vertical distance between x and y as abs(x/-3-y/-3).

• Horizontal distance

For columns, we can avoid treating 0 as a special case by replacing it with 1.5, thus placing it "between" the first and second column.

Modulus (%) always has the sign of the divisor in Python, yielding the following results for the 10 possible dividend modulo -3.

0  1  2  3  4  5  6  7  8  9
-1.5 -2 -1  0 -2 -1  0 -2 -1  0

Thus, by rounding down (//1) the result of abs((x or 1.5)%-3-(y or 1.5)%-3), we can compute the horizontal difference between x and y.

Java 149 160 chars

The obligatory: Because... you know... Java! Having fun with Java in under 150 161 chars:

int d(int f,int t){if(f==t)return 0;if(Math.min(f,t)==0){int m=Math.max(f,t);return Math.min(d(1,m),d(2,m))+1;}return Math.abs(--t%3- --f%3)+Math.abs(t/3-f/3);}

Ungolfed into a class:

public class Q80357 {

static int distance(int from, int to) {
if (from == to)
return 0;
if (Math.min(from, to) == 0) {
int max = Math.max(from, to);
return Math.min(distance(1, max), distance(2, max)) + 1;
}
return Math.abs(--to % 3 - --from % 3) + Math.abs(to / 3 - from / 3);
}
}

How it works

First it catches the standard case where we don't have to move anywhere.

Now we can assume that both integers differ, thus only the smaller one can be 0. If this is the case we calculate the distance from key 1 and 2 to the other key. We will use the one with the shorter distance and add one step to get from 1 or 2 to 0.

If we don't want to go to/from zero we only have to move in the 3x3 grid. We can determine the column and row of the key by using mod or div respectively. Then we calculate the column and row distance and add them. This is the distance we need to get from one key to another.

I hope the explanation could be understood, feel free to golf :)