너클을 세어 31 개월 동안 몇 개월을 보냈는지 계산하십시오


12

한 달이 31 일 이하인지 확인하기 위해 여전히 너클을 사용하는 사람은 몇 명입니까?

당신은 "너클을 계산"하여 한 달 범위 내에서 몇 달 동안 전체 31 일을 보냈고 몇 일 동안 31 일보다 적은지를 계산하는 프로그램을 작성해야합니다.

너클로 월 계산

의례 : amsi.org.au


입력

한 달의 두 달, 첫 번째는 두 번째 이전에 연대순으로 올 필요가 없으며 적절한 형식으로 제공됩니다. 예를 들어 : 201703 201902- 2007 년 2 2019 년 3 월 2017 사용자가 선택하는 입력 형식을 설명하십시오. 입력은 1 년에서 9999 년까지의 모든 연도를 포함 할 수 있어야합니다. 지정된 월 범위에는 시작 월과 종료 월이 모두 포함됩니다.

산출

두 개의 정수 : 31 일이 지정된 범위의 월 수와 31 일이 아닌 범위의 월 수

예 : 14 10— 14 개의 너클, 10 개의 홈 (해당 월 범위에는 전체 31 일의 14 개월, 31 일 미만의 10 개월)이 있습니다.

예를 들어 201612 201611, 범위의 두 번째 달이 첫 번째 시간 이전에 시간순으로 나오는 입력의 경우 한 쌍의 0을 출력해야합니다.

입력 및 출력의 예

| 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         |

규칙

  • 원하는 언어를 선택할 수 있습니다
  • 라인 당 하나의 입력
  • 이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다!
  • 우승자는 4 월 9 일에 선정됩니다
  • 표준 허점 적용
  • 추신 : 이것은 PCG의 첫 번째 질문이며 일부 불일치가있을 수 있습니다. 불분명 한 내용을 편집하고 확인하십시오.

5
당신은 말을 두 번째 전에 순으로 올 보장되는 첫 번째 ,하지만이 테스트 케이스에 대한 false입니다 201612 201611.
Dennis

2
사이트에 샌드 박스 가있어 모든 의심을 없애기 위해 질문을 게시 할 수 있습니다.
ghosts_in_the_code

1
9 월, 4 월, 6 월, 11 월 30 일. 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

자바 스크립트 (ES6), 70 68 67 64 바이트

yyyymm카레 구문 에서 입력 형식을 정수 2 개로 취 합니다 (a)(b). 두 정수의 배열을 출력합니다 [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)

테스트 사례

NB : 세 번째 테스트 사례는이 스 니펫에 포함되어 있지 않습니다. 브라우저에서 Tail Call Optimization을 활성화하지 않으면 작동하지 않기 때문입니다.


5

파이썬 2 , 92 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 덕분에 람다로 변환하여 6 더. 이제 두 숫자가 포함 된 목록을 출력합니다.

이전 비 람다 버전 (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)마지막 조각에서 괭이를 제거하려고했습니다 . 감사.
ElPedro

1
람다를 사용하여 6 바이트를 절약 할 수 있습니다. TIO
math junkie

4

PHP , 259 256 249 248 237 221 바이트

aross에 의해 outgolfed : 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 형식 (예 : 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 입력 형식이 잘못되었습니다. 죄송합니다. 연도에는 선행 0이 없어야합니다.
Neil

3

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)

반복

yyyymm yyyymm 형식으로 입력을받습니다.

출력을 number_of_knuckles 로 인쇄합니다.

  • 절약 된 2 바이트 : Cole 덕분에
  • 8 바이트 저장 : 불필요한 변수 제거
  • 절약 된 2 바이트 : 감소 된 t = 0; k = 0을 t = k = 0으로
  • 2 바이트 절약 : Cole 덕분에 (이전에 놓친 적이 있습니다)
  • 2 바이트 절약 : Keerthana 덕분에
  • 8 바이트 저장 : 불필요한 변수 제거
  • 3 바이트 저장 : math_junkie 덕분에 (split ( '') to split ())

1
나는 당신이 n=int또한 약간의 exectomfoolery를 함으로써 바이트를 줄일 수 있다고 생각합니다 .
Cole

1
나는 당신이 할 수 있다고 생각 2773&1<<r%12-1>0대신에int('101010110101'[r%12-1])
Loovjo

@Loovjo 그렇게하는 데 오류가 발생했습니다!
officialaimm

1
사용 print([k,t-k])print(k,t-k)으로 원하는 결과를 얻을 것이다 (k,g)하여 2 바이트를 감소!
Keerthana Prabhakaran 2016 년

1
나는 당신이 바꿀 수 있다고 생각 split(' ')split()
수학 마약 중독자

3

파이썬 (2) , 147 (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절을 배열 조회 로 바꾸어 바이트를 절약 할 수 있습니다 . 자세한 내용은 게시물을 참조하십시오
math junkie

정말 멋진 방법이었습니다! 전에 몰랐어요! 감사!
Keerthana Prabhakaran 2016 년

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 바이트 절약
  • 종료 날짜 시간 소인을 variable에 지정하지 않고 6 바이트를 절약했습니다 $e. 바로 비교하십시오.
  • 그루브 수를 유지하지 않고 루프 후 계산하여 1 바이트를 절약했습니다.

$x++대신 +$x++작동합니다.
Titus

@Titus, 나는 처음에 그했지만, 함께 실현 $x초기화되지 않은 문자열이 될 2017-12month1970 년에 인식 할 수없는 형식과 결과 인
aross

사악한 ... 어딘가에서 일했습니다. +문자열에 리터럴없이 작동하지만 충분히 악 합니다.
Titus

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

온라인으로 사용해보십시오!

form으로 입력을 2017-03받습니다. 용도 내장 된 .NET 날짜 도서관을 통해 입력에서 루프 $a$b, 각 반복이 증가 $x++하고에 추가 $z전류가있는 경우 .Month이다 -in 2,4,6,9,11(즉, 비 - 31 일 월). 그런 다음 총 개월 수에서 31 일이 아닌 달 $x-$z과 31 일이 아닌 달을 뺀 값을 출력합니다 $z.

상의 오류가 토스 0001-019999-12.NET 만 년까지 지원하기 때문에, 시험의 경우 9999최종 때문에, .AddMonths(1)원인 오버 플로우. 그래도 끝나지 않는 오류이므로 올바른 값을 출력합니다. 루프가 종료됩니다.

아마도 파이썬이나 JavaScript 답변과 같이 산술적 으로이 작업을 수행하는 것이 더 짧을 수도 있지만 .NET 내장 기능을 사용하여 접근 방식을 보여주고 싶었습니다.


2

배쉬 , 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

스위프트, 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}

입력은 예제에 따른 형식의 두 정수 배열입니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.