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.
-
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\$Justin– Justin2013年12月09日 04:21:53 +00:00Commented Dec 9, 2013 at 4:21
-
\$\begingroup\$ @Quincunx, you're like my conscience, only digital... \$\endgroup\$Eliseo D'Annunzio– Eliseo D'Annunzio2013年12月09日 04:22:42 +00:00Commented Dec 9, 2013 at 4:22
-
2\$\begingroup\$ Except I'm not digital... \$\endgroup\$Justin– Justin2013年12月09日 04:22:58 +00:00Commented 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\$Justin– Justin2013年12月09日 04:27:32 +00:00Commented Dec 9, 2013 at 4:27
-
3\$\begingroup\$ I presume you want the Gregorian calendar, but for what range of years? \$\endgroup\$Peter Taylor– Peter Taylor2013年12月09日 12:31:36 +00:00Commented Dec 9, 2013 at 12:31
9 Answers 9
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)
-
\$\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\$manatwork– manatwork2013年12月10日 08:22:36 +00:00Commented Dec 10, 2013 at 8:22
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
-
\$\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\$John Dvorak– John Dvorak2013年12月09日 14:37:10 +00:00Commented 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.timesdoing? Its not multiplication? \$\endgroup\$user8777– user87772013年12月09日 20:33:48 +00:00Commented Dec 9, 2013 at 20:33 -
1\$\begingroup\$ It's a looping construct.
n.times{...}is identical to(0...n).each{...}or0.upto(n-1){...}. Multiplication would be52 * ...\$\endgroup\$John Dvorak– John Dvorak2013年12月09日 20:42:47 +00:00Commented 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\$Eliseo D'Annunzio– Eliseo D'Annunzio2013年12月10日 07:15:46 +00:00Commented 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\$Eliseo D'Annunzio– Eliseo D'Annunzio2013年12月12日 23:54:46 +00:00Commented Dec 12, 2013 at 23:54
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
-
\$\begingroup\$ Great use of Mathematica! \$\endgroup\$Eliseo D'Annunzio– Eliseo D'Annunzio2013年12月10日 07:12:48 +00:00Commented Dec 10, 2013 at 7:12
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↳;Ṅ;⁋,
-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
-
\$\begingroup\$ Try it Online! for 88 bytes \$\endgroup\$2021年06月26日 00:38:47 +00:00Commented Jun 26, 2021 at 0:38
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...
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
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
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);}
-
\$\begingroup\$ Suggest
(13*m+4)/5+y%X*5/4-7*y/X/4instead of1+(26*m-2)/10-2*y/X+5*(y%X)/4+y/X/4\$\endgroup\$ceilingcat– ceilingcat2018年07月15日 03:51:49 +00:00Commented Jul 15, 2018 at 3:51
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