次の祝日


18

オーストラリア人は祝日や飲酒が大好きです。昨日、1月26日はオーストラリアの日で、祝日です。昨日は仕事をしていなかったのが嬉しかったです。また、次に祝日が来るのを知りたいと思いました!残念ながら、私は少し飲みすぎて、自分で解決することはできません。

入力としてオーストラリアの日付/時刻表記(dd / mm)で日付を取り、次の祝日までの日数を出力するプログラムを作成します。私はクイーンズランド(QLD)の居住者であるため、クイーンズランダーに影響を与える祝日のみに興味があります

25/03 | グッドフライデー
26/03 | イースター土曜日
28/03 | イースター月曜日
25/04 | Anzac Day
02/05 | 労働者の日
03/10 | 女王の誕生日
25/12 | クリスマスデー
26/12 | ボクシングデー
27/12 | クリスマスの休日

サイトから次のことに注意してください。

クリスマスの休日

元旦、クリスマス、ボクシングデーが週末になると追加の祝日が追加されます。

クリスマスは日曜日なので、余分な祝日があります。クリスマスはまだ祝日です。

私は朝の人間なので、現在の日付を1日として含める必要があります(次の祝日のプログラムをチェックする可能性が最も高いため)。つまり、祝日の日付が入力された場合、出力は次のようになり0ます。祝日の前日が入力された場合、出力はになります1

から年末までの日付(27/01)にのみ興味があります。計算する必要がある最終日は、出力が行われる1(正月の)31/12 です。

標準的な抜け穴は禁止されています。

入力

  • 入力は常に5文字です:ハイフン-またはスラッシュで区切られた4文字/
  • 入力は27/01〜31/12の日付のみです

出力

  • クイーンズランドオーストラリアの次の祝日までの日数(入力日を含む)は、0153(最長のギャップ)の間の数である必要があります
  • 新しい行やエラーはありません

01-05 = 1  
02-05 = 0  
03-05 = 153  
25/12 = 0
26-12 = 0
27/12 = 0
30/12 = 2
31-12 = 1

うまくいけば、これは明確で、見逃されないものです。ただし、これは2番目の質問なので、フィードバックに感謝し、できるだけ早く問題を解決するために最善を尽くします。


@insertusernamehere素晴らしい提案をありがとう!私は質問に日付を追加しました
タス

@Tasこれらの日付が正しいと確信していますか?例にあるものは引用と一致せず、両方ともウェブサイトと一致しません。
アダムマーティン

@AdamMartinそれを指摘してくれてありがとう。12月の日付を間違って入れていました。この例の日付は任意の日付であり、祝日固有のものではありません。これらは入力可能な日付の例であり、出力はどうあるべきかを示しています。引用符で囲まれたもの、Webサイトからのものと一致する必要があります(できればうまくいきます)。
タス

クイーンズランドで10月にクイーンの誕生日を祝いますか?それはとても奇妙ですが、リンクからは正しいようです。
レベルリバーセント

わあ、君たちは6月から9月まで休日がないの?それは大雑把です。
ジョーZ.

回答:


2

Pyth98 84 62 67バイト

更新:日数の計算で12か月すべての日数のリストを短縮することにより、14バイトを節約しました。他のリストを圧縮する良い方法を見つけられませんでしたが、まだ試しています!

Update2:日番号のリストをbase256文字列としてエンドコーディングすることにより、さらに22バイトを保存しました。

J30KhJ=Yc:z"\W"dd=N+s<[KtJKJKJKKJKJK)tseYshY-hfgTNCMc"UVXt{ĕŨũŪů"1N

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

私のPythonの答えと同じアルゴリズム。そして、その日の曜日を取得するための組み込み機能がないので、私は自分でそれをしなければなりませんでした。年中の計算用と休日の日用にこれらの2つのリストを作成するのは非常にコストがかかります...もう一度見て、より少ないバイトで生成しようとします。


これは、入力がハイフンで区切らように思えるが、それ以外は素晴らしいですしない
タス

@Tasヒントをありがとう、その部分を完全に上書きしました...さらに5バイトのコストで修正しました。可能性のあるすべての入力バリエーションをカバーしたいので、テストケースにハイフンを追加する必要があるかもしれません。
デンカー

5

Visual Basic for Applications、155または118バイト

バージョン1-ロケールに依存しない、155バイト

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-DateSerial(16,Val(Right(d,2)),Val(Left(d,2)))
If h>=0Goto 9
Next
9 End Function

バージョン2-ロケール依存、118バイト

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-CDate(d)
If h>=0Goto 9
Next
9 End Function

バイトカウントは、改行文字を含む最終的な.BASファイル用です。標準のVBAエディターの外で編集(一部のキーワードに追加のスペースと冗長形式を課すため)-ただし、Officeアプリケーションでインポートおよび実行を実行します(? h("10/08")イミディエイトウィンドウやExcelでセル式で直接テストするため)。

(編集)最初はDateSerial、関数をロケールセーフにするために使用することを選択しました(バージョン1)。私はブラジルに住んでいるため、日付に「dd / mm / yy」形式を使用するようにシステムが構成されているため(オーストラリアと同様)、CDate代わりに(バージョン2)を使用してさらに小さなバージョンを作成できます。CDateシステムロケール情報を使用して、テキストを日付に変換します。また、このバージョンでは、コードは2016年にのみ実行されると想定していました(年を省略した場合(-6バイト)CDateは、システムクロックに従って現在の年を想定しています)。

3行目の42454は、VBAでの2016年1月1日の数値表現である42450と、最初の休日の日である84の合計です。配列には、各休日の日付(2017年1月1日を含む)が含まれます。2016の代わりに16を使用すると、DateSerialさらに2バイト消費されます。

反復内で同じ配列を9回作成するのは「悪い」コードですが、機能し、さらに3バイトを節約します(1つは配列名、もう1つはループ外の等号、もう1つはループ内の配列を参照します)。

モジュールがインポートされるとVBEによって自動的に再導入されるため、2行目と4行目の0から次のキーワードまでの「欠落」スペースは不要です。If <...> Goto <linenumber>ループから抜けるために、古くはあるがバイトが安い(両方の文字If <...> Then Exit ForIf <...> Then Exit Function使用する)。

また、VBAの関数名はローカル変数として動作し、その値は実行の最後に関数によって自動的に返されるという事実を利用しました。


PPCGへようこそ!ここでは、インタプリタによってプログラミング言語を定義しているため、特定のロケールを要求することは完全に受け入れられます。
リルトシアスト

ありがとう!より小さなロケール依存バージョンを追加するために編集されました。
16年

4

JavaScript(ES6)、131 128バイト

d=>[56,57,59,87,94,248,331,332,333,338].map(n=>r=r||(q=1454e9+n*864e5-new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`))>=0&&q/864e5,r=0)|r

説明

JavaScriptの組み込みDateコンストラクターを使用して、入力文字列をエポック以降のミリ秒数に変換し、これを各祝祭日のミリ秒数と比較します。

これは、基準日からの日数として配列に祝日を格納することによりこれを行います。2016-01-29エポックからのミリ秒数をこの日付の最短に凝縮できるため、基準日として選択しました。結果が切り捨てられるため、この日から次の日までの任意のミリ秒数が機能し、数値を中央に保持すると夏時間の影響が回避されます(ただし、OPのタイムゾーンには夏時間はありません)。この日の数字はで1453986000000あり、それを切り上げる1454000000000(数時間を追加する)とは、と書くことができることを意味します1454e9

d=>
  [56,57,59,87,94,248,331,332,333,338]             // list of day offsets from 01/29
  .map(n=>                                         // for each public holiday offset n
    r=r||                                          // if r is already set, do nothing
      (q=                                          // q = approximate difference in ms
        1454e9+n*864e5                             // time of public holiday
        -new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`)    // time of input date
      )
      >=0&&                                        // if q >= 0
        q/864e5,                                   // r = q in days
    r=0                                            // r = result
  )
  |r                                               // floor and return r

テスト

このソリューションは、ユーザーのタイムゾーンに依存しています。これは、OP(および私の)タイムゾーン(GMT +1000)で機能します。別のタイムゾーンでテストする場合はnumberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000、参照日付番号に追加する必要があります。(例:GMT +0430は-5.5 * 60 * 60 * 1000 + 1454e9+n*864e5


日付がハイフンで区切られている場合、これは常に0になります。私はすでにOPに彼のテストケースを調整するように依頼しました。なぜなら、それらはすべてセパレータとしてスラッシュを持っているからです。
デンカー

@DenkerAffeああ、彼は私たちがセパレータを自由に選択できることを意味すると思った。ちなみに、それをセパレータアンビバレントにすることで3バイト節約できたので、ありがとう!
user81655

1
ルールseparated with a hyphen - or slash /は少し曖昧なようです。私にとっては、両方に対処する必要があることを意味しますが、あなたの側を明確に見ることができます。OPがこれを明確にする必要があると思います。
デンカー

3

T-SQL、210206、194バイト

(最初の投稿はこちら、大丈夫ですが、どうぞよろしくお願いします:)

入力に入る@iの両方の向き、/および-セパレータとして。私はオーストラリアにいるので、日付の形式は@Tasと同じです

DECLARE @i CHAR(5)='23-09';DECLARE @c INT=DATEPART(dy,CAST(REPLACE(@i,'-','/')+'/2016' AS DATE))-1;SELECT MIN(b)-@c FROM(VALUES(84),(85),(87),(115),(122),(276),(359),(360),(361))a(b)WHERE b>=@c;

更新 varcharしてchar3バイトを節約し、スペースを削除しました:)

Update 2で@cの選択なしの宣言と割り当て


2

T-SQL、296バイト

テーブル値関数として作成

create function d(@ char(5))returns table return select min(o)o from(select datediff(day,cast('2016'+right(@,2)+left(@,2)as date),cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1)o from(values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231))d(d))d where 0<=o

次の方法で使用

SELECT *
FROM (
    VALUES
        ('01/05') --= 1  
        ,('02/05') --= 0  
        ,('03/05') --= 153  
        ,('25/12') --= 0
        ,('26/12') --= 0
        ,('27/12') --= 0
        ,('30/12') --= 2
        ,('31/12') --= 1
    )testData(i)
    CROSS APPLY (
        SELECT * FROM d(t)
    ) out

i     o
----- -----------
01/05 1
02/05 0
03/05 153
25/12 0
26/12 0
27/12 0
30/12 2
31/12 1

(8 row(s) affected)

簡単な説明

create function d(@ char(5)) returns table  -- function definition
return 
select min(o)o -- minimum set value
from(
    select datediff( -- date difference
        day, -- day units
        cast('2016'+right(@,2)+left(@,2)as date), -- convert input parameter to date
        cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1 -- convert int values into datetimes and add a day
        )o 
    from(
        values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231) -- integers representing the day before public holidays
        )d(d)
    )d 
where 0<=o -- only for values >= 0

2

JavaScript(ES6)、134バイト

x=>[0,1,3,31,38,192,275,276,277,282].find(z=>z>=(q=x[0]+x[1]- -[...'20212122121'].slice(0,x[3]+x[4]-1).reduce((a,b)=>+b+a+29,0)-85))-q

user81655にはまだ3バイトのビートがありますが、ここから何かを絞り出す場所が他にありません。Dateを使用する代わりに、経過した日数を計算し、それを休日オフセットの配列と比較することにより機能します。


2

パイソン2、204 185 165 166バイト

更新:日付を自分で計算することで、最大20バイトまで削減しました。もう長いインポートの必要はありません:)

更新2:新しい年を367日と同じように扱うことができることを認識し、他の小さな調整を行うことにより、さらに20バイトダウンします。

def f(d):d=[d[:2],d[3:]];y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0]);return filter(lambda n:n>=y,[85,86,88,116,123,277,360,361,362,367])[0]-y

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

ゴルフをしていない:

def f(d):
    l=[85,86,88,116,123,277,360,361,362,367]
    d=[d[:2],d[3:]]
    y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0])
    f=filter(lambda n:n>=y,l)
    return f[0]-y

年末年始の番号をリストに保存し、指定された日付より前の年末年始をフィルタリングし、そのフィルタリングされたリストの最初の要素を取得して、その年の日入力から計算されました。


1

PHP、116バイト

かなり簡単なアプローチ。休日の年の日を保存し、過去にある限りポップします。最後に、要求された年の日が差し引かれます。

for($x=[366,361,360,359,276,122,115,87,85,84];($a=date(z,strtotime($argv[1].'-2016')))>$t=array_pop($x););echo$t-$a;

過去のすべてのテストケース。コマンドラインから実行し、次のようにハイフンを使用して入力を受け入れます。

$ php holidays.php "12-05"

1

ルビー1.9.3、155の 153バイト

クリスマスの祝日の後、私たちは特別な日の366が必要です!@DenkerAffeと同様のケース。

require'date'
c=(Date.strptime(ARGV[0],'%d/%m')-Date.parse('01/01')).to_i
print [84,85,87,115,122,276,359,360,361,366].map{|i|(i-c)}.select{|i|i>=0}.min

使用法:

$ ruby i_want_to_break_free.rb "03/05"

Rubyについてはあまり知りませんが、1行目と3行目の空白を削除することで3バイトを節約できると思います。また、使用している入力メソッドを指定する必要があります。関数を定義することでいくつかのバイトを節約できるため、入力を引数として受け取り、戻り値を出力として使用できます。
デンカー

@DenkerAffeありがとうございます!2バイトを節約しましたが、関数によって数が増えると思います。使用例で回答を更新しました。
タロッド

0

05AB1E、45 バイト

•9JRt€ª´Q®Ië•368вDI„-/S¡`•Σ₁t•ºS₂+s<£O+©@Ïн®-

もう2016年ではないかもしれませんが、何でも..;)292月のle年のために、まだ2016年であると仮定しています。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

9JRt€ª´Q®Ië•  # Push compressed integer 10549819042671399072072399
  368в         # Converted to base-368 as list: [85,86,88,116,123,277,360,361,362,367]
      D        # Duplicate this list
I              # Take the input
 „-/S¡         # Split it on ["-","/"]
      `        # Push both integer separated to the stack
•Σ₁t          # Push compressed integer 5354545
     º         # Mirror it without overlap: 53545455454535
      S        # Converted to a list of digits: [5,3,5,4,5,4,5,5,4,5,4,5,3,5]
       ₂+      # Add 26 to each: [31,29,31,30,31,30,31,31,30,31,30,31,29,31]
         s     # Swap to get the month-integer
          <    # Decrease it by 1
           £   # Only leave the first month-1 values from the integer-list
            O  # Sum that sublist
             + # And add it to the day-integer (so we now have the N'th day of the year)
©              # Save this in the register (without popping)
 @             # Do a >= check with each integer in the first (duplicated) list we created
  Ï            # Only leave the truthy values from the list
   н           # Then pop this sublist and only leave its first value
    ®-         # And subtract the integer we saved in the register (N'th day of the year)
               # (after which the result is output implicitly)

私のこの05AB1Eヒントを参照してください(セクションでは、どのように大きな整数の圧縮方法は?圧縮整数リストにどのように?理由を理解すること•9JRt€ª´Q®Ië•です10549819042671399072072399•9JRt€ª´Q®Ië•368вです[85,86,88,116,123,277,360,361,362,367]。と•Σ₁t•です5354545

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