计算月相


10

介绍

tl; dr

在此挑战中,您必须计算给定日期的月相。


这项挑战的灵感来自游戏 心理社交视听实验Superbrothers:Sword&Sworcery EP ”。在S:S&S EP中,月亮的阶段对冒险的结果很重要,因为某些事件仅在特定的时间点发生。

《超级兄弟:剑与巫术》 EP的屏幕截图

问题是:在特定日期出现哪个月相。每个主要阶段-从新月到第一季度到满月到第三季度-大约需要7.38天。整个月球周期大约为29.52天。基于这些值,存在各种计算方法。1个

输入值

  • 基于公历的日期,在1970年1月1日至2116年12月31日之间。
  • 您可以选择以下格式之一:yyyy-mm-dddd.mm.yyyydd/mm/yyyyyyyymmddddmmyyyy

输出量

[0-7]根据此零索引数组输出月相索引:

['New moon', 'Waxing crescent', 'First quarter', 'Waxing gibbous', 'Full moon', 'Waning gibbous', 'Third quarter', 'Waning crescent`]

要求

  • 您可以编写程序或函数。如果您使用匿名函数,请提供一个如何调用它的示例。
  • STDIN命令行参数,函数参数或最接近的等效参数都接受输入。
  • 这是因此最短答案以字节为单位。
  • 不允许使用内置的或外部的库来计算月相。2
  • 不允许出现标准漏洞。

测验

值是: date | index of the phase | illumination | name

完整的月球周期:

08.02.2016 | 0 |   0% | New moon
07.02.2016 | 7 |   2% | Waning crescent
07.02.2016 | 7 |   2% | Waning crescent
06.02.2016 | 7 |   6% | Waning crescent
05.02.2016 | 7 |  12% | Waning crescent
04.02.2016 | 7 |  19% | Waning crescent
03.02.2016 | 7 |  28% | Waning crescent
02.02.2016 | 7 |  37% | Waning crescent
01.02.2016 | 6 |  47% | Third quarter
31.01.2016 | 5 |  56% | Waning gibbous
30.01.2016 | 5 |  65% | Waning gibbous
29.01.2016 | 5 |  74% | Waning gibbous
28.01.2016 | 5 |  82% | Waning gibbous
27.01.2016 | 5 |  89% | Waning gibbous
26.01.2016 | 5 |  94% | Waning gibbous
25.01.2016 | 5 |  98% | Waning gibbous
24.01.2016 | 4 | 100% | Full moon
23.01.2016 | 3 | 100% | Waxing gibbous
22.01.2016 | 3 |  97% | Waxing gibbous
21.01.2016 | 3 |  93% | Waxing gibbous
20.01.2016 | 3 |  86% | Waxing gibbous
19.01.2016 | 3 |  77% | Waxing gibbous
18.01.2016 | 3 |  67% | Waxing gibbous
17.01.2016 | 3 |  56% | Waxing gibbous
16.01.2016 | 2 |  45% | First quarter
15.01.2016 | 1 |  33% | Waxing crescent
14.01.2016 | 1 |  23% | Waxing crescent
13.01.2016 | 1 |  14% | Waxing crescent
12.01.2016 | 1 |   7% | Waxing crescent
11.01.2016 | 1 |   2% | Waxing crescent
10.01.2016 | 0 |   0% | New moon

随机测试用例:

14.12.2016 | 4 | 100% | Full moon
16.10.1983 | 3 |  75% | Waxing gibbous
04.07.1976 | 2 |  47% | First quarter
28.11.1970 | 0 |   0% | New moon

由于大多数方法都不准确到科学水平,而且您在这几天之间在不同的网站上也会得到不同的结果,因此,如果结果在±1天的范围内,则可以接受。

奖金

减少字节数并退出

  • 15% –打印输出部分中列出的阶段的实际名称,而不是其索引。
  • 25% –在空输入上打印即将到来的新月和满月的日期,并用空格或换行符分隔。

1例如:Wikipedia上的计算阶段
2对不起,Mathematica


我的钱在贾普上。
lirtosiast '16

每个阶段持续多长时间?您指的是大约持续7天的四个主要阶段,但是有8个阶段需要处理。
Sherlock9

1
我想帮助我理解每个阶段应该持续多长时间,您是否可以发布一个大约连续五天的测试用例,或者根据您的判断从“打蜡隆起”变为“逐渐隆起”需要多长时间?我在定义上遇到麻烦,例如,四分之一月是50%光照的瞬间,因此“第一季度” 仅在当天进行,而“蜡新月”和“下降新月”应在前一天和之后后。但我不确定。
Sherlock9

好吧,我将开始解决方案。感谢您清除部分内容。
Sherlock9

@ Sherlock9我已经用一个完整的农历周期和一些随机值(包括每天的照度)更新了测试用例。希望这会有所帮助。
insertusername此处,2016年

Answers:


3

2 3,255个 204 180 178字节

这是在几个地方(包括某些测试用例)在一两天之内是不准确的答案,尽管有人告诉我有些不正确的地方是可以接受的。无论如何,月球的运动永远不会非常精确,并且此功能通常保持正确(或者至少不会变化太大)。

编辑:在更正我的代码并使之更准确的过程中,我已将其大大降低了。

编辑:此代码现在是单行Python 3程序。(向TimmyD授予 “魔术数字”的名称)

p,q,r=(int(i)for i in input().split("-"));t=q<3;y=p-2000-t;i,j=divmod(((r+(153*(q+12*t-3)+2)//5+365*y+y//4-y//100+y//400+11010)*86400-74100)%2551443,637861);print((86400<=j)+2*i)

取消高尔夫:

def jul(p,q,r):
    '''
    The Julian Day Number (JDN) of the input minus the JDN of January 7, 1970,
    the first new moon after January 1, 1970.
    '''
    t=q<3
    y=p-2000-t  # -2000 years to push day 0 to January 1, 2000
    return r+(153*(q+12*t-3)+2)//5+365*y+y//4-y//100+y//400+11010
    # +11010 days to push day 0 to January 7, 1970

def moon(s):
    '''
    Input format: yyyy-mm-dd

    An attempt at explaining the "magic numbers"
    - 29.53059 days is close to 2551443 seconds, so I used that
    - The offset of +12300 seconds because the new moon of 1970-01-07 was at 2035 UTC 
      or 12300 seconds before midnight. For those of you saying that this pushes 
      the beginning of my calendar to 2035, *6* January 1970, yes it does.
      But if I need to the calendar to recognize 1970-01-07 as the day of the new moon 
      which means that midnight needed to be a positive number of seconds, 0 <= x < 86400.
      Basically, I hacked it together, and +12300 worked.        
    '''
    d = 86400
    p,q,r = map(int, s.split("-"))
    z=(jul(p,q,r)*d+12300)%2551443  # 2551443 is about the number of seconds in a lunar month
    div, mod = divmod(z, 637861)    # 637861 seconds is about a quarter of a lunar month
                                    # div is what part of the lunar month this is (0 - 3)
                                    # mod is seconds since the start of the main phase
    return 2*div + (86400 <= mod)   # 2*div for the main phase, and 
                                    # is mod >= the number seconds in a day?
                                    # (+0 if within a day of the main phase, +1 otherwise)

@TimmyD您不知道我尝试并扔了多少个幻数来使它工作XD
Sherlock9'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.