1か月の稼働日の割合


11

年と月を考えて、その月の就業日の割合を調べます。稼働日は、月曜日から金曜日で、休日やその他の特別なことは考慮されません。グレゴリオ暦が使用されます。

入力

ISO 8601形式の年と月(YYYY-MM)。年は常に4桁、月は常に2桁です。指定された年は1582年より前ではありません。

出力

出力は、整数に丸められた、指定された月の就業日(上記の定義による)のパーセンテージです。パーセント記号や小数桁は続きません。

サンプル1

Input                Output

2010-05              68

サンプル2

Input                Output

2010-06              73

サンプル3

Input                Output

1920-10              68

サンプル4

Input                Output

2817-12              68

1週間が経過し、回答が受け入れられました。好奇心旺盛な方のために、コンテストで私たちが受け取った提出物のサイズ:

129 – Zシェル
174 – VB.NET
222 – C
233 – C
300 – C

独自の(ランク付けされていない)ソリューションと同様に:

  75 – PowerShell
  93 – Ruby
112 – Bourneシェル


2
私は大学院生なので、...echo 100
Amory 2014年

大学院生でさえ、自分の仕事の基本的な定義から逃れることはできません。そして、私は異なって労働日を定義しました;-)
ジョーイ14年

回答:


4

64ビットPerl、67 68

5.10以降、で実行perl -E 'code here'またはperl -M5.010 filename

map{$d++,/^S/||$w++if$_=`date -d@ARGV-$_`}1..31;say int.5+100*$w/$d

コードサイズの譲歩:

  • ロケール依存:date出力が大文字のSで始まらない日を就業日としてカウントしますLC_ALL=C。疑わしい場合は実行してください。
  • 出力は純粋で適切な形式ですが、31か月より短い月のstderrには「ゴミ」があり 2> /dev/nullます。
  • 何らかの理由で、私のバージョンのdate2817-12は無効な月と見なされます。誰が知っていたのか、GNUの新しい黙示録は当然だ!date2038以降の日付の64ビットビルドが必要です。(ありがとうJoey)

1
どうやらそれは彼の支配の間に「シフスのヘム」によって廃止されました。ref 「聖書の新しい歴史」
マーティンヨーク

1
2038年以降毎年壊れていますか?その後、64ビットビルドのtaを切り替えると、日付処理の頭の悪さのために役立つ場合があります;-)
Joey

@Joeyそれはまさにそれです。先端をありがとう!
JB、

JB:単なる推測であり、奇妙なエポックから秒数をカウントする32ビット整数のみをC以外で使用することを私は実際に期待していませんでした。しかし、正直に言うと、この目的のために、2038を超える日付に関する要件をそこに入れました;-)
Joey

3

PHP-135

私がPHPで作成したのは、数日前に同様の問題があったためです。

<?php $a=array(2,3,3,3,2,1,1);$t=strtotime($argv[1]);$m=date(t,$t);echo round((20+min($m-28,$a[date(w,strtotime('28day',$t))]))/$m*100)

(やや)より読みやすく、定数が文字列として使用されていることに気づかずに:

<?php
date_default_timezone_set('America/New_York');
$additionalDays = array(2, 3, 3, 3, 2, 1, 1);
$timestamp = strtotime($argv[1]);
$daysInMonth = date('t', $timestamp);
$limit = $daysInMonth - 28;
$twentyNinthDayIndex = date('w', strtotime("+28 days", $timestamp));
$add = $additionalDays[$twentyNinthDayIndex];
$numberOfWorkDays = 20 + min($limit, $add);
echo round($numberOfWorkDays / $daysInMonth * 100);
?>

これは、1か月の就業日数を計算する非常に単純なアルゴリズムによって可能になります。29日、30日、31日(それらの日付が存在する場合)の平日をチェックし、20を加算します。


素晴らしいアルゴリズム、貧弱なゴルフ。最新のPHP 5.3.5とを使用すると-R、このアプローチは86バイト(63.7%)まで下がることができ$a="2333211";echo.5+min(-8+$m=date(t,$t=strtotime($argn)),20+$a[date(w,$t)])/$m*100|0; ます。ゴルフの手順を参照してください。
Titus

80バイト:<?=.5+min(-8+$m=date(t,$t=strtotime($argn)),20+(5886>>date(w,$t)*2&3))/$m*100|0;
Titus

2

Python 152キャラクター

from calendar import*
y,m=map(int,raw_input().split('-'))
c=r=monthrange(y,m)[1]
for d in range(1,r+1):
 if weekday(y,m,d)>4:c-=1
print '%.f'%(c*100./r)


2

Windows PowerShell、80

$x=$args;1..31|%{"$x-$_"|date -u %u -ea 0}|%{$a++
$b+=!!($_%6)}
[int]($b*100/$a)

よろしいです[int]本当にラウンド?私はそれが床だと信じがちです。
zneak

@zneak:PowerShellはCまたはC派生言語ではありません。.NETのデフォルトの丸めモードである「最も近い偶数に丸める」を使用します。試してみてください:Both [int]1.5[int]2.5yield 2。この正確な動作は、フロア除算が必要なタスクで問題を引き起こすことがよくあります(その場合、追加のが必要に[Math]::Floor()なり.5ます)。
ジョーイ

あなたが確信しているなら、私はあなたを信じています。代わりにC#のように動作することを期待しており、自宅でテストできるWindowsマシンがありません。
zneak

@zneak:いいえ、間違いなくC#のようには機能しません。[int]PowerShellのようなものは通常、キャストよりも変換です:-)。[int[]][char[]]'abc'また、他の多くの言語では機能しないような機能もあります。
ジョーイ

Necrobumpが$input-> $argsバイトを節約します。
Veskah

1

D:186キャラクター

auto f(S)(S s){auto d=Date.fromISOExtendedString(s~"-28"),e=d.endOfMonth;int n=20;while(1){d+=dur!"days"(1);if(d>e)break;int w=d.dayOfWeek;if(w>0&&w<6)++n;}return rndtol(n*100.0/e.day);}

より読みやすく:

auto f(S)(S s)
{
    auto d = Date.fromISOExtendedString(s ~ "-28"), e = d.endOfMonth;
    int n = 20;

    while(1)
    {
        d += dur!"days"(1);

        if(d > e)
            break;

        int w = d.dayOfWeek;

        if(w > 0 && w < 6)
            ++n;
    }

    return rndtol(n * 100.0 / e.day);
}

1

パイソン-142

from calendar import*
y,m=map(int,raw_input().split('-'))
f,r=monthrange(y,m)
print'%.f'%((r-sum(weekday(y,m,d+1)>4for d in range(r)))*100./r)

カレンダビットを提供してくれたfR0DDYに感謝します。


1

ルビー、124 119 111

require 'date'
e=Date.civil *$*[0].split(?-).map(&:to_i),-1
p ((e+1<<1..e).count{|d|d.cwday<6}*1e2/e.day).round

-1 "day"引数の前と年の前に年と月をスプラッティングするため、Ruby 1.9が必要?-です"-"。Ruby 1.8の場合、2文字を追加する必要があります。

require 'date'
e=Date.civil *$*[0].split('-').map(&:to_i)<<-1
p ((e+1<<1..e).count{|d|d.cwday<6}*1e2/e.day).round

編集:@Dogbertのヘルプに基づいて5文字を剃ります。
編集:@steenslagのヘルプに基づいて、さらに8文字を剃ります。


なぜDに日付を割り当てるのですか?
Dogbert

@Dogbertおっと!Date.civilが2つあったときのホールドオーバー。ありがとう!
Phrogz '28 / 02/28

'-'?-Ruby 1.9のように書くことができます
Dogbert

@Dogbertニース。私も入れます。平日を選ぶより短い方法があるに違いないと感じていますが、まだ見つけていません。
Phrogz

e + 1 << 1はee.day + 1より3短い
steenslag

1

PHP 5.2、88バイト

私はすでに85バイトまでzneakのソリューションを試しましたが(もう1つ見つけたところです)、これは私自身のもの
です。ここでさらに3バイトを絞ることができるかどうか疑問です。

$a=_4444444255555236666304777411;echo$a[date(t,$t=strtotime($argn))%28*7+date(N,$t)]+67;

STDINから入力を受け取りますecho <yyyy>-<mm> | php -nR '<code>'

文字列$aは、月あたりの日数(date(t))と月の最初の曜日(date(N):月曜日= 1、日曜日= 7)を就業日の67パーセントにマッピングします。strtotime入力をUNIXタイムスタンプに変換します。残りのコードはハッシュを行います。

古いPHP 5のための1バイト:取り替えNw$a=_...;して$a="..."
PHP 4の別の+3バイト:.-1後に挿入$argnます。

:-5 PHP 5.5以降(postdates挑戦)のためにバイトを
削除すべてが前echoと交換してください$a"4444444255555236666304777411"


ええと... 1バイト:の%7代わりに%28
タイタス

0

REBOL - 118 113

w: b: 0 o: d: do join input"-01"while[d/2 = o/2][if d/7 < 6[++ w]++ b d: o + b]print to-integer round w / b * 100

非ゴルフ:

w: b: 0 
o: d: do join input "-01"
while [d/2 = o/2] [
    if d/7 < 6 [++ w]
    ++ b
    d: o + b
]
print to-integer round w / b * 100

0

C#、158バイト

s=>{var d=DateTime.Parse(s);int i=0,t=DateTime.DaysInMonth(d.Year,d.Month),w=0;while(i<t)w-=-(int)d.AddDays(i++).DayOfWeek%6>>31;return Math.Round(1e2*w/t);};

必要なパーセンテージを返す匿名メソッド。

コメントなしのコメント付きのメソッドとテストケースを含む完全なプログラム:

using System;

class WorkingDayPercentage
{
    static void Main()
    {
        Func <string, double> f =
        s =>
        {
            var d = DateTime.Parse(s);                      // extracts a DateTime object from the supplied string
            int i = 0,                                      // index variable
                t = DateTime.DaysInMonth(d.Year, d.Month),  // number of total number of days in the specified month
                w = 0;                                      // number of working days in the month

            while (i < t)                                   // iterates through the days of the month
                w -= -(int)d.AddDays(i++).DayOfWeek%6 >> 31;// d.AddDays(i) is the current day
                                                            // i++ increments the index variable to go to the next day
                                                            // .DayOfWeek is an enum which hold the weekdays
                                                            // (int)..DayOfWeek gets the days's index in the enum
                                                            // note that 6 is Saturday, 0 is Sunday, 1 is Monday etc.
                                                            // (int)DayOfWeek % 6 converts weekend days to 0
                                                            // while working days stay strictly positive
                                                            // - changes the sign of the positive numbers
                                                            // >> 31 extracts the signum
                                                            // which is -1 for negative numbers (working days)
                                                            // weekend days remain 0
                                                            // w -= substracts the negative numbers
                                                            // equivalent to adding their modulus

            return Math.Round(1e2 * w / t);                 // the Math.round function requires a double or a decimal
                                                            // working days and total number of days are integers
                                                            // also, a percentage must be returned
                                                            // multiplying with 100.0 converts the expression to a double
                                                            // however, 1e2 is used to shorten the code
        };

        // test cases:
        Console.WriteLine(f("2010-05")); // 68
        Console.WriteLine(f("2010-06")); // 73
        Console.WriteLine(f("1920-10")); // 68
        Console.WriteLine(f("2817-12")); // 68
    }
}

代替の関数。稼働日数に負の値を追加し、追加のバイトコストなしで戻りの符号を変更します。

s=>{var d=DateTime.Parse(s);int i=0,t=DateTime.DaysInMonth(d.Year,d.Month),w=0;while(i<t)w+=-(int)d.AddDays(i++).DayOfWeek%6>>31;return-Math.Round(1e2*w/t);};

0

Oracle SQL、110バイト

select round(100*sum(1-trunc(to_char(x+level-1,'d')/6))/sum(1))from dual,t connect by level<=add_months(x,1)-x

これは、入力データがdateデータ型を使用してテーブルに格納されているという前提で機能します。たとえば、

with t as (select to_date('2010-06','yyyy-mm') x from dual)

0

APL(Dyalog Unicode)、55 バイトSBCS

匿名の暗黙のプレフィックス関数。

.5+100×2÷/(2 5)2{≢⍎⍕↓⍺↓¯2' ',cal' '@5⊢⍵⊣⎕CY'dfns'}¨⊂

 それを全体として扱うために日付を同封する

(2 5)2{ その上で次の関数を適用しますが、左の引数を使用します[2,5]2

⎕CY'dfns' 「dfns」ライブラリをコピーする

⍵⊣ 日付を優先してレポートを破棄する

' '@5⊢ 5番目の文字(-)をスペースにます

 それを実行して2要素リストを取得します

cal その上でカレンダー関数を呼び出します

' ', スペースの列を前に付ける

¯2⌽ 最後の2列(土曜日)を前に回転させる

⍺↓ 左引数の行(2、ヘッダー)と列(指定されている場合、5 =土+日)の数を削除

 行列を行のリストに分割する

 フォーマット(ダブルスペースを挿入してフラット化)

 実行(残りの日数をフラットな数値リストに変換)

 それらを集計する

2÷/ 各ペアを分割します(1つだけあります)

100× 百を掛ける

.5+ 半分を追加

 床

オンラインでお試しください!


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.