Skip to content

Instantly share code, notes, and snippets.

@Nia-TN1012
Forked from Myoga1012/Abstract
Last active January 30, 2023 08:58
Show Gist options
  • Save Nia-TN1012/c3b6002fc9dba0af15c6611ba519e807 to your computer and use it in GitHub Desktop.
Save Nia-TN1012/c3b6002fc9dba0af15c6611ba519e807 to your computer and use it in GitHub Desktop.
【最新バージョン】F#でカレンダーを出力するソースコードです。CalendarMin.fsはCalendar.fsと同じ動作をするミニマムコードです。
このGistに上がっているF#ソースファイルの概要
以下のファイルは最新バージョン( Ver. 2.2 )です。F#ではこの Ver. 2.2 で応募します。
Calendar.fs : オリジナルです。コメントによる簡単な解説付き
Calendar.fsx : スクリプト版です。コメントによる簡単な解説付き
CalendarMin.fs : Calendar.fsと同じ動作をする、ミニマムコードです。サイズは 265バイト( メイン内 230バイト )です。
CalendarMin.fsx : Calendar.fsxと同じ動作をする、ミニマムスクリプトです。サイズは 244バイトです。
CalendarMin2.fs : Calendar.fsで可読性をある程度残しつつ、Minifyしたコードです。
CalendarMin2.fsx : Calendar.fsxで可読性をある程度残しつつ、Minifyしたコードです。
これより以下のファイルは旧バージョンです。
CalendarOld.fs : Ver. 2.0です。リストの結合が特徴です。
CalendarOld2.fs : Ver. 2.1です。パイプライン演算子が初登場しました。
これより以下のファイルは https://gist.github.com/Nia-TN1012/b58e951b626f9c9b3ac0515acfb651f3 にあります。
Calendar.fs : Ver. 1.1です。
CalendarOld.fs : 初版( Ver. 1.0 )です。
// 名前 : Nia Tomonaka
// Twitter : https://twitter.com/nia_tn1012
open System [<EntryPoint>]
let main argv =
// 現在の日付を取得し、当月1日の曜日と末日を求めます。
DateTime.Now |> fun now -> ( now.AddDays( float( 1 - now.Day ) ).DayOfWeek |> int, DateTime.DaysInMonth( now.Year, now.Month ) )
// 範囲を[( - 1日の曜日 + 1 )..末日]にし、要素が負の時に空白を、そうでなければ日付を文字列に変換します。
// こうすることで1日の曜日に合わせてオフセットすることができます。
// また、要素の位置が7の倍数なら、改行記号も付け足します。
|> fun( prePad, lastDay ) -> [ for curDay in -prePad + 1..lastDay -> if curDay < 1 then " " else sprintf ( if ( curDay + prePad ) % 7 = 0 || curDay = lastDay then "%3d\n" else "%3d" ) curDay ]
// イテレーターで各要素を出力します。
|> Seq.iter( fun cal -> printf "%s" cal )
0
// Calender.fs( Ver. 2.2 )
// Copyright (c) 2014-2023 Nia T.N. Tech Lab. / Chronoir.net.
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// 名前 : Nia Tomonaka
// Twitter : https://twitter.com/nia_tn1012
open System
// 現在の日付を取得し、当月1日の曜日と末日を求めます。
DateTime.Now |> fun now -> ( now.AddDays( float( 1 - now.Day ) ).DayOfWeek |> int, DateTime.DaysInMonth( now.Year, now.Month ) )
// 範囲を[( - 1日の曜日 + 1 )..末日]にし、要素が負の時に空白を、そうでなければ日付を文字列に変換します。
// こうすることで1日の曜日に合わせてオフセットすることができます。
// また、要素の位置が7の倍数なら、改行記号も付け足します。
|> fun( prePad, lastDay ) -> [ for curDay in -prePad + 1..lastDay -> if curDay < 1 then " " else sprintf ( if ( curDay + prePad ) % 7 = 0 || curDay = lastDay then "%3d\n" else "%3d" ) curDay ]
// イテレーターで各要素を出力します。
|> Seq.iter( fun cal -> printf "%s" cal )
// Calender.fsx( Ver. 2.2 )
// Copyright (c) 2014-2023 Nia T.N. Tech Lab. / Chronoir.net.
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
open System[<EntryPoint>]let m a=DateTime.Now|>fun n->(n.AddDays(float(1-n.Day)).DayOfWeek|>int,DateTime.DaysInMonth(n.Year,n.Month))|>fun(p,l)->[for d in -p+1..l->if d<1 then" "else sprintf(if(d+p)%7=0||d=l then"%3d\n"else"%3d")d]|>Seq.iter(fun d->printf"%s"d);0
open System;DateTime.Now|>fun n->(n.AddDays(float(1-n.Day)).DayOfWeek|>int,DateTime.DaysInMonth(n.Year,n.Month))|>fun(p,l)->[for d in -p+1..l->if d<1 then" "else sprintf(if(d+p)%7=0||d=l then"%3d\n"else"%3d")d]|>Seq.iter(fun d->printf"%s"d);0
open System [<EntryPoint>]
let m a =
DateTime.Now |> fun n -> (n.AddDays(float(1-n.Day)).DayOfWeek |> int, DateTime.DaysInMonth(n.Year,n.Month))
|> fun(fw, ld) -> [for cd in -fw+1..ld -> if cd<1 then " " else sprintf (if (cd+fw)%7=0 || cd=ld then "%3d\n" else "%3d") cd]
|> Seq.iter (fun cd -> printf "%s" cd); 0
open System
DateTime.Now |> fun n -> (n.AddDays(float(1-n.Day)).DayOfWeek |> int, DateTime.DaysInMonth(n.Year,n.Month))
|> fun(fw, ld) -> [for cd in -fw+1..ld -> if cd<1 then " " else sprintf (if (cd+fw)%7=0 || cd=ld then "%3d\n" else "%3d") cd]
|> Seq.iter (fun cd -> printf "%s" cd)
// 旧コード( Ver. 2.0 )です。
[<EntryPoint>]
let main argv =
// 現在の日付を取得し、当月1日の曜日と末日を求めます。
let now = System.DateTime.Today
let prePad = int( System.DateTime( now.Year, now.Month, 1 ).DayOfWeek )
let lastDay = System.DateTime.DaysInMonth( now.Year, now.Month )
// カレンダーを出力します。
// iはリストのインデックスであり、日曜始まりでです。dは日付もしくは空白スペースです。
// iの7の余剰が6、即ち土曜日であるもしくは月末日であれば、改行も出力します。
Seq.iteri ( fun i d -> printf ( if i % 7 = 6 || i + 1 = prePad + lastDay then "%s\n" else "%s" ) d )
// 1日のパディング部と日付(あらかじめ文字列に変換します)部のリストを連結し、カレンダー用リストを生成します。
( [ for i in 1..prePad -> " " ] @ [ for d in 1..lastDay -> System.String.Format( "{0, 3}", d ) ] )
0
// 旧コード( Ver. 2.1 )です。
[<EntryPoint>]
let main argv =
// 現在の日付を取得し、当月1日の曜日と末日を求めます。
let now = System.DateTime.Today
let prePad = System.DateTime( now.Year, now.Month, 1 ).DayOfWeek |> int
let lastDay = System.DateTime.DaysInMonth( now.Year, now.Month )
// 1日のパディング部と日付(あらかじめ文字列に変換します)部のリストを連結し、カレンダー用リストを生成します。
[ for i in 1..prePad -> " " ] @ [ for d in 1..lastDay -> sprintf "%3d" d ]
// iはリストのインデックスであり、日曜始まりでです。dは日付もしくは空白スペースです。
// iの7の余剰が6、即ち土曜日であるもしくは月末日であれば、要素に改行を入れます。
// マッピングを終えたら、イテレーターで各要素を出力します。
|> Seq.mapi( fun i d -> if i % 7 = 6 || i + 1 = prePad + lastDay then d + "\n" else d ) |> Seq.iter( fun d -> printf "%s" d )
0
Ver. 2.2の動作
※「|>」はパイプライン演算子であり、左辺の値を右辺の関数の引数に渡します。
1. DateTime.Nowで現在の日時を表します。
2. 1.の値を引数に、1日の曜日と月末日を求め、タプルとして表します。
  例:2014年10月の場合、値は ( 3, 31 ) です。
3. 2.の値を引数に、カレンダーリストを作成します。
[( - 1日の曜日 + 1 )..月末日]のシーケンスから、for in 文を使って列挙し、
要素が負の値ならば、半角スペース×3を、正の値であれば、日付を文字列に変換してリストの要素を初期化します。
※ シーケンスの要素が7の倍数の位置ならば、リストの要素に改行記号も追加します。
例:2014年10月の場合、リストは [ " "; " "; " "; " 1"; " 2"; " 3"; " 4\n"; " 5"; ... " 31\n"; ] です。
4. 3.のリストを引数にイテレーターで要素を文字列形式で出力します。
END
@Nia-TN1012
Copy link
Author

GitHubのアカウント統合のため、Myoga1012→Nia-TN1012に移行しました。

旧URL: https://gist.github.com/Myoga1012/e4c9e921ed1ae635185b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment