Consider the following piecewise surjective function:
$$ f(x) = \begin{cases} x + 19 & x < 0 \\ x & x \geq 0 \end{cases} $$
We have the following restriction on the domain:
- $x \in \{ -16,-15,-14,-9,-8,-7,-6,-2,-1,0,1,2,6,7,8,9,14,15,16 \}$
Hence, the codomain has the following values:
- $f(x) \in \{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 \}$
Naively, we can define the inverse as follows:
$$ g(y) = \begin{cases} y - 19 & y \in \{ 3,4,5,10,11,12,13,17,18 \} \\ y & y \in \{ 0,1,2,6,7,8,9,14,15,16 \} \end{cases} $$
Is there a better way to determine which set $y$ is an element of? Unfortunately, the two sets are non-contiguous and the contiguous subsets are of variable sizes. Otherwise, my first instinct was to use modular arithmetic to define a closed-form expression. I'm interested in a general solution because I have a whole family of such functions that I need to find the inverse of.
To explain how I defined the domain, consider the following vectorization of a hexagonal map:
16
15 09
14 08 02
07 01
06 00 13
18 12
17 11 05
10 04
03
I've already explained what this means at length in this linked answer. The general idea is to convert a two-dimensional hexagonal map into a one-dimensional array. The numbering in the above diagram denotes the ordering of hexagonal cells in the one-dimensional array. It's arranged in a way that enables neighbors of any given cell (including neighbors that wraparound the edges of the map) to be computed easily using modular arithmetic.
Now, I'd like to create a bijection between the above indices and the following axial coordinates:
+0,+2
-1,+2 +1,+1
-2,+2 +0,+1 +2,+0
-1,+1 +1,+0
-2,+1 +0,+0 +2,-1
-1,+0 +1,-1
-2,+0 +0,-1 +2,-2
-1,-1 +1,-2
+0,-2
We can convert the axial coordinates into numbers that are congruent to the corresponding indices $\bmod{19}$ (the total number of cells in the hexagonal map) using the following function:
$$ fromAxial(x, y) = x + 8y $$
This converts the axial coordinates into the following values (which is how we get our domain). Notice that only the values at the bottom are negative and that they mirror the values on the top:
+16
+15 +09
+14 +08 +02
+07 +01
+06 +00 -06
-01 -07
-02 -08 -14
-09 -15
-16
We can convert these values back into axial coordinates using the following functions:
$$ \begin{align} toAxialX(v) &= ((v + 2) \bmod 8) - 2 \\ toAxialY(v) &= \lfloor (v + 2) \div 8 \rfloor \end{align} $$
Now, to convert axial coordinates to the corresponding indices we use $f \circ fromAxial$ where $f$ is the function I defined in the beginning. Equivalently, we could write $fromAxial(x, y) \bmod 19$.
Similarly, to convert indices back to axial coordinates we use $toAxialX \circ g$ and $toAxialY \circ g$ respectively where $g$ is the inverse of $f$. Note that these functions are currently defined for a hexagonal map of side length $3$. For different sized hexagonal maps we'd use similar functions with only certain values changing. Hence, I'm looking for a general solution to define the inverse of $f$.