Return neighbors index in an 3x3 grid

11

1

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

hcorion

Posted 2017-03-26T02:39:33.063

Reputation: 143

4

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?

– Poke – 2017-03-26T02:53:16.340

7Just 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. – Dennis – 2017-03-26T03:35:03.160

1Can the output be a list of numbers, e.g. [0,4,6] instead of 046? – Laikoni – 2017-03-26T07:42:37.327

@Laikoni Yes, a little bit too late because you've already answered it. – hcorion – 2017-03-26T21:59:49.903

@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. – hcorion – 2017-03-26T22:03:23.873

Answers

2

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.

Dennis

Posted 2017-03-26T02:39:33.063

Reputation: 196 637

The rules state: "The pretend array's index can start at 0 or 1." - you can drop the Decrement at the end. – steenbergh – 2017-03-26T05:57:50.687

@steenbergh I assume I'd have to take 1-based input as well then, which costs as many bytes as it saves. – Dennis – 2017-03-26T12:41:54.150

9

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]

Luis Mendo

Posted 2017-03-26T02:39:33.063

Reputation: 87 464

1Wat? How did you come up with this? – Robert Fraser – 2017-03-26T18:38:03.693

1@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 – Luis Mendo – 2017-03-26T18:48:22.487

5

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

Not a tree

Posted 2017-03-26T02:39:33.063

Reputation: 3 106

Gotta love those builtins... – Neil – 2017-03-27T20:43:17.750

4

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?

Greg Martin

Posted 2017-03-26T02:39:33.063

Reputation: 13 940

3I'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. – HyperNeutrino – 2017-03-26T05:28:16.463

2You can save a byte by using 0-indexing and 31[420,51,...,75][[#]]&. – Martin Ender – 2017-03-26T08:27:57.420

1You can use GridGraph@{3,3}~AdjacencyList~#& for 32 bytes, with 1-indexing. – Not a tree – 2017-03-27T00:54:37.707

@lanlock4 Awesome! Please make that an answer so I can upvote it! – Greg Martin – 2017-03-27T02:41:02.267

4

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

rahnema1

Posted 2017-03-26T02:39:33.063

Reputation: 5 435

3

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!

ovs

Posted 2017-03-26T02:39:33.063

Reputation: 21 408

2

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

Steadybox

Posted 2017-03-26T02:39:33.063

Reputation: 15 798

2In 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? – Neil – 2017-03-27T00:07:24.817

@Neil Yes I can. Thanks! – Steadybox – 2017-03-27T10:06:16.483

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?

– Kevin Cruijssen – 2017-03-27T11:10:33.283

1@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. – Steadybox – 2017-03-27T13:23:22.817

@Steadybox Ah, you're indeed right. I missed the 1-indexed part, my bad. Thanks for adding the TIO. +1 – Kevin Cruijssen – 2017-03-27T13:56:54.240

2

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.

Laikoni

Posted 2017-03-26T02:39:33.063

Reputation: 23 676

1You can use [n-3,n-1..n+3] and gcd 3n>1. – Ørjan Johansen – 2017-03-26T16:01:45.883

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. – Ørjan Johansen – 2017-03-26T17:47:12.577

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.) – Ørjan Johansen – 2017-03-26T18:02:04.467

2

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.

G B

Posted 2017-03-26T02:39:33.063

Reputation: 11 099

1

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.

Kevin Cruijssen

Posted 2017-03-26T02:39:33.063

Reputation: 67 575

1

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.

G B

Posted 2017-03-26T02:39:33.063

Reputation: 11 099

0

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)

Brian McCutchon

Posted 2017-03-26T02:39:33.063

Reputation: 503

0

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.

Neil

Posted 2017-03-26T02:39:33.063

Reputation: 95 035