下一个公众假期


18

澳大利亚人喜欢公共假期和饮酒。昨天,1月26日是澳大利亚国庆日,这是一个公共假期。我很高兴昨天没上班,并渴望知道下一次我的公共假期!不幸的是,我喝太多了,我自己也无法解决。

编写一个程序,该程序将采用澳大利亚日期/时间表示法(dd / mm)的日期作为输入,并输出直到下一个公共假日的天数。因为我是昆士兰(QLD)居民,所以我只对影响昆士兰人的公共假期感兴趣:

25/03 | 耶稣受难日
26/03 | 复活节星期六
28/03 | 复活节星期一
25/04 | 安扎克纪念日
02/05 | 劳动节
03/10 | 女王生日
25/12 | 圣诞节
26/12 | 节
礼日27/12 | 圣诞节假期

请注意网站上的以下内容:

圣诞节假期

当元旦,圣诞节或节礼日为周末时,将添加一个额外的公共假日。

因为圣诞节在星期天,所以有一个额外的公共假期。圣诞节仍然是公众假期。

因为我是早起的人,所以您应该将当前日期包括在内(因为这是我将在下一个公共假期检查程序的最可能的时间)。也就是说,如果输入了公众假期的日期,则输出应为0; 如果输入公共假期的前一天,则输出为1

我只对从现在(27/01)到年底的日期感兴趣。您需要考虑的最终日期是31/12,这是您的输出结果1(元旦)。

禁止出现标准漏洞

输入值

  • 输入将始终为5个字符:4个字母,以连字符-或斜杠分隔/
  • 输入的日期只能是27/01到31/12之间的日期

输出量

  • 直到下一个澳大利亚昆士兰州公众假期的天数,包括输入日期:应为0和之间的数字153(最长的间隔)
  • 没有新行或错误

例子

01-05 = 1  
02-05 = 0  
03-05 = 153  
25/12 = 0
26-12 = 0
27/12 = 0
30/12 = 2
31-12 = 1

希望这是清楚的,不会遗漏任何东西;但是,这是我的第二个问题,因此,我将感谢您的反馈,并会尽快解决问题。


@insertusernamehere感谢您的出色建议!我已经添加了日期中的问题
泰斯

@Tas您确定这些日期正确吗?示例中的那些与引号不匹配,并且两者均与网站不匹配。
亚当·马丁

@AdamMartin感谢您指出这一点。我错误地输入了12月的日期。示例中的日期仅是任何日期,并不特定于公共假期。它们只是可以输入的日期以及输出内容的示例。引用的内容应该(并希望如此)与网站上的内容匹配。
塔斯州

您在10月在昆士兰庆祝女王的生日吗?太奇怪了,但是从链接来看似乎是正确的。
水平河圣

哇,你们从六月一直到九月都没有假期吗?太粗糙了
Joe Z.

Answers:


2

Pyth98 84 62 67字节

更新:通过缩短所有12个月的天数列表来节省天数,从而节省了14个字节。还没有找到压缩其他列表的好方法,仍在尝试!

Update2:通过将天数列表结尾编码为base256字符串,节省了另外22个字节。

J30KhJ=Yc:z"\W"dd=N+s<[KtJKJKJKKJKJK)tseYshY-hfgTNCMc"UVXt{ĕŨũŪů"1N

在线尝试!

与我的Python回答中的算法相同。而且没有内置功能来获得一年中的每一天,所以我必须自己做。创建这两个列表用于按年计算和假期的日子是非常昂贵的……将再次查看它并尝试以更少的字节生成它们。


它似乎不喜欢用连字符将输入分隔开,但否则效果很好
Tas 2016年

@Tas谢谢您的提示,完全覆盖了该部分...以5个字节为单位修复了它。也许您应该在测试用例中添加一些连字符,因为您希望它们涵盖所有可能的输入变化。
Denker

5

Visual Basic for Applications,155或118字节

版本1-与语言环境无关,155个字节

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-DateSerial(16,Val(Right(d,2)),Val(Left(d,2)))
If h>=0Goto 9
Next
9 End Function

版本2-与语言环境相关的118字节

Function h(d)
For i=0To 9
h=Array(0,1,3,31,38,192,275,276,277,282)(i)+42454-CDate(d)
If h>=0Goto 9
Next
9 End Function

字节数用于最终的.BAS文件,包括换行符。在标准VBA编辑器外部进行编辑(因为它会附加空格和某些关键字的冗长形式)-但可以在任何Office应用程序上导入并顺利运行(以测试类型,例如? h("10/08")在立即窗口中或在Excel中直接在单元格公式中使用)。

(编辑)最初,我选择使用DateSerial来使该功能区域安全(版本1)。当我住在巴西时,因此我的系统配置为对日期使用“ dd / mm / yy”格式(就像在澳大利亚一样),我可以CDate改为使用较小的版本(版本2)。CDate使用系统区域设置信息将文本转换为日期。我还在此版本中假设代码仅在2016年运行(如果省略year(-6字节),则CDate假定当前年份为每个系统时钟)。

第三行上的数字42454是42450(这是VBA上的01/01/2016)和84(这是第一个假期的年中的数字)之和的总和。数组包含每个假期(包括2017年1月1日)的年中日期,以-84偏移,因为这需要一些数字。使用16代替2016 DateSerial会占用另外两个字节。

在迭代内部创建9次相同的数组是“错误的”代码,但是可以工作并节省3个字节(其中一个用于数组名称,另一个用于等号循环外,另外一个用于在循环内引用该数组)。

导入模块时,VBE会自动在第二行和第四行的0和以下关键字之间的“缺失”空格之间将其分隔开。使用过时,而且字节低价If <...> Goto <linenumber>从回路断线(包括If <...> Then Exit ForIf <...> Then Exit Function使用多个字符)。

还利用了以下事实:VBA中的函数名称表现为局部变量,并且其值在执行结束时由函数自动返回。


欢迎来到PPCG!在这里,我们由解释器定义了一种编程语言,因此要求特定语言环境是完全可以接受的。
lirtosiast

谢谢!编辑以添加一个较小的依赖于语言环境的版本。
dnep

4

的JavaScript(ES6),131个 128字节

d=>[56,57,59,87,94,248,331,332,333,338].map(n=>r=r||(q=1454e9+n*864e5-new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`))>=0&&q/864e5,r=0)|r

说明

使用JavaScript内置的Date构造函数将输入字符串转换为自纪元以来的毫秒数,然后将其与每个公共假日的毫秒数进行比较。

它通过将公共假日存储在数组中作为自参考日期以来的天数来实现此目的。我选择2016-01-29参考日期是因为可以将自纪元以来的毫秒数压缩为该日期的最短时间。从今天开始到下一个工作日之间的任何毫秒数都是有效的,因为结果会四舍五入,并且将数字保留在中间可以避免夏令时的影响(尽管OP的时区没有夏令时)。今天的天数是,1453986000000并且四舍五入到最后1454000000000(加上几个小时)意味着它可以写成1454e9

d=>
  [56,57,59,87,94,248,331,332,333,338]             // list of day offsets from 01/29
  .map(n=>                                         // for each public holiday offset n
    r=r||                                          // if r is already set, do nothing
      (q=                                          // q = approximate difference in ms
        1454e9+n*864e5                             // time of public holiday
        -new Date(d[3]+d[4]+`/${d[0]+d[1]}/16`)    // time of input date
      )
      >=0&&                                        // if q >= 0
        q/864e5,                                   // r = q in days
    r=0                                            // r = result
  )
  |r                                               // floor and return r

测试

此解决方案取决于用户的时区。这适用于OP的(和我的)时区(GMT +1000)。如果要在其他时区进行测试,则应添加numberOfHoursDifferentFromGMT1000 * 60 * 60 * 1000参考日期编号。(例如,格林尼治标准时间+0430为)-5.5 * 60 * 60 * 1000 + 1454e9+n*864e5


当日期用连字符分隔时,该值始终为0。我已经要求OP调整他的测试用例,因为它们都带有斜线作为分隔符。
Denker

@DenkerAffe哦,我以为他的意思是我们可以自由选择分隔符。顺便说一句,将其设置为分隔符可比我节省了3个字节,所以谢谢!
user81655 '16

1
好像规则separated with a hyphen - or slash /有点模棱两可。对我来说,这意味着我们必须同时处理这两者,但我可以明确地看到您的立场。猜猜OP应该澄清这一点。
Denker

3

T-SQL,210206,194字节

(这里的第一篇文章,希望可以,但是请保持友好:)

输入进入@i,既适合/-作为分隔符。我在澳大利亚,所以我的日期格式与@Tas相同

DECLARE @i CHAR(5)='23-09';DECLARE @c INT=DATEPART(dy,CAST(REPLACE(@i,'-','/')+'/2016' AS DATE))-1;SELECT MIN(b)-@c FROM(VALUES(84),(85),(87),(115),(122),(276),(359),(360),(361))a(b)WHERE b>=@c;

更新 varcharchar节省3个字节再加上一个空格:)

Update 2声明@c和分配而没有选择


2

T-SQL,296字节

创建为表值函数

create function d(@ char(5))returns table return select min(o)o from(select datediff(day,cast('2016'+right(@,2)+left(@,2)as date),cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1)o from(values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231))d(d))d where 0<=o

以下列方式使用

SELECT *
FROM (
    VALUES
        ('01/05') --= 1  
        ,('02/05') --= 0  
        ,('03/05') --= 153  
        ,('25/12') --= 0
        ,('26/12') --= 0
        ,('27/12') --= 0
        ,('30/12') --= 2
        ,('31/12') --= 1
    )testData(i)
    CROSS APPLY (
        SELECT * FROM d(t)
    ) out

i     o
----- -----------
01/05 1
02/05 0
03/05 153
25/12 0
26/12 0
27/12 0
30/12 2
31/12 1

(8 row(s) affected)

简要说明

create function d(@ char(5)) returns table  -- function definition
return 
select min(o)o -- minimum set value
from(
    select datediff( -- date difference
        day, -- day units
        cast('2016'+right(@,2)+left(@,2)as date), -- convert input parameter to date
        cast(right('2016'+right('0'+cast(d as varchar(4)),4),8)as datetime)+1 -- convert int values into datetimes and add a day
        )o 
    from(
        values(324),(325),(327),(424),(501),(1002),(1224),(1225),(1226),(1231) -- integers representing the day before public holidays
        )d(d)
    )d 
where 0<=o -- only for values >= 0

2

JavaScript(ES6),134个字节

x=>[0,1,3,31,38,192,275,276,277,282].find(z=>z>=(q=x[0]+x[1]- -[...'20212122121'].slice(0,x[3]+x[4]-1).reduce((a,b)=>+b+a+29,0)-85))-q

user81655仍然让我被3个字节击败,但是我找不到其他地方可以压缩任何东西。通过计算过去的天数(而不是使用日期),然后将其与假日补偿数组进行比较来进行工作。


2

Python 2中,204 185 165 166字节

更新:通过自己计算一年中的某天将其降低了约20字节。不再需要长时间的进口了:)

更新2:通过意识到我可以像对待367天一样对待新年并进行其他一些小的调整,又减少了20个字节。

def f(d):d=[d[:2],d[3:]];y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0]);return filter(lambda n:n>=y,[85,86,88,116,123,277,360,361,362,367])[0]-y

在线尝试!

取消高尔夫:

def f(d):
    l=[85,86,88,116,123,277,360,361,362,367]
    d=[d[:2],d[3:]]
    y=sum([31,29,31,30,31,30,31,31,30,31,30,31][:int(d[1])-1])+int(d[0])
    f=filter(lambda n:n>=y,l)
    return f[0]-y

通过将假日的年中日期存储在列表中,过滤掉给定日期之前的假日,将过滤后的列表中的第一个元素减去该年中的日期来工作从输入中计算得出。


1

PHP,116字节

很简单的方法。它存储一年中的假日日期,并一直保留过去的时间。最终减去一年中要求的日期。

for($x=[366,361,360,359,276,122,115,87,85,84];($a=date(z,strtotime($argv[1].'-2016')))>$t=array_pop($x););echo$t-$a;

过去所有测试用例。从命令行运行,并使用连字符接受输入,例如:

$ php holidays.php "12-05"

1

红宝石1.9.3,155个 153字节

圣诞节假期后,我们需要超级特殊的366天!与@DenkerAffe类似的情况。

require'date'
c=(Date.strptime(ARGV[0],'%d/%m')-Date.parse('01/01')).to_i
print [84,85,87,115,122,276,359,360,361,366].map{|i|(i-c)}.select{|i|i>=0}.min

用法:

$ ruby i_want_to_break_free.rb "03/05"

我对Ruby不太了解,但是我认为您可以通过删除第1行和第3行中的空格来节省3个字节。另外,您还应该指定要使用的输入方法,因为它在代码中并不那么明显。您可以通过定义一个函数来保存一些字节,因此可以将输入作为参数,并使用返回值作为输出。
Denker

@DenkerAffe非常感谢!我已经保存了2个字节,但是我认为一个函数会增加数量。我用用法示例更新了答案。
Tarod

0

05AB1E,45 个字节

•9JRt€ª´Q®Ië•368вDI„-/S¡`•Σ₁t•ºS₂+s<£O+©@Ïн®-

现在可能不再是2016年了,但是..;)仍然假设该年是2016年,29因为它是2月的a年。

在线尝试验证所有测试用例

说明:

9JRt€ª´Q®Ië•  # Push compressed integer 10549819042671399072072399
  368в         # Converted to base-368 as list: [85,86,88,116,123,277,360,361,362,367]
      D        # Duplicate this list
I              # Take the input
 „-/S¡         # Split it on ["-","/"]
      `        # Push both integer separated to the stack
•Σ₁t          # Push compressed integer 5354545
     º         # Mirror it without overlap: 53545455454535
      S        # Converted to a list of digits: [5,3,5,4,5,4,5,5,4,5,4,5,3,5]
       ₂+      # Add 26 to each: [31,29,31,30,31,30,31,31,30,31,30,31,29,31]
         s     # Swap to get the month-integer
          <    # Decrease it by 1
           £   # Only leave the first month-1 values from the integer-list
            O  # Sum that sublist
             + # And add it to the day-integer (so we now have the N'th day of the year)
©              # Save this in the register (without popping)
 @             # Do a >= check with each integer in the first (duplicated) list we created
  Ï            # Only leave the truthy values from the list
   н           # Then pop this sublist and only leave its first value
    ®-         # And subtract the integer we saved in the register (N'th day of the year)
               # (after which the result is output implicitly)

看到这个05AB1E尖矿(部分如何压缩大的整数?以及如何压缩整数列表?理解为什么•9JRt€ª´Q®Ië•10549819042671399072072399; •9JRt€ª´Q®Ië•368в[85,86,88,116,123,277,360,361,362,367]; 并且•Σ₁t•5354545

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.