[Question]
  [
Consider the following spiral of positive integers:
[![spiral of integers](https://i.stack.imgur.com/FlVDV.png)](https://i.stack.imgur.com/FlVDV.png)
We now define [grambulation](https://www.reddit.com/r/mathmemes/comments/tvn2gj/the_solution_to_the_april_fools_math/) as a binary operation \$\lozenge : \mathbb N \times \mathbb N \to \mathbb N\$, using this grid. Some example inputs and outputs for grambulation are:
\begin{align\*}
1 & \lozenge 9 = 25 \\
1 & \lozenge 2 = 11 \\
11 & \lozenge 10 = 25 \\
9 & \lozenge 1 = 5 \\
19 & \lozenge 4 = 13 \\
76 & \lozenge 6 = 62 \\
17 & \lozenge 17 = 17 \\
62 & \lozenge 55 = 298
\end{align\*}
Feel free to try to figure out the pattern before continuing.
---
### How to grambulate \$x\$ and \$y\$
The two coordinates of the inputs, \$x \lozenge y\$, in the spiral grid above are found, where \$1\$ is located at \$(0, 0)\$, \$2\$ at \$(1, 0)\$ and so on. For \$x \lozenge y\$, call these coordinates \$x'\$ and \$y'\$. You then find the vector from \$x'\$ to \$y'\$, and calculate the coordinates found by applying this vector to \$y'\$.
A worked example: \$3 \lozenge 11 = 27\$. First, we calculate our coordinates: $$x' = (1, 1), y' = (2, 0).$$ Next, we see that the vector from \$x'\$ to \$y'\$ is \$\vec v = (+1, -1)\$. Finally, we add this to \$y'\$ to get the coordinate \$(3, -1)\$, which is the coordinates of \$27\$.
Alternatively, a visual demonstration:
[![visual example with arrows from 3 to 11 and 11 to 27](https://i.stack.imgur.com/UzeJpm.png)](https://i.stack.imgur.com/UzeJpm.png)
Note from the \$62 \lozenge 55 = 298\$ example above, our spiral is not limited to integers below \$121\$, and in fact, this binary operation is well defined for all pairs of positive integers.
Some properties of grambulation:
* \$x \lozenge x = x\$
* \$x \lozenge y = z \iff z \lozenge y = x\$
* It is non-associative and non-commutative
* It is non-injective but is surjective
* \$x^2 \lozenge y^2 = z^2\$ where \$x < y\$ and \$x, y, z\$ all have the same parity
Additionally, \$x^2 \lozenge y^2 = z^2 - 1\$ where \$x\$ and \$y\$ have different parities
Further, \$x^2 \lozenge (x + 2c)^2 = (x + 4c)^2\$ for \$x, c \in \mathbb N\$.
---
Given two positive integers \$x, y \in \mathbb N\$, output \$x \lozenge y\$. You may take input and output in any reasonable format or [method](https://codegolf.meta.stackexchange.com/questions/2447), and this is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest code in bytes wins.
Note that the order of inputs does matter (\$x \lozenge y \ne y \lozenge x\$ for most \$x, y \in \mathbb N\$), but you may take input in either consistent order.
### Test cases
```
  x   y   x◊y
  1   9    25
  1   2    11
 11   2     1
 11  10    25
  9   1     5
 19   4    13
 76   6    62
 17  17    17
 62  55   298
  3  11    27
 16 400  1296
182 240   306
249   1   281
281   1   249
 32  98   196
 88  16   202
 60  41   210
 59  85   227
```
And, a visual guide for the last few, on a larger grid:
[![grid with 15 colored cells, indicated a visual guide for the last 5 test cases](https://i.stack.imgur.com/nqT1M.png)](https://i.stack.imgur.com/nqT1M.png)
  
[Answer]
# [MATL](https://github.com/lmendo/MATL), 22 bytes
```
sQ1YLXIG"I@=&fh]Ew-X{)
```
[**Try it online!**](https://tio.run/##y00syfn/vzjQMNInwtNdydPBVi0tI9a1XDeiWvP//2hTSwUL01gA "MATL – Try It Online")
As a **bonus**, see the beautiful pattern of the function for all pairs of inputs from 1 to *L*. [MATL Online](https://matl.io/?code=%3AtXg%2Cwle%5Dv%22%40sQ1YLXI%40%21%22I%40%3D%26fh%5DEw-X%7B%29%5D50Y02ZGv%5B%5De1YG&inputs=14&version=22.7.4) times out for *L* moderately large, but here's the result for *L*=100 (click [here](https://i.stack.imgur.com/YrysR.png) for a view with better resolution):
[![enter image description here](https://i.stack.imgur.com/YrysRm.png)](https://i.stack.imgur.com/YrysRm.png)
### How it works
```
        % Implicit input: row vector of two numbers. 
sQ      % Sum, add 1. This is enough for the size of the spiral
1YL     % Matrix with spiral of that size
XI      % Copy into clipboard I
G"      % For each number in the input
  I     %   Push the spiral again
  @=    %   True for the entri that equals the number
  &fh   %   Row and column indices of that entry as a vector of two numbers 
]       % End
E       % Multiply by two, element-wise
w-      % Swap, subtract. Gives the coordinates of the result
X{      % Convert to cell array, for indexing
)       % Index into the spiral
        % Implcit display
```
The version with graphical input is as above but replaces the input by a loop over all pairs of values from 1 to *L*. The results are concatenated and reshaped as a square matrix, which is displayed with the [`autumn`](https://www.mathworks.com/help/matlab/ref/autumn.html) colormap.
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), ~~49~~ ~~32~~ 31 bytes
```
@Jsua_MCG+LheeGUGysQ]]1s-MPBxLJ
```
[Try it online!](https://tio.run/##K6gsyfj/38GruDQx3tfZXdsnIzXVPdS9sjgwNtawWNc3wKnCx@v/fxMdQ0sA "Pyth – Try It Online")
Takes input as `[y, x]`.
* `Jsua_MCG+LheeGUGysQ]]1`: Generate the spiral to a sufficient size, then collapse it to a flat list and save it in `J`.
* `xLJ`: Find the index in J of the two inputs.
* `s-MPB`: Convert to the target index.
* `@`: Index into `J` to get the target number.
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), 187 bytes
```
(t=(n=#;{1,-1}(Sum[#[.5π⌊(4k-3)^.5⌋],{k,n-1}]&/@{Sin,Cos}))&;(x=#1;y=#2;s=#1+#2;Which[x>y&&x>-y,(2x-1)^2+s,x<=y&&x>-y,4y^2-s+1,x<=y&&x<=-y,4x^2-s+1,True,(2y-1)^2+s])&@@(2t@#2-t@#1))&
```
[Try it online!](https://tio.run/##NY3hCoIwAIQfZjA23Kwtg2BOBr1AYNAPUZAQFdFAJ2yI0O/y3XqHXsQW1J@74@OOa3NdFW2u62u@lnJFWqJOAjExQtmM4rFNQOLvX/f38kBBQ3c48/fv5ZmSqSGdq6Rwo6a47sjxNswYQ4GMBExYCbgYXPKcX6r6WiUmshCaiFqCuKEMZ9wbiAnlnwY243Tw2J@F8gvND577sXBD@xumGCqFuFaAUyfMPa@nvu60KhN24IQH23T9AA "Wolfram Language (Mathematica) – Try It Online")
Ungolfed self-explained:
```
Clear[toXY, fromXY, main]; 
toXY[n_] := {
   Sum[
     Sin[.5 π ⌊Sqrt[4 k - 3]⌋], {k, 
      n - 1}], 
  -Sum[
      Cos[-.5 π ⌊Sqrt[4 k - 3]⌋], {k, 
       n - 1}]};
fromXY[{x_, y_}] := Which[
   x > y && x > -y, (x*2 - 1)^2 + (x + y),
   x <= y && x > -y, (y*2)^2 - (x + y) + 1,
   x <= y && x <= -y, (x*2)^2 - (x + y) + 1,
   True, (y*2 - 1)^2 + (x + y)
   ];
main[n1_, n2_] := fromXY[2 toXY@n2 - toXY@n1];
```
[Answer]
# [Raku](https://raku.org/), 74 bytes
```
{.first(2*.[$^b]-.[$^a]):k given ½,0,|[\+] flat (1,*i...*)Zxx(1,1.5...*)}
```
[Try it online!](https://tio.run/##RY5NCoJAAEav8i0CfxoHR3JEMQ@SGihoDImFWoyYF@gCnaZNR@ki5sym1XvvW33Xqmv40t9KiLYWMoq/r2eyTLQWXT@Ynk3TzbHMHYUit6IzTuJetfi8iUseabbNUTfFAJMRW1BKbesg5RqM@rrmpb50iBnChCh4Gn8yV0kIpjvETjHg4LoDsEAJ9@D7CZwEaSYJsjHHhL4YsYaB9TEMglH5XpnU04h5@QE "Perl 6 – Try It Online")
* `{ expr1 given expr2 }` is the function body. It evaluates `expr1` after assigning the value of `expr2` to the `$_` topic variable. `expr2` here is an expression for the lazy infinite sequence of spiral coordinates, in the form of complex numbers.
* `(1, *i ... *)` is the sequence of `1`, `i`, `-1`, and `-i`, repeated infinitely.
* `(1, 1.5 ... *)` is the infinite arithmetic sequence 1, 1.5, 2, 2.5, 3, 3.5, ....
* `Zxx` `Z`ips the two preceding sequences together using the `xx` replication operator: `1 xx 1`, `i xx 1.5`, `-1 xx 2`, `-i xx 2.5`, .... The half-integer replication numbers are rounded down, producing `(1)`, `(i)`, `(-1, -1)`, `(-i, -i)`, `(1, 1, 1)`, `(i, i, i)`, ....
* `flat` flattens that list of lists.
* `[\+]` scans that list with the addition operator `+`, producing the infinite list of partial sums. This is the spiral, except that it lacks the first origin element `0`.
* `½, 0, |...` pastes the origin `0` onto the front of the spiral, as well as another leading element `½` to make the whole thing 1-indexed instead of 0-indexed.
* `.[$^a]` and `.[$^b]` are the coordinates in the spiral of the first and second arguments to the function, respectively.
* `2 * .[$^b] - .[$^a]` are the coordinates of the grambulated output.
* `.first(...):k` finds the first index (thanks to the `:k`ey adverb) within the spiral where the value is the coordinates found in the previous step.
[Answer]
# JavaScript (ES6), 132 bytes
Expects `(p)(q)` and returns \$p\lozenge q\$.
```
p=>q=>((g=(t,h=o=[1],v=n=x=y=0)=>n==t|x+[,y]==t?x:g(t,(i=o[o[[x-=h,y-=v]]=++n,[x-v,y+h]])?h:v,i?v:-h))(q),Y=2*y,g([2*x-g(p),Y-y]),n)
```
[Try it online!](https://tio.run/##dZBNboMwEIX3PQVLTzCNbf4M0sA5KuRFlCZAFWHSIARS704dIFJq0o1lzTfvzZv5OvSH2/G7bjuv0Z@n6YxTi9kVM0JKJB2tUGPBFe2xwQFHZIBZg9j9DG5BR2V@@ZCWppHUqAtdFIOHFR097JVC122oKfR0dCulIK/SntZ5n3oVALkC/UCxG2lJCrEbvJK0puKNCmgD01E3N305vV90Sc7EcTiYJwFw9ntHhG8vsVgw5zbmf/BLytm/3gnMA2a8oXymwWrt2ziO7jhacCQ26hjmZ1HHNo6EwWG4JkvkJpoPc/yFb@TcDA/YuhgXSWQ1cGn8RbA2@MzmInheXUj7cqbyzIPEDuDf8ydyDbCZ70gJc8pFzzbniZjhwcOfM5uH93zycR8RT78 "JavaScript (Node.js) – Try It Online")
### How?
The helper function \$g\$ expects a target \$t\$ which is either the index *or* the coordinates of an element in the spiral.
Whenever \$g\$ is called, it starts at the origin and walks through the spiral until the target is reached, keeping track of its index \$n\$ and its position \$(x,y)\$ (all these variables being available in the global scope).
We first invoke \$g(q)\$ to get the coordinates \$(X,Y)\$ of the 2nd element, then \$g(p)\$ to get the coordinates \$(x,y)\$ of the 1st element, and finally \$g([2X-x,2Y-y])\$ to get the index of \$p\lozenge q\$.
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), ~~65~~ ~~47~~ ~~45~~ ~~38~~ ~~34~~ ~~31~~ 30 bytes
*-18 bytes by changing the loop structure*   
*-2 bytes by altering some assignment*   
*-7 bytes by switching to integer coordinates*   
*-1 byte from swapping input order, -3 bytes from better list construction*   
*-3 bytes by switching to imaginary coordinates*   
*-1 byte from better representation of i*
```
xJ+bm=+Z^.j).Ey@d2^sQ3_i@LJQ_2
```
[Try it online!](https://tio.run/##K6gsyfj/v8JLOynXVjsqTi9LU8@10iHFKK440Dg@08HHKzDe6P//aCMdw1gA "Pyth – Try It Online")
Takes input as a list of integers `[y,x]`. Generates a list `J` of spiral coordinates in the imaginary plane, then gets the index in `J` for `2*J[y] - J[x]`. To generate this list, we take advantage of the fact that `ceil(2*sqrt(x))` stays the same values for increasingly long intervals, in the exact same way that the direction of travel when traversing this kind of spiral does.
### Explanation
```
                                  # implicitly assign Z = 0 and Q = eval(input())
 J                                # assign J to
    m             ^sQ3            # map range(sum(Q)**3) over lambda d
     =+Z                          #   add and assign to Z
        ^.j)                      #   i to the power of
            .E                    #   ceiling
              y@d2                #   2 * sqrt(d)
  +b                              # prepend a char (to offset list)
xJ                                # find the index in J of
                        @LJQ      # map x and y to their coordinates in J
                      _i    _2    # double the first and subtract the second
```
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), ~~60~~ ~~59~~ 58 bytes
```
1//.i_/;{1,-2,1}.Tr/@+I^⌈2√Range[{##,i}-1]⌉!=0:>i+1&
```
[Try it online!](https://tio.run/##TU3NasJAEL7PU0xjKS2uJrOJMakoHtqDt1K9hbQEiXZBY4hbsIbcLfgEPp4vks7GWnr4hvlmvp91oj/SdaLVPKkXw5psu6ve7UFJoiMFVd1ZYY/bk7fz8SDPh9Nrki3TqGy1hKo6FJ@P3zdD53Gk2nRXP20iKHfiS@wrHOJs87zLi3S7VZtsPNWFypbTfKX0eKWydAAvfNCRkVfYGeEi4i0WaOG9JXDPy4MVgyiNWPxzR7fTeaFyPcnyT325CwusuIprRELEkIGyBxcmDSMCxpXhLyPnT2k81PyYkWFeI3QB@z4vBuhL/vWxgZnAFzb0TEgYcIqLlxaU/CMfPYcbSIY@UCBReqbPdXyQ3rVPBgSMK/NCQJczw8Bc2IcBb2TapcPtPid4jZIcwB6nBE277P8A "Wolfram Language (Mathematica) – Try It Online")
Input `[x, y]`.
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 68 bytes
```
ＮθＮη≔⁰ζ≔⁰εＷ¬ε«⊞υ⟦ⅈⅉ⟧≧⁺⊗¬ΣＫＤ²✳⁺²ζζ✳ζ¹¿›Ｌυ⌈⟦θη⟧≔⊕⌕υＥ§υ⊖η⁻⊗κ§§υ⊖θλε»⎚Ｉε
```
[Try it online!](https://tio.run/##dVDLTsMwEDwnX@HjRgpSixCXnqpGoEikiuACqnpwkyW26jiNY0MVxLeHddIHHPDJszNjz2whuCkaroYh1Qdn167eoYE2WoS/sSC87DpZaZjFrP@DkNCnkAoZrBsLGEXsKwxy1wlwMdu8QhSzN4i2JAsyfpiMz7ISFnLlupgljdspLEf3i6shR9wn0mBhZaPhlgQX4A1@0kfjmaIEuZHawlXVEzH3hHxn8GiQW6rwhLqyFIm4jB9lTR9t2piJLb3DTm1SXRisUVtK8yB16QtQZFjaVJd49DDBq0T4BJnUlOncYU@Ts/ofV@td6pTfL@87XCnkBug6NVnxbtzjYhjuZ@xuPtx8qB8 "Charcoal – Try It Online") Link is to verbose version of code. Explanation:
```
ＮθＮη
```
Input `x` and `y`.
```
≔⁰ζ
```
Start in an arbitrary direction.
```
≔⁰ε
```
Start not knowing `x◊y`.
```
Ｗ¬ε«
```
Repeat until `x◊y` is known.
```
⊞υ⟦ⅈⅉ⟧
```
Save the current position.
```
≧⁺⊗¬ΣＫＤ²✳⁺²ζζ
```
Turn if this is a corner.
```
✳ζ¹
```
Take one step.
```
¿›Ｌυ⌈⟦θη⟧
```
If we know `x'` and `y'`, then...
```
≔⊕⌕υＥ§υ⊖η⁻⊗κ§§υ⊖θλε
```
... see if we can find `x◊y`.
```
»⎚Ｉε
```
Output `x◊y`.
I tried using complex numbers but that also took 68 bytes:
```
ＮθＮη≔⁰ζ≔⁰ε≔¹δＷ¬ζ«⊞υεＦ¬№υ⁺ε×δＩ1j≧×Ｉ1jδ≧⁺δε¿›Ｌυ⌈⟦θη⟧≔⊕⌕υ⁻⊗§υ⊖η§υ⊖θζ»Ｉζ
```
[Attempt This Online!](https://ato.pxeger.com/run?1=dVFNS8NAEMVj8iuWnDawhQZEhJ5KixIwJYi30sMmmWRXkk2zH1oqnvwZXnqw6G_y17jJBloF9_bmvZ03b-b9K2dU5i2tD4ej0eXk-vviLRZbo1emyUDiLpz555hZPFeKVwJPCdr_QnBCEUGFRc-M14DwqtV4H4boxfdSoxg2TuuVrXTkojVC9-W0NgoDQQ-8AYULghZUaRxEj0E4PJTQrbO45xXTeNCdq5yv90fWt7XMaMtLhG8lUG3z3IGotJ3IfkzojjemweuOILbpzcYwscglNCA0FPiGi6IfNOHCTrpsTVbb6lzHooBdTyzhJGa2CUH_kN0QyO3w1U8ltxsYcthNzT5UlqvxIp_rYPJUB5vj1RRdRq72Aw "Charcoal – Attempt This Online") Link is to verbose version of code. Explanation:
```
ＮθＮη
```
Input `x` and `y`.
```
≔⁰ζ
```
Start not knowing `x◊y`.
```
≔⁰ε≔¹δ
```
Start at the origin in an arbitrary direction.
```
Ｗ¬ζ«
```
Repeat until `x◊y` is known.
```
⊞υε
```
Save the current position.
```
Ｆ¬№υ⁺ε×δＩ1j
```
If this is a corner, then...
```
≧×Ｉ1jδ
```
... rotate the direction.
```
≧⁺δε
```
Take one step.
```
¿›Ｌυ⌈⟦θη⟧
```
If we know `x'` and `y'`, then...
```
≔⊕⌕υ⁻⊗§υ⊖η§υ⊖θζ
```
... see whether we know `x◊y`.
```
»Ｉζ
```
Output `x◊y`.
[Answer]
# [Uiua](https://www.uiua.org/), 47 chars
```
f←⁅≡/+○[¯+η.÷2×π⌊√-3×4↘1⇡]
+1⊗-∶×2⊃∩f(∵f↘1⇡ⁿ3+)
```
[Try It Online!](https://uiua.org/pad?src=ZiDihpAg4oGF4omhLyvil4tbwq8rzrcuw7cyw5fPgOKMiuKImi0zw5c04oaYMeKHoV0KZyDihpAgKzHiipct4oi2w5cy4oqD4oipZijiiLVm4oaYMeKHoeKBvzMrKQp-fn4K4o2kLj0yNSBnOSAxCuKNpC49MTEgZzIgMQrijaQuPTEgZzIgMTEK4o2kLj0yNSBnMTAgMTEK4o2kLj01IGcxIDkKIyBleGNlZWQgdGltZW91dAojIOKNpC49MTMgZzE5IDQKIyDijaQuPTYyIGc3NiA2Cn5-fg==)
takes input as y,x on the stack
[Answer]
# [Scala](http://www.scala-lang.org/), 395 bytes
395 bytes, it can be golfed much more. Golfed version. [Try it online!](https://tio.run/##fZFBS8NAEIXv@RVzKjPpJrixgqTdgpCLB0EQTyJlU5Mam@zG7FYTSn573ATBUtG5zc733jxmzVaWctDpW7a1cCcLBcehqGrdWDDjKKykfQ03nu3qDBKR6ENaZt5LloNFFSckkIPVoEKrb5UNODlBjXuxNoXC8Mq/L/y81LpB895YXPj74JJcheZQBWsI/lJvtcHgf/kUIsc6xoQlROL4IUtsWUei9ooc23U3m7VuRUe1/sTIbwPOIppjO@8oK00GI7QSZ1TnmGBi5hzOsJU4cfvFfetPtvRTxAoVjxOmovFaPyHd@SJajq1k6dRyWuY4BZVsNEqJ@gFg8nAfg7LZmRhumkZ2Tw@2KdTumWJ4VIUFAUcPXNXu1ZYKK@TXEYNocUHkBr3XD18)
```
import scala.math._
type D=Double
def t(n:D)=(1 to n.toInt-1).map(k=>sin(.5*Pi*floor(sqrt(4*k-3)))).sum-> -(1 to n.toInt-1).map(k=>cos(-.5*Pi*floor(sqrt(4*k-3)))).sum
def f(p:(D,D))={val(x,y)=p
if(x>y&&x> -y)pow(2*x-1,2)+(x+y)else if(x<=y&&x> -y)pow(2*y,2)-(x+y)+1 else if(x<=y&&x<= -y)pow(2*x,2)-(x+y)+1 else pow(2*y-1,2)+(x+y)}
def m(n1:D,n2:D)={val(x,y)=t(n2);val(a,b)=t(n1);f((2*x-a,2*y-b))}
```
Ungolfed version. [Try it online!](https://tio.run/##lVJNS8NAEL3nV7xT2a1JMLGCFFsQvHgQBBEUEUlqUtcmu3F3qwnS3x6n@Wgr1YJ7GObrvX0zjJlFWVTXIi@UtjDryM8j@@o/O46K35KZxXUkJL4c4CVJYdX9A5NjXKplnCV8DNZ6bp/BpOkFPqIMJUUswFJakUH6Vl1Jy4m/YAtMpjBCMv8UQ9wIMmmmlGbmXVs2onABDyecnm@W@YaxIkbvAOVMGeb9g5OVLipO7srpJky1ymnGQglp98fj/eg/5mxZKNWgmrRIWYkp6R0MsHY8qhfqk4XDkkQELkKOIwKSaf4HkswkLex88huuajBejyET/Ikjb@fDQ8CO@1dNm53kdAJMBv3sLmS4cwKHFtLeS8i3lchFvK0EbaVbercdamklxXxfRqTnZowLraPq8dZqIedPpOFOCrtRUFDWZpI1/cFZSHSj445qVdff)
```
import scala.math._
object Main {
  def toXY(n: Double): (Double, Double) = {
    val x = (1 until n.toInt).map(k => sin(.5 * Pi * floor(sqrt(4 * k - 3)))).sum
    val y = -(1 until n.toInt).map(k => cos(-.5 * Pi * floor(sqrt(4 * k - 3)))).sum
    (x, y)
  }
  def fromXY(point: (Double, Double)): Double = {
    val (x, y) = point
    if(x > y && x > -y) pow(2*x - 1, 2) + (x + y)
    else if(x <= y && x > -y) pow(2*y, 2) - (x + y) + 1
    else if(x <= y && x <= -y) pow(2*x, 2) - (x + y) + 1
    else pow(2*y - 1, 2) + (x + y)
  }
  def main(n1: Double, n2: Double): Double = {
    val (x, y) = toXY(n2)
    val (a, b) = toXY(n1)
    fromXY((2*x - a, 2*y - b))
  }
  def main(args: Array[String]): Unit = {
    println(main(182, 240))
  }
}
```
]