Skip to main content
4 of 5
added 565 characters in body

C++ (g++), 60 54 47 bytes

1-indexed. f(2)==29.

int f(int n){return(n/8|n/4|n)%2+(n^n/8)%2+29;}

Solution from k-map, which simplified to A=w+x+z and B=zw'+z'w.

int f(int n){          //N is a 4-digit binary number wxyz.
return (n/8|n/4|n) %2  //Add 1 if (w OR x OR z)
     + (n^n/8) %2      //Add 1 if (w XOR z)
     + 29;             //Add 29, the length of the shortest month.
}

At first I tried adding 1 or 2 instead of 1 or 1, but my solution was 87 bytes (if I remember correctly). I tried that with 0-indexing and 1-indexing, but they ended up being the exact same length.

Edit: Thanks to Herman L. for the improvement from f(int n){return(n>>3&1|n>>2&1|n&1)+((n&1)^(n>>3&1))+29;}, I'm glad someone found my approach interesting even though it's clearly not the shortest!

Edit 2: Thank you to ceilingcat for the suggestion to use (n/8|n/4|n)%2+(n^n/8)%2 instead of ((n>>3|n>>2|n)&1)+((n^n>>3)&1). This uses division instead of bit shifting, which saves one byte in each of three places. It also replaces &1 with %2 in two places. Both of these functionally return the last byte of the integer, but the modulo operator has precedence over addition. This means that two pairs of parentheses can be removed, saving four bytes. In total, by mixing arithmetic and bitwise operators, ceilingcat managed to improve the answer by seven bytes!