• ベストアンサー

カレンダーを生成する、極少コードに挑戦!?

<html> <script> var t = new Date, c=-new Date(y=t.getFullYear(),m=t.getMonth()).getDay()+1,i=b=f=0; var x=[31,28+(y%400==0)^(y%100==0)^(y%4==0),31,30,31,30,31,31,30,31,30,31][m]; var ht='<table border="1"><caption>'+y+'/'+(m+1)+'</caption><tr>'; ht+='<th>'+'日 月 火 水 木 金 土'.replace(/ /g,'</th><th>')+'</tr>'; while(f<2){ if(!b) ht+='<tr>'; ht+='<td>'+((c<1||f)?'-':c)+'</td>'; f=(++c>x);if(++b>6) {ht+='</tr>';b=0;f*=2;} } document.write(ht); </script> HTMLの質問に答えるために考えていたら、深夜だというのに 目がさえてしまいました。 さらに短く書くテクニックを教えてください?^^;

質問者が選んだベストアンサー

  • ベストアンサー
  • mibusys
  • ベストアンサー率60% (18/30)
回答No.5

できました。みなさんの合作という感じですね。もう寝ます。 <script> with(new Date)c=-new Date(y=getFullYear(),m=getMonth()).getDay(x=new Date(y,++m,0).getDate(b=-1)) h='<table border="1"><caption>'+y+'/'+m+'<tr>'+'日月火水木金土'.replace(/(.)/g,'<th>$1') while((b++>5?b=0:b)|c<x)h+=(b?'':'<tr>')+'<td>'+(++c<1|c>x?'-':c);document.write(h+'</table>') </script>

noname#84373
質問者

お礼

だっ脱帽です! たったの3行ですよ!3行っ! しかも文章で言えば、段落になってるし^^; これを見てみんなは感動しないのだろうか!? そして、しかも! とても深夜の2時から3時にできることじゃ~ありませんぜぇ~! ところでこのような書き方を、どうすれば得とくできるのでしょう? どこか「トラの穴」みたいなところでもあるのでしょうか? ポイントなら20点どころか100点プレゼントしたい気持ちです ありがとうございました。

noname#84373
質問者

補足

後世の人のために訳文を原文に復元してみました。^^; <html> <body> <script> var tmp = new Date(); //今日の日付 var year = tmp.getFullYear(); //西暦年 var month = tmp.getMonth(); //月 var day_count = -(new Date( year, month )).getDay(); //今月の曜日数分前もって引いておく(dayを省略すると月初め) var max_day = new Date( year, month +1, 0).getDate();//今月の末日をこれで得られる var youbi = -1;//何曜日か?ループの最初で+1するので、最初は-1にしておく。0が日曜 month = month +1;//数値上は0が1月なので、表示用のため+1 var html = '<table border="1">';//document.write()は処理が遅いので、htmlにためて最後にまとめて表示 html+= '<caption>' +year +'/' +month +'</caption>'; //暦のヘッダ部分 html+= '<tr>'; tmp ='日月火水木金土'; for(var i=0; i<tmp.length; i++){ var tmpChar = tmp.substr(i, 1);//一文字ずつ抜き出して html+= '<th>' +tmpChar +'</th>';//<th>のタグでくくる } html+= '</tr>'; //暦の数字部分の展開 while( true ){//whileの中に分岐処理をかかず if( youbi >5 ) {//この時点で6、つまり土曜の表示は終えているので行変え html += '</tr>'; if( day_count >= max_day ) { break; }//月末日を超えても余白が必要なのでここでループを抜ける youbi = 0;//土曜の次は日曜 } else { youbi = youbi +1;//曜日が5以下ならカウント } if( youbi == 0 ){ html +='<tr>';}//日曜日なら行の初めに必要 var moji;//暦の文字が入る day_count = day_count +1; if( day_count<1 || max_day<day_count ){ moji = '-'; } //暦の空欄期間だったら'-'にする else { moji = day_count } html+= '<td>' +moji +'</td>'; } html+= '</table>'; document.write( html ); //以上の処理が以下の3行と同じ //with(new Date)c=-new Date(y=getFullYear(),m=getMonth()).getDay(x=new Date(y,++m,0).getDate(b=-1)) //h='<table border="1"><caption>'+y+'/'+m+'<tr>'+'日月火水木金土'.replace(/(.)/g,'<th>$1') //while((b++>5?b=0:b)|c<x)h+=(b?'':'<tr>')+'<td>'+(++c<1|c>x?'-':c); </script>

その他の回答 (4)

  • mibusys
  • ベストアンサー率60% (18/30)
回答No.4

月初と月末処理が軽くバグっていたので修正して、少し工夫しました。 (わかりにくかったので変数は戻しました) あとはbの処理をなんとかwhileの評価式の中にまとめて、そしてwhile文を1行にすれば完成な気がします。 <script> b=0 with(new Date)c=-new Date(y=getFullYear(),m=getMonth()+1).getDay(); x=new Date(y,++m,0).getDate(); h='<table border="1"><caption>'+y+'/'+m+'<tr>'+'日月火水木金土'.replace(/(.)/g,'<th>$1') while(b!=0|c<x){ h+=(b?'':'<tr>')+'<td>'+(++c<1|c>x?'-':c) if(++b>6)b=0; } document.write(h+'</table>') </script>

  • mibusys
  • ベストアンサー率60% (18/30)
回答No.3

月末の計算は自分でやる必要はないと思います。 Dateオブジェクトに任せたらx算出部分のロジックが割とシンプルになりました。 var x = new Date(y, m + 1, 0).getDate(); tr開始タグ付加の部分を以下のようにすると数文字削れます。 ロジックは変わらないので無駄な抵抗っぽいですが。 b?'':ht+='<tr>'; あとこれもロジック自体には影響しないのでどうでもいいことですが tr, td, th要素は終了タグが省略可となっているので 気にならなければ削除してもいいと思います。

noname#84373
質問者

お礼

<html> <script> with(new Date)c=getDate(y=getFullYear(m=getMonth(b=0)))%7-getDay(x=new Date(y,++m,0).getDate(f=1))-1; h='<table border="1"><caption>'+y+'/'+m+'<tr>'+'日月火水木金土'.replace(/(.)/g,'<th>$1') while(f){f=++c>x b?'':h+='<tr>';h+='<td>'+(c<1|f?'-':c) if(++b>6)b=0;f--}document.write(h+'</table>') </script> ありがとうございます。たしかにXの計算は任せたほうが短いですね! 万年カレンダーと考えつつも万年は使えないのだし・・ </tr></th></td>の省略は知っていました。 しかし、とある掲示板で文法についてガンガン言われてこともあり なんとなく抵抗がありました。そして気づきました! </table>が抜けていたことを!^^; まぁ~それを加えてもかなり減りました! 最初の半分くらいになりましたかね~!? それと >b?'':ht+='<tr>'; の意味が最初わかりません。 b?'':h+='<tr>';h+='<td>'+(c<1|f?'-':c) h+=(b?'':'<tr>')+'<td>'+(c<1|f?'-':c) 一文字多くなります^^;

  • 15mm
  • ベストアンサー率65% (65/100)
回答No.2

アルゴリズムですか。友人が来てたのでそこまで見る時間ありませんでした。 っと、言い訳しておいて、月初めの曜日の位置、変えてみました。 with(new Date)c=1-new Date(y=getFullYear(),m=getMonth()).getDay() with(new Date)c=getDate(y=getFullYear(m=getMonth()))%7-getDay()-1 with()を使った時点で文字数同じになっちゃいましたが、 new Dateの回数が減ったので処理としては効率的に・・・なったかも・・・? fの使い方もちょっと変更。 カレンダーのメインの出力はなかなかよかったのであまり変更なしです。 これで完成というわけでも無いのに 本気で詰め込みすぎて汚くなっちゃいましたが、 <script> with(new Date)c=getDate(y=getFullYear(m=getMonth(b=0)))%7-getDay(x=30+[f=1,!(y%400)^!(y%100)^!(y%4)-2,1,,1,,1,1,,1,,1][m++]|0)-1 ht='<table border="1"><caption>'+y+'/'+m+'</caption><tr>'+'日月火水木金土'.replace(/(.)/g,'<th>$1</th>')+'</tr>' while(f){f=++c>x ht+=(b?'':'<tr>')+'<td>'+(c<1|f?'-':c)+'</td>' if(++b>6){ht+='</tr>';b=0}f--}document.write(ht) </script> iはどこにも出てなかったので消しましたが、 htだけ変数名に2文字も取っちゃってるの削っていいですかね? こういう質問が増えるといいなーとか思いますよ^^

noname#84373
質問者

お礼

なんだかすごくなってきました! 今回の件で自分のレベルが1つ上がったような気がします! >こういう質問が増えるといいなーとか思いますよ^^ 本当にそう思います。 自分が判らないときに、こういう掲示板で教えていただきました。 だから感謝の気持ちを込めて、できるだけ答えるようにしてますが 正直つまらないです。だからほとんど説明はせず。自分で勉強しろ! って感じで。 だからこういう ぎゅっと詰まったコードを見ると楽しくなってきます! ありがとうございます! 締め切りはもうちょっと先にします! でもJavascriptの板に書かなくても見てくれているんですね!?

noname#84373
質問者

補足

x=m==2?28+!(y%400)^!(y%100)^!(y%4):7<m^(30|m&1) どうでしょう?

  • 15mm
  • ベストアンサー率65% (65/100)
回答No.1

こっちも熱中しちゃって疲れたので解説抜きで^^; 自分で読んで悟ってください。 本気で短くするなら、 ・行末の;は不要。 ・無駄なスペースは消す くらいはやっておいたほうがよいでしょう。 <html> <script> t=new Date,c=1-new Date(y=t.getFullYear(),m=t.getMonth()).getDay(i=b=f=0),T="</t" x=30+[1,!(y%400)^!(y%100)^!(y%4)-2,1,0,1,0,1,1,0,1,0,1][m++] ht='<table border="1"><caption>'+y+'/'+m+'</caption><tr><th>'+'日 月 火 水 木 金 土'.replace(/ /g,T+'h><th>')+T+'r>' while(f<2){ if(!b)ht+='<tr>';ht+='<td>'+((c<1|f)?'-':c)+T+'d>' f=(++c>x);if(++b>6){ht+=T+'r>';b=0;f*=2} }document.write(ht); </script>

noname#84373
質問者

お礼

わざわざありがとうございます!^^; 実は、Javascriptの板に書き込むものを、寝ぼけていて こっちに書いてしまいました。 悟れるほど腕はありませんが、参考になります なんとなく'日 月 火 水 木 金 土'の空白さえも 無駄に思えて詰めてしまいたいなぁ~と考えてました それと月初めの曜日の位置を、他の人はどう処理するか (アルゴリズムのほうね)知りたかったですね~! もう少し効率的なものが、あるのではないかと・・・

noname#84373
質問者

補足

x=30+[1,!(y%400)^!(y%100)^!(y%4)-2,1,,1,,1,1,,1,,1][m++]|0 ht='<table border="1"><caption>'+y+'/'+m+'</caption><tr>'+'日月火水木金土'.replace(/(.)/g,'<th>$1</th>')+'</tr>' ちょっとだけさらに短くなりました~!

関連するQ&A