タイムスパンを数える


17

私はここへの答えを求めた現実のシナリオに触発されました:https : //superuser.com/questions/1312212/writing-a-formula-to-count-how-many-times-each-date-日付のセットに表示されます

タイムスパンの配列(または開始日と終了日のペア)を指定すると、合計範囲内のすべての日について、1日をカバーするタイムスパンの数を出力します。

例えば:

  #      Start      End
  1    2001-01-01 2001-01-01
  2    2001-01-01 2001-01-03
  3    2001-01-01 2001-01-02
  4    2001-01-03 2001-01-03
  5    2001-01-05 2001-01-05

上記のデータを考えると、結果は次のようになります。

2001-01-01: 3 (Records 1,2,3)
2001-01-02: 2 (Records 2,3)
2001-01-03: 2 (Records 2,4)
2001-01-04: 0
2001-01-05: 1 (Record 5)

各日のカウントのみを出力する必要があります(順番に古いものから新しいものへソートされます)。どのレコードに表示されるかではありません。

各タイムスパンには、時刻ではなく日付のみが含まれると想定できます。したがって、丸1日は常に表されます。

I / O

入力は、タイムスパンのセットを表す任意の形式です。つまり、時間のペアのセット、または開始日と終了日を含む(ビルトイン)オブジェクトのコレクションのいずれかです。PPCGチャレンジでは通常のように、日時は1901〜2099に制限されています。

入力は好きなように事前にソートされていると仮定できます(答えを指定してください)。入力日付は包括的です(したがって、範囲には開始日と終了日全体が含まれます)。

また、特定の範囲内の2つの日付のうち、最初の日付が2番目の日付よりも古いか等しいと見なすこともできます(つまり、負の日付範囲はありません)。

出力は、開始日でソートされたときの入力の最も古いものから最も新しいものまでの各日のカウントを含む配列です。

したがって、上記の例の出力は次のようになります {3,2,2,0,1}

一部の日がどの時間範囲にも含まれていない可能性があり0ます。その場合、その日付に対して出力されます。

受賞基準

これはコードゴルフなので、最低バイトが勝ちです。通常の除外が適用されます

擬似アルゴリズムの例

For each time range in input
    If start is older than current oldest, update current oldest
    If end is newer than current newest, update current newest
End For
For each day in range oldest..newest
   For each time range
       If timerange contains day
            add 1 to count for day
End For
Output count array

同じ結果を得るための他のアルゴリズムは問題ありません。


3
整数の配列が必要ですか、それとも他の何かを返すことができますか?たとえば、各日付としてキーを持つ辞書?辞書を返すことが許可されている場合、どのタイムスパンにも属さない日付を省略できますか?
ジョンファンミン

1
入力を開始日と対応する終了日を持つ2つのリストとして取得できますか?
ジュゼッペ

ええ、日付を省略することを除いて、これらはすべて問題ありません
-simonalexander2005

3
なぜ0辞書に入れるべきなのか尋ねてもいいですか?それだけから反復するためにユーザーを強制的に表示されるmin(input)までmax(input)の挑戦(コンピューティングのタイムスパン)のコアに何も追加していないようだこれは、。
ジョンファンミン

2
@JungHwanMinそれはそれを変えないと思います。しかし、私がそれを投稿したときに仕様に明示的に含まれていたので、私はそれをいじりに行き、他の誰かに答えをやり直したくありません
-simonalexander2005

回答:


3

APL(Dyalog Unicode)、32 バイトSBCS

完全なプログラム。国際日付番号のペアのリストの入力を要求します(ExcelやMATLABが使用するものなど)。リストとペアの両方は、(End、Start)などの任意の順序で指定できます。カウントのリストを標準出力に出力します。

¯1+⊢∘≢⌸(R,⊢)∊(R←⌊/,⌊/+∘⍳⌈/-⌊/)¨⎕オンラインでお試しください!

これが無効な場合、(YMD)ペアのリストは合計21バイト、合計53バイトに変換できます。

¯1+⊢∘≢⌸(R,⊢)∊(R⌊/,⌊/+∘⍳⌈/-⌊/)¨{2⎕NQ#'DateToIDN'⍵}¨¨⎕オンラインでお試しください!


 評価された入力のプロンプトコンソール

( 次の暗黙関数を各ペアに適用します

⌊/ 最小(lit. min-reduction)、つまり開始日

⌈/- 最大(つまり終了日)からそれを引いたもの

⌊/+∘⍳ 開始日と1からその範囲の範囲

⌊/, その前に開始日

R← この機能をRRの場合)に割り当てます

ε NLIST(平坦化)1つのリストに範囲のリスト

() 次の暗黙関数をそれに適用します。

R,⊢ 適用の結果R(日付範囲)とそれに続く引数
  (これにより、範囲内の各日付が少なくとも1回は表され、日付はソートされた順序で表示されます)

 一意の各ペア(日付、入力におけるその出現インデックス)に対して、次を実行します。

⊢∘≢ インデックスの集計を支持して実際の日付を無視する

¯1+ それらの集計に-1を追加します(範囲内の各日付の1つを追加したため)


9

JavaScript(ES6)、85バイト

入力をDateペアのリストとして受け取ります。リストが開始日でソートされることを期待します。整数の配列を返します。

f=(a,d=+a[0][0])=>[a.map(([a,b])=>n+=!(r|=d<b,d<a|d>b),r=n=0)|n,...r?f(a,d+864e5):[]]

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

またはJSタイムスタンプを入力として使用できる場合は84バイト(@Shaggyが示唆するとおり)



プリミティブ値を入力としてバイトを保存します:TIO
Shaggy

7

JavaScript、75 73バイト

入力を日付プリミティブペアの配列のソートされた配列として受け取り、キーが各日付のプリミティブであるオブジェクトと、範囲内のそれらの日付のカウント値を出力します。

a=>a.map(g=([x,y])=>y<a[0][0]||g([x,y-864e5],o[y]=~~o[y]+(x<=y)),o={})&&o

それを試してみてください


どの範囲にも表示されない日付を含める必要があることが確認されるまで、私はこの60バイトバージョンに取り組んでいたので、上記のソリューションに急いで更新しました。

a=>a.map(g=([x,y])=>x>y||g([x+864e5,y],o[x]=-~o[x]),o={})&&o

オンラインで試してみてください(または出力で人間が読める日付で


ES6はJSオブジェクト(stackoverflow.com/a/31102605/8127)のキー順序、文字列とシンボルキーの基本的な挿入順序を定義しているように見えます(そしてTIOのNodejsはそれに従っているようです:tinyurl.com/ybjqtd89)。一般的に、私の意見では、実装の詳細(ここでのオブジェクト)はチャレンジルールの解釈を指示するものではないが、Metaの投稿を待ちます。
スンダ-モニカを復元18年

6

オクターブ、63バイト

@(x)histc(t=[cellfun(@(c)c(1):c(2),x,'un',0){:}],min(t):max(t))

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

今ではthatいです!

説明:

入力をdatenum要素のセル配列(つまり、次の"2001-01-01"ように数値に変換された文字列)として受け取ります。

{[d("2001-01-01") d("2001-01-01")]
[d("2001-01-01") d("2001-01-03")]
[d("2001-01-01") d("2001-01-02")]
[d("2001-01-03") d("2001-01-03")]
[d("2001-01-05") d("2001-01-05")]};

どこd()関数ですdatenum。次にcellfun、これらの行ごとに、最初の列から2番目の列までの範囲を持つセルを作成します。これらの範囲を水平方向に連結し、すべての日付を含む長い水平ベクトルを作成します。

次にhistc、これらの値を使用してヒストグラムを作成し、ビンは最低日付と最高日付の間の範囲で指定されます。


5

R、75バイト

function(x,u=min(x):max(x))rowSums(outer(u,x[,1],">=")&outer(u,x[,2],"<="))

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

入力は、最初の列が開始で、2番目の列が終了である行列です。Start <= Endを想定していますが、開始日を並べ替える必要はありません。


これは、Stewie GriffinによるOctaveの答えを再現しようとしてできた限りです...何が間違っていますか?
JayCe

これは、Rがそのビンを行う方法のためhistです。あなたは何ができるc(-25668,min(x):max(x))ので、-25568前である1900が、あなたの提案の答えよりも長いアップこれは終了。そうは言っても、日付を生成するよりも良い方法がありapplyます。68バイトのサイズがあり、自分で投稿する時間を見つけられませんでした。
ジュゼッペ

ああ、いや、実際に使用(min(x)-1):max(x)して、期待どおりに動作するはずです。apply日付を生成する方法が見つからない場合は、これを63バイトに取得してOctaveの回答を結び付けることができます。
ジュゼッペ

@Giuseppe別の回答として投稿する必要があります:)
JayCe

投稿しました :-)私は使用tableしてfactorいましたが、以前Mapは68バイトを使用していましたhistが、おそらく忘れてしまったきちんとしたアプローチです)
ジュゼッペ

4

、174バイト

func[b][m: copy #()foreach[s e]b[c: s
until[m/(c): either none = v: m/(c)[1][v + 1]e < c: c + 1]]c: first sort b
until[print[either none = v: m/(c)[0][v]](last b)< c: c + 1]]

非常に長く、リテラルの実装。

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

読みやすい:

f: func [ b ] [
    m: copy #()
    foreach [ s e ] b [
        c: s
        until [
            m/(c): either none = v: m/(c) [ 1 ] [ v + 1 ]   
            e < c: c + 1
        ]      
    ]
    c: first sort b
    until[
        print [ either none = v: m/(c) [ 0 ] [ v ] ]
        ( last b ) < c: c + 1
    ]      
]

4

Groovy、142バイト

{a={Date.parse('yyyy-mm-dd',it)};b=it.collect{a(it[0])..a(it[1])};b.collect{c->b.collect{it}.flatten().unique().collect{it in c?1:0}.sum()}}

フォーマット済み:

 {                                   // Begin Closure
    a={Date.parse('yyyy-mm-dd',it)}; // Create closure for parsing dates, store in a().
    b=it.collect{                    // For each input date pair...
        a(it[0])..a(it[1])           // Parse and create date-range.
    };
    b.collect{                       // For each date range...
        c->
        b.collect{                   // For each individual date for that range...
           it
        }.flatten().unique().collect{ // Collect unique dates.
            it in c?1:0
        }.sum()                      // Occurrence count.
    }
}

4

パイソン2114の 87 93バイト

-27バイト、Jonathan Allanの
おかげ+6バイト、sundarのおかげ

日時オブジェクトのペアのリストとして入力を受け取ります。
最初のペアが最も低い日付で始まると仮定します。

def F(I):
 d=I[0][0]
 while d<=max(sum(I,[])):print sum(a<=d<=b for a,b in I);d+=type(d-d)(1)

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


daysはのデフォルト引数ですtimedelta
ジョナサンアラン

...実際には、入力は既にs であるため、ドロップしfrom datetime import*て置換できると思います。87バイトd+=timedelta(days=1)d+=type(d-d)(1)date
ジョナサンアラン

1
これは、最初の範囲の開始が最低日付であり、最後の範囲の終了が最高であると仮定しているように見えますが、OPがソートされた入力を許可したとしても、それは不可能な場合があります。例えば 入力がの場合[(2001-01-01, 2001-01-05), (2001-01-02, 2001-01-03)]。OPが前処理中にこれらの範囲を分割および再配置することを許可しない限り(これはありそうもない)、この入力はこのコードによって適切に処理できません。
スンダ

@sundarはい、あなたの言っていることがわかります。これを処理するためにソリューションを更新しました。ありがとう!
デッドポッサム

3

Wolfram言語(Mathematica)、62バイト

Lookup[d=DayRange;Counts[Join@@d@@@#],#[[1,1]]~d~#[[-1,1]],0]&

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

0出力に含める必要があるOPが指定されているため、+ 35バイト。

辞書のエントリの省略が許可されている場合、27バイト

Counts[Join@@DayRange@@@#]&

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

ビルトインDayRangeは2つDateObjectのs(または同等の文字列)を受け入れDates、それらの日付間のリスト(包括的)を出力します。


3

R65 63バイト

function(x)hist(unlist(Map(`:`,x[,1],x[,2])),min(x-1):max(x))$c

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

これは、JayCeと私とのコラボレーションであり、Stewie Griffinの答えをRに移植しています。

JayCeを引用するには:

入力は、最初の列が開始で、2番目の列が終了である行列です。Start <= Endを想定していますが、開始日を並べ替える必要はありません。

おそらく$c不要ですが、それはチャレンジの精神に完全には合っていないので、含めました。


1
2バイトのMin(x-1)?
JayCe


@JayCeはい、いいね!これに早く戻るつもりでしたが、忘れました。
ジュゼッペ

3

Powershell、122 121 118 113バイト

filter d{0..($_[-1]-($s=$_[0])).Days|%{$s.AddDays($_)}}$c=@{};$args|d|%{++$c.$_};,($c.Keys.Date|sort)|d|%{+$c.$_}

として保存しますcount-timespan.ps1。テストスクリプト:

.\count-timespan.ps1 `
    @([datetime]"2001-01-01", [datetime]"2001-01-01")`
    @([datetime]"2001-01-01", [datetime]"2001-01-03")`
    @([datetime]"2001-01-01", [datetime]"2001-01-02")`
    @([datetime]"2001-01-03", [datetime]"2001-01-03")`
    @([datetime]"2001-01-05", [datetime]"2001-01-05")

説明

filter d{                           # define a function with a pipe argument (it's expected that argument is an array of dates)
    0..($_[-1]-($s=$_[0])).Days|%{  # for each integer from 0 to the Days
                                    # where Days is a number of days between last and first elements of the range
                                    # (let $s stores a start of the range)
        $s.AddDays($_)              # output to the pipe a date = first date + number of the current iteration
    }                               # filter returns all dates for each range
}                                   # dates started from first element and ended to last element
$c=@{}                              # define hashtable @{key=date; value=count}
$args|d|%{++$c.$_}                  # count each date in a array of arrays of a date
,($c.Keys.Date|sort)|d|%{+$c.$_}    # call the filter via pipe with the array of sorted dates from hashtable keys

# Trace:
# call d @(2001-01-01, 2001-01-01) @(2001-01-01, 2001-01-03) @(2001-01-01, 2001-01-02) @(2001-01-03, 2001-01-03) @(2001-01-05, 2001-01-05)
# [pipe]=@(2001-01-01, 2001-01-01, 2001-01-02, 2001-01-03, 2001-01-01, 2001-01-02, 2001-01-03, 2001-01-05)
# $c=@{2001-01-03=2; 2001-01-01=3; 2001-01-05=1; 2001-01-02=2}
# call d @(2001-01-01, 2001-01-02, 2001-01-03, 2001-01-05)
# [pipe]=@(2001-01-01, 2001-01-02, 2001-01-03, 2001-01-04, 2001-01-05)
# [output]=@(3, 2, 2, 0, 1)

ありがとう!$cnt.Keys.Dateもちろん。
奇抜な

-3バイト:にfunction置き換えられscriptblockます。ゴルフとゴルフのないコードがテストされます。
mazzy

-5バイト:でscriptblock置き換えられfilterます。aの呼び出しfilterはよりコンパクトです。
mazzy

3

J、43バイト

(],.[:+/@,"2="{~)&:((>./(]+i.@>:@-)<./)"1),

入力は整数のペアのリストで、各整数は任意の一般的な0日からのオフセットです。

食べない

(] ,. [: +/@,"2 ="{~)&:((>./ (] + i.@>:@-) <./)"1) ,

説明

構造は次のとおりです。

(A)&:(B) C
  • Cは、メイン動詞A&:Bに左側の入力と右側の平坦化された入力を与えるフックを作成します
  • B aka ((>./ (] + i.@>:@-) <./)"1)はリストの最小値と最大値を取り、結果の範囲を返し、ランク1で動作します。したがって、右側に合計範囲、左側に個々の範囲が表示されます。
  • 次に、A =ランク"0 _(つまり、ランク{)を使用して、各入力が範囲内に出現する回数をカウントします。最後に、それらのカウントで毎年圧縮されます。

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


2

JavaScript(Node.js)、80バイト

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-864e5],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u

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

undefinedゼロを意味します。最初の要素は最も早く開始する必要があります

(a,u=[])=>a.map(g=([p,q])=>p>q||g([p,q-1],u[z=(q-a[0][0])/864e5]=-~u[z]))&&u 要素のみが表示され、より多くのスタックを使用する場合は短くなります


6
別の値を代用して0もかまわないことを確認してください。
シャギー


1

R(70)

function(x)(function(.)tabulate(.-min(.)+1))(unlist(Map(seq,x$S,x$E,"d")))

データフレームを前提とx二つの列(持つStartEnd又はおそらくSE日付(クラスでの)Date)。

オンラインで試す


こんにちは、TIOリンク(他の回答を参照)をサンプルの入出力に含めることができますか?パッケージを含めることは不正行為ではありませんlibrary(magrittr)が、バイトカウントに含める必要があります。
JayCe

また、コンセンサスによると、提出はスニペットではなく完全な関数またはプログラムである必要があります。そのため、唯一の引数が関数である場合x、答えfunction(x)は関数の本体で始まります。
JayCe

1

ジュリア0.6、77バイト

M->[println(sum(dM[r,1]:M[r,2]for r1:size(M,1)))for dM[1]:max(M...)]

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

@DeadPossumのPythonソリューションに触発されました。

入力をマトリックスとして受け取ります。各行には、入力範囲の開始日と終了日という2つの日付があります。入力の最初の日付が最初であり、各行の開始日が最初であると仮定しますが、異なる行間でそれ以上のソートは行わないと想定します。


古いソリューション:

ジュリア0.6、124バイト

R->(t=Dict();[[dkeys(t)?t[d]+=1:t[d]=1 for dg]for gR];[dkeys(t)?t[d]:0 for dmin(keys(t)...):max(keys(t)...)])

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

日付範囲の配列として入力を受け入れます。配列内の異なる範囲間でのソートは想定していません。

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