5
\$\begingroup\$

Please write a program that takes as input two numbers 'day of the month' and 'month number' for any day of this year (2012) and outputs day of the week. Examples:

% ruby ./golf.rb 14 07 # 14th of July 
"Sat"
% ruby ./golf.rb 14 7  # the same
"Sat"
% ruby ./golf.rb 01 12 # Dec 1
"Sat"
% ruby ./golf.rb 31 12 # Last day of the year
"Mon"
  • Output format should be like Mon, Tue, Wed, Thu, Fri, Sat, Sun, not less than 3 letters
  • Do not use date libs/modules, just math and logic
  • Wins the shortest script in any language.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Please post a scoring criteria or use the "code-golf" tag if the shortest code should win. Othwerwise your question might very soon be closed! \$\endgroup\$
    – vsz
    Jul 14, 2012 at 20:33

10 Answers 10

4
\$\begingroup\$

GolfScript (46 44 chars)

~.5*1$8>+2/\3<++7%"WedThuFriSatSunMonTue"3/=

Calculation can be more efficient than lookup if the days are rotated. I doubt that the mapping to day names can get shorter, but it may still be possible to shave a character or two off the hash function.

However, my best idea for how to do it, finding a power which starts with a suitable string, doesn't look like a contender. After about 9 CPU-days of brute forcing I found a couple of solutions, but they're also 44 chars. The faster one is

~16795 33303?`=+7%"WedThuFriSatSunMonTue"3/=
\$\endgroup\$
4
\$\begingroup\$

C++ (142) (135) (129 chars)

main(){string s[]={"Mon","Tue","Wen","Thu","Fri","Sat","Sun"};int d,m,t[]={0,5,1,1,4,6,2,4,0,3,5,1,3};cin>>d>>m;cout<<s[(d+t[m]+15-(m<3))%7];}

The requirement that the letters Mon, Tue etc. appear made it quite bad, otherwise it would be only 84 chars. I'll search a golf for the strings...

Hm, trying to golf the string only made it 2 chars longer, but I find it more aesthetically pleasing.

main(){char s[]={"MonTueWenThuFriSatSun"};int d,m,t[]={0,5,1,1,4,6,2,4,0,3,5,1,3};cin>>d>>m;d=((d+t[m]+15-(m<3))%7)*3;s[d+3]=0;printf("%s",s+d);}

Well, this for my first entry at a golf contest, I have still much to learn...

HA! Got it!

main(){char s[]={"MonTueWenThuFriSatSun"},t[]={"0511462403513"};int d,m;cin>>d>>m;d=((d+t[m]-33-(m<3))%7)*3;s[d+3]=0;printf("%s",s+d);}

with a well set compiler and some luck we might chop another 3 characters, by using char* instead of char[], but it will crash on most systems. Anyway, it doesn't matter, as I believe soon someone will post a solution in J or K with less than 10 characters, as usual :P

I'll never give up!

main(){char s[]={"MonTueWenThuFriSatSun0511462403513"};int d,m;cin>>d>>m;d=((d+s[m+21]-33-(m<3))%7)*3;s[d+3]=0;printf("%s",s+d);}
\$\endgroup\$
11
  • \$\begingroup\$ It's a leap year this year... ;-) (and my J solution's currently about 75 chars). \$\endgroup\$
    – Gareth
    Jul 14, 2012 at 21:40
  • \$\begingroup\$ @Gareth: Even if I optimized better for that, there is no chance to beat J. Requiring to write "main(){}", the variable declarations and input/output requires 38 characters, versus nearly nothing in J. \$\endgroup\$
    – vsz
    Jul 14, 2012 at 21:44
  • 1
    \$\begingroup\$ Don't try to beat a non-existent answer, just make your code as small as possible given the questions constraints. In this case the question specifically says "2012" so you could change your month offsets to '401462403513' and take out the -(m<3) to save 6 characters. My C++ is pants but I think you can also use main(d,m){ to initialize your variables and save another 4. If you change your day order so that Wed comes first I think you can get rid of the -33 too. \$\endgroup\$
    – Gareth
    Jul 14, 2012 at 22:07
  • \$\begingroup\$ "char s[]" ==> "char *s" \$\endgroup\$
    – Behrooz
    Jul 16, 2012 at 11:47
  • \$\begingroup\$ This isn't a valid C++ program, main needs a return type and you are using cin without std:: and without including iostream. \$\endgroup\$ Jul 17, 2012 at 3:07
4
\$\begingroup\$

c, 101 chars

d,m;main(){scanf("%d %d",&d,&m);printf("%.3s\n","SunMonTueWedThuFriSat"+(d+".034025036146"[m])%7*3);}
\$\endgroup\$
1
  • \$\begingroup\$ main(d,m) and scanf("%d%d" save 2 chars. \$\endgroup\$
    – ugoren
    Jul 23, 2012 at 7:24
3
\$\begingroup\$

APL (57 56)

D M←⎕⋄3↑'MonTueWedThuFriSatSun'↓⍨3×7|D+⍎M⌷'512503514624'
\$\endgroup\$
1
  • \$\begingroup\$ I reckon it's hard to bit APL with Ruby or Python :-) \$\endgroup\$
    – defhlt
    Jul 15, 2012 at 0:12
3
\$\begingroup\$

Ruby, 75 74

Ok, my ruby:

a,b=$*.map &:to_i;p:MonTueWedThuFriSatSun[(a-:x365274263153[b].to_i)%7*3,3]

Saved one char:

a,b=$*;p:MonTueWedThuFriSatSun[(a.to_i-:x365274263153[b.to_i].to_i)%7*3,3]
\$\endgroup\$
2
\$\begingroup\$

Python3 (93) (86)

print("MTWTFSSouehraunenuitn"[eval('%s+%s+14'%(input(),"0512573514624"[int(input())]))%7::7])

Thanks to vsz. That is just his idea translated to python (plus comments, plus python-tricks).

print("MTWTFSSouehraunenuitn"[(int(input())+int("0512573514624"[int(input())]))%7::7])
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I don't understand why you're adding 14 if you're just going to do %7 to the result? \$\endgroup\$
    – Gareth
    Jul 14, 2012 at 23:19
2
\$\begingroup\$

Pip, 44

Not a competing entry, language is newer than question.

("SunMonTueWedThuFriSat"<>3a+562361462503@b)

Pip is my imperative code-golf language. The code above requires today's version of the interpreter (0.15.04.23 or newer) for the <> operator.

Command-line arguments are stored into a and b automatically. The program uses a simple lookup-table approach; taking advantage of the fact that numbers and strings are the same data type in Pip, we can define the table via integer literal, get a digit out by subscripting, and again do math with the result. As in CJam, subscripts are cyclic; so when b is 12, 562361462503@b gives 5.

<> is the grouping operator: "Hello"<>2 gives the list ["He";"ll";"o"], for instance. We then use the ( ) alternate subscripting syntax (again taking advantage of cyclic subscripts to avoid needing %7) to grab the appropriate day name, which is auto-printed.

(The main use of the (x y z) syntax--borrowed from Lisp--is to call a function x with args y and z; but if x is a list or string, the operation is subscripting instead. The typical subscript operator, @, is very high-precedence, so when the subscript or list are compound expressions like here, the function-call syntax saves on extra parentheses that @ would require.)

\$\endgroup\$
1
\$\begingroup\$

C, 96 chars

Reads from standard input. Usage: echo 23 7 | ./a.out

main(a,b){
    scanf("%d%d",&a,&b);
    a+=b*30.56-(b>2);
    puts("Thu\0Fri\0Sat\0Sun\0Mon\0Tue\0Wed"+a%7*4);
}

The formula b*30.56, rounded down, gives the accumulated number of days before each month, assuming a 30-day February. -(b>2) corrects for 2012's 29-day February.

\$\endgroup\$
0
\$\begingroup\$

Python (130 chars)

d=raw_input().split()
n=int(d[0])+sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])-1
print 'SMTWTFSuouehranneduit'[n%7::7]

It's rather longish for Python, but I like it.

\$\endgroup\$
0
\$\begingroup\$

Factor 98

: day ( x x -- x )
{ 0 3 6 5 2 7 4 2 6 3 1 5 3 } nth - 7 mod "MonTueWedThuFriSatSun" 3 group nth ;

Output:

( scratchpad ) 23 7 day

--- Data stack:
"Mon"
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.