20
\$\begingroup\$

Given an integer from 1 to 999 inclusive, output a truthy value if it appears horizontally, vertically, or diagonally, either forwards or backwards, anywhere in the 3x3 square of digits 1-9 on a standard number pad:

789
456
123

If the number does not appear, output a falsy value.

The exact 65 numbers you need to output truthy for are:

1
2
3
4
5
6
7
8
9
12
14
15
21
23
24
25
26
32
35
36
41
42
45
47
48
51
52
53
54
56
57
58
59
62
63
65
68
69
74
75
78
84
85
86
87
89
95
96
98
123
147
159
258
321
357
369
456
654
741
753
789
852
951
963
987

Everything else is falsy.

The shortest code in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ Relevant OEIS. \$\endgroup\$ – Fatalize Dec 4 '16 at 14:41
  • \$\begingroup\$ The input may contain 0, it can be a string. \$\endgroup\$ – Calvin's Hobbies Dec 4 '16 at 19:43
  • \$\begingroup\$ I see Luis Mendo showing up with a MATL answer in the near future heh. \$\endgroup\$ – Magic Octopus Urn Dec 5 '16 at 13:32
16
\$\begingroup\$

JavaScript (ES6), 83 ... 74 73 bytes

Takes input as a string.

n=>1/([a,b,c]=[...n].map(v=>--v+v/3|0))||45242>>(a^b)&(~c&&n<99|b*2==a+c)

Saved 3 bytes thanks to ETHproductions

How it works

We transform the number pad by applying an offset to each digit according to the row it belongs to:

  • +1 for the top row
  • 0 for the middle row
  • -1 for the bottom row.

All codes below are represented in hexadecimal.

7 8 9      8 9 A  (+1)
4 5 6  =>  4 5 6  (unchanged)
1 2 3      0 1 2  (-1)

Let's consider all XOR combinations of these new key codes. Contiguous keys are highlighted with brackets.

XOR|  0   1   2   4   5   6   8   9   A 
---+------------------------------------
 0 |  0  [1]  2  [4] [5]  6   8   9   A 
 1 | [1]  0  [3] [5] [4] [7]  9   8   B 
 2 |  2  [3]  0   6  [7] [4]  A   B   8 
 4 | [4] [5]  6   0  [1]  2  [C] [D]  E 
 5 | [5] [4] [7] [1]  0  [3] [D] [C] [F]
 6 |  6  [7] [4]  2  [3]  0   E  [F] [C]
 8 |  8   9   A  [C] [D]  E   0  [1]  2 
 9 |  9   8   B  [D] [C] [F] [1]  0  [3]
 A |  A   B   8   E  [F] [C]  2  [3]  0 

We can see that two keys are contiguous if and only if XORing their codes leads to one of the following values:

1, 3, 4, 5, 7, C, D, F

This list can be packed into the following binary mask:

  FEDCBA9876543210
  ----------------
0b1011000010111010 = 0xB0BA = 45242

Hence the test to determine if two key codes (a, b) correspond to two contiguous keys:

45242 >> (a ^ b) & 1

For three key codes (a, b, c), we need this additional test:

b * 2 == a + c

Example:

a = 0xA
b = 0x6
c = 0x2

0xB0BA >> (0xA ^ 0x6) & 1 == 0xB0BA >> 0xC & 1 == 1
=> 0xA and 0x6 are contiguous key codes

0x6 * 2 == 0xA + 0x2
=> 0xA, 0x6 and 0x2 are contiguous key codes on the same row, column or diagonal

Demo

This snippet outputs the list of truthy values.

let f =

n=>1/([a,b,c]=[...n].map(v=>--v+v/3|0))||45242>>(a^b)&(~c&&n<99|b*2==a+c)

console.log([...Array(1000).keys()].filter(n=>n && f(n+'')).join(' '))

\$\endgroup\$
  • \$\begingroup\$ Coercion is your friend here: a-.5 returns true for any array a containing (zero or) one integer. n=>([a,b,c]=[...n].map(v=>--v+v/3|0))-.5||n%10&&n<100|b*2==a+c&&45242&1<<(a^b) \$\endgroup\$ – ETHproductions Dec 4 '16 at 20:38
  • \$\begingroup\$ @ETHproductions Ah, nice! 1/a is even shorter and should work just as well, I think. \$\endgroup\$ – Arnauld Dec 4 '16 at 20:56
5
\$\begingroup\$

Python3, 72 bytes

lambda n,s="123 456 789 741 852 963 42 753 86 26 159 84 ":n in s+s[::-1]

Input is taken as a string.

Golfing suggestions welcome! :D

\$\endgroup\$
  • \$\begingroup\$ Does this take the number as a string? \$\endgroup\$ – FlipTack Dec 4 '16 at 18:29
  • \$\begingroup\$ @Flp.Tkc Yes it does. I'll mention that in the post. Thanks! \$\endgroup\$ – Yytsi Dec 4 '16 at 18:54
  • \$\begingroup\$ @TuukkaX there is an additional space in string s, you can save 1 byte. \$\endgroup\$ – Gurupad Mamadapur Dec 5 '16 at 15:38
  • \$\begingroup\$ @GurupadMamadapur I don't see why I would change my current 72 bytes solution to your 74 bytes solution... :D And if you refer to my string s, which has an whitespace after 84, then you're incorrect, since it's required. If it wouldn't contain a whitespace, the resulted string would have a chain '8448', which would lead to failed testcases. Thanks for the suggestions though! \$\endgroup\$ – Yytsi Dec 5 '16 at 22:53
  • \$\begingroup\$ @TuukkaX Yeah you're right about the extra whitespace, missed that one :) \$\endgroup\$ – Gurupad Mamadapur Dec 6 '16 at 9:12
4
\$\begingroup\$

Befunge, 169 161 159 bytes

38*:2+"*0>DTV{51"3*\3*"kV"3*\3*"{w"3*\3*"mr"v
v:\&+*83:++66:+"c":+"?":+"$":++66:+"W":*6\*4<
_v#:\_v#*-+%+55g00*+55g02\*-g02\*-g00\`9::::p02/+55p00%"d":
0<@.!!<

Try it online!

The first two lines are just pushing the list of test numbers onto the stack. This is done in order of size, since it can sometimes be easier to generate a number as an offset from the previous one in the series rather than generating it from scratch. Once we get to the larger numbers, we can also sometimes save a byte by generating them in pairs, e.g. "kV"3*\3* gives us 258 and 321 in nine bytes, where individually they would take five bytes each.

The main loop is on line three, executing right to left with wrap around. This just iterates through all the test numbers on the stack, comparing the value itself, value%100, and value/10. If any of those match the input number or the number <= 9 then we output 1 and exit. If there is no match, we continue looping. If we run out of test numbers on the stack then we output 0 and exit.

Thanks to Mistah Figgins for saving me a couple of bytes.

\$\endgroup\$
  • \$\begingroup\$ I think you can change the last line to 0<@.!!< to save 2 bytes. This relies on the top of the stack being non-zero when the IP comes down onto the second arrow. Try it Online! \$\endgroup\$ – MildlyMilquetoast Dec 5 '16 at 3:10
3
\$\begingroup\$

Jelly, 29 24 19 bytes

Saved 5 bytes thanks to @Dennis's suggestion of K and Ɠ.

9s3µUŒD;;Z;ŒDµ;UKƓẇ

Try it online!

Explanation

9Rs3µUŒD;;Z;ŒDµ;UKƓẇ  Main link. Argument: number
9s3                   Split [1..9] into [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
   µ                  New monadic chain
    U                 Reverse the rows
     ŒD               Take the diagonals of the result
       ;              Append the original rows
        ;Z            Append the original columns
          ;ŒD         Append the original diagonals
             µ        New monadic chain
              ;U      Append the reverse of everything
                K     Join by spaces
                 Ɠẇ   Check if a line from STDIN is in the result
\$\endgroup\$
  • \$\begingroup\$ If you read the input from STDIN, 9s3µUŒD;;Z;ŒDµ;UKƓẇ saves 5 bytes. \$\endgroup\$ – Dennis Dec 4 '16 at 19:02
  • \$\begingroup\$ Do you need to reverse the rows? They can appear forward or backwards, so 123,456,789 should be the same as 789,456,123 \$\endgroup\$ – Riley Dec 5 '16 at 14:41
  • \$\begingroup\$ @Riley I reverse each row, not the rows as an array. I guess I could've been clearer there. Anyway, it's done in order to get half of the diagonals. \$\endgroup\$ – PurkkaKoodari Dec 5 '16 at 14:51
2
\$\begingroup\$

Ruby, 77 bytes

->n{!!((s='123 456 789 147 258 369 753 951 86 62 24 48 ')+s.reverse)["#{n}"]}
\$\endgroup\$
  • \$\begingroup\$ You are creating a string that is '123 456 789 147 258 369 753 951 ' + the same string reversed, and checking whether the parameter is found on the string, right? If it's so, then this solution is invalid. For example, 86 and 24 will fail. \$\endgroup\$ – Yytsi Dec 4 '16 at 15:26
  • \$\begingroup\$ The rules say you need only output a truthy or falsey value, so you don't need !! or the attendant parentheses. \$\endgroup\$ – Jordan Dec 5 '16 at 1:22
0
\$\begingroup\$

bash, 75

printf %s\\n 123 456 789 741 852 963 42 753 86 26 159 84|tee >(rev)|grep $1

outputs something and returns 0 for all the values in that list

prints nothing and returns 1 in all other cases

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

Java, 397 bytes

public class Numpad {public static void main(String[] args){Scanner input=new Scanner(System.in);int in=input.nextInt();int h=in/100;int u=in%10;int t=(in%100)/10;boolean out=false;input.close();if(in<10)out=true;else if( h==0){int decider=Math.abs(t-u);if((decider==1)||(decider==3)||(decider==4))out=true;}else{if ( Math.abs(h-t) == Math.abs(t-u))out=true;}System.out.println("RESULT : "+out);}}
\$\endgroup\$
  • \$\begingroup\$ I am new to this .. kindly excuse any oblivionism. \$\endgroup\$ – Nefi knomore Dec 7 '16 at 4:37
  • \$\begingroup\$ Hello, and welcome to the site! I've edited your post so that the code section is displayed as code and added a byte count, which is standard for answers here. This competition is a code-golf competition, meaning the ultimate goal is to make your code as short as possible. For example, you can use short variable names, and define a function instead of a full class. I'm not great at Java, but some more tips are available here. You should try to make your code shorter, and then edit the new version into your post. \$\endgroup\$ – DJMcMayhem Dec 7 '16 at 4:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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