该日期最后一次是什么时候可以被n整除?


24

日期可以用无符号整数表示,例如:YYYYMMDD。您需要做的是编写最短的程序或函数,找出最接近的日期,该日期或日期可被给定的数字整除n(包括今天的日期),然后以上面显示的格式返回该日期。如果从未有过可被给定整数整除的日期(介于00000101和今天之间),则应返回-1。

例子

Current Date     Input     Output

30 July, 2014      4       20140728
30 July, 2014      7       20140729
28 July, 2014      4       20140728
28 July, 2014      7       20140722
28 July,    5    90000     -1

输入项

您可以从STDIN读取或接受函数参数,甚至可以期望将输入存储在变量中。输入将是一个无符号整数。

输出量

写入STDOUT或以YYYYMMDD格式返回(或保存在变量中)表示日期的整数。

限制条件

您可以使用您的语言提供的任何标准库。有标准漏洞

获奖条件

这是一个,因此以最小的程序(以字节为单位)获胜。如果是平局,则以票数最多的答案为准。


4
日期00000101不存在。年计数开始由1 en.wikipedia.org/wiki/0_%28year%29
edc65

1
@ edc65我们可以假装它确实存在吗?
overactor 2014年

3
那2月29日呢?我们是否需要应用完整的leap年规则来检查有效日期?zh.wikipedia.org/wiki/Leap_year
数字创伤

6
儒略历-格里高利历转换带来的损失天数呢?还是我们一路走来? en.wikipedia.org/wiki/Gregorian_calendar
数字创伤

1
您的输入/输出规格相当宽松。例如,“期望输入存储在变量中”应该用C之类的语言来计算变量声明吗?您说“编写程序”,但您说“采用函数参数”-这是否意味着我们只能编写函数而不是完整程序?
鲍勃

Answers:


16

Mathematica,93个 60字节

For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n∣r,];r~Max~-1

期望输入存储在中n

请注意,垂直线是“分隔”的Unicode字符,我将其视为3个字节(UTF-8)。

编辑:找到了一个巧妙的技巧,以避免avoid肿DateString和格式规范:)。

编辑:完全忘记了-1要求。立即修复。

这是一个解释

For[i=0,            i--                        ,];         (* i is the number of days AFTER
                                                              today. Hence, we decrement 
                                                              it. *)
For[i=0,   DatePlus@i--                        ,];         (* If no reference date is
                                                              provided, DatePlus will add
                                                              the given number of days to
                                                              today's date. The result is a 
                                                              list of 3 integers, luckily 
                                                              in order {year,month,day} *)
For[i=0,   DatePlus@i--~FromDigits~100         ,];         (* Interpret these as the digits
                                                              of a base 100 number. The 
                                                              beauty is that FromDigits
                                                              doesn't care about digits 
                                                              greater than the base and 
                                                              just carries them over. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)        ,];         (* Store the number in r. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0      ,];         (* Make sure it's positive. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n|r,];         (* And keep going while n does 
                                                              not divide r. *)
For[i=0,(r=DatePlus@i--~FromDigits~100)>0&&!n|r,];r~Max~-1 (* Clamp result to -1. *)

请注意,我使用|而不是在解释中使用,因为Unicode混淆了单间距。


+1。您是否有一个链接指出应该将Unicode字符计为3个字节?
belisarius博士2014年

2
@belisarius OP指出此代码高尔夫球是按字节而不是字符计数的(这也是标记Wiki中所述的默认值)。
马丁·恩德

我从来没有读过维基的末尾:)谢谢!
belisarius博士2014年

6

Python 2-150

import datetime as d,re
def f(n):
 t=d.date.today()
 while t:
    c=int(re.sub("-","",str(t)))
    if c%n<1:return c
    try:t-=d.timedelta(1)
    except:return-1

感谢@ chill0r提出删除days =的建议,感谢Jason S提出的提示,try块可以减少到一行。


是。那是一个标准的操作程序;)。粘贴后,选项卡将转换为空格。
2014年

您可以删除days=中的t-=d.timedelta(days=1)。这也可以正常工作(至少在python3中有效)
chill0r 2014年

@bitpwner啊,我明白了,没关系。
Martin Ender 2014年

1
您可以节省更多:(1)使用int(t.strftime("%Y%m%d"))和拖放re,(2)使用单行,try因为只t-=d.timedelta(1)需要插入其中。
詹森·S

1
@bitpwner strftime在较早的日期在python3中有效,已检查,但在python2中确实收到错误
Jason S

5

C#136

在修订的规范中,该函数采用无符号int并返回int。

int F(uint n){var d=System.DateTime.Now;int i;try{while((i=int.Parse(d.ToString("yyyMMdd")))%n>0)d=d.AddDays(-1);}catch{i=-1;}return i;}

152个字符,具有可变的输入/输出

利用宽松的输入/输出要求,将输入存储在变量中n(当前计算除整数文字外的所有字符),并为输出提供变量s

class P{static void Main(){var n=4;var d=System.DateTime.Now;string s;try{while(int.Parse(s=d.ToString("yyyMMdd"))%n>0)d=d.AddDays(-1);}catch{s="-1";}}}

STDIN / STDOUT的204个字符:

using System;class P{static void Main(){int n=int.Parse(Console.ReadLine());var d=DateTime.Now;string s;try{while(int.Parse(s=d.ToString("yyyMMdd"))%n>0)d=d.AddDays(-1);}catch{s="-1";}Console.Write(s);}}

1
真的,不赞成投票吗?这不能正确解决问题吗?请解释。如果有人认为我重复了另一个C#答案,则实际上是在另一个C#之前一个小时写的,甚至考虑将C#6.0用于声明表达式。有点偏了,导致答案发布晚了。即便如此,那仍然是拒绝投票的脆弱理由。
鲍勃

4

T-SQL(2012)-148

假设有一个带有n值的自由变量@n。

declare @ date=getdate()while convert(char,@,112)%@n>0 and'00010101'<@ set @=dateadd(d,-1,@)print iif(convert(char,@,112)%@n=0,convert(char,@),'-1')

4

哥夫鲁亚 90 86

n=I.r()d="%Y%m%d"i=O.d(d)+0j=0@i>0?i%n==0w(i)O.q()$j=j+1i=O.d(d,O.t()-j*86400)+0$w(-1)

一个没有版本的Lua版本是,

n = io.read()
d = "%Y%m%d"
i = os.date(d)+0   -- implicitly casts os.date(d) to int
j = 0
while i>0 do
   if i % n == 0 then
      print(i)
      os.exit()
   end
   j = j+1
   i = os.date(d,os.time()-j*86400)+0
end
print(-1)

2
在这里测试n = 20140699输出20140699
William Barbosa

@WilliamBarbosa:固定;20140699返回-1。
凯尔·坎诺斯

4

MATLAB:61

-1,s=str2num(datestr(1:now,'YYYYmmDD')),d=s(~mod(s,n)),d(end)

假设除数存储在中n。结果将存储在名为的变量中ans


评论版本:

-1                                     % Store -1 in ans in case we don't find anything
s=str2num(datestr(1:now,'YYYYmmDD'))   % Make a list of date numbers
d=s(~mod(s,n)),                        % Select only those who are dividable and prepend -1
d(end)                                 % Store last found value in ans, if anything is found

如果未找到结果,将生成错误,但是尽管如此,答案仍然在变量中可用。


可以避免错误,但要额外增加2个字符:

s=str2num(datestr(1:now,'YYYYmmDD')),d=[-1;s(~mod(s,n))],d(end)

@MartinBüttnerHmm,解决了该问题,但现在该解决方案仅适用于最小字符数。您看到任何改进了吗?
丹尼斯·贾赫鲁丁

1
不,不是我的头顶上。但是我帮助您击败我的动力有点有限。;)
Martin Ender 2014年

4

PHP(92 = 85 + 7)

期望输入存储在中$n

for($d=date("Ymd");!($d%$n==0&checkdate($d/100%100,$d%100,substr($d,0,4))|$d<0);$d--);echo$d

我只记得为什么我不再喜欢PHP =)

编辑:现在也实现了规范的-1。


不,只需检查一下,$ d在回显时将太低。你“锻造”是什么意思?(对不起,没有英语的母语=)
瑕疵的

哦,我没有看到该规格,当然必须添加此规格,谢谢!
瑕疵的

3

JavaScript(ES6)115

预期变量n中的数字,结果存储在变量r中。每天都会进行检查,从当前日期开始,然后递减-必须有更好的方法。
此外,使用标准的javascript日期功能,所有日期都是公历直到1年((年因此在公历改革之前是错误的)。

for(z=new Date,t=n+1;t>n&&t%n;)
  d=z.getDate(),
  t=z.getFullYear()*1e4+(z.getMonth()+1)*100+d,
  z.setDate(d-1);
r=t>n?t:-1

3

C#-144(或LINQPad中为124)+1为每个数字 n

这期望输入在变量中n。在执行结束时,所需的值将在变量中r00010101但是,这被视为第一个日期,因为该日期00000101不存在。随时欢迎提出改进建议。

class P{static void Main(){int n=7,r;var d=System.DateTime.Now;try{for(;(r=int.Parse(d.ToString("yyyMMdd")))%n>0;d=d.AddDays(-1));}catch{r=-1;}}}

LINQPad版本:

int n=7,r;var d=System.DateTime.Now;try{for(;(r=int.Parse(d.ToString("yyyMMdd")))%n>0;d=d.AddDays(-1));}catch{r=-1;}r.Dump();

3

Groovy- 301300个字符

非常简单(且缓慢),没有任何技巧可以掩盖它使用Joda Time的事实。

打高尔夫球:

@Grab(group='joda-time', module='joda-time', version='2.3')
import org.joda.time.*
import org.joda.time.format.*
f={DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(it)) as int}
n=args[0] as int;b=0;x=-1;c=0
while(!b){if(f(c++)%n==0){x=f(--c);b=1};if(f(0)-c<=101){b=1}}
println x

运行示例(2014年7月30日):

$ groovy D.groovy  7
20140729
$ groovy D.groovy  16
20140720
$ groovy D.groovy  90000
-1

取消高尔夫:

@Grab(group='joda-time', module='joda-time', version='2.3')

import org.joda.time.*
import org.joda.time.format.*

f = { DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(it)) as int }

n = args[0] as int
b = 0 
x = -1
c = 0

while (!b) {
    if(f(c++)%n==0) { x=f(--c); b=1}
    if(f(0)-c<=101){b=1}
}

println x

3

R,146 139

D=function(n){
z=as.double(gsub("-","",y<-Sys.Date()))
d=F
while(z>100&!d){
y=y-1 
z=as.double(gsub("-","",y))
d=!z%%n}
ifelse(z>100,z,-1)}

祝您约会愉快。microbenchmark报告说,回溯15天大约需要半秒钟。截至2014年7月31日,-1至少要根据信封的背面,这大约需要2000万秒(约23天)。

编辑:评论中的一些快捷方式


!d比短d==F!z%%nz%%n==0。另外,将其as.numeric(gsub("-","",...)转换为函数也应减少字符数。还是,不错!
plannapus 2014年

哦,as.real通常是一个更好的,更短的选择as.numeric
plannapus 2014年

不幸的as.real是,自R 3.0.0起已失效。但是我们仍然要as.double短一个字符。
shadowtalker 2014年

哦,我还不知道,因为我仍在使用R 2.14
plannapus 2014年

1
我不是在拥有管理权限的计算机上工作,所以这不是我自己决定的。但我已经自然地拥有paste0.Rprofile:)
plannapus 2014年

3

Matlab 104

function d=f(v);for d=fix(now):-1:1 d=str2num(datestr(d,'YYYYmmDD'));if~mod(d,v)return;end;end;d=-1;end

松散

function d = f(v)
   for d=fix(now):-1:1
       d = str2num(datestr(d,'YYYYmmDD'));
       if ~mod(d,v)
          return; 
       end
   end
   d = -1;
end

编辑:我设法对其进行了优化,但@DennisJaheruddin在这里有真正的解决方案


这仍然可以打很多,我将对其进行更新。
丹尼斯·贾赫鲁丁

@DennisJaheruddin我已拒绝您根据此meta帖子所做的编辑。请在评论中提出您的改进建议,以便OP可以在修改其答案之前对其进行审核。
Martin Ender 2014年

请注意,您可以通过多种方式保存字符:使用脚本而不是函数,让事物分配给ans,从低到高执行循环,并让每个结果覆盖前一个,因此您无需中断循环。-当然向量化也有帮助,请参阅我的回答
丹尼斯·贾赫鲁丁

这是基于67个字符的较短循环版本:-1,for s=str2num(datestr(1:now,'YYYYmmDD'))',if~mod(s,n),+s,end,end
Dennis Jaheruddin 2014年

@MartinBüttner感谢您的评论。如您所说,有一个错误。现在应该可以了。
斯科特

3

Python的3 - 151个 148字节,发电机

from datetime import*
t=date.today()
f=lambda n:next((y for y in(int((t-timedelta(o)).strftime("%Y%m%d"))for o in range(t.toordinal()))if y%n<1),-1)

感谢@ nyuszika7h的import*建议



2

Java:373个字符

这是Groovy答案的一部分,并使用Joda Time。

打高尔夫球:

import org.joda.time.*;
import org.joda.time.format.*;
public class D {
static int f(int i){return Integer.parseInt(DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(i)));}
public static void main(String[] args){
int n=Integer.parseInt(args[0]);int b=0,c=0,x=-1;
while(b!=1){if(f(c++)%n==0){x=f(--c);b=1;};if(f(0)-c<=101){b=1;}}
System.out.println(x);}}

样本运行(在类路径上使用joda-time-2.4.jar:

$ java D 7
20140729
$ java D 4
20140728
$ java D 16
20140720
$ java D 90000
-1

取消高尔夫:

import org.joda.time.*;
import org.joda.time.format.*;

public class D {
    static int f(int i) {
        return Integer.parseInt(DateTimeFormat.forPattern("yyyyMMdd").print(new LocalDate().minusDays(i)));
    }

    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        int b = 0,c = 0,x = -1;

        while(b!=1) {
            if(f(c++)%n==0) { x=f(--c);b=1; }
            if(f(0)-c<=101) { b=1; }
        }

        System.out.println(x);
    }
}

3
还有java.time.*在Java中的最新版本。
ntoskrnl 2014年

2

Bash + coreutils(8.21),67字节

seq -f-%gday $[9**9]|date -f- +[pq]sp[_1pq]sq%Y%m%ddA1=qd$1%%0=p|dc
  • seq生成1到9 9的整数,每行一个,并将其格式化为-<x>day
  • 用管道将date -f其解释为每一行并输出格式化为dc表达式的日期,例如[pq] sp [_1pq] sq 20140728 d A1 =q d 7% 0=p(为便于阅读而添加空格)
    • [pq] 定义一个宏以打印堆栈顶部,然后退出
    • sp 将宏保存在寄存器p中
    • [pq] 定义一个宏以推送-1,打印堆栈的顶部,然后退出
    • sq 将宏保存在寄存器q中
    • 20140728 嵌入日期整数
    • d 堆栈顶部重复
    • A1 推101(00000101)
    • =q弹出顶部2个堆栈值:比较日期和101,q如果相等则调用宏
    • 7 推式分隔线
    • % 弹出除法器和除法器,除法器并推入余数
    • 0 推0
    • =p弹出顶部2个堆栈值:比较余数和0,p如果相等则调用宏
    • d 堆栈顶部重复
    • p被称为:打印日期整数并dc完全退出
  • dc表达式通过管道传递dc给求值。一旦dc输出正确的值并退出,其余的管道将被拆除

输出:

$ ./lastdivdate.sh 4
20140728
$ ./lastdivdate.sh 7
20140729
$ ./lastdivdate.sh 123456
17901120
$ ./lastdivdate.sh 77777
19910912
$ ./lastdivdate.sh 7777777
-1
$ 

由于此程序会生成1到9 9的整数,因此在未来一百万年之内将一直有效。我希望这个限制是可以接受的;-)


感谢@ WumpusQ.Wumbley缩短-1的返回值。


@MartinBüttner诅咒!现在,它以19字节的罚款:)
Digital Trauma

将空输出转换为-1的更短方法:添加|grep .||echo -1到管道的末尾,或使用zsh可以在其中嵌套扩展echo ${$(cmd):-1}(例如,在其他地方花费反斜杠...)

@ WumpusQ.Wumbley为什么我没有想到呢?谢谢!
Digital Trauma 2014年

1
顺便说一句,这似乎对coreutils版本很敏感。Mine(8.15)拒绝在1901年之前采用“几天前”的规格。

1
实际上,这似乎是一个sizeof time_t问题,因为它打破的边界是在1970年1月1日之前的2 ** 31秒。我的旧安装也是可怜的32位

2

PYTHON:134个字节

不能击败当前的领导者,并且它没有比Python的最佳答案要好得多,但是我决定发布自己的最佳Python解决方案。

from datetime import*
def y(a,n):
 s=a.strftime("%Y%m%d")
 if int(s)%n==0:yield s
 try:x=y(a-timedelta(1),n)
 except:yield -1
 yield x

取消高尔夫:

from datetime import *
def y(a, n):
    s=int(a.strftime("%Y%m%d"))
    if s%n==0:
        yield s
    try:
        x=y(a-timedelta(1), n)
    except:
        yield -1
    yield x

实际上是138个字节。您可以使用from datetime import*代替import datetime as dtimedelta(1)代替d.timedelta(1)yield来节省4个字节return
nyuszika7h 2014年

我正在使用随机在线字节计数器,是否有更好的选择?
RageCage 2014年


是什么让这个与这个不同?bytecount.bluebus112.com
RageCage 2014年

那不算换行符,它算字符,而不是字节。对于ASCII文本,两者是相同的,因此后者在这里没有区别。在code-golf中,除非OP另有说明,否则通常会计算字符数。(此外,我链接的链接是Google 此处“字节数”的第一个结果。)
nyuszika7h 2014年

2

JavaScript(ES5)-94

它期望输入为变量x,并将输出置于中o

for(i=Date.now();i>-7e13&&(o=(new Date(i)).toISOString().replace(/-|T.*/g,''))%x;i-=864e5)o=-1

2

k4 (84)(73)

f:{f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;.z.D];x]}

这只是想到的第一个算法的初步切入。我确信在性能和长度上都可能更好。

这个版本硬编码“今天”部分(即.z.D);将其更改为日期文字(yyyy.mm.dd)或q日期系统(自2000年1月1日以来的天数)中的整数以运行测试用例。(q不会解析早于18世纪初的日期文字,因此对于之前的日期,您需要计算出值并直接使用适当的整数。1月1日,规格中的“ AD 0”变成证明是-730457,这是在功能代码中使用。7月28日,5 AD,从最后一个测试的情况下,原来是-728450)。

给定的测试用例:

  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.30];x]}4
20140728
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.30];x]}7
20140729
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.28];x]}4
20140728
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;2014.07.28];x]}7
20140722
  "d"$-728450
0005.07.28
  {f d@*|&~.q.mod[(f:{$[^x;-1;.($x)@&~"."=$x]})'d:{"d"$x+!1+"i"$y-x}[-730457;-728450];x]}90000
-1

编辑:

g:.,/$`\:`$$:;f:{$[Z=r:{(z>x)&.q.mod[g z]y}[Z:-730458;y]{x-1}/x;-1;g"d"$r]}

这是一种不同的方法,它使用收敛运算符之一来递减日期,直到找到一个可整除的日期或超过1/1/0000边界为止。从日期到整数的转换也略有不同。

测试用例,这次一次全部:

  g:.,/$`\:`$$:;{$[Z=r:{(z>x)&.q.mod[g z]y}[Z:-730458;y]{x-1}/x;-1;g"d"$r]}'[2014.07.30 2014.07.30 2014.07.28 2014.07.28,"d"$-728450;4 7 4 7 90000]
20140728 20140729 20140728 20140722 -1

1

VBA 343字节(模块)

Sub divD(i As Long)
a = Now()
b = Format(a, "yyyymmdd")
    Do While b / i <> Int(b / i)
    a = DateAdd("d", -1, a)
    b = Format(a, "yyyymmdd")
        If b = "01000101" Then
            MsgBox -1
            Exit Sub
        End If
    Loop
MsgBox b
End Sub

这可以很大程度上凝聚到Sub d(i):a=Now:b=a:Do Until b/i=Int(b/i):a=DateAdd("d",-1,a):b=Format(a,"yyyymmdd"):If b="01000101"Then:b=-1:Exit Sub:Loop:Debug.?b:End Sub为139字节
泰勒·斯科特

1

PowerShell的-76

这取决于存储在变量中的数字$n

try{@(0..$n|%{'{0:yyyyMMdd}'-f(date).AddDays(-$_)}|?{!($_%$n)})[0]}catch{-1}
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.