Какой сегодня день (или другие даты)?

12

задача

Напишите программу или функцию, которая вычисляет название дня недели для даты, которую вводит пользователь.

Ввод, вывод

Ввод - это строка YYYYMMDD.

Пример входных значений:

20110617: 17 июня 2011
19040229: 29 февраля 1904 г.
06661225: 25 декабря 666
00000101: 1 января, 0
99991231: 31 декабря 9999

Вы можете предположить, что все данные верны. Обратите внимание, что нулевой год действителен.

Выход - это целое число между 0и 6. Каждое целое число представляет название дня недели. Вы можете свободно выбирать, какое целое число представляет название дня недели, например, это

0: понедельник
1: вторник
2: среда
...
6: воскресенье

(по порядку) или этот

0: понедельник
1: среда
2: воскресенье
...
6: суббота

(не в порядке).

Тестовые случаи

Input Выходной день недели (в этом примере используется [0..6 -> Monday..Sunday].)

20110617 пятница 4
19500101, воскресенье 6
22220202 суббота 5
19000228 среда 2
19000301 четверг 3
19450815 среда 2
19040229 Понедельник 0
19040301 вторник 1
17760704 четверг 3
20000228 Понедельник 0
20000229 вторник 1
20000301 среда 2
20121223 воскресенье 6
00000401 суббота 5
66660606 среда 2
59161021 суббота 5

ограничение

Вы не должны использовать какую- либо функцию / класс / ..., связанную с отметкой времени или датой, например, Dateкласс в Java/ JavaScript/ ActionScriptили getdateфункцию в PHP.

Вы должны использовать григорианский календарь , который используется многими людьми сейчас.

Конечно, выигрывает самый короткий код. Если два кода имеют одинаковую длину, то выигрывает код с наибольшим количеством голосов.

(Должно быть: когда есть более 5 кодов, у которых больше (или равно) +1голосов.)

JiminP
источник
Сегодня? Почему, Рождество!
Джои Адамс
3
Оптимистичный решение написано в Bash (6 символов): echo 4.
Истина
1
@trutheality Нет, я не это имел в виду .. То, что я хотел, это код, который печатает / возвращает день недели даты, которую кто-то напечатал, а не просто печатает день недели сегодня.
JiminP
О, я знаю. Вот что делает этот.
Истина
Это правильно, по крайней мере, в 14% случаев!
Draco18s больше не доверяет SE

Ответы:

2

Рубин, 95 92 персонажа

Простая прямая реализация ruby ​​с 0: понедельник, ...

p ((y=(d=gets.to_i)/(k=100)/k-((m=d/k%k)<3?1:0))+y/4-y/k+y/400+"squsptrotqro"[-m].ord+d%k)%7
Говард
источник
4

PHP - 101 97 103 125 символов

  • Алгоритм Сакамото
  • 0 = воскресенье

Код

<?php fscanf(STDIN,"%4d%2d%2d",$y,$m,$d);@$a=a032503514624;$y-=$m<3;$z=$y+1;echo($y+$y/4%$z-$y/100%$z+$y/400%$z+$a[$m]+$d)%7;

Заметка

К сожалению, из-за динамической слабой типизации PHP алгоритм Sakamoto не работает должным образом без явного указания каждой операции деления.

rintaun
источник
Можете ли вы проверить еще раз? В течение нескольких лет он дает мне другие результаты (например, тестовый пример 17760704 дает вторник вместо среды).
Говард
@ Как это странно; за 17760704 я получаю среду. Однако я получаю другие несоответствия, которые не могу объяснить, например, 19040229 возвращается во вторник. Не уверен, что может быть причиной этого. Я получаю те же результаты, когда расширяю алгоритм до y+y/4-y/100+y/400.
Ринтаун
Я вижу, что это происходит с 497 * y / 400: y=4в этом случае возвращается 4 вместо правильных 5 от y+y/4+y/100+y/400(где вступают в игру только первые два слагаемых). Это то, что мучает мой ответ JavaScript. Возможно ли, что двойники создаются вместо целых? (Мой PHP слишком слаб, чтобы знать.)
DocMax
@DocMax: Оставление расширенного выражения приводит к тому же результату (497y / 400 должно быть эквивалентным: y / 100 вычитается и y / 400 добавляется снова независимо от этого). Я предполагаю, что PHP просто отсекает все после десятичной дроби вместо ее округления. Я проверил это, округлив перед модулем. Это исправляет две аномалии, но 19040229 по-прежнему возвращает тот же результат. Есть еще идеи?
Ринтаун
@rintaun Я не думаю, что это округление. Они принципиально разные. Возьмите пример сверху (у = 4): 497 * 4/400 = 1988/400 = 4, но с другой стороны 4 + 4 / 4-4 / 100 + 4/400 = 4 + 1-0 + 0 = 5 , Термины / 100 и / 400 приобретают слишком большой вес в ваших вычислениях, так что 2000 не может быть достигнут.
Говард
2

С - 129

main(y,m,d,s)
{
    scanf("%04d%02d%02d",&y,&m,&d);
    y-=s=86400;
    d+=y+"-addgbegcfadf"[m];
    m>2?y++:0;
    putchar(48+(d+y/4-y/100+y/400+s+s)%7);
}

Это злоупотребляет тем, как деление округляется до нуля, по крайней мере, в моей системе (Linux x86).

Магическая константа 86400, служит двум целям:

  • Вычтите из года, чтобы сделать его отрицательным, не влияя на день недели. Это позволяет округлениям округляться вверх, а не вниз.
  • Сдвиньте номер дня, чтобы в понедельник было 0.

Так же бывает и количество секунд в дне.

Джои Адамс
источник
Используйте y+=m>2;вместо m>2?y++:0;и сбрейте несколько байтов.
Яснее
2

Javascript, 126 123 символов

Используя алгоритм Сакамото с 0 = воскресенье:

prompt().replace(/(....)(..)(..)/,function(_,y,m,d){y-=m<3;alert((+d+y-~(y/4)+~(y/100)-~(y/400)+ +".621462403513"[+m])%7)})

Я подозреваю, что разделение может быть разрушено, но сейчас я этого не вижу.

Редактировать: Улучшено деление (нет необходимости, ~~когда вы можете просто ~).

DocMax
источник
2

Python 2 , 83 116 113 109 байт

Реализует алгоритм Сакамото . Предложения по игре в гольф приветствуются. Попробуйте онлайн!

Изменить: я должен был исправить это давным-давно. -6 байт из предложений Джонатана Аллана +2 байта для фактического исправления кода.

def w(s):m=int(s[4:6]);y,d=int(s[:4])-(m<3),int(s[6:]);return(y+y/4-y/100+y/400+int('032503514624'[m-1])+d)%7
Sherlock9
источник
Ввод должен быть одной строкой.
msh210
int('032503514624'[m-1])спасает 6
Джонатан Аллан
0

Perl - 110 байт

Вот решение для запуска с помощью perl -p source.pl ИЛИ perl -pe 'here-is-code'.

s/((..)(..))(..)(..)/(1+3*$1+$2-2*($1%4+$2%4)-(2<$4?$4+(1&$4&&4-(8&$4)):(2^$4)+(!($3%4)-!-$3+!($2%4)))+$5)%7/e

Просто скопируйте и вставьте контрольные примеры в стандартный ввод.

Кажется, это единственный код без переменных, строковых констант и делений.

Лайош
источник
0

JavaScript (ES6), 73 байта (не конкурирует)

d=>(w=new Date(d[s="slice"](0,4),d[s](4,6)-1,d[s](-2)).getDay())-(w?1:-6)

Попытайся

f=
d=>(w=new Date(d[s="slice"](0,4),d[s](4,6)-1,d[s](-2)).getDay())-(w?1:-6)
o.innerText=f(i.value="59161021")
oninput=_=>i.value.length==8&&(o.innerText=f(i.value))
<input id=i type=number><pre id=o>

мохнатый
источник
Почему не конкурирует?
programmer5000
@ programmer5000, проверьте дату публикации заявки;)
Shaggy