【问题标题】:Calculating future occurrences of Friday the 13th计算 13 日星期五的未来事件
【发布时间】:2010-10-07 11:39:43
【问题描述】:

我希望能够从一年开始,计算 13 日星期五的出现次数。蛮力解决方案简单明了。我有一些稍微好一点的东西,但我毫不怀疑其他人可以为此提出一个优雅的算法。

也许有点棘手,我有兴趣给这个程序一个月,让它找到那个月有 13 号星期五的下一年。

随意使用伪代码,但我希望人们会更多地投票支持使用您喜欢的语言的工作代码示例。

【问题讨论】:

  • 快乐 1234567890 unix time day!
  • 也许这是一次不错的高尔夫挑战……
  • 这些电影现在很规律地上映,估计大约需要 3 年听起来不错:)

标签: algorithm language-agnostic datetime


【解决方案1】:
initialize startDate to 13th of the month given in the current year
while (true) {
    if (startDate.dayOfWeek == Date.FRIDAY)
         break;
    else
         startDate.year ++;
}
return startDate.year;

【讨论】:

    【解决方案2】:

    由于您的蛮力算法显然是直观的逐日迭代选项,也许您没有考虑过Doomsday Algorithm。它可以让您简单地检查 13 日是否是星期五。据我所知,这是解决问题最有效的方法。

    【讨论】:

      【解决方案3】:

      任何以星期日开始的月份都有一个星期五在十三号。只有 14 种组合可能知道一年中的第一天是哪一天(有或没有闰年和太阳-星期六)。您应该只计算一次并完成它。您只需检查 14*12 可能的月份即可开始,并且有理由。

      结果表元素(从 2009 年到 2010 年):

      [Thursday,false] => Feb, March, Nov
      [Friday,false] => Aug
      

      要填写表格,您有一个通用月份 Jan(31),Feb(28).. 然后使用一周中每一天的种子进行迭代,注意从星期日开始的月份,以及闰年和没有。非常简单,完成后,您可以与我们分享:)

      【讨论】:

      • 这是最快的表格方法,afaict。工作日有 14 种类型——非闰年 7 种,闰年 7 种,以及 12 个月。一旦您知道 1 月 1 日是一周中的哪一天以及是否是闰年,2D 或 3D 数组可以提供非常快速的答案 - 两者都很容易计算。
      • 对于所有想要整张桌子的人,这是非闰年:[[4, 7], [9, 12], [6], [2, 3, 11], [8], [5], [1, 10]],这是闰年:[[9, 12], [6], [3, 11], [2, 8], [5], [10], [1, 4, 7]]。数组内部的值是从 1 开始的月份索引,外部数组从星期一开始
      【解决方案4】:

      我注意到的一件事是,在 13 号星期五的月份中,每月的第一天是星期日。您或许可以利用它来简化计算。

      【讨论】:

        【解决方案5】:

        我会这样做:

        • 假设年份是已知的并且是整数。

        • 从 1 到 12 循环

          • 使用循环索引、年份和 13 创建日期

            • 根据established algorithms确定星期几

            • 如果上面计算的星期几是星期五,请做好你的工作

        如果你想从月份和年份开始(你必须假设某种年份),你的算法就变成了

        • 假设年份已知且为整数

        • 假设月份是一个整数

        • 循环

          • 创建日期,循环索引为年份,已知月份变量,日期为 13

          • 根据established algorithms确定星期几

          • 如果上面计算的星期几是星期五,则返回日期,否则

          • 否则每年递增 1

        【讨论】:

          【解决方案6】:

          Here's some example PHP code 在一个范围内通过一个非常直接的日期循环。我会修改它以检查每个月的 13 日是否为星期五,而不是像示例中那样每个星期五检查 13 日。

          【讨论】:

          • 检查每个月的 13 号肯定是更好的方法。
          • 是的,对我来说似乎效率提高了 4 倍。 :)
          【解决方案7】:

          我在 Windows 10 上使用 PowerShell 7.1 x64,我对此也很感兴趣,虽然我的编程技能还不够先进,无法开发独立且复杂的算法(没有内置)来解决这个问题,目前我可以这样做:

          $start=Read-Host "Input start year"
          $end=Read-Host "Input end year"
          $years=$start..$end
          $blackfriday=@()
          foreach ($year in $years) {
              $blackfriday+=1..12 | foreach { [datetime]"$year-$_-13" } | where { $_.DayOfWeek -eq 'Friday'} | foreach {$_.tostring("yyyy, MMMM dd, dddd")}
          }
          $blackfriday
          

          更新: 现在我有了这个,通过暴力强制 year-month-13 将日期转换为天,并得到天 mod 7 等于 5 的结果,我使用了维基百科上的所有高级算法:https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week 而且我发现它们不能很好地与 PowerShell 配合使用,不知道是我还是 Wikipedia 弄错了,无论如何这是我的脚本,我已经 fc 将脚本的结果与内置和这个脚本进行了比较,它显示“FC:没有遇到差异”:

          $months=@(
          [PSCustomObject]@{Month='January';Days=31}
          [PSCustomObject]@{Month='February';Days=28}
          [PSCustomObject]@{Month='March';Days=31}
          [PSCustomObject]@{Month='April';Days=30}
          [PSCustomObject]@{Month='May';Days=31}
          [PSCustomObject]@{Month='June';Days=30}
          [PSCustomObject]@{Month='July';Days=31}
          [PSCustomObject]@{Month='August';Days=31}
          [PSCustomObject]@{Month='September';Days=30}
          [PSCustomObject]@{Month='October';Days=31}
          [PSCustomObject]@{Month='November';Days=30}
          [PSCustomObject]@{Month='December';Days=31}
          )
          function BlackFriday {
              param(
              [Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=0)] [int64] $start,
              [Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=1)] [int64] $end
              )
              $years=$start..$end
              $blackfriday=@()
              foreach ($year in $years) {
                  $array=1..12
                  foreach ($arra in $array) {
                      $month=0
                      for ($i=0;$i -lt $arra-1;$i++) {
                          $month+=$months[$i].Days
                      }
                      [int]$ye=$year
                      if ($arra -le 2) { $ye-=1}
                      if ($ye % 4 -eq 0) {$leap=$ye/4}
                      else {while ($ye % 4 -ne 0) {$ye-=1}
                      $leap=$ye/4}
                      if ($ye % 100 -eq 0) {$century=$ye/100}
                      else {while ($ye % 100 -ne 0) {$ye-=4}
                      $century=$ye/100}
                      if ($ye % 400 -eq 0) {$cycle=$ye/400}
                      else {while ($ye % 400 -ne 0) {$ye-=100}
                      $cycle=$ye/400}
                      $leap=$leap-$century+$cycle
                      $date=[int64](($year-1)*365+$month+13+$leap)
                      if ($date % 7 -eq 5) {
                          $name=$months[$arra-1].Month
                          $blackfriday+=[string]"$year, $name 13, Friday"
                      }
                  }
              }
              $blackfriday
          }
          $start=Read-Host "Input start year"
          $end=Read-Host "Input end year"
          BlackFriday $start $end
          

          【讨论】:

            猜你喜欢
            • 2015-11-26
            • 2011-10-12
            • 2011-08-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多