11
\$\begingroup\$

Alright, my second attempt at a code golf, let's see how this goes.

Pretend you have an array of 9 values. Now imagine that array in a 3x3 grid.

You need to return neighbors that number has as indexes of the array.

0 | 1 | 2

3 | 4 | 5

6 | 7 | 8

Rules:

  • It's code golf, so shortest answer wins.
  • The pretend array's index can start at 0 or 1. (all examples use 0 though)
  • Just returning values values is frowned upon (like if 3: return 046)
  • The submission can be just a procedure/function/method, but an example would be nice
  • The returned value can be in any order(like if input is 0 it could be 13 or 31)
  • if you want, the output can be a list of numbers, e.g. [0,4,6] instead of 046
  • diagonals don't count, as seen by the examples.

Examples:

input:

0

output:

13

input:

3

output:

046

input:

4

output:

1357

\$\endgroup\$
  • 4
    \$\begingroup\$ It looks like this challenge could benefit from some time in the Sandbox. You can post your challenge there so others can review it and help you out with it before posting it to main. From your examples I'm guessing you're not counting diagonals. You may want to add this to the question itself. You also mention the requirement to output the indexes of the array that are neighbors. I think this could just be hardcoded for a 3x3 grid. Would it maybe be better to output the neighbors themselves? \$\endgroup\$ – Poke Mar 26 '17 at 2:53
  • 7
    \$\begingroup\$ Just so you know, frowned upon isn't really something we do here; hardcoding the output is either allowed or it isn't. Since it's usually pretty hard to define what exactly counts as hardcoding, I'd personally just allow it or give the grid size as an additional input. \$\endgroup\$ – Dennis Mar 26 '17 at 3:35
  • 1
    \$\begingroup\$ Can the output be a list of numbers, e.g. [0,4,6] instead of 046? \$\endgroup\$ – Laikoni Mar 26 '17 at 7:42
  • \$\begingroup\$ @Laikoni Yes, a little bit too late because you've already answered it. \$\endgroup\$ – hcorion Mar 26 '17 at 21:59
  • \$\begingroup\$ @Dennis Yes, I wasn't quite sure how to put it. I like how the C and python answers did it, by providing both, but having the non-hard coded answer as the final. I wanted to encourage algorithms rather than hard-coding, but I wasn't sure if it was even possible (without overly long answers), and I didn't want to have no answers to my question. \$\endgroup\$ – hcorion Mar 26 '17 at 22:03

13 Answers 13

2
\$\begingroup\$

Jelly, 16 13 bytes

9Ḷ,d3ạ/S€=1T’

Try it online!

How it works

9Ḷ,d3ạ/S€=1T’  Main link. Argument: n (0, ..., 8)

9              Set the return value to 9.
 Ḷ             Unlength; yield [0, ..., 8].
  ,            Pair; yield [[0, ..., 8], n].
   d3          Divmod 3; yield [[[0, 0], ..., [2, 2]], [n:3, n%3]]].
     ạ/        Reduce by absolute difference, yielding
               [[|0 - n:3|, |0 - n%3|], ..., [[|2 - n:3|, |2 - n%3|]].
       S€      Sum each, yielding
               [|0 - n:3| + |0 - n%3|, ..., [|2 - n:3| + |2 - n%3|].
         =1    Compare the sums with 1.
           T   Truth; yield all 1-based indices of 1.
            ’  Decrement to yield all 0-based indices of 1.
\$\endgroup\$
  • \$\begingroup\$ The rules state: "The pretend array's index can start at 0 or 1." - you can drop the Decrement at the end. \$\endgroup\$ – steenbergh Mar 26 '17 at 5:57
  • \$\begingroup\$ @steenbergh I assume I'd have to take 1-based input as well then, which costs as many bytes as it saves. \$\endgroup\$ – Dennis Mar 26 '17 at 12:41
9
\$\begingroup\$

MATL, 17 16 bytes

9:qWIe1Y6Z+i)BPf

The array is 1-based, that is, contains numbers from 1 to 9.

Try it online! Or verify all test cases.

Explanation

Consider input 2 as an example.

9:q  % Push [0 1 2 ... 8]
     % STACK: [0 1 2 ... 8]
W    % Rise to 2, element-wise
     % STACK: [1 2 4 ... 256]
Ie   % Reshape as 3-row matrix (column-major order)
     % STACK: [1   8  64;
               2  16 128;
               4  32 256]
1Y6  % Push [0 1 0; 1 0 1; 0 1 0]
     % STACK: [1   8  64;
               2  16 128;
               4  32 256],
              [0   1   0;
               1   0   1;
               0   1   0]
Z+   % Convolution, maintaining size
     % STACK: [10  81 136;
               21 170 336;
               34 276 160]
i    % Take input, n
     % STACK: [10  81 136;
               21 170 336;
               34 276 160],
               2
 )   % Get n-th entry (1-based; column-major order)
     % STACK: 21
B    % Convert to binary
     % STACK: [1 0 1 0 1]
P    % Flip
     % STACK: [1 0 1 0 1]
f    % Find: gives indices of nonzeros. Implicitly display
     % STACK: [1 3 5]
\$\endgroup\$
  • 1
    \$\begingroup\$ Wat? How did you come up with this? \$\endgroup\$ – Robert Fraser Mar 26 '17 at 18:38
  • 1
    \$\begingroup\$ @RobertFraser These challenges about finding neighbours always suggest to me a convolution approach. But convolution inherently adds the neighbours' values, so I needed to be able to separate them at the end---that's the powers-of-two and binary expansion parts \$\endgroup\$ – Luis Mendo Mar 26 '17 at 18:48
5
\$\begingroup\$

Mathematica, 32 bytes

GridGraph@{3,3}~AdjacencyList~#&

Uses a graph instead of an array. GridGraph@{3,3} constructs a 3x3 grid-shaped graph, shown below, which Mathematica helpfully labels with the numbers 1–9 for the vertices by default. Then ~AdjacencyList~#& tells you the neighbours of a vertex.

The 3x3 grid graph

\$\endgroup\$
  • \$\begingroup\$ Gotta love those builtins... \$\endgroup\$ – Neil Mar 27 '17 at 20:43
4
\$\begingroup\$

Mathematica, 40 bytes

{24,135,26,157,2468,359,48,579,68}[[#]]&

1-indexed. Just looks up the answer. Can someone do better in Mathematica?

\$\endgroup\$
  • 3
    \$\begingroup\$ I'm surprised that there isn't a builtin for this. Like I'd expect there to be a builtin to find all neighbors of an element in a 2D array, but I'm not sure, I don't know anything about Mathematica other than the fact that it has too many builtins. \$\endgroup\$ – HyperNeutrino Mar 26 '17 at 5:28
  • 2
    \$\begingroup\$ You can save a byte by using 0-indexing and 31[420,51,...,75][[#]]&. \$\endgroup\$ – Martin Ender Mar 26 '17 at 8:27
  • 1
    \$\begingroup\$ You can use GridGraph@{3,3}~AdjacencyList~#& for 32 bytes, with 1-indexing. \$\endgroup\$ – Not a tree Mar 27 '17 at 0:54
  • \$\begingroup\$ @lanlock4 Awesome! Please make that an answer so I can upvote it! \$\endgroup\$ – Greg Martin Mar 27 '17 at 2:41
4
\$\begingroup\$

Octave, 42 40 39 bytes

@(n,x=~e(3),y=x(n)=1)find(bwdist(x)==1)

1-based index.

Verify all test cases.

Explanation:

x=~e(3);         % create a 3*3 matrix of zeros
x(n)=1;          % set the element with index n to 1
d=bwdist(x);     % compute the distance transform of the matrix
find(d == 1)     % find where the distance is 1.

Example: n = 2

x =

   0   0   0
   1   0   0
   0   0   0

(In Octave data is stored column-wise.)

d =

   1.00000   1.41421   2.23607
   0.00000   1.00000   2.00000
   1.00000   1.41421   2.23607

logical index where distance is 1:

d == 1

 1   0   0
 0   1   0
 1   0   0

find(d ==1)

 1
 3
 5
\$\endgroup\$
3
\$\begingroup\$

Python 2, 71 bytes

lambda n:filter(abs,[(n-3)*(n>3),(n+3)*(n<7),~-n*(n%3!=1),-~n*(n%3>0)])

1-indexed
Try it online!


Getting the result from a predefined list of results is shorter (46 bytes):

[13,204,15,406,1357,248,37,468,57].__getitem__

0-indexed
Try it online!

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

Haskell, 74 71 68 bytes

f n=[x|x<-[n-3,n-1..n+3],0<x,x<10,gcd 3x<2||n-1/=x,gcd 3n<2||n+1/=x]

Try it online! Uses a 1-indexed grid. Example usage: f 3 returns [2,6].

Edit: Saved 3 6 bytes thanks to Ørjan Johansen!


For 77 75 bytes, the following function # works for an arbitrary grid size m:

n#m=[x|x<-[n-m,n-1,n+1,n+m],0<x,x<=m*m,gcd x m<m||n-1/=x,gcd n m<m||n+1/=x]

Try it online! For each n the list [n-m,n-1,n+1,n+m] contains all four neighbours. For each entry x in this list we check -1<x and x<m*m to make sure x is not above or below the grid, mod n 3>0||n-1/=x to enforce the left grid border and mod(n+1)m>0||n+1/=x for the left border.

\$\endgroup\$
  • 1
    \$\begingroup\$ You can use [n-3,n-1..n+3] and gcd 3n>1. \$\endgroup\$ – Ørjan Johansen Mar 26 '17 at 16:01
  • \$\begingroup\$ Oops, never mind that gcd part. It should have been <3, and then breaks for n==0. You might be able to use that trick if you change everything to 1-indexed. \$\endgroup\$ – Ørjan Johansen Mar 26 '17 at 17:47
  • \$\begingroup\$ Oh, and the n/=2&&n/=5 can be replaced by mod x 3>0. (Or the gcd version with reindexing, which might now be used twice.) \$\endgroup\$ – Ørjan Johansen Mar 26 '17 at 18:02
2
\$\begingroup\$

Ruby, 51 48 45 bytes

->a{[a+3,a-3][a/6..a/3]+[a+1,a-1][a%-3..a%3]}

Try it online!

Create 2 arrays, with vertical and horizontal neighbours, then select one or more of them.

Ruby hardcoded, 44 bytes

->a{%w(13 024 15 046 1357 248 37 468 57)[a]}

... Not worth it.

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

C, 100 92 91 83 78 74 bytes

p(n){putchar(n+48);}f(n){n>3&&p(n-3);n<7&&p(n+3);n%3&&p(n+1);--n%3&&p(n);}

1-indexed. Thanks to @Neil for saving 4 bytes.

Try it online!

Hardcoded version, 56 bytes

l[]={13,204,15,406,1357,248,37,468,57};
#define L(n)l[n]

0-indexed

\$\endgroup\$
  • 2
    \$\begingroup\$ In the first version, can you not write n>3&&p(n-3) etc. to save 4 bytes? In the second version, can you not write l[]= to save a byte? \$\endgroup\$ – Neil Mar 27 '17 at 0:07
  • \$\begingroup\$ @Neil Yes I can. Thanks! \$\endgroup\$ – Steadybox Mar 27 '17 at 10:06
  • \$\begingroup\$ Are you sure your code is currently correct? When I try the test cases it fails for all three.. :S Try it here. Could you perhaps provide a working TIO-link, perhaps I'm doing something wrong? \$\endgroup\$ – Kevin Cruijssen Mar 27 '17 at 11:10
  • 1
    \$\begingroup\$ @KevinCruijssen TIO link added, and it seems that I forgot to edit the actual code on the last edit... Oh, well. Your link is working correctly too, but notice that my answer is 1-indexed whereas the example test cases are 0-indexed. \$\endgroup\$ – Steadybox Mar 27 '17 at 13:23
  • \$\begingroup\$ @Steadybox Ah, you're indeed right. I missed the 1-indexed part, my bad. Thanks for adding the TIO. +1 \$\endgroup\$ – Kevin Cruijssen Mar 27 '17 at 13:56
1
\$\begingroup\$

Python 2, 51 bytes

lambda x:[x+3,x-3][x/6:x/3+1]+[x+1,x-1][x%-3:x%3+1]

Based on a previous version of my Ruby answer, I found it interesting because it was mostly the same code, using a different trick, and produces the same result. Getting this one right helped me golf the ruby answer a little more.

Basically, ruby has it shorter because the array slice index are inclusive, python needs a +1 to compensate.

Explanation

Get the 2 arrays (vertical and horizontal neighbours), then select one or both based on some calculations.

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

Java 7, 63 bytes (hardcoded)

int c(int i){return new int[]{31,420,51,640,7531,842,73,864,75}[i];}

0-indexed
(Reversed order output because 024 and 046 aren't valid integers.)
Still working on a non-hardcoded version, but I can assure you it won't be shorter..

Try it here.


82 bytes

String c(int n){return""+(n>3?n-3:"")+(n<7?n+3:"")+(n%3>0?n+1:"")+(--n%3>0?n:"");}

1-indexed
Based on @Steadybox' C answer

Try it here.

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

JavaScript + lodash, 71 bytes

f=a=>_.range(9).filter(b=>a>b?f(b).includes(a):[,1,,1][b-a]&&b%3|a%3<2)
\$\endgroup\$
0
\$\begingroup\$

Batch, 116 bytes

@set c=cmd/cset/a%1
@set/ar=%1%%3
@if %1 gtr 2 %c%-3
@if %r% gtr 0 %c%-1
@if %r% lss 2 %c%+1
@if %1 lss 6 %c%+3

0-indexed.

\$\endgroup\$

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.