15
\$\begingroup\$

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!

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Are we allowed to use a 0-indexed spiral? \$\endgroup\$ Feb 23 at 6:34
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – Philippos
    Feb 23 at 6:46
  • \$\begingroup\$ Related \$\endgroup\$
    – Arnauld
    Feb 23 at 7:57
  • \$\begingroup\$ 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? \$\endgroup\$
    – Fmbalbuena
    Feb 23 at 19:08
  • 1
    \$\begingroup\$ @Marius_Couet I added n>=3. Thank you. \$\endgroup\$
    – Philippos
    Mar 7 at 14:12

12 Answers 12

4
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ 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) \$\endgroup\$
    – Luis Mendo
    Feb 23 at 17:20
  • 1
    \$\begingroup\$ 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! \$\endgroup\$
    – Philippos
    Feb 26 at 7:16
  • 1
    \$\begingroup\$ @Philippos Thanks! Having a spiral builtin (inherited from Matlab) helps :-) \$\endgroup\$
    – Luis Mendo
    Feb 26 at 10:52
3
\$\begingroup\$

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)
\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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
    
\$\endgroup\$
2
\$\begingroup\$

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!

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

Charcoal, 60/62 bytes

F⊗N≔⁺⟦Eυ⊕λ⟧E∧υ⌊υ⁺LυE⮌υ§μλυNθ≔⊟Φυ№ιθηIΣEΦυ‹↔⁻κ⌕υη²ΣΦι‹↔⁻μ⌕ηθ²

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

F⊗N≔⁺⟦Eυ⊕λ⟧E∧υ⌊υ⁺LυE⮌υ§μλυ

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

Nθ≔⊟Φυ№ιθη

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

IΣEΦυ‹↔⁻κ⌕υη²ΣΦι‹↔⁻μ⌕ηθ²

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:

F⊗N≔⁺⟦Eυ⊕λ⟧E∧υ⌊υ⁺LυE⮌υ§μλυNθ≔⊟Φυ№ιθηI⁻ΣEΦυ‹↔⁻κ⌕υη²ΣΦι‹↔⁻μ⌕ηθ²θ

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

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

Google Sheets, 423 bytes

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
```
\$\endgroup\$
1
\$\begingroup\$

Uiua SBCS, 47 bytes

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

Try it!

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for your contribution. Could you please add some explanation? \$\endgroup\$
    – Philippos
    Feb 26 at 7:18
1
\$\begingroup\$

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

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

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)

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

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
read_cell: { .[snail; x] };

// 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
    if[read_cell[next_cell] <> 0;
        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
\$\endgroup\$
0
\$\begingroup\$

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.
\$\endgroup\$
1

Your Answer

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

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