8
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ Related. \$\endgroup\$
    – Dennis
    May 22, 2016 at 4:57

8 Answers 8

3
\$\begingroup\$

Jelly, 11 bytes

o-1.’d3ạ/ḞS

Try it online! or verify all test cases.

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.
\$\endgroup\$
1
  • \$\begingroup\$ Nice comeback . \$\endgroup\$
    – Leaky Nun
    May 22, 2016 at 5:45
3
\$\begingroup\$

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)
\$\endgroup\$
6
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – user45941
    May 22, 2016 at 9:00
  • \$\begingroup\$ @Mego How does divmod help? I don't think I've ever saved bytes with that \$\endgroup\$
    – Sp3000
    May 22, 2016 at 10:22
  • \$\begingroup\$ @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) \$\endgroup\$
    – Sherlock9
    May 22, 2016 at 11:39
  • 2
    \$\begingroup\$ @Sherlock9 The thing is, p,q=x//3,x%3 is always better than p,q=divmod(x,3), even in Python 3 \$\endgroup\$
    – Sp3000
    May 22, 2016 at 11:47
  • 1
    \$\begingroup\$ @DrGreenEggsandHamDJ Python lambdas don't support multiple assignment. He'd lose a lot of bytes without those definitions. \$\endgroup\$
    – Sherlock9
    May 23, 2016 at 11:14
2
\$\begingroup\$

Jelly, 13 bytes

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

Try it online!

Port of my Pyth answer.

Test suite.

\$\endgroup\$
2
\$\begingroup\$

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)]+' '

\$\endgroup\$
1
  • \$\begingroup\$ 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! \$\endgroup\$
    – Neil
    May 22, 2016 at 8:54
1
\$\begingroup\$

Pyth, 22 21 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]
\$\endgroup\$
1
\$\begingroup\$

Julia, 56 bytes

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

Try it online!

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

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

Updates

Had to change it into an actual function as it uses recursion which isn't possible with lambdas :,(

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.