ナックルを数えることで、31日間が何ヶ月あるかを数えます


11

まだ自分のナックルを使用して、1か月が31日以内であるかどうかを判断する人はどれくらいいますか?

あなたの仕事は、「ナックルを数える」ことで、1か月の範囲で何月が31日間完全になり、31日間未満になるのかを数えるプログラムを書くことです。

ナックルで月の日を数える

礼儀:amsi.org.au


入力

一対の月。最初の月は2番目の月の前に時系列に来る必要はなく、適切な形式で与えられます。例:201703 201902— 2017年3月から2019年2月。選択した入力形式を説明してください。入力には、1〜9999のすべての年を含めることができる必要があることに注意してください。指定された月の範囲には、開始月と終了月の両方が含まれます。

出力

2つの整数:31日の範囲内の月数と31日未満の範囲内の月数。

例:14 10— 14個のナックル、10個の溝(つまり、その月の範囲では、完全な31日を持つ14か月と、31日未満の10か月があることを意味します)。

たとえば、範囲内の2番目の月が最初の月よりも前に来る入力の場合、201612 201611ゼロのペアを出力する必要があります。

入力と出力の例

| Input         | Output      |
|---------------|-------------|
| 201703 201902 | 14 10       |
| 201701 202008 | 26 18       |
| 000101 999912 | 69993 49995 |
| 201802 201803 | 1 1         |
| 201601 201601 | 1 0         |
| 201612 201611 | 0 0         |

ルール

  • 好きな言語を選択できます
  • 1行に1つの入力
  • これはなので、バイト単位の最短コードが勝ちです!
  • 勝者は4月9日に選ばれます
  • 標準的な抜け穴が適用されます
  • PS:これはPCGでの私の最初の質問です。いくつかの矛盾があるかもしれません。不明な点がある場合は、自由に編集して確認してください。

5
あなたは最初のものが2番目の前に時系列で来ることが保証されていると言いますが、これはテストケースのために偽です201612 201611
デニス

2
サイトにはサンドボックスがあり、疑問をすべて解消するためだけに質問を投稿できます。
ghosts_in_the_code

1
30日間は9月、4月、6月、11月です。2月の終了後、残りはすべて31です。それは私がそれを覚えている方法です。
AdmBorkBork

@AdmBorkBorkそれに関する唯一の問題は、無限ループ(必須のxkcdリファレンス)です。
-wizzwizz4

日付範囲全体でグレゴリオ暦を使用するつもりだと思いますか?
追って通知があるまで一時停止します。

回答:


7

ゼリー、21バイト

ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$

のような入力を受け取ります[[y, m], [y, m]]

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

使い方

ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$  Main link. Argument: [[a, b], [c, d]]

ḅ12                    Unbase 12; yield [x, y] := [ 12a + b, 12c + d].
   r/                  Reduce by range; yield [x, ..., y].
           ¤           Combine the five links to the left into a niladic chain.
      7                  Set the return value to 7.
       R                 Range; yield [1, 2, 3, 4, 5, 6, 7].
        Ḃ                Bit; yield [1, 0, 1, 0, 1, 0, 1].
         ṁ12             Mold 12; repeat the Booleans to create an array of length
                         12. Yields [1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1].
     ị                 At-index; yield the elements of the array to the right at 
                       the indices (1-based and modular) of the array to the left.
               $       Combine the two links to the left into a monadic chain.
              C          Complement; map t -> 1-t over the array.
             ż           Zip the original array with the complements.
                S      Take the sum of each column.
                    $  Combine the two links to the left into a monadic chain.
                  Ṣ      Sort [[a, b], [c, d]].
                   ⁼     Compare the result with [[a, b], [c, d]], yielding 1 if
                         the input is sorted, 0 if not.
                 ×     Multiply the results to both sides.

5

JavaScript(ES6)、70 68 67 64バイト

入力をyyyymm、構文をカリー化する形式の2つの整数として受け取ります(a)(b)。2つの整数の配列を出力します[knuckles, grooves]

a=>g=(b,c=d=0)=>a>b?[c,d-c]:g(--b,c+!((b%=100)>11||b/.87&!!++d))

フォーマットおよびコメント

a =>                        // main function: takes start date (a) as input / returns g
  g = (                     // recursive function g, which takes:
        b,                  //   - b = end date
        c = d = 0           //   - c = number of knuckles
      ) =>                  // and also keeps track of: d = total number of months
    a > b ?                 // if a is greater than b:
      [ c, d - c ]          //   stop recursion and return the final result
    :                       // else:
      g(                    //   do a recursive call to g():
        --b,                //   - decrement the end date
        c +                 //   - increment the # of knuckles if
        !(                  //     both of these conditions are false:
          (b %= 100)        //     - the end month (now stored in b in 0-based indexing)
          > 11 ||           //       is greater than 11
          b / 0.87 & !!++d  //     - the number of days in this month is not 31
        )                   //       (at the same time, d is incremented if the first
      )                     //       condition is false)

テストケース

注意:3番目のテストケースは、このスニペットに含まれていません。これは、ブラウザーでTail Call Optimizationが有効になっていないと機能しないためです。


5

パイソン292の 90 86 80バイト

lambda a,b,c,d:[(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x)for x in'10']

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

アイデアを提供してくれた@math_junkieに感謝します。2つの数値を含むリストを出力するようになりました。

以前の非ラムダバージョン(86バイト)

a,b,c,d=input()
for x in'10':print(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x),

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

2を削除してくれた@ovsに感謝しlen(k)ます。私は使用することを考えていませんでしたNone

入力は次の形式の整数のリストです y1,m1,y2,m2

bin(2741)[2:]私がやる前に得た@KeerthanaPrabhakaranによるクレジットは、バイナリ文字列のハードコーディングを1バイト節約します。


印象的... k = bin(2741)[2:] *(c + 1-a)が私の心を吹き飛ばした
officialaimm

1
これは、 2バイトの短い
OVS

鮮やかさ!私はlen(k)最後のスライスから取り除くためにを作ろうとしていました。ありがとう。
エルペドロ

1
:あなたは、ラムダ使って、6つのバイトを保存することができますTIO
数学中毒を

4

PHP259 256 249 248 237 221バイト

arossによるアウトゴルフhttps : //codegolf.stackexchange.com/a/114512/38505

入力フォーマット: yyyymm,yyyymm

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";foreach(new DatePeriod($_(Ym,$i[0]),new DateInterval(P1M),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))>30?++$x:++$y;
echo $x.' '.++$y;

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


古いバージョン

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_("Ym",$i[0]),new DateInterval('P1M'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.$y;

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

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_(Ym,$i[0]),DateInterval::createFromDateString('1 month'),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))>30?++$x:++$y;
echo $x.' '.$y;

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

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_(Ym,$i[0]),DateInterval::createFromDateString('1 month'),$_(Ym,$i[1])) as$f)date(t,mktime(0,0,0,$f->format(m),1,$f->format(y)))==31?++$x:++$y;
echo $x.' '.$y;

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

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";foreach(new DatePeriod($_("Ym",$i[0]),DateInterval::createFromDateString('1 month'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.++$y;

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

$i=explode(",",fgets(STDIN));$_="DateTime::createFromFormat";$y=1;foreach(new DatePeriod($_("Ym",$i[0]),DateInterval::createFromDateString('1 month'),$_("Ym",$i[1])) as$f)date("t",mktime(0,0,0,$f->format("m"),1,$f->format("y")))==31?++$x:++$y;
echo $x.' '.$y;

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


3

バッチ、93バイト

@set/ag=(y=%2/100-%1/100)*5+(x=%2%%100+6)*5/12-(w=%1%%100+5)*5/12,k=y*12+x-w-g
@echo %k% %g%

ymm形式の2つのパラメーター(101-999912)を受け入れます。以前の129バイトのループベースのソリューション:

@set/al=%1-%1/100*88,u=%2-%2/100*88,k=g=0
@for /l %%i in (%l%,1,%u%)do @set/a"m=%%i%%12,k+=1451>>m&1,g+=2644>>m&1
@echo %k% %g%

おそらく整数のサイズ制限のため、000101 999912の誤った結果ですか?
officialaimm

1
@officialaimm入力形式が間違っています。申し訳ありません。年の先頭にゼロを付けないでください。
ニール

3

Python 3.5(164 162 154 152 150 148 140 137バイト)

n=int;a,b=input().split();t=k=0
for r in range(n(a[4:]),(n(b[:4])-n(a[:4]))*12+n(b[4:])+1):t+=1;k+=n('101010110101'[r%12-1])
print(k,t-k)

repl.it

yyyymm yyyymmの形式で入力を取ります

出力をnumber_of_knuckles number_of_groovesとして出力します

  • 2バイト節約:Coleに感謝
  • 8バイトを節約:不要な変数を削除
  • 2バイトを節約: t = 0; k = 0をt = k = 0に削減
  • 2バイトの節約: Coleのおかげで(以前は見逃していた)
  • :2バイト保存に感謝をKeerthana
  • 8バイトを節約:不要な変数を削除
  • :3バイト保存のおかげmath_junkie(スプリットに分割(」「)())

1
私はあなたがすることによっていくつかのバイトを減らすことができると思うn=int、そしておそらくいくつかのexecごまかしも。
コール

1
2773&1<<r%12-1>0代わりにできると思うint('101010110101'[r%12-1])
-Loovjo

@Loovjoそうするとエラーが発生します!
officialaimm

1
print([k,t-k])as print(k,t-k)を使用すると、望ましい結果が得られ(k,g)、2バイトが削減されます。
Keerthana Prabhakaran

1
私はあなたが交換することができると信じてsplit(' ')split()
数学中毒

3

パイソン2147の 146 142バイト

def s(a,b):y=100;r=bin(2741)[2:];x=b/y-a/y;i=r*(x-1);return((0,0),map((i+r[a%y-1:]+r[:b%y]if i or x else r[a%y-1:b%y]).count,('1','0')))[a<=b]

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

  • 4バイトの保存-配列検索でif-else句を提案してくれた@math_junkieに感謝します!

コードを分解し、

def s(a,b):
 y=100
 r=bin(2741)[2:] #'101010110101'
 x=b/y-a/y #to get the difference between the two years
 i=r*(x-1)
 return((0,0),map((i+r[a%y-1:]+r[:b%y]if i or x else r[a%y-1:b%y]).count,('1','0')))[a<=b]

1
if-else句を配列ルックアップに置き換えることでバイトを節約できます。詳細については、この投稿を参照してください
数学中毒

それは確かにクールな方法でした!以前は知らなかった!ありがとう!
Keerthana Prabhakaran

3

PHP、120 103 97 96バイト

for($f=strtotime;$f($argv[2])>=$n=$f($argv[1].+$x++.month);)$k+=date(t,$n)>30;echo+$k,_,$x-1-$k;

次のように実行します:

php -nr 'for($f=strtotime;$f($argv[2])>=$n=$f($argv[1].+$x++.month);)$k+=date(t,$n)>30;echo+$k,_,$x-1-$k;' 0001-01 9999-12;echo
> 69993_49995

説明

for(
  $f=strtotime;          # Alias strtotime function which is called twice.
  $f($argv[2]) >=        # Create end date timestamp. Iterate until the end
                         # date is reached.
  $n=$f(
    $argv[1].+$x++.month # Create timestamp from start date + X months.
  );
)
  $k+=date(t,$n) > 30;   # If "t" of current date (days in month) is 31
                         # increment $k (knuckles).

echo+$k,_,$x-1-$k;       # Compute grooves (iterations - $k) and output,
                         # implicit cast to int to account for 0 count.

微調整

  • DateTimeオブジェクトスタイルの代わりにタイムスタンプスタイルを使用して17バイトを保存しました
  • 終了日タイムスタンプを変数に割り当てないことで6バイトを節約しました。$e直接比較するだけです
  • グルーブの数を保持せず、ループ後に計算するだけで1バイトを節約

$x++代わりに+$x++動作します。
タイタス

@Titus、最初はそれを持っていましたが、$x初期化されていない文字列2017-12monthは、認識されない形式であり、1970年の結果であることに
気付きました

邪悪...それはどこかで働いた。+文字列にリテラルがなくても動作するほど十分に邪悪です。
タイタス

2

PowerShell、96バイト

for($a,$b=[datetime[]]$args;$a-le$b;$a=$a.AddMonths(1)){$x++;$z+=$a.Month-in2,4,6,9,11};$x-$z;$z

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

入力をフォームとして受け取ります2017-03。組み込みの.NET日付ライブラリを使用し、入力$aからにループします$b。各反復は、現在の日付(つまり、31日以外の月)である場合、増分$x++および加算されます。次に、合計月から非31日の月、および非31日の月を差し引いた月を出力します。$z.Month-in 2,4,6,9,11$x-$z$z

上のエラートス0001-019999-12テストケース、.NETはわずかに年までサポートしているため9999、最終的な.AddMonths(1)原因オーバーフロー。ただし、終了しないエラーであるため、依然として正しい値が出力されます。ループが終了するだけです。

PythonやJavaScriptの答えのように、算術的にこれを行うにはおそらく短くなりますが、.NETビルトインを使用したアプローチを示したかったのです。


2

Bash、113バイト

s="$1-1";e="$2-1";sort <(while [ "$s" \< "$e" ];do s=$(date +%F -d"$s+1month");date +%d -d"$s-1day";done)|uniq -c

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

ゴルフが必要...

入力を受け取ります 2016-03 2018-10

出力:

  1 28
  7 30
 12 31

権利なし:

s="$1-1"
e="$2-1"                     # adds first day of month to the dates
sort <(                    
while [ "$s" \< "$e" ]; do   #iterates over dates
s=$(date +%F -d"$s+1month")  #adds one month to start date
date +%d -d"$s-1day"         #outputs last day of previous month
done) | uniq -c              #counts ocurrences of day number prevously sorted

1

Swift、151バイト

let f={(m:[Int])->[Int] in var k=[0,0]
(m.min()!...m.max()!).map{$0%100}.filter{$0>0&&$0<13}.forEach{m in let n = m>7 ?m-7:m
k[(n%2+1)%2]+=1}
return k}

入力は、例の形式の2つの整数の配列です。

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