通过计算指关节数来计算整整31天有多少个月


12

你们中仍有多少人仍然使用自己的指关节来确定一个月是否已不足31天?

您的工作是编写一个程序,通过“计算转向节”来计算一个月范围内有多少个月的时间已满31天,有多少个月的时间少于31天。

用指关节计数一个月中的天数

礼貌:amsi.org.au


输入值

一两个月,第二个月不必按时间顺序排在第二个月之前,可以以任何合适的格式给出。例如:201703 201902— 2017年3月至2019年2月。请描述您选择的输入格式。请注意,输入必须能够包含从1到9999的所有年份。指定的月份范围包括开始和结束月份。

输出量

两个整数:给定范围(31天)中的月数和少于31天(范围)中的月数。

示例:14 10— 14个指关节,10个凹槽(这意味着在该月范围内,我们有14个月的时间为整整31天,而10个月的时间少于31天)。

例如,对于范围中第二个月按时间顺序在第一个月之前的输入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         |

规则

  • 您可以选择任何喜欢的语言
  • 每行一个输入
  • 这是,因此以字节为单位的最短代码胜出!
  • 获奖者将于4月9日入选
  • 适用标准漏洞
  • PS:这是我在PCG中的第一个问题,可能存在一些不一致之处。随时编辑并确认您不清楚的地方。

5
您说保证第一个按时间顺序排在第二个之前,但这对于测试用例是错误的201612 201611
丹尼斯

2
网站上有一个沙箱,您可以在其中发布问题,以消除所有疑问。
ghosts_in_the_code

1
九月,四月,六月和十一月有三十天。在2月完成后,其余所有成员都剩下31个。这就是我记得的方式。
AdmBorkBork

@AdmBorkBork唯一的麻烦是无限循环(强制性xkcd参考)。
wizzwizz4

我假设您打算在整个日期范围内使用公历?
暂停,直到另行通知。

Answers:


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

采用yyyymmcurrying语法,将输入形式为两个整数,格式为(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)

测试用例

注意:此代码段中不包含第三个测试用例,因为除非您的浏览器启用了“尾叫优化”功能,否则它不会起作用。


5

Python 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']

在线尝试!

通过转换为lambda还有6个,感谢@math_junkie的建议。现在输出包含两个数字的列表。

先前的非lambda版本(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

@KeerthanaPrabhakaran bin(2741)[2:]在我之前获得了一些荣誉,这比硬编码二进制字符串节省了1个字节。


令人印象深刻... k = bin(2741)[2:] *(c + 1-a)令我震惊
Officialaimm

1
是2个字节短
OVS

辉煌!我试图找出out头以摆脱len(k)最后一刻。谢谢。
ElPedro

1
您可以使用lambda来保存6个字节:TIO
数学迷

4

PHP259个 256 249 248 237 221字节

通过Outgolfed aross/codegolf//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输入格式错误,对不起-年份不应包含前导零。
尼尔

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 number_of_grooves

  • 保存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,也可以减少一些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

Python 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个字节-感谢@math_junkie建议使用数组查找建议if-else子句!

分解代码,

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

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年无法识别的格式和结果
aross

邪恶的...它在某处起作用。足够邪恶,尽管它+在字符串中不带文字的情况下也可以工作。
泰特斯

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循环遍历$x++$z如果当前日期.Month-in 2,4,6,9,11(即非31天月份),则每次迭代递增并增加。然后,我们输出总月份减去非31天月份$x-$z和非31天月份$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

迅捷,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}

输入是两个整数的数组,格式如示例所示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.