Суеверное Программирование

19

Ваша задача предельно проста. Если в качестве входных данных указан год, выведите все месяцы этого года, которые будут содержать пятнадцатое число по григорианскому календарю. Обратите внимание, что хотя григорианский календарь не был введен до 1582 года, для простоты мы будем делать вид, что он используется с 0001 года нашей эры.

правила

  • Полные программы или функции разрешены.

  • Вы можете принимать входные данные как аргументы функции, из STDIN или как аргументы командной строки.

  • Вам не разрешено использовать любые встроенные дату и время.

  • Вы можете смело предположить, что ввод будет действительным годом. Если входное значение меньше 1, недопустимое целое число или больше, чем тип чисел собственного языка в вашем языке, вам не нужно обрабатывать это, и вы получите неопределенное поведение.

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

  • Убедитесь, что вы учитываете високосные годы. И помните, високосные годы не случаются каждые 4 года!

подсказки

Поскольку есть много разных способов сделать это, я не хочу рассказывать вам, как это сделать. Однако, может быть непонятно, с чего начать, поэтому вот пара надежных способов определения дня недели по дате.

Образец ввода-вывода

2016 --> May
0001 --> 4, 7
1997 --> Jun
1337 --> 09, 12
123456789 --> January, October

Как обычно, это код-гольф, поэтому применяются стандартные лазейки, и выигрывает самый короткий ответ.

DJMcMayhem
источник
5
При запуске в пятницу 13-го числа он должен поменять местами и вывести месяцы без пятницы 13-го. (Причудливые пятничные ссылки на победу)
Эддисон Крамп
1
Связанный
Цифровая Травма
Является ли этот пример правильно: 0001 --> 5? Согласно этой странице (и моему коду) это должны быть апрель и июль.
Faubi
@ faubiguy мой плохой, ты прав. Это было в юлианском календаре. Позвольте мне это исправить.
DJMcMayhem
«Вы не можете использовать встроенные функции даты или времени», я тоже не могу конвертировать время в unix?
Busukxuan

Ответы:

1

Pyth, 73 байта

L?>b2QtQfq%+++13+/-*2.6?qT2 12%-T2 12 .2 1*5%yT4*4%yT100*6%yT400 7 5r1 13

Попробуйте онлайн!

Используя алгоритм Гаусса, как в моем ответе на Python. ~ 55 байтов кода предназначены для вычисления дня недели, поэтому выбор лучшего алгоритма может значительно снизить это, я полагаю ... но, по крайней мере, теперь он работает! :)

Denker
источник
2

Python 2, 157 144 136 байт

Мое решение использует алгоритм Гаусса. Вводим год как целое число. Выводится список месяцев с пятницей 13 числа в виде цифр (1-12). Возможно, возможно еще немного игры в гольф, но уже поздно ... Собираюсь отредактировать это завтра и разобраться в этом немного больше. Предложения всегда приветствуются!

def f(i):y=lambda m:(i-1,i)[m>2];print[m for m in range(1,13)if(13+int(2.6*((m-2)%12,12)[m==2]-.2)+y(m)%4*5+y(m)%100*4+y(m)%400*6)%7==5]

редактирование: опустил до 144, заменив цикл for списком и сделав некоторые другие небольшие изменения.

edit2: Гольф до 136 с предложениями от Morgan Thrapp и исправил обнаруженную ошибку. Большое спасибо! :)

Denker
источник
1

Perl - 141 107 103 байт

$y=<>-1;map{$y++if++$i==3;print"$i "if($y+int($y/4)-int($y/100)+int($y/400))%7==$_}'634163152042'=~/./g

При этом используется модифицированная версия формулы для юлианского дня, чтобы вычислить день недели 13 марта, затем используется число дней недели, которые каждый месяц смещается относительно января, чтобы найти день недели для оставшейся части дня. месяцы, начиная с последних 2 месяцев предыдущего года, начиная с марта, затем с первых 10 месяцев текущего года (чтобы избежать високосных лет дважды).

faubi
источник
1

C - 164 153 112 байт

Я нашел милое небольшое решение, используя сильно модифицированную версию метода Швердтфегера. Он кодирует необходимую таблицу в целое число, используя основание 7, измененное, чтобы соответствовать 32-битному слову со знаком. Он выводит месяц в виде ASCII-символа, причем январь кодируется как 1, февраль - как 2и так далее, октябрь - как :, ноябрь - как, ;а декабрь - как <.

t=1496603958,m;main(y){for(scanf("%d",&y),y--;(y%100+y%100/4+y/100%4*5+t+5)%7||putchar(m+49),t;t/=7)2-++m||y++;}

Вот это немного разглажено:

t=1496603958,m;
main(y){
  for(
    scanf("%d",&y),y--;
    (y%100+y%100/4+y/100%4*5+t+5)%7||putchar(m+49),t;
    t/=7
  )
    2-++m||y++;
}

Я уверен, что есть несколько способов сделать его еще меньше, но я думаю, что алгоритм или его небольшая вариация почти идеальны для нахождения месяцев, когда наступает пятница 13-е (в отношении размера кода). Примечания:

  1. Если бы можно было использовать 64-битное слово, можно было бы избавиться от раздражающего дополнения ( +5).
  2. Переменная на mсамом деле не нужна, так как месяц, на который мы смотрим, выводится из t.

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


Это основано на решении связанной проблемы ( /codegolf//a/22531/7682 ).

Y,M,D,d;main(y){for(scanf("%d",&y);Y<=y;++D>28+(M^2?M+(M>7)&1^2:!(Y&3)&&(Y%25||!(Y&15)))&&(D=1,M=M%12+1)<2&&Y++)(d=++d%7)^1||D^13||y^Y||printf("%d,",M);}

Он в основном имитирует григорианский календарь, продвигаясь по одному за раз, печатая месяц, когда это пятница и 13-е число. Вот это в несколько более читаемой форме:

Y,M,D,d;
main(y){
  for(
    scanf("%d",&y);
    Y<=y;
    ++D>28+(
      M^2
        ?M+(M>7)&1^2
        :!(Y&3)&&(Y%25||!(Y&15))
    )&&(
      D=1,
      M=M%12+1
    )<2&&Y++
  )
    (d=++d%7)^1||D^13||y^Y||
      printf("%d,",M);
}
Форс
источник
впечатляющий ecc, но не найти в 123456789 -> январь, октябрь октябрь
RosLuP
Хм, это для меня. Может, у меня какая-то платформо-зависимая причина? Он работает для меня на довольно современном Macbook Pro при компиляции с Clang. Обратите внимание, что он выводит 1:для 123456789, где :обозначает октябрь. Я уточнил кодировку выше.
Форс
Да 1: здесь тоже; Я не понял ':' было за октябрь ...
РосЛуП
0

Excel, 137 байт

Вводит год в А1. Выводится неразделенным списком шестнадцатеричного числа. (Январь = 0, декабрь = B)

Использует алгоритм Гаусса для января и августа.

=CHOOSE(MOD(6+5*MOD(A1-1,4)+4*MOD(A1-1,400),7)+1,"","",1,"","",0,"")&CHOOSE(MOD(5*MOD(A1-1,4)+4*MOD(A1-1,400),7)+1,9,35,"8B",5,"2A",7,4)
Wernisch
источник
В этом ответе в настоящее время используются встроенные функции даты и времени, которые явно указаны в отношении правил в задании.
Форс
@Fors, спасибо за указание на это. Обновлено.
Верниш
0

C 276 219 байт

#define R return
#define L(i) for(;i-->0;) 
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}s(y,m,g){g+=4;L(m)g+=u(y,m),g%=7;L(y)g+=1+u(y,1),g%=7;R g;}z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}

ввод из stdin вывод в stdout попробуйте http://ideone.com/XtuhGj [функция отладки z]

w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}
/*    
// ritorna il numero dei giorni di anno=y mese=m con mese in 0..11
// m==1 significa febbraio   y%4?0:y%100?1:!(y%400) non funziona
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}

// argomenti anno:y[0..0xFFFFFFF]  mese:m[0..11]  giorno:g[1..u(y,m)]
// ritorna il numero del giorno[0..6]
s(y,m,g)
{g+=4; // correzione per il giorno di partenza anno mese giorno = 0,1,1
 L(m)g+=  u(y,m),g%=7; // m:0..m-1  somma mod 7 i giorni del mese dell'anno y
 L(y)g+=1+u(y,1),g%=7; // y:0..y-1  somma mod 7 gli anni da 0..y-1
                       // g+=1+u(y,1) poiche' (365-28)%7=1 e 1 e' febbraio
 R g;
}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
// calcola tutti gli ultimi giorni del mese dell'anno y che cadono di lunedi'
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
//ritorna in r il numero dei mesi che ha giorno 13 di venerdi[==4]
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}
*/

#define P printf
#define W while 
#define M main 
#define F for
#define U unsigned
#define N int
#define B break
#define I if
#define J(a,b)  if(a)goto b
#define G goto
#define P printf
#define D double
#define C unsigned char
#define A getchar()
#define O putchar
#define Y malloc
#define Z free
#define S sizeof
#define T struct
#define E else
#define Q static
#define X continue
M()
{N y,m,g,r,arr[]={1,297,1776,2000,2016,3385}, arr1[]={2016,1,1997,1337,123456789};
 C*mese[]={"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"};
 C*giorno[]={"Lun","Mar","Mer","Gio","Ven","Sab","Dom"};
 P("Inserisci Anno mese giorno>");r=scanf("%d %d %d", &y, &m, &g);
 P("Inseriti> %d %d %d r=%d\n", y, m, g, r);
 I(r!=3||m>12||m<=0||g>u(y,m-1))R 0;
 r=s(y,m-1,g);// 12-> 11 -> 0..10
 P("Risultato=%d giorno=%s\n", r, giorno[r]);
 r=w(y,0,0);P(" r=%d ", r);P("\n");
 F(m=0;m<6;++m)
        {P("N anno=%d -->",arr[m]); 
         r=w(arr[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }
 F(m=0;m<4;++m)
        {P("N anno=%d -->",arr1[m]); 
         r=z(arr1[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }

}
RosLuP
источник