x86-16 machine code, 18 16 bytes (No Loop):
Bytecode: "\xD4\x07\x88\xC1\xC1\xE8\x08\x6B\xC0\x05\x49\x78\x02\x01\xC8\xC3"
0: d4 07 aam 0x7 ; eax contains n, with aam 0x7 -> al = n % 7 and ah = n / 7
2: 88 c1 mov cl,al ; keep result of n%7 in ecx
4: c1 e8 08 shr ax,0x8 ; by shifting 8 times ax, ax=al=n/7;
7: 6b c0 05 imul ax,ax,0x5 ; we multiply by 5
a: 49 dec ecx ; ecx = ecx - 1 -> give 65535 if n was power of 7
b: 78 02 js 11 <end> ; if it happened we don't care about the remainder so we can just return n/7*5, the Signed Flag will be set so we can jump 2 bytes forward.
d: 01 c8 add eax,ecx ; if not then we add (n%7)-1 to n/7*5
00000011 <end>:
f: c3 ret
obtained from assembling thanks to objdump -d -mi8086 dayofweek.s
global dayofweek
bits 16
section .text
dayofweek:
aam 7
mov cl, al
shr ax, 8
imul ax,5
dec ecx
js end
add eax,ecx
end:
ret
Test: main.c
int main() {
for (short i = 0; i < 50; i++)
printf("%2d %2d\n", dayofweek(i), (i*20/7+i%7)/4);
return 0;
}
output:
0 0
0 0
1 1
2 2
3 3
...
33 33
34 34
35 35
35 35
It is not as short as @640KB (16 bytes) but I believe it is still an interesting answer as it provides a better performance (no loop)
edit: Thanks to Peter -2 bits
NB (Peter): Do note that aam only divides AL, not AX, so you might as well declare the arg in C as uint8_t, as well as specifying the gcc -mregparm=3 calling convention to put it in the reg you want.