# Sum up snail number neighbours

Input: You are given two numbers n and m.

Create the snail: Given an n >= 3, fill an n * n grid with the numbers from 1 to n * n, starting at the top left, going clockwise to the middle like this (for n = 5):

 1  2  3  4  5
16 17 18 19  6
15 24 25 20  7
14 23 22 21  8
13 12 11 10  9


Calculate the sum of the neightbours of m: for 4*n – 4 < m <= n*n, calculate the sum of the eight neighbour numbers in the snail. In the 5 * 5 example, for m= 17, this would be:

1+2+3+16+18+15+24+25 = 104


Output: Only the sum

Test cases:

4,14 --> 64
5,17 --> 104
5,25 --> 164
6,24 --> 112
6,30 --> 176
6,32 --> 200
6,33 --> 234


Win by finding the shortest code for your language of choice!

• Are we allowed to use a 0-indexed spiral? Feb 23 at 6:34
• @Mukundan314 Of course you can; then simply add 8 to the sum to get the correct result. You can even create no spiral at all if you find another way to get the correct sum. Feb 23 at 6:46
• Related Feb 23 at 7:57
• If you say that 0-indexed spirals are allowed, if only by adding 8, then what if the cell m has fewer than 8 neighbors like in the corner? Feb 23 at 19:08
• @Marius_Couet I added n>=3. Thank you. Mar 7 at 14:12

# MATL, 19 bytes

UQG1YL-t3Y6Z+wi=*Xz


Try it at MATL online!

### How it works

UQ     % Implicit input: n. Square, add 1
G      % Push n again
1YL    % Generate spiral with side length n, from 1 to to n^2 outwards
-      % Subtract, element-wise. The spiral is now from 1 to n^2 inwards
t      % Duplicate
3Y6    % Push predefined literal: [1 1 1; 1 0 1; 1 1 1]
Z+     % 2D convolution, preserving size. This computes the sums
w      % Swap. This moves the spiral to the top of the stack
i=     % Input: m. Compare for equality, element-wise
*      % Multiply, element-wise. This keeps the wanted sum, and makes the rest 0
Xz     % Nonzeros. This keeps the only non-zero value. Implicit display

• This assumes m is excluded, as in most of the test cases. To include it, 3 should be replaced by 4. The code works even if m is on the rim of the square (pending clarifications by Philippos) Feb 23 at 17:20
• m was defined to always having eight neighbours, so your solution even over-targets the question. And it beats my expectations: I hoped I finally found a simple question which can't be solved with a few hand full of bytes, then you did even beat the 05AB1E answer. Congratulations to the clever implementation! Feb 26 at 7:16
• @Philippos Thanks! Having a spiral builtin (inherited from Matlab) helps :-) Feb 26 at 10:52

# 05AB1E, 31/32†bytes

¯I·FāUøí¬g+Xš}2Fø€ü3}€ʒ˜4èQ}˜O


Inputs in the order $$\n,m\$$.

31 bytes - sum including $$\m\$$: Try it online or verify all test cases.
32 bytes - sum excluding $$\m\$$: Try it online or verify all test cases. (Contains an additional trailing α.)

Explanation:

Step 1: Create the spiral matrix for the given $$\n\$$, taken from this answer of mine:

¯             # Start with an empty list []
I·           # Push the first input n and double it
F          # Pop and loop that many times:
ā         #  Push a list in the range [1,length] (without popping the matrix)
U        #  Pop and store this list in variable X
øí      #  Rotate the matrix 90 degrees clockwise:
ø       #   Zip/transpose; swapping rows/columns
í      #   Reverse each row
¬     #  Push the first row (without popping the matrix)
g    #  Pop and push its length
+   #  Add that to each value in the matrix
Xš #  Prepend list X as first row
}          # Close the loop


Step 2: Create overlapping 3x3 blocks of this matrix:

2F            # Loop 2 times:
ø           #  Zip/transpose; swapping rows/columns
€          #  Map over each inner list:
ü3        #   Create overlapping triplets
}            # Close the loop


Step 3: Only keep the 3x3 block with $$\m\$$ in the center:

€            # Flatten the matrix of 3x3 blocks one level down to a list of 3x3 blocks
ʒ           # Filter this list by:
˜          #  Flatten the 3x3 block to a list of 9 values
4è        #  Pop and leave the 0-based 4th item (the center)
Q       #  Check whether it equals the second (implicit) input m
}           # Close the filter


Step 4: Sum the found 3x3 block, and output the result:

˜             # Flatten the single wrapped 3x3 block to a list
O            # Sum it together
α           # (optionally) Take the absolute difference with the second (implicit)
# input m to subtract m from this sum
# (after which this is output implicitly as result)


# R, 116 bytes

\(n,k){m=t(1)
while(F<n)m=rbind(1:n,(F=nrow(m))+t(m[F:1,]))
sum(m[t(t(expand.grid(-1:1,-1:1))+c(which(m==k,T)))])-k}


Attempt This Online!

Uses some code from the spiral challenge.

# J, 55 54 bytes

([-~1#.]#&,~[:+/(>,{;~i:1)|.=)+:@<:_&(]#\,#+|:@|.),.@1


Try it online!

Uses Bubbler's clever APL/Jelly method from an old problem for constructing the involute itself.

Consider input 17 f 5:

• +:@<:_&(]#\,#+|:@|.),.@1 Construct the involute iteratively using Bubbler's method (see link above for explanation):

1  2  3  4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

• = Where does the left input equal that?

0 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

• [:+/(>,{;~i:1)|. Rotate that in the 8 neighbor directions, and sum the planes:

1 1 1 0 0
1 1 1 0 0
1 1 1 0 0
0 0 0 0 0
0 0 0 0 0

• 1#.]#&,~ Filter using that mask and sum:

121

• [-~ Subtract the left input (17):

104


# JavaScript (ES6), 174 bytes

Derived from this answer by tsh to this other challenge.

Expects (n)(m).

n=>m=>(g=(s,[l]=t=s[0])=>l>1?g([0,...t].map((_,i)=>s.map((r,x)=>(v=r[i-1]||--l)-m?v:(X=x,Y=i,v)).reverse())):s)([[n*n]]).map((r,y)=>r.map(v=>m-=v*=--x*x+y*y<3,x=n-X,y-=Y))|-m


Try it online!

# Charcoal, 60/62 bytes

Ｆ⊗Ｎ≔⁺⟦Ｅυ⊕λ⟧Ｅ∧υ⌊υ⁺ＬυＥ⮌υ§μλυＮθ≔⊟Φυ№ιθηＩΣＥΦυ‹↔⁻κ⌕υη²ΣΦι‹↔⁻μ⌕ηθ²


Try it online! Link is to verbose version of code. Explanation:

Ｆ⊗Ｎ≔⁺⟦Ｅυ⊕λ⟧Ｅ∧υ⌊υ⁺ＬυＥ⮌υ§μλυ


Input n and generate the spiral using the method from my answer to Print a NxN integer involute except 1-indexed.

Ｎθ≔⊟Φυ№ιθη


Input m and find the row containing m in the spiral.

ＩΣＥΦυ‹↔⁻κ⌕υη²ΣΦι‹↔⁻μ⌕ηθ²


Extract the neighbours of m and output the sum.

Note that the 5, 17 test case includes the 17 itself in the total; if this is not wanted then it can be subtracted at a cost of 2 bytes:

Ｆ⊗Ｎ≔⁺⟦Ｅυ⊕λ⟧Ｅ∧υ⌊υ⁺ＬυＥ⮌υ§μλυＮθ≔⊟Φυ№ιθηＩ⁻ΣＥΦυ‹↔⁻κ⌕υη²ΣΦι‹↔⁻μ⌕ηθ²θ


Try it online! Link is to verbose version of code.

Assuming $$\n\$$ is in A1 and $$\m\$$ is in A2.

=SUMPRODUCT(LET(n,A1,s,SEQUENCE(n,n),t,TOCOL(SPLIT(REDUCE(s,s,LAMBDA(x,_,LET(r,INDEX(x,1),a,FILTER(x,r),HSTACK(JOIN(",",r),SORT(TRANSPOSE(QUERY(a,"offset 1")),SEQUENCE(COLUMNS(a)),))))),","),3),p,XLOOKUP(s,{t;INDEX(t,n*n-1)+IF(ISODD(n),1,-1)},TOCOL(s)),x,TEXTJOIN(,,IF(p=A2,SEQUENCE(n)&","&SEQUENCE(1,n),)),i,SPLIT(x,","),r,INDEX(i,1),k,INDEX(i,2),p*MAKEARRAY(n,n,LAMBDA(i,j,ISBETWEEN(i,r-1,r+1)*ISBETWEEN(j,k-1,k+1)))))-A2


Ungolfed

// Create the spiral

=LET(n,A1,s,SEQUENCE(n,n),
t,TOCOL(
SPLIT(REDUCE(s,s,LAMBDA(x,_,
LET(r,INDEX(x,1),a,FILTER(x,r),
HSTACK(JOIN(",",r),
SORT(TRANSPOSE(QUERY(a,"offset 1")),SEQUENCE(COLUMNS(a)),))))),
","),3),
p,XLOOKUP(s,{t;INDEX(t,n*n-1)+IF(ISODD(n),1,-1)},TOCOL(s)),

// Find the coordinates of m

x,TEXTJOIN(,,IF(p=A2,SEQUENCE(n)&","&SEQUENCE(1,n),)),

// Assign them to (r,k)

i,SPLIT(x,","),r,INDEX(i,1),k,INDEX(i,2),

// Create a nxn array composed of 1s in the 3x3 array around (r,k) and 0s everywhere else and multiply it by the spiral

p*MAKEARRAY(n,n,LAMBDA(i,j,ISBETWEEN(i,r-1,r+1)*ISBETWEEN(j,k-1,k+1))))

// Array enabling sum on the above result to which we subtract m

SUMPRODUCT(all_of_the_above)-A2
$$$$


# UiuaSBCS, 47 bytes

-:/+♭⍜↻(↙3_3)-1♭⊚⌕⊙.:+1⍥(⊂⇡⟜(≡⇌⍉+)⧻.):¤[]-1+.⊙.


Try it!

# APL+WIN, 106 bytes

Prompts for n followed by m:

a←1 1⍴1⋄i←1⋄⍎∊(¯1+n←⎕)⍴⊂'a←(⍳i+1)⍪⌽⍉(i+1)+(⍳i)⍪⌽⍉a+i⋄i←i+1⋄'⋄+/((,a)[(k-n),(k+n),(k←((,a)⍳m)+¯1 0 1)])~m←⎕


Try it online! Thanks to Dyalog Classic

# JavaScript (Node.js), 137 bytes

n=>h=(v,i,j=n,g=(x=i,y=j,w=n,h=w)=>y?w+g(y-1,w+~x,h-1,w):x+1)=>j--?h(v,i,j)+(1/i?(v.i-i)**2+(v.j-j)**2<3?g():g()==v&&h({i,j})-v:h(v,j)):0


Try it online!

g() gets the number at position (x,y)

Q, 169 Bytes

Golfed:

b:1 0 -1 0;d:0;c:0 0;s:n#(,)n#0;a:{c+{x d}'[(0,b;b)]};{.[s;c;:;x];if[x=m;l::c];if[0<>.[s;n:a[]];d::mod[d+1;4];n:a[]];c::n}'[1+til n*n];sum[(s/')[(cross/){x+3#b}'[l]]]-m


Ungolfed:

snail: n#enlist n#0;   // create an n x n array (the "snail") where each cell has value 0; it's populated properly below
direction: 0;          // 0=right, 1=down, 2=left, 3=up
current_cell: 0 0;     // the row/column of the current cell to populate in the n x n array
m_cell: -1 -1;         // the row/column of the cell in the n x n array whose value is m

// given a 2-item list returns the value of the snail cell at the row & column; returns null (0N) if there is no such row or column

// returns the row + index (2-item list) of the cell after "current_cell" that should be populated given the current value of "direction"
get_next_cell: { (current_cell[0] + (0 1 0 -1)[direction]; current_cell[1] + (1 0 -1 0)[direction]) };

// loop through integers in range [1..n x n] to populate the snail
{
// set value of current_cell in the snail to the current integer in the loop
snail:: .[snail; current_cell; :; x];

// record m_cell if the current integer in the loop is "m
if[x=m; m_cell:: current_cell];

// calculate the next cell
next_cell: get_next_cell[];

// if the calculated next cell has a non-zero value, either:
//      * the value is 0N, meaning we've gone past the bounds of the n x n array or
//      * the value is a positive integer, meaning the cell has already been populated
// in which case we change direction and re-calculate the next cell
direction:: (direction + 1) mod 4;
next_cell: get_next_cell[];
];

current_cell:: next_cell;
} each 1+til n*n;

// "return" the difference between (a) the sum of all 9 cells in the 3x3 square centered on m_cell and (b) m
sum[read_cell each .[cross]{x + -1 0 1} each m_cell] - m


# AWK, 216 212 193 bytes

func f(){r=$2-(g[x,y]=++c)?r:-g[m=x,n=y]}{for(x=y=0;i++<$1;y++)f();for(y--;s++<$1;){for(i=s;i++<$1;)f(x+=t=s%2?1:-1);for(i=s;i++<$1;)f(y-=t)}for(i=m-2;++i<m+2;)for(j=n-1;j<n+2;)r+=g[i,j++]}$0=r


Try it online!

• -4 bytes, used ternary operator (exp?a:b) instead of if statement and replaced == with - expression.
• -19 bytes, replaced ternary operation with function.
• 184 bytes Mar 16 at 17:36