Calcular la fase lunar

10

Introducción

tl; dr

En este desafío, debes calcular la fase de la luna para una fecha determinada.


Este desafío está inspirado en el juego de psico experimento audiovisual sociales " Superbrothers: Sword & Sworcery EP ". En S: S&S EP, las fases de la luna son importantes para el resultado de la aventura, ya que algunos eventos ocurren solo en un momento específico.

Captura de pantalla de Superbrothers: Sword & Sworcery EP

La pregunta es: ¿Qué fase lunar está presente en una fecha específica? Cada fase principal, desde la luna nueva hasta el primer trimestre, pasando por la luna llena hasta el tercer trimestre, dura aproximadamente 7.38 días. Todo el ciclo lunar es de aproximadamente 29.52 días. En base a estos valores, existen varios métodos de cálculo. 1

Entrada

  • Una fecha basada en el calendario gregoriano, entre el 1 de enero de 1970 y el 31 de diciembre de 2116.
  • Puede elegir uno de los siguientes formatos: yyyy-mm-dd, dd.mm.yyyy, dd/mm/yyyy, yyyymmddo ddmmyyyy.

Salida

Salida del índice [0-7]de la fase lunar basado en esta matriz de índice cero:

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

Requisitos

  • Puedes escribir un programa o una función. Si utiliza una función anónima, incluya un ejemplo de cómo invocarla.
  • La entrada se acepta desde STDINargumentos de línea de comandos, como parámetros de función o desde el equivalente más cercano.
  • Este es el por lo que la respuesta más corta en bytes gana.
  • Las bibliotecas integradas o externas que calculan la fase lunar no están permitidas. 2
  • Las lagunas estándar no están permitidas.

Pruebas

Los valores son: date | index of the phase | illumination | name

Un ciclo lunar completo:

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

Casos de prueba aleatorios:

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

Como la mayoría de los métodos no son precisos a nivel científico y también obtiene resultados mixtos en diferentes sitios web durante un par de estos días, es aceptable si sus resultados están dentro de un rango de ± 1 día .

Prima

Reduzca su recuento de bytes y retire :

  • 15% : imprime el nombre real de la fase como se indica en la sección Salida en lugar de su índice.
  • 25% : imprima las fechas de la próxima luna nueva y luna llena separadas por un espacio en blanco o una nueva línea en la entrada vacía.

1 Por ejemplo: Fase de cálculo en Wikipedia.
2 Lo siento, Mathematica .

insertusernamehere
fuente
Mi dinero está en Japt.
lirtosiast
¿Cuánto dura cada fase? Se refiere a cuatro fases principales que duran aproximadamente 7 días, pero hay 8 fases para tratar.
Sherlock9
1
Creo que para ayudarme a comprender cuánto debe durar cada fase, ¿puede publicar un caso de prueba de aproximadamente cinco días consecutivos, o el tiempo que tome cambiar, digamos, "gibosa creciente" a "gibosa menguante" según su cálculo? Tengo problemas con las definiciones porque, por ejemplo, los cuartos de lunas son el instante del 50% de iluminación, por lo que el "primer trimestre" solo debería ser el mismo día, con "creciente creciente" y "creciente creciente" los días anteriores y después. Pero no estoy seguro.
Sherlock9
Bien entonces, comenzaré con mi solución. Gracias por aclarar algo de esto.
Sherlock9
@ Sherlock9 He actualizado los casos de prueba con un ciclo lunar completo y algunos valores aleatorios, incluida la iluminación de cada día. Espero que esto sea útil.
insertusernamehere

Respuestas:

3

Python 2 3, 255 204 180 178 bytes

Esta respuesta es inexacta por uno o dos días en varios lugares, incluso para algunos de los casos de prueba, aunque me dijeron que alguna imprecisión era aceptable. En cualquier caso, el movimiento de la luna nunca es muy exacto y esta función sigue siendo generalmente correcta (o al menos, no varía demasiado).

Editar: En el curso de corregir mi código y hacerlo más preciso, lo he reducido considerablemente.

Editar: este código ahora es un programa Python 3 de una línea. (Crédito a TimmyD por el nombre "números mágicos")

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)

Sin golf:

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)
Sherlock9
fuente
@TimmyD No tienes idea de cuántos números mágicos intenté y descarté para que esto funcione XD
Sherlock9