In group theory, the modulus function is often taken to be a function from Z to Z/nZ. That is, the output is not an integer, but the equivalence class of integers that have the same remainder when divided by n. E.g. 1->{...-5,-2,1,4,7...}. In computer science, on the other hand, modulus functions generally give a particular representative of the equivalence class, more specifically whatever representative lies in [0,n-1]. You're trying to instead get the representative that lies in [1,n]. Note that this differs only in how 0+nZ is treated; the standard function sends it to 0, but you want it sent to n. So if you were writing a program, one option would be to simply do output = (k mod n)
then if output==0: output=n
. However, that's somewhat of an inelegant solution.
A solution that is in some sense more elegant is to realize that you want your output range shifted up one. If you do output = (k mod n)+1
, then instead of your output ranging from 0 to n-1, your output will be 1 to n. However, this shifts not only the output range, but also what each input goes to; 1 goes to 2 instead of 1, 2 goes to 3, etc. If you subtract 1 before taking the modulus, then this will cancel out with the adding 1 afterwards. The exception to this will be multiples of n; by subtracting 1, you get to n-1, then when you add 1 afterwards, you get to n, instead of 0.
Your formula adds n-1 instead of subtracting 1, but since (n-1) mod n = -1, this amounts to the same thing.
One way of visualizing this is imagining n tick marks in a circle. There's a tick mark labeled 1, a tick mark labeled 2, etc., up to n-1. But when you get to n, the tick mark is labeled 0, and then at n+1 you're back at the tick mark labeled 1. What if you want your output for n to be n, instead of 0? Well, you can think of there being a "drop" between the tick mark labeled n-1 and the one labeled 0; between those two tick marks, the output drops from n-1 to 0. You want to move n over to before this drop, and make the drop to instead be between n and n+1. So to move n to before the drop, you subtract 1; this shifts n over to before the drop. But now you need to add 1 back. The addition and subtraction cancel out in the sense that you end up in the same equivalence class (remember, the equivalence class for both 0 and n is {-2n,-n,0,n,2n...}), but by doing the subtraction before doing the modulus, and the addition after, you end up with a different representative.
More generally, if you want to shift j numbers from the beginning to the end, you can do (k-j) mod n + j. For instance, k mod 12 would take k to between 0 and 11, but (k-3) mod 12 + 3 will take k to between 3 and 14. To go the other way, you reverse the addition and subtraction; (k+3) mod 12 - 3 will take k to between -3 and 8.
def f(n): return [2,1,2,3][n%4]
would finish the job quickly and cleanly. $\endgroup$