Write a pluralization function for Russian In English, nouns can take on two different forms depending on whether they are singular (one) or plural (anything else). For example, we would say "1 dog" but "2 dogs", "0 dogs", "57 dogs" and so forth.

In Russian, there are three categories. Instead of "1 dog, 2 dogs, 5 dogs", in Russian it would be "1 собака, 2 собаки, 5 собак".

The categories are divided according to the following logic:


"Singular": used for 1 and any number ending in 1, except for numbers ending in 11.


Examples: 1 собака, 21 собака, 101 собака

"Few": used for 2, 3, and 4, and any number ending in 2, 3, or 4 except for numbers ending in 12, 13, and 14.


Examples: 2 собаки, 3 собаки, 4 собаки, 32 собаки, 43 собаки, 104 собаки

"Many": anything that is not considered "Singular" or "Few".


Examples: 0 собак, 5 собак, 11 собак, 13 собак, 25 собак, 111 собак, 114 собак



The challenge

Given an integer input in the range [0, 1000], return 1 if it belongs to the "singular" category, 2 if it belongs to the "few" category, and 5 if it belongs to the "many" category.

Your program may be a function or it can use STDIN. You may print to STDOUT or return a value from the function

This is a code golf challenge, so the solution with the fewest number of bytes wins.
Python 2, 36 bytes



lambda n:'5521'[n%~9/-3&gt;&gt;n/10%~9/-9]


Try it online!

Same length arithmetically:

lambda n:5/(n%~9/-3&gt;&gt;n/10%~9/-9or 1)


Let's first look at simpler code that doesn't account for teens.

lambda n:'5521'[n%~9/-3]


Here, we want a mapping of the one's digit to an output that works like

[5, 1, 2, 2, 2, 5, 5, 5, 5, 5][n%10]


But, rather than take n modulo 10 (%10), we can do n%-10, which maps to the intervals [-9..0] to give remainders:

&gt; [n%~9 for n in range(10)]
[0, -9, -8, -7, -6, -5, -4, -3, -2, -1]


This is promising because the first two entries 0 and -9 are far apart, and they need to be sent to different outputs. Also, -10 can be shortened to ~9.

From here, floor-dividing by /-3 gives chunks of 3 with the right starting spot

&gt; [n%~9/-3 for n in range(10)]
[0, 3, 2, 2, 2, 1, 1, 1, 0, 0]


To get the desired output, we now just need to map 0-&gt;5, 1-&gt;5, 2-&gt;2, 1-&gt;1, which we do with the string selection '5521'[_].

Now, we also need numbers ending in 11 to 15 to always give 5. We first do this by detecting whether then tens digit is 1. Taking n/10 to remove the last digit, we then apply %~9 as before to get the outcomes

[0, -9, -8, -7, -6, -5, -4, -3, -2, -1]


for respective final digits. The digit of 1 that we want to detect is mapped to the extremal value -9. Floor-dividing by -9 turns it to 1 and everything else to 0.

&gt; [k%~9/-9 for k in range(10)]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]


Finally, we make this indicator being 1 always give output 5. This is done by bit-shifting the result of n%~9/-3 right by the indicator. The result of 0,1,2,3 always bit-shifts right to 0 or 1, which gives an output of 5 as desired.