「#カレンダープログラミング プチコンテスト 2014」ピックアップ Vol. 1

2014/10/20DevelopmentAndroid, C#, Java, PHP, Unity, VBA, カレンダープログラミング

慧: こんにちは! 「カレンダープログラミング プチコンテスト」の応募されたコードをピックアップして紹介していくよ。これは、別に良い悪いって話じゃないからね! たくさん応募があるから、他の人のコードを参考にアップデートしてもいいし、バグがあったらつっこむのもアリだよ!

現在の応募状況!

10/15 20:15 の時点で、私の例を除くと、こんなに応募があるよ!

  • PowerShell 1件
  • Python 3件
  • SmileBASIC(プチコン) 1件
  • Windows cmd.exe 1件
  • C# 1件
  • VBA (Excel) 2件
  • Android (Java) 1件
  • Unity (C#) 1件
  • Ruby 1件
  • Java 1件
  • Pascal 1件
  • C 4件
  • Perl 3件
  • Objective-C 1件
  • F# 1件
  • Tcl 1件
  • 一太郎マクロ 1件
  • Clojure 1件
  • HSP 1件
  • PL/SQL 1件
  • MSX BASIC 1件
  • Forth (GForth) 1件
  • Smalltalk 1件

みんなのコードを見るには、Togetter まとめ から。

まだまだ、メジャーなものからマイナーなものまで、オーソドックスなものからトリッキーなものまで、たくさん応募待ってるよ~。

カレンダー表示の基本的な処理?

はじめに、ちょっと確認。カレンダー表示をオーソドックスに記述した場合ポイントになりそうな処理はこんな感じかな?

calendar_proc

  1. 1日目の曜日の取得と1週目の余白表示処理
  2. 1桁の日の空白パディング処理(があると見た目が良いね)
  3. 各週の改行処理
  4. 月の日数の取得と最終日の改行処理

以上を実装した例がこんな感じ。

static void Main(string[] args)
{
var t = DateTime.Today;
var offset = (int)t.AddDays(t.Day + 1).DayOfWeek; // 曜日の取得
var count = DateTime.DaysInMonth(t.Year, t.Month); // 月の日数の取得
Console.Write(new string(' ', offset * 3)); // 1週目の余白
for (var i = 1; i <= count; i++)
{
Console.Write(i.ToString().PadLeft(2) + // 1桁の日の空白パディング処理と日の出力
(((i + offset) % 7 == 0 || i == count) ? "\n" : " ")); // 日と日の間の空白出力と各週と最終日の改行処理
}
}

view raw
calendar.cs
hosted with ❤ by GitHub

きれいな見た目にしようとすると、最終日が土曜日の時に改行2回連続しないよう注意が必要だね。

日付の操作ができる言語・できない言語

プログラミング言語によって、日付に関するライブラリやクラスの有無、日付の演算ができるかもポイントかな。さらに、言語によっては、カレンダー自体のライブラリやクラスがあったり。

日付関連の操作ができない言語は、上の処理をするには、次の処理がオーソドックスだね。

  • 1日目の曜日の取得は「ツェラーの公式」を用いる
  • 月の日数の取得は「うるう年の判定」が必要

月が変わった瞬間に実行すると……?

あと、月の最終日から翌月になる瞬間の前後に、正しく動作しそうかも気になるかな。1日目の曜日の取得と、月の日数の取得を、それぞれで「日付の取得」をしていると、おかしなことになりそう。そんなケースは気にしない?

ピックアップ No.1 VBA (Excel)

ひとつ目は、VBA のコード!

Sub calendar()
Row = 1
Col = Weekday(DateSerial(Year(Date), Month(Date), 1))
DaysOfMonth = Day(DateSerial(Year(Date), Month(Date) + 1, 0))
For Current = 1 To DaysOfMonth
Cells(Row, Col) = Current
Col = Col Mod 7 + 1
If Col = 1 Then Row = Row + 1
Next
End Sub

view raw
calendar_vba.vb
hosted with ❤ by GitHub

スッキリした見た目だよね。Excel だと、行と列があるから、1週目の余白分の出力処理が不要で、直接表示する行と列の位置を指定しているね。最終日の改行や、Excel のデフォルトの状態を前提とすると、一桁の日の空白パディング処理も不要だね。

ちょっとだけ短くしようとすると、If Col = 1 Then Row = Row + 1 は、 Row = Row - (Col = 1) ともできるかな。

もう1件の VBA の応募は、If ステートメントなしで、土日の色付けのオマケ付だよ。

ピックアップ No.2 Android (Java)

次は、1番最初に応募があったアイデア賞! CalendarView を画面に表示させるだけっていう。

基本部分のコードはこんな感じだね。

public class PronamaChanCalendarActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout layout = new RelativeLayout(this);
setContentView(layout);
addContentView(new CalendarView(this),
new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
}
}

view raw
calendar.java
hosted with ❤ by GitHub

ピックアップ No.3 Unity (C#)

Unity 製の大作が!? 絶対カレンダーの用紙に収まりきらないよね。

unity_calendar

コレ、マスコットアプリ文化祭 にも応募できるよ。

ピックアップ No.4 PHP

次は PHP。

<?php
echo str_repeat("\t", $fwday = date("w", mktime(0, 0, 0, date('n'), 1, date('Y'))));
for ($day = 1; checkdate(date('n'), $day, date('Y')); $day++)
echo ($day < 10 ? " " : "") . $day. (($day + $fwday) % 7 == 0 ? "\n" : "\t");
?>

view raw
calendar.php
hosted with ❤ by GitHub

オーソドックスなコードと違うポイントは、最終日を取得してないところ。checkdate 関数を使って、「2014/10/32」みたいな不正な日付になった時点でループ処理を終わるようにしているね。これは、他でも使えるコードを短くするテクニックかも?


以上、Vol.1 は、ここまで! まだまだ、コードを紹介していくから待っててね。関数型言語編とかレトロな言語編とかできそうな勢いだね。

The following two tabs change content below.
都内の公立高校に通う高校生。部活は、情報処理研究会。身体を動かすのも好きで、気が向いたときはなぜか体育会系の部活に混ぜてもらっていろんなスポーツをすることも。プログラミング生放送のキャラクターとして活動中!