Розрахуйте місячну фазу


10

Вступ

тл; д-р

У цьому виклику ви повинні обчислити фазу місяця для даної дати.


Цей виклик натхненний ігровим психологічним аудіовізуальним експериментом " Superbrothers: Sword & Sworcery EP ". У S: S&S EP фази Місяця є важливими для результату пригоди, оскільки деякі події відбуваються лише в певний момент часу.

Знімок екрана від Superbrothers: Sword & Sworcery EP

Питання: Яка місячна фаза присутня в конкретний день. Кожна основна фаза - від молодого місяця до першої чверті до повного місяця до третьої чверті - триває приблизно 7,38 дня. Весь місячний цикл становить приблизно 29,52 дня. На основі цих значень існують різні методи обчислення. 1

Вхідні дані

  • Дата, заснована на григоріанському календарі, з 1 січня 1970 по 31 грудня 2116 року.
  • Ви можете вибрати один з наступних форматів: yyyy-mm-dd, dd.mm.yyyy, dd/mm/yyyy, yyyymmddабо ddmmyyyy.

Вихідні дані

Виведіть індекс [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 Наприклад: Етап обчислення у Вікіпедії.
2 Вибачте Mathematica .


Мої гроші на Japt.
lirtosiast

Скільки триває кожна фаза? Ви посилаєтесь на чотири основні фази, що тривають приблизно 7 днів, але для цього потрібно 8 фаз.
Шерлок9

1
Я думаю, щоб допомогти мені зрозуміти, якою тривалістю має бути кожна фаза, чи можете ви розмістити тестовий випадок приблизно п’ять днів поспіль, або як би тривало це, щоб змінити, скажімо, «воскову хибність» до «згасаючої хитрості» вашим рахунком? У мене виникають проблеми з визначеннями, оскільки, наприклад, чверть місяця - це момент 50% освітленості, тому "перша чверть" повинна бути лише в день, з "восковим півмісяцем" і "спадаючим півмісяцем" за дні до і після. Але я не впевнений.
Шерлок9

Добре тоді, я почну своє рішення. Дякуємо, що очистили щось із цього.
Шерлок9

@ Sherlock9 Я оновлював тестові випадки з повним місячним циклом і деякими випадковими значеннями, включаючи освітлення кожного дня. Сподіваємось, це корисно.
insertusernamehere

Відповіді:


3

Python 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.