# Black Hole challenge from codewars

I came across this challenge from codewars. I wish to know how to solve this problem. The problem description is given below.

Its elements are in range[1..n^2]. The matrix is filled by rings, from the outwards the innermost. Each ring is filled with numbers in the following way:

1. The first number is written in the top left corner;
2. The second number is written in the top right corner;
3. The third number is written in the bottom right corner;
4. The fourth number is written in the bottom left corner;
5. Each next number is written next to the number written 4 steps before it, until the ring is filled.

The matrix is constructed when all numbers are written. Given the size of the hole, return the number written at (a, b) - you may use any consistent indexing, but please specify if (a, b) is anything other than 0-indexed and row-major.

# Example

For n = 4, a = 1, b = 1, the output should be 13.

The hole looks like this:

[ [  1,  5,  9,  2 ]
[ 12, 13, 14,  6 ]
[  8, 16, 15, 10 ]
[  4, 11,  7,  3 ]
]

The element at (1, 1) is 13


### Test cases

(a, b) is 0-indexed and row-major here.

n   a   b   result
1   0   0    1
2   0   0    1
3   0   0    1
4   0   0    1
2   0   1    2
3   0   1    5
3   1   1    9
4   1   1   13
4   2   1   16
5   2   3   22

• Welcome to the site. As it stands your question is lacking a crucial component that we require of all questions, an "objective winning criterion". That is, an objective way to score answers. The most common one is code-golf. – Post Rock Garf Hunter Mar 9 '19 at 14:17
• @SriotchilismO'Zaic, Hi When I heard about Programming Puzzles and Code gulf, I thought it's about asking a programming challenge and getting a solution to it. Am sorry, am new to this site. I don't know 'Objective winning criterion' – s326280 Mar 9 '19 at 14:59
• If you want an easy winning criterion, the majority of the questions on this site are tagged as code-golf, meaning that the winning criterion is the least bytes. – senox13 Mar 9 '19 at 15:48
• Does codewars allow their challenges to be posted on other sites? – Jo King Mar 10 '19 at 0:38
• If you're going to accept an answer at all, then at least accept the one that is actually winning by the winning criterion – Jo King Mar 14 '19 at 8:48

# Python 2, 120119 90 bytes

def f(n,a,b):n-=1;A,B,C=min((a,b,1),(n-b,a,2),(n-a,n-b,3),(b,n-a,4));return(n-A)*4*A+4*B+C


Try it online!

# Python 3, 87 bytes

def f(n,a,b):A,B=min((a,b+1/4),(n+~b,a+.5),(n+~a,n-b-1/4),(b,n-a));return(n+~A)*4*A+B*4


Try it online!

Returns a float

-3 bytes, thanks to Arnauld

### Explanation:

This takes advantage of the fact that there is some symmetry to the matrix.

The matrix can be split into four quarters, which are equal when rotated (+ an offset of 1-3).

The first part A,B,C=... finds out which quarter the current coordinates are in, by finding the smallest coordinates, relative to each quarter:

(green: (a,b), yellow: (n-b,a), red: (n-a,n-b), blue: (b,n-a))

The coordinate pair is then converted to a value:

(0,0) = 1, (0,1) = 5, and so on; each coordinate is 4 larger than the previous.

sum((n-(i*2))*4for i in range(A)) skips the rows above, +(B-A)*4 moves along the row, and +C adds the offset.

sum((n-(i*2))*4for i in range(A))+(B-A)*4+C is shortened to (n-A)*4*A+4*B+C

• it's interesting, the question seems to imply the input is always an even number, but your algorithm works for odd as well? – don bright Mar 14 '19 at 2:53
• @donbright The testcases have both even and odd numbers? – TFeld Mar 14 '19 at 7:33
• lol oops! my bad – don bright Mar 14 '19 at 23:25

# 05AB1E (legacy), 363128 25 bytes

<αìRDÀsā)ø{нŠ4*ŠD¹<α4**O


Port of @TFeld's Python answer, so make sure to upvote him!
-3 bytes thanks to @Emigna.

Inputs are $$\n\$$ and $$\[a,b]\$$.

Uses the legacy version instead of the new 05AB1E version, because there seems to be a bug with the sorting ({) of multidimensional lists.

Explanation:

<          # Decrease the (implicit) input n by 1
α         # Take the absolute difference with the (implicit) input-list
#  (we now have [n-1-a, n-1-b])
ì        # Prepend the input (we now have [n-1-a, n-1-b, a, b])
R       # Reverse the list (we now have [b, a, n-1-b, n-1-a])
DÀ         # Duplicate this list, and rotate it once towards the left
s      # Swap these two lists
ā          # Push a list in the range [1, length_list] without popping the list: [1,2,3,4]
)     # Wrap all three lists into a list (we now have
#  [[a, n-1-b, n-1-a, b], [b, a, n-1-b, n-1-a], [1, 2, 3, 4]])
ø    # Zip/transpose; swapping rows/columns (we now have
#  [[a, b, 1], [n-1-b, a, 2], [n-1-a, n-1-b, 3], [b, n-1-a, 4]])
{н  # Get the minimum by sorting the lists and getting the first inner list
# (since the minimum builtins in 05AB1E flatten multidimensional lists
#  and give a single integer)
          # Push all three values to the stack: A, B, and C
Š          # Triple-swap once, so the order is now C, A, B
4*        # Multiply B by 4
Š          # Triple-swap again to B*4, C, A
D         # Duplicate A
¹<α      # Take the absolute difference with n-1 (so basically n-1-A)
4*    # Multiply that by 4
*   # Multiply it with the duplicated A
O          # Sum all values on the stack (B*4 + C + (n-1-A)*4*A)
# (and output the result implicitly)

• <αRIRì can be <αìR and 4L can be ā. – Emigna Mar 14 '19 at 7:31
• @Emigna I'm an idiot.. I tried some things with append, prepend, and rotates, and eventually ended up with what I had. Two reverses and a prepend.. Why not just prepend first and then reverse.. dohh.. Thanks! Oh, also thanks for ā. I always forget about that builtin for some reason.. – Kevin Cruijssen Mar 14 '19 at 7:47

# Jelly, 28 bytes

³_1ị’;1×4
’0;_ⱮpƝẎAµżJṂFµæ.Ç


Try it online!

Based on @TFeld’s python answer so be sure to upvote that one too.

# JavaScript (ES6), 86 bytes

(w,y,x)=>[x+(Y=w+~y)*y,y+(w+=~x)*x,w+Y*y,Y+w*x][k=x<y?x>Y?2:3:x<Y?0:x>y?1:Y-y&&2]*4-~k


Try it online!

# Jelly, 20 bytes

ZUẎTḢṬ_Ʋṁ
+þṠÇƬSœị@


A dyadic Link accepting n on the left and [a,b] (1-indexed) on the right.

Try it online!

### How?

ZUẎTḢṬ_Ʋṁ - Link 1, next matrix (rotated): current matrix
Z         - transpose          }
U        - reverse each row   } -> rotate clockwise 1/4
Ẏ       - tighten into a flat list of values
T      -   truthy indices -- e.g. [0,0,1,0,1,1,0] -> [3,5,6]
Ḣ     -   head (empty list yields 0)             ->  3
Ṭ    -   un-truth (0 yields an empty list)      -> [0,0,1]
_   - subtract (vectorises)                    -> [0,0,0,0,1,1,0]
ṁ - mould to shape of the current matrix again

+þṠÇƬSœị@ - Main Link: integer, n; list of integers [a,b]
- using left (n) as both arguments:
þ          -   table of (implicit range of integer arguments)
Ṡ        - sign -- now we have an n by n matrix of ones
Ƭ      - collect up (a list of matrices) while results are different with:
¬     - logical NOT (replace the 1s with 0s and vice-versa)
S    - sum (vectorises)
@ - with swapped arguments:
œị  -   multidimensional index into


# Rust - 340 bytes

fn f(n:usize,x:usize,y:usize)->usize{let (mut r,d)=(0,(n-1)&1);for l in ((1+d)..=n).step_by(2) {let (mut i,m,mx,mut z)=(0,l/2,n/2,0);loop {z=4*i+n*n-l*l;let u=[mx+m-i-d,mx-m,mx+m-d,mx-m+i];if (x,y)==(u[0],u[1]){r=z+4}if (x,y)==(u[2],u[0]){r=z+3}if (x,y)==(u[3],u[2]){r=z+2}if (x,y)==(u[1],u[3]){r=z+1}i+=1;if i>=l-1{break};}}r}


still got some work to do, but it basically draws the whole spiral, centered on a point in the middle, and saves the value at requested point x,y.

ungolf spiral draw at play.rust-lang.org