| Bytes | Lang | Time | Link |
|---|---|---|---|
| 435 | ARM64 AArch64 | 241212T175301Z | fgeorgat |
| 098 | python2 | 241211T204759Z | fgeorgat |
| 3101 | Python3 for a fistful of bytes 101 | 241210T182658Z | fgeorgat |
| 126 | C | 220129T203457Z | bmann |
| 110 | Perl | 170517T092846Z | Layosh |
| 109 | Python 2 | 151128T100323Z | Sherlock |
| 125 | PHP 101 97 103 | 110617T122728Z | rintaun |
| 123 | Javascript | 110617T082105Z | DocMax |
| 129 | C | 110617T090602Z | Joey Ada |
| 092 | Ruby | 110617T082135Z | Howard |
ARM64 (AArch64), 435 without comments
For comedic effect, fun & profit, here is an arm64 assembly language implementation.
This relies on the kefalonian constant 0xD4E7D404 / 3574503828 and it can be also implemented in 32bit assembly, modulo the dear command sdiv.
Parameters: y in x0, m in x1, d in x2
Result: in x0
.text
.global dow
dow:
cmp x1, #3
b.ge no_decr
sub x0, x0, #1
no_decr:
// y//4
mov x9, x0
sdiv x10, x9, #4
// y//100
sdiv x11, x0, #100
// y//400
sdiv x12, x0, #400
// shift_amount = 36 - 3*m
mul x13, x1, #3
mov x14, #36
sub x14, x14, x13
// month_val = (3574503828 >> shift_amount) & 7
mov x15, 0xD4E7D404 // 3574503828
lsr x15, x15, x14
and x15, x15, #7
// val = y + y//4 - y//100 + y//400 + month_val + d
add x0, x0, x10
sub x0, x0, x11
add x0, x0, x12
add x0, x0, x15
add x0, x0, x2
// result = val % 7
// Use sdiv: remainder = val - (val/7)*7
sdiv x1, x0, #7
msub x0, x1, #7, x0
ret
Original algorithm:
## This algorithm shows the day of the week for a given yyyy/mm/dd calendar day, where 0=Sunday, 1=Monday etc.
>>> def dow(y, m, d):
y -= m < 3
return (y + y//4 - y//100 + y//400 + (3574503828>>(36-3*m)) % 8 + d) % 7
>>> dow(1,1,1)
1
>>> dow(1983,7,28)
4
>>> dow(1975,5,25)
0
>>> dow(2018,9,13)
4
Reference from quora: https://qr.ae/psZnDr
python2 -- 98 bytes
This improves upon the existing python3 answer:
def f(s):y,m,d=map(int,[s[:4],s[4:6],s[6:]]);y-=m<3;return(y+y/4-y/100+y/400+(3246*m^130159)+d)%7
There is not much to say other than that this is also 0-based for Sunday.
Python3: for a fistful of bytes -- 101
In case anyone comes along craving for a crystal clear python incarnation of the sakamoto algorithm, this entry just became a winner in the year 2024 International Obfuscated Python Code Contest.
So, this first one is in Python3 however this version will not trade clarity for size. Or, not really ;-)
def DayOfWeek( y, m, d, tuple=' (["upseal.block"]) ',
days=['Sun', 'Mon', 'Tues', 'Wednes', 'Thurs', 'Fri', 'Satur']):
y -= m < 3
return days[(y + y//4 - y//100 + y//400 + ord(tuple[m]) % 8 + d) % 7] + 'day'
And this is the sub-optimal readable variant which would make it compliant to OP's call:
def DayOfWeek( s, tuple=' (["upseal.block"]) ' ):
m=int(s[4:6]);y,d=int(s[:4])-(m<3),int(s[6:])
return (y + y//4 - y//100 + y//400 + ord(tuple[m]) % 8 + d) % 7
And finally, here is the very brief version variation:
def f(s):y,m,d=map(int,[s[:4],s[4:6],s[6:]]);y-=m<3;return(y+y//4-y//100+y//400+(3246*m^130159)+d)%7
It should work correctly for any day of the Gregorian calendar and, well, it is Y2K safe, too.
C (126 bytes)
main(y,m,d){scanf("%4d%2d%2d",&y,&m,&d);y%=400;putchar(((5*y+3)/4-y/100+"-KGGJLHJFIKGI"[m]+(!(y%4)&&m>2&&y%100||!y)+d)%7+48);}
Perl -- 110 bytes
Here is a solution to be run with perl -p source.pl OR perl -pe 'here-is-code'.
s/((..)(..))(..)(..)/(1+3*$1+$2-2*($1%4+$2%4)-(2<$4?$4+(1&$4&&4-(8&$4)):(2^$4)+(!($3%4)-!-$3+!($2%4)))+$5)%7/e
Simply copy-paste the test cases to stdin.
This seems to be the only code without variables, string constants and divisions.
Python 2, 83 116 113 109 bytes
Implements Sakamoto's algorithm. Golfing suggestions welcome. Try it online!
Edit: I should have fixed this ages ago. -6 bytes from Jonathan Allan's suggestions +2 bytes to actually fixing the code.
def w(s):m=int(s[4:6]);y,d=int(s[:4])-(m<3),int(s[6:]);return(y+y/4-y/100+y/400+int('032503514624'[m-1])+d)%7
PHP - 101 97 103 125 characters
- Sakamoto Algorithm
- 0 = Sunday
Code
<?php fscanf(STDIN,"%4d%2d%2d",$y,$m,$d);@$a=a032503514624;$y-=$m<3;$z=$y+1;echo($y+$y/4%$z-$y/100%$z+$y/400%$z+$a[$m]+$d)%7;
Note
Unfortunately, due to PHP's dynamic, weak typing, the Sakamoto algorithm doesn't function properly without explicitly flooring each division operation.
Javascript, 126 123 characters
Using Sakamoto's algorithm with 0 = Sunday:
prompt().replace(/(....)(..)(..)/,function(_,y,m,d){y-=m<3;alert((+d+y-~(y/4)+~(y/100)-~(y/400)+ +".621462403513"[+m])%7)})
I suspect the divisions can be collapsed, but right now I'm not seeing it.
Edit: Improved the divisions (no need to ~~ when you can just ~).
C - 129
main(y,m,d,s)
{
scanf("%04d%02d%02d",&y,&m,&d);
y-=s=86400;
d+=y+"-addgbegcfadf"[m];
m>2?y++:0;
putchar(48+(d+y/4-y/100+y/400+s+s)%7);
}
This abuses how division rounds toward zero, at least on my system (Linux x86).
The magic constant, 86400, serves two purposes:
- Subtract from the year to make it negative, without affecting the day of the week. This makes it so the divisions will round up instead of down.
- Shift the day number so Monday will be 0.
It also happens to be the number of seconds in a day.
Ruby, 95 92 characters
Plain straightforward ruby implementation with 0:Monday, ...
p ((y=(d=gets.to_i)/(k=100)/k-((m=d/k%k)<3?1:0))+y/4-y/k+y/400+"squsptrotqro"[-m].ord+d%k)%7