LL Golf Hole 3 - 13日の金曜日を数え上げる
Posted feedbacks - Flatten
Nested Hidden毎月の 13 日が金曜かどうかを調べ上げています。
初めに現在が 13 日であるかどうか調べ、 ・13日より前なら、現在の日時を 13 日に設定 ・13日より後なら、現在の日時を翌月の 13 日に設定 とし、調べ上げを開始しています。
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 | import java.util.*;
import static java.util.Calendar.*;
public class Count13Friday {
public static void main(String[] args) {
Calendar to = new GregorianCalendar(2013, 12, 31);
Calendar current = new GregorianCalendar();
int currentDate = current.get(DATE);
if (currentDate != 13) {
current.set(DATE, 13);
if (13 < currentDate) {
current.add(MONTH, 1);
}
}
List<Date> fridays = new ArrayList<Date>();
while (current.compareTo(to) <= 0) {
if (current.get(DAY_OF_WEEK) == FRIDAY) {
fridays.add(current.getTime());
}
current.add(MONTH, 1);
}
System.out.println("Fridays = " + fridays);
}
}
|
数の出力が抜けてました。
1 2 3 4 5 6 7 8 9 10 11 | bash.exe -c "diff -u old/Count13Friday.java Count13Friday.java"
--- old/Count13Friday.java 2008-08-06 18:51:31.343750000 +0900
+++ Count13Friday.java 2008-08-06 18:49:00.625000000 +0900
@@ -22,6 +22,7 @@
current.add(MONTH, 1);
}
System.out.println("Fridays = " + fridays);
+ System.out.println("Fridays count = " + fridays.size());
}
}
|
Squeak Smalltalk で。
1 2 3 4 5 | | fridayThe13ths |
fridayThe13ths := (Date today to: 2013 asYear end) dates
select: [:date | date dayOfMonth = 13 and: [date dayOfWeekName = #Friday]].
World findATranscript: nil.
^fridayThe13ths do: [:each | Transcript cr; show: each]; size
|
素直な枝刈りとして毎月の13日だけを調べています。
;; Eager comprehension の終点が exclusive なのでハマったのは秘密。
1 2 3 4 5 6 7 8 9 10 | (use srfi-1)
(use srfi-19)
(use srfi-42)
(let ((ds (filter (compose (cut = <> 5) date-week-day)
(drop (list-ec (: y 2008 2014) (: m 1 13)
(make-date 0 0 0 0 13 m y 0))
7))))
(for-each (compose print (cut date->string <> "~1")) ds)
(print (length ds)))
|
;>>> Friday, February 13, 2009
;>>> Friday, March 13, 2009
;>>> Friday, November 13, 2009
;>>> Friday, August 13, 2010
;>>> Friday, May 13, 2011
;>>> Friday, January 13, 2012
;>>> Friday, April 13, 2012
;>>> Friday, July 13, 2012
;>>> Friday, September 13, 2013
;>>> Friday, December 13, 2013
;==> 10
1 2 3 4 5 6 7 8 9 10 11 12 | (use-package :series)
(defun friday13-p (ut)
(and (= 13 (nth-value 3 (decode-universal-time ut)))
(= 4 (nth-value 6 (decode-universal-time ut)))))
(let* ((from (get-universal-time))
(to (encode-universal-time 59 59 23 31 12 2013))
(uts (choose-if #'friday13-p (scan-range :from from :upto to :by (* 60 60 24)))))
(iterate ((ut uts))
(format t "~A~%" (metatilities:date-string ut)))
(collect-length uts))
|
あんまりゴルフっぽくなりませんでした。 anarchy golf なら embed するところ。
1 2 3 4 5 6 | (princ (loop for y from 2008 to 2013 sum
(loop for m from 1 to 12
as x = (encode-universal-time 0 0 0 13 m y)
as a = (and (< (get-universal-time) x)
(= (elt (multiple-value-list (decode-universal-time x)) 6) 4))
count a if a do (format t "~D-~D-13~%" y m))))
|
とりあえずナイーブなものを。
1 2 3 4 5 6 | from datetime import*
d,n=date.today(),0
while d.year<2014:
if d.day==13 and d.weekday()==4:print d;n+=1
d+=timedelta(1)
print n
|
Lispといえば AI (Artificial Intelligence) ですが、今回はコンピュータの前にいる NI (Natural Intelligence) を使って解いてみました。ただ、信頼性がいまいち低いため、一部コンピュータにより補助を行い、精度を高めています。
実行例:
% gosh countup13fri.scm (... 略 ...) December 2013 Su Mo Tu We Th Fr Sa 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 この月に13日の金曜日は含まれますか? 含まれる場合は y, 疲れたときは g, それ以外のときはリターンキーを押してください: y 2009/2/13 2009/3/13 2009/11/13 2010/8/13 2011/5/13 2012/1/13 2012/4/13 2012/7/13 2013/9/13 2013/12/13 ==> 10
※実行には外部コマンドの cal が必要です。
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 | #!/usr/bin/env gosh
(use gauche.process)
(let* ((now (sys-localtime (sys-time)))
(lst '()))
(do ((y #0=(+ 1900 (ref now 'year)) (+ y 1)))
((<= 2014 y)
(dolist (elem (reverse lst))
(apply format #t "~d/~d/13~%" elem))
(format #t "==> ~d~%" (length lst)))
(do ((m 0 (+ m 1)))
((<= 12 m))
(unless (and (= #0# y)
(or (< m #1=(ref now 'mon))
(and (= #1# m) (< 13 (ref now 'mday)))))
(let ((l (process-output->string-list `(cal ,(+ m 1) ,y))))
(let loop ((ans (find #/8 9 10 11 12 13 14/ l)))
(for-each print l)
(print "この月に13日の金曜日は含まれますか?\n含まれる場合は y, 疲れたときは g, それ以外のときはリターンキーを押してください: ")
(case (string->symbol (read-line))
((y Y) (if ans
(push! lst (list y (+ m 1)))
#2=(begin
(print "\n*** 本当ですか? もう一度よく確認してみてください ***\n")
(loop ans))))
((g G) (error "out of patience, aborting ..."))
(else
(when ans
#2#)))))))))
|
文章では20013年とあり、プログラムは2013年となっていますがどちらでしょう。
2013年と都合よく解釈しました。
私にはこのくらいが限度のようです。
1 | with(as.POSIXlt(l<-(seq(Sys.Date(),as.Date("2013-12-31"),"d"))), length(print(l[mday==13 & wday==5])))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 | var counter=0;
var today = new Date();
for(var y=2008;y<2014;y++){
for(var m=0;m<12;m++){
var d13= new Date(y,m,13);
if(d13 < today) continue;
if(d13.getDay()==5){
print(d13);
counter++;
}
}
}
print(counter)
|
PHPがなかったので。 あまりうまく書けませんでしたが。
1 2 3 | for($i=new DateTime;$i<=new DateTime('2013-12-31');$i->modify('+1 day')){
if($i->format('wd')==513){$s.=$i->format('Y-m-d ');++$n;}
}echo$s,$n;
|
素直に書いてみましたが,長いですね。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import java.util.Calendar
import java.text.SimpleDateFormat
class Friday13(from:Calendar) {
var f13:List[Calendar] = null
val to:Calendar = Calendar.getInstance
to.setTime((new SimpleDateFormat("yyyy/MM/dd")).parse("2014/01/01"))
def this() = this(Calendar.getInstance)
def search:List[Calendar] = {
val d:Calendar = from.clone.asInstanceOf[Calendar]
if (d.get(Calendar.DAY_OF_MONTH) > 13) {
d.set(Calendar.DAY_OF_MONTH,1)
d.add(Calendar.MONTH,1)
}
def search(l:List[Calendar],d:Calendar,to:Calendar):List[Calendar] = {
d.before(to) match {
case false => l
case _ => {
val n = d.clone.asInstanceOf[Calendar]
n.add(Calendar.MONTH,1)
(d.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) match {
case true => search(l+d,n,to)
case _ => search(l,n,to)
}
}
}
}
d.set(Calendar.DAY_OF_MONTH,13)
f13 = search(List(),d,to)
f13
}
def print:Unit = {
def print(l:List[Calendar]):Unit = l match {
case List() => ()
case d::rest => {
Console.printf("%04d/%02d/%02d\n",d.get(Calendar.YEAR),d.get(Calendar.MONTH) + 1,d.get(Calendar.DAY_OF_MONTH))
print(rest)
}
}
print(f13)
Console.printf("%dday matched\n",f13.size)
}
}
object Main extends Application {
try {
val f:Friday13 = new Friday13(Calendar.getInstance)
f.search
f.print
} catch {
case e:Exception => e.printStackTrace
}
}
|
see: std.date - D Programming Language - Digital Mars
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private import std.stdio, std.date;
enum Friday = 5;
void main(){
auto count = 0;
foreach(day; Day(getUTCtime) .. MakeDay(2014, 1, 1)) {
auto date = MakeDate(day, 0);
if(WeekDay(date) == Friday && DateFromTime(date) == 13) {
writefln("%04d-%02d-%02d", YearFromTime(date), MonthFromTime(date) + 1, DateFromTime(date));
++count;
}
}
writeln(count);
}
|
少し短くしてみました。
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 | import java.util.Calendar
import java.text.SimpleDateFormat
class Friday13 {
val to:Calendar = Calendar.getInstance
to.setTime((new SimpleDateFormat("yyyy/MM/dd")).parse("2013/12/13"))
def print:Unit = {
def search(l:List[Calendar],d:Calendar):List[Calendar] = Calendar.getInstance().after(d) match {
case true => l
case _ => {
val n:Calendar = d.clone.asInstanceOf[Calendar]
n.add(Calendar.MONTH,-1)
(d.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) match {
case true => search(d::l,n)
case _ => search(l,n)
}
}
}
Console.printf("%dday matched\n",(search(List(),to).foldLeft(0) { (c,d) => Console.printf("%04d/%02d/%02d\n",d.get(Calendar.YEAR),d.get(Calendar.MONTH)+1,d.get(Calendar.DAY_OF_MONTH)); c + 1 }))
}
}
object Main extends Application {
try {
(new Friday13).print
} catch {
case e:Exception => e.printStackTrace
}
}
|
ぎゃー、すみません。 2013年の間違いです。 修正させていただきました。
1 | using System;class P{static void Main(){DateTime d=DateTime.Now;int c=0;for(;d<=new DateTime(2013,12,31);d=d.AddDays(1)){if(d.Day==13&(int)(d.DayOfWeek)==5){Console.WriteLine(d);c++;}}Console.Write(c);}}
|
まずはfor文で。誰かLINQ版を書こうよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | const int WEEK = 7;
DateTime today = DateTime.Now.Date;
DateTime from = today.AddDays((DayOfWeek.Friday - today.DayOfWeek + WEEK) % WEEK);
DateTime to = new DateTime(2013, 12, 31);
int count = 0;
for (DateTime d = from; d <= to; d = d.AddDays(WEEK))
{
if (d.Day == 13)
{
Console.WriteLine(d.ToShortDateString());
count++;
}
}
Console.WriteLine("{0} days", count);
|
JavaはGolf向きじゃないんですよねー,といいつつChallenge。 基本アルゴリズムは同じで,削れるだけ削ってみました。 現在243バイト。
1 | import java.util.*;class F{public static void main(String[]a){int n=0,d;for(Calendar c=new GregorianCalendar();c.get(1)<2014;c.add(2,1)){d=c.get(5);c.set(5,13);if(d<=13&&c.get(7)==6){System.out.println(c.getTime());n++;}}System.out.print(n);}}
|
LLでないですし、ぜんぜん短くありませんし(ry
えーっと。ほとんどCです。
「今日から」の部分が一番面倒くさいことになってしまいました。
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 32 33 34 35 36 37 | #include <ctime>
#include <iostream>
int dayOfWeek(int y, int m, int d)
{
if((m == 1) || (m == 2))
{
y--;
m += 12;
}
return (y + y / 4 - y / 100 + y / 400 + (13 * m + 8) / 5 + d) % 7;
}
int main(int, char* [])
{
std::time_t today = std::time(0);
std::tm* todayTm = std::localtime(&today);
int count = 0;
int m = (todayTm->tm_mday <= 13) ? todayTm->tm_mon : todayTm->tm_mon + 1;
for(int y = todayTm->tm_year + 1900; y <= 2013; ++y)
{
while(m <= 12)
{
if(dayOfWeek(y, m ,13) == 5)
{
std::cout << y << "/" << m << "/13" << std::endl;
++count;
}
++m;
}
m = 1;
}
std::cout << "total: " << count << std::endl;
return 0;
}
|
Javaで頑張って短くしてみました。 自分はこれが限界・・・。
1 | import java.util.*;public class P{public static void main(String[]s){int c=0;for(Calendar a=Calendar.getInstance();a.get(1)<2014;a.add(5,1)){if(a.get(5)==13&&a.get(7)==6){System.out.println(a.getTime());c++;}}System.out.print(c);}}
|
実はLINQも試したのですが、長くなったので投稿しませんでした。 LINQで抽出する対象のDateTimeのコレクションを作る為に結局ループを回しちゃってるんですよね。
1 | using System;using System.Collections.Generic;using System.Linq;class C{static void Main(){List<DateTime>l=new List<DateTime>();for(DateTime d=DateTime.Now;d<=new DateTime(2013,12,31);d=d.AddDays(1)){l.Add(d);}var v=from f in l where(int)(f.DayOfWeek)==5&f.Day==13select f.Date;foreach(var d in v){Console.WriteLine(d);}Console.Write(v.Count<DateTime>());}}
|
ツェラーの公式を変形して。「今日の日付」はコマンドライン引数でもらいます。 $ ./fri13 2008 8 7 '09年2月13日 '09年3月13日 '09年11月13日 '10年8月13日 '11年5月13日 '12年1月13日 '12年4月13日 '12年7月13日 '13年9月13日 '13年12月13日 総数:10個 $
see: ツェラーの公式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <stdio.h>
#include <stdlib.h>
int main(int c, char *v[]) {
int n = 0, y, m, y0 = atoi(v[1])-2000, m0 = atoi(v[2]);
if (m0 < 3) { y0--; m0 += 12; }
for (y = y0; y < 14; y++)
for (m = 3; m < 15; m++) {
if (y == y0 && (m < m0 || (m == m0 && atoi(v[3]) > 13))) continue;
if (!((26*(m+1)/10+y+y/4)%7)) {
printf("'%02d年%d月13日\n", (m>=13)?y+1:y, (m>=13)?m-12:m);
n++;
}
}
printf("総数:%d個\n", n);
return 0;
}
|
LINQのみ。 もうちょっと書きようがあるかなぁ?
1 2 3 4 5 6 7 8 9 10 11 12 | DateTime today = DateTime.Now.Date;
var q = from year in Enumerable.Range(today.Year, 2014 - today.Year)
from month in Enumerable.Range(1, 12)
let d = new DateTime(year, month, 13)
where (d.DayOfWeek == DayOfWeek.Friday) && (d >= today)
select d;
foreach (DateTime d in q)
{
Console.WriteLine("{0:yyyy/MM/dd(ddd)}", d);
}
Console.WriteLine(q.Count());
}
|
1 2 | <?for(;1388415600>$t=strtotime($i++."day");$c+=date(dw,$t)-135?0:print date("Y-m-d
",$t));echo$c;
|
ワンライナで157バイト。かなり行儀悪いです。
1 | perl -MClass::Date=now,date -e"$d=now;$d+=[0,$d->day>13,13-$d->day];$\=\"\n\";until($d>date '2013-12-31'){++$_&&print$d->ymd if$d->wday==6;$d+='0-1-0'}print"
|
勉強になりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | using System;
using System.Linq;
class Program
{
static void Main()
{
var d =
from n in Enumerable.Range(0, (new DateTime(2013, 12, 31) - DateTime.Today).Days)
where DateTime.Today.AddDays(n).Day == 13
where DateTime.Today.AddDays(n).DayOfWeek == DayOfWeek.Friday
select DateTime.Today.AddDays(n);
foreach (var item in d)
{
Console.WriteLine(item.ToShortDateString());
}
Console.WriteLine(d.Count());
}
}
|
大元になる日付のリストは素直に1日ごとのものを生成しています。
escript ファイル名
として実行します。
実行結果例(2008/8/7に実行)
[{2009,2,13},
{2009,3,13},
{2009,11,13},
{2010,8,13},
{2011,5,13},
{2012,1,13},
{2012,4,13},
{2012,7,13},
{2013,9,13},
{2013,12,13}]
10 days
1 2 3 4 5 6 7 8 | main(_) ->
L=a(date(),{2013,12,31}),
M=[{X,Y,13} || {X,Y,13} <- L, calendar:day_of_the_week({X,Y,13}) =:= 5],
io:format("~p~n~p days~n", [M, length(M)]).
a(X,X) -> [X];
a(X,Y) -> [X] ++ a(calendar:gregorian_days_to_date(
calendar:date_to_gregorian_days(X)+1),Y).
|
1 2 3 4 | require'date'
i=0
Date.today.upto(Date.new(2014)-1){|d|puts d.strftime'%Y-%m-%d'if d.mday*d.wday==65&&i+=1}
puts i
|
Cだとmktime(3C)を使うと便利です。 まぁ、ほんとにmktime()が本領発揮するのは日時へ変換したときなのですけど^^;; // gcc -Wall -std=c99 doukaku197.c -o doukaku197
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 32 33 34 35 36 37 | #include <stdio.h>
#include <time.h>
static const char *weekdayname[] = {"Sun","Mon","Tue","Wed","Thi","Fri","Sat"};
int main(int argc, char *argv[])
{
static const int YEAR_END = (2013 - 1900) + 1;
struct tm t = {0};
time_t now = 0;
int count = 0;
now = time(NULL);
localtime_r(&now, &t);
t.tm_mday = 13; // 13日固定
/* 2014年までの13日の金曜日を検索する */
count = 0;
while( t.tm_year < YEAR_END )
{
// 13日の金曜日を探す
if( t.tm_wday == 5 )
{
// 13日の金曜日なら表示してカウントアップ
printf("%d/%02d/%02d (%s)\n"
, t.tm_year+1900, t.tm_mon+1, t.tm_mday
, weekdayname[ t.tm_wday ]);
count ++;
}
t.tm_mon ++;
mktime( &t ); // 日時の再計算(正規化)
}
printf("COUNT:[%d]\n", count);
return 0;
}
/* EOF */
|
愚直なつくりをしています。 *Main> :main (10,[2009-02-13,2009-03-13,2009-11-13,2010-08-13,2011-05-13,2012-01-13,2012-04-13,2012-07-13,2013-09-13,2013-12-13])
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 | module Main where
import Data.Time
import Data.Time.Calendar.WeekDate
import Control.Arrow
getCurrentZonedTime :: a -> IO ZonedTime
getCurrentZonedTime = (const getCurrentTimeZone &&& const getCurrentTime)
>>> joinTuple
>>> (=<<) (return . uncurry utcToZonedTime)
where joinTuple :: Monad m => (m a, m b) -> m (a, b)
joinTuple (x,y) = do { x' <- x; y' <- y; return (x' |





takano32
#6985()
[
Ruby
]
Rating2/6=0.33
今日から2013年12月31日までの、13日の金曜日とその総数を表示してください。
余力のあるものはこのプログラムを短くしてみたり、短くしてみたり、短くしてください。
※LL Future実行委員の高野光弘です。この出題は LL Future公式の出題であり、優れたものについてはLL Golfのセッションでご紹介させていただくかもしれません。ご理解の上、ご投稿ください。また、LL Futureのチケットは現在も発売中です。よろしければ、メインイベントの方にもぜひご参加ください。
see: DateTime - Rubyリファレンスマニュアル
Rating2/6=0.33-0+
[ reply ]