8
\$\begingroup\$

Upon receiving month and year in YYYYMM format, generate output of the corresponding calendar month for that year.

For example the input 201312 should generate the following output:

Mo Tu We Th Fr Sa Su
 1
 2 3 4 5 6 7 8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

Only trick is, NO native calendar generating functions... so Linux clones, no "cal" function... Muahahahahah!

PS: The calendar must start out with Monday as the left-most day, this is to ensure that the output is like the "cal" function, but does not output like "cal", which has Sunday as its left-most day...

Smallest code size wins.

Laikoni
26.4k7 gold badges54 silver badges116 bronze badges
asked Dec 9, 2013 at 4:20
\$\endgroup\$
7
  • 1
    \$\begingroup\$ You want it to look like a calendar, might want to change your text to say that more clearly. Also, what are the winning conditions? \$\endgroup\$ Commented Dec 9, 2013 at 4:21
  • \$\begingroup\$ @Quincunx, you're like my conscience, only digital... \$\endgroup\$ Commented Dec 9, 2013 at 4:22
  • 2
    \$\begingroup\$ Except I'm not digital... \$\endgroup\$ Commented Dec 9, 2013 at 4:22
  • 1
    \$\begingroup\$ "Smallest size wins." size of what? If it is code size, then please change the tag to code-golf \$\endgroup\$ Commented Dec 9, 2013 at 4:27
  • 3
    \$\begingroup\$ I presume you want the Gregorian calendar, but for what range of years? \$\endgroup\$ Commented Dec 9, 2013 at 12:31

9 Answers 9

9
\$\begingroup\$

Ruby, (削除) 170 (削除ここまで) 168 characters

g=gets.to_i
require'date'
d=Date.new g/100,g%100
puts'Mo Tu We Th Fr Sa Su'
l=['']*(d.jd%7)+[*1..(d>>1).jd-d.jd]
56.times{|i|$><<"#{l[i].to_s.rjust 2} #{?\n if i%7>5}"}

Bugfix: didn't require the neccessary library (+16) used julian date modulo 7 instead of current week day directly (-3)
used /100 and %100 to parse date instead of regex (-13). Taken from LegoStormtroopr's answer.
removed the parentheses around the argument to rjust and Date.new(-2)

answered Dec 9, 2013 at 6:54
\$\endgroup\$
1
  • \$\begingroup\$ Cool. Not tested exhaustively, but seems that you can change "#{l[i].to_s.rjust 2} #{?\n if i%7>5}" with "%2s %s"%[l[i],i%7>5?$/:""]. \$\endgroup\$ Commented Dec 10, 2013 at 8:22
6
\$\begingroup\$

Python 2.7 - 152

Unfortunately it fails for September 1752. Granted, it imports all of the calender functions, but only uses 1, and that just returns the start day of the week and the number of days.

from calendar import*
w,l=monthrange(*divmod(input(),100))
print" Mo Tu We Th Fr Sa Su\n"+" "*w+''.join(["%3d"%s+"\n"*((s+w)%7<1)for s in range(1,l+1)])

Relatively standard code, but this is my favourite bit:

"\n"*((s+w)%7<1)

It prints the new line using string multiplication, if the number of the current day and start day of the week is Sunday (e.g. 7) as the boolean is cast to an integer.

This saves a character on the more intuitive x%7==0 by using x%7<1 instead.

Test output:

> 198210
Mo Tu We Th Fr Sa Su
 1 2 3
 4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
answered Dec 9, 2013 at 7:39
\$\endgroup\$
7
  • \$\begingroup\$ let me guess: you have just translated my approach to another language and it came up shorter. I'm okay with that, but disclosure would be nice. \$\endgroup\$ Commented Dec 9, 2013 at 14:37
  • \$\begingroup\$ @JanDvorak Oh no. Not at all. I couldn't even understand yours. To be honest, given the verbose imports I needed, I was shocked it was going to come close to beating yours. Just out of curiousity what is 52.times doing? Its not multiplication? \$\endgroup\$ Commented Dec 9, 2013 at 20:33
  • 1
    \$\begingroup\$ It's a looping construct. n.times{...} is identical to (0...n).each{...} or 0.upto(n-1){...}. Multiplication would be 52 * ... \$\endgroup\$ Commented Dec 9, 2013 at 20:42
  • \$\begingroup\$ @JanDvorak I played with Python a few years ago in a job I was working in... I found the indent syntax a little bit of a pain... So used to curly brackets I guess... LOVE the "\n"*((s+w)%7<1) trick... I've never checked to see if this would work in JavaScript... ;) \$\endgroup\$ Commented Dec 10, 2013 at 7:15
  • \$\begingroup\$ The Wiki reference you mentioned was interesting... "It reformed the calendar of England and British Dominions so that a new year began on 1 January rather than 25 March (Lady Day) and would run according to the Gregorian calendar, as used in most of western Europe." I'm surprised the English were a little behind then...? \$\endgroup\$ Commented Dec 12, 2013 at 23:54
5
\$\begingroup\$

Mathematica 203

g@d_:=Module[{w={"Mo","Tu","We","Th","Fr","Sa","Su"},c},
c@n_:=" "~ Table ~{n};
Grid@Partition[Join[w,c[Position[w,StringTake[ToString@DayName@d,2]][[1,1]]-1],
Range@DayCount[d,d~DatePlus~{1,"Month"}],c@6],7]]

Testing

g[{2013, 12}]
g[{2014, 1}]
g[{2014, 2}]

calendars

answered Dec 9, 2013 at 19:36
\$\endgroup\$
1
  • \$\begingroup\$ Great use of Mathematica! \$\endgroup\$ Commented Dec 10, 2013 at 7:12
4
\$\begingroup\$

Vyxal, 87 bytes

k§2vẎṄ,4ȯI:3ドル<?4ẎIεD4/⌊‟1/⌊N‟:400/⌊»∧+ż↵`»8τv‹\Ẏt2Ṡ7%7ε¤w$ẋf»∇ė{»4τ\Ẏt28+ɾJ7ẇƛƛS2↳;Ṅ;⁋,

Try it Online!

-7 thanks to lyxal.

=== Part 1: Header ===
k§ # Monday to Sunday
 2vẎ # Get first two letters of each
 Ṅ, # Join by spaces
=== Part 2: What day does it start? ===
4ȯI # Last two (month) as integer
 :£ # Store a copy to register
 3<?4ẎIε # Decrement the year if the month is Jan or Feb 
 D # Calculate:
 4/⌊‟ # floor(y/4)
 1/⌊N‟ # -floor(y/100)
 : # y
 400/⌊ # And floor(y/400)
 »...»8τv‹ # Compressed list of the days (mod 7) at the start of each month
 \Ẏt # Get the correct item
 2 # Add 2 (1 because first day of month, 1 because it ends on Sunday)
 Ṡ7% # Take the sum of the whole thing, mod 7.
=== Part 3: Get the whole month ===
7ε # Difference from 7
 ¤w$ẋf # Copies of the empty string
 »...»4τ # Compressed list of days in each month, -28
 \Ẏt # Get the correct item
 28+ # Add 28
 ɾ # Make a range out of that
 J # Add on the empty strings
=== Part 4: Format nicely ===
7ẇ # Divide into chunks of 7
 ƛ ; # Foreach...
 ƛ ; # For each item...
 S # Stringify
 2↳ # Align
 Ṅ # Join by spaces
 ⁋, # Output joined by newlines
answered Jun 25, 2021 at 23:57
\$\endgroup\$
1
  • \$\begingroup\$ Try it Online! for 88 bytes \$\endgroup\$ Commented Jun 26, 2021 at 0:38
3
\$\begingroup\$

SmileBASIC, 204 bytes

INPUT Y$Y$[3]=Y$[3]+"/
DTREAD Y$+"/01"OUT Y,M,,W
W=W-1+!W*7?"Mo Tu We Th Fr Sa Su
FOR I=1TO 30+(1AND M-(M>7))-(M==2)*2+(Y MOD 4<1&&(Y MOD 100||Y MOD 400<1))LOCATE W*3,?STR$(I,2);
W=W+1
IF W>6 THEN W=0?
NEXT

Wow, that leap year detector is VERY long...

answered Feb 7, 2017 at 20:54
\$\endgroup\$
2
\$\begingroup\$

PHP, (削除) 153 (削除ここまで) 147 bytes

Mo Di We Th Fr Sa Su
<?=str_pad("",3*$w=date(w,$t=strtotime(chunk_split($argv[1],4,"-")."7")));while($d++<date(t,$t))printf("%2d "."
"[++$w%7],$d);

breakdown

echo"Mo Di We Th Fr Sa Su\n"; // header
echo str_pad("",3* // 4. print leading spaces
 $w=date(w, // 3. get weekday
 $t=strtotime( // 2. convert to unix timestamp
 chunk_split($argv[1],4,"-")."7" // 1. import, split to year-month-, append day 7
)));
while($d++<date(t,$t)) // 5. loop $d through days of month:
 printf("%2d "."\n"[++$w%7],$d); // print date, plus a linebreak for sundays
answered Dec 20, 2016 at 4:53
\$\endgroup\$
1
\$\begingroup\$

JavaScript (239)

h=prompt();y=h.slice(i=0,4);m=h[4]+h[5]-1;d=new Date(y,m);a='MoTuWeThFrSaSu'.match(/../g);for(p=0;p<(d.getDay()||7)-1;p++)a.push(' ');while(d.setDate(++i)&&d.getMonth()==m)a.push(9<i?i:' '+i);while(c=a.splice(0,7).join(' '))console.log(c)

Output:

(for 198210) (for 201312)
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
 1 2 3 1
 4 5 6 7 8 9 10 2 3 4 5 6 7 8
11 12 13 14 15 16 17 9 10 11 12 13 14 15
18 19 20 21 22 23 24 16 17 18 19 20 21 22
25 26 27 28 29 30 31 23 24 25 26 27 28 29
 30 31
answered Dec 15, 2013 at 22:54
\$\endgroup\$
1
\$\begingroup\$

C (gcc), 242 bytes

Not the most elegant solution, I suspect.

Input in the form of an integer with the four high digits forming the year, and the low two digits the month.

X=100,W;f(d){int m=d%X,y=d/X,i=0,M=" >8><><>><><>"[m]/2+(m==2&(!(y%4)&&(y%X|!(y%400))));for(m+=m<3?y--,10:-2,W=(((1+(26*m-2)/10-2*y/X+5*(y%X)/4+y/X/4)%7)+6)%7,printf("Mo Tu We Th Fr Sa Su\n%*s",3*W,"");i<M;)printf("%2d%c",++i,W++%7^6?32:10);}

Try it online!

answered Jul 12, 2018 at 12:39
\$\endgroup\$
1
  • \$\begingroup\$ Suggest (13*m+4)/5+y%X*5/4-7*y/X/4 instead of 1+(26*m-2)/10-2*y/X+5*(y%X)/4+y/X/4 \$\endgroup\$ Commented Jul 15, 2018 at 3:51
0
\$\begingroup\$

APL(NARS), 183 chars

L←{(0=400∣⍵)∨(0≠25∣⍵)∧0=4∣⍵}⋄C←{Y←(30+2741⊤⍨12/2)+( ̄2+L⍵[2])×ばつ2=⍳12⋄d←7∣+/Y[⍳⍵[1]-1],{1+L⍵}1900..⍵[2]-1⋄7 7⍴(,/7 2⍴'MoTuWeThFrSaSu'),(d⍴⊂''),{2 0⍕⍵} ̈(⍳Y[⍵[1]]),12⍴⊂''}∘{(100∣⍵),⌊⍵÷100}

Input ok only from 1900. Test & how to use it:

 C 201312 
 Mo Tu We Th Fr Sa Su 
 1 
 2 3 4 5 6 7 8 
 9 10 11 12 13 14 15 
 16 17 18 19 20 21 22 
 23 24 25 26 27 28 29 
 30 31 
 C 202312 
 Mo Tu We Th Fr Sa Su 
 1 2 3 
 4 5 6 7 8 9 10 
 11 12 13 14 15 16 17 
 18 19 20 21 22 23 24 
 25 26 27 28 29 30 31 
 
answered Dec 18, 2023 at 6:26
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.