Ролловер Календарь

17

Это вдохновлено одним из вопросов Даунгоата в Песочнице, где я предложил, чтобы он включил 31 апреля как день Пи для людей, которые используют формат день / месяц, только для того, чтобы он сообщил мне, что 31 апреля нет!

Если задана строка даты в формате месяц / день , которая может быть недопустимой, выведите правильную дату с помощью ролловера. (Сначала перенесите месяц, затем перенесите день).

Примеры:

«15/43» - это читается как 43-й день 15-го месяца. Сначала мы переносим месяц на следующий год, поэтому у нас получается 3 (март). Теперь, поскольку в марте только 31 день, мы переносим дополнительные дни на апрель, поэтому мы выводим фактическую дату как «4/12» (12 апреля).

«3/16» - это действительная дата (16 марта). Верни как есть.

«12/64» - Ах, как много приятных воспоминаний о 64 декабря ... Декабрь имеет 31 день, январь - 31 день, так что я на самом деле имею в виду «2/2» (2 февраля).

«19/99» - во-первых, 19 становится 7 (июль). В июле 31 день, в августе 31 день, в сентябре 30 дней, поэтому выходное значение равно «10/7» (7 октября).

«1/99999» - год имеет 365 дней. 99999 (mod 365) = 354. 354 дня года - «12/20» .

«9999999/10» - очевидно, 9999999 (мод. 12) = 3, так что это «3/10» (10 марта).

Критерии:

Месяц ввода - это целое число> 0. День ввода - это целое число> 0. Год не нужно указывать, так как для этого не существует високосных лет.

Обновить:

Поскольку я думаю, что это слишком упростит задачу, функции календаря, такие как функции в классе Java Calendar , запрещены. Функции разбора и форматирования даты все еще разрешены.

geokavel
источник
1
Другим важным тестовым примером может быть тот, у которого достаточно дней, чтобы пролонгировать более 8 лет, так что ответы, использующие встроенные модули, должны обращать внимание на те встроенные модули, которые используют високосные годы.
Мартин Эндер
О, это ответы, которые ... Я как раз собирался опубликовать ответ Mathematica, который использует встроенный. : /
Мартин Эндер
@Martin К сожалению об этом;).
геокавель
Для справки, решение Mathematica по-прежнему имеет длину 90 байт (хотя в нем преобладает обработка строк). Если вы хотите добавить такой тестовый пример все же, 1/99999должен дать, 12/19я думаю.
Мартин Эндер

Ответы:

11

LabVIEW, 32 примитива LabVIEW

Eumel
источник
Это было быстро.
Аддисон Крамп
Можете ли вы заверить меня, что здесь нет функций календаря?
геокавель
Хорошая вещь о LabVIEW - это то, что она в основном выглядит. Первым делом сканируется число из строки 2 по модулю, поле представляет собой структуру регистра переключателя, которая выдает 28, 30 или 31, а затем снова собирается в виде строки.
Eumel
4

C #, 269 223

string v(string n){var x=new[]{31,28,31,30,31,30,31,31,30,31,30,31};var s=n.Split('/');Func<string,int> p=int.Parse;var m=p(s[0]);var d=p(s[1]);m=m>=12?m%12:m;while(d>x[m]){d-=x[m];m=++m>=12?m%12:m;}return(m==0?1:m)+"/"+d;}

Редактировать : Исправлена ​​работа в таких случаях, как 24/1, 36/1 и т. Д. И немного гольф. Спасибо за комментарии, я сохранил несколько мест!

Ungolfed:

string v(string n)
{
    var x = new [] { 31 ,28, 31, 30, 31, 30,31, 31, 30, 31, 30, 31 };

    var s = n.Split('/');
    Func<string,int> p = int.Parse;
    var m = p(s[0]);
    var d = p(s[1]);
    m = m >= 12 ? m % 12 : m;
    while (d > x[m])
    {
        d -= x[m];
        m = ++m >= 12 ? m % 12 : m;
    }
    return (m==0?1:m) + "/" + d;
}
DrewJordan
источник
Прежде всего: добро пожаловать в сообщество! Я предполагаю, что вы можете сохранить несколько байтов, назначив словарь в цикле или используя функцию переключения (хотя здесь нет C # pro). Также может помочь прямая печать ´m + "/" + d´. И последнее (это может или не может работать) использование char * вместо строки в аргументах.
Eumel
Это терпит неудачу на определенных тестовых примерах, например 24/1.
LegionMammal978
@ Eumel спасибо! Непосредственно печать использует Console.Writeболее чем return, и в C # я бы использовалchar[] в качестве замены string, но это такое же количество символов и делает разбиение на /более проблематичным. Но ваша заметка в словаре привела меня к лучшей версии!
DrewJordan
4

R 208 182 байта

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/");n=(e[1]/12-1)*12;if(!n%%12)n=12;if(n<0)n=e[1];j=e[2];while((j<-j-m[n])>0){n=n+1;if(n>12)n=1};j=m[n]+j;cat(n,j,sep="/")

Получите месяц, разделив его на 12, затем выполните цикл, удаляя количество дней в текущем месяце, пока не получите отрицательное число., Переверните последний шаг и напечатайте.

На нескольких строках (необходимо использовать файл и его источник):

m=c(31,28,31,30,31,30,31,31,30,31,30,31)
e=scan(sep="/")
n=(e[1]/12-1)*12
if(!n%%12)n=12
if(n<0)n=e[1]
j=e[2]
while((j<-j-m[n])>0){n=n+1;if(n>12)n=1}
j=m[n]+j;cat(n,j,sep="/")
Tensibai
источник
Это сообщение я получаю при попытке запустить вашу программу в R: pastebin.com/dPh1n64a
geokavel
Странно, я перепроверю позже
Tensibai
Я также получил это сообщение. У вашей программы, похоже, проблемы с некоторыми месяцами. В противном случае он работает. pastebin.com/g3BCUDi8
геокавель
Спасибо за ответ. Я нахожусь в дороге, на самом деле, я
исправлю
1
@ Тенсибай, да, ты прав, мой плохой (я должен был помнить, что сообщение об ошибке говорит, что оно ожидает "настоящего").
plannapus
3

PHP> = 5,5, 181 байт

list($m,$d)=explode("/",$argv[1]);$m%=12;$d%=365;$i=0;while($d>100)$d-=[31,28,31,30,31,30,31,31,30,31,30,31][$i++];$m+=$i;echo date_create_from_format("m/d","$m/$d")->format("n/j");

PHP почти поддерживает ролловер только с инструкциями разбора даты и форматирования. Например:

echo date_create_from_format("m/d","12/64")->format("n/j"); // Output: 2/2

Тем не менее, как только число становится больше 100, PHP отклоняет его разбор и возвращает ошибку (возможно, по какой-то произвольной причине). Итак, теория с этим ответом - вернуть его туда, где PHP его проанализирует, а затем отправить date_create_from_format().

Ungolfed:

list($month, $day) = explode("/", $argv[1]);
$month = $month % 12;
$day = $day % 365;
$i = 0;
$days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
while($day > 31) $day -= $days[$i++];
$month += $i;
echo DateTime::createFromFormat("m/d", $month . "/" . $day)->format("n/j");

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

nickb
источник
1
Вы должны дать мне способ ввода строки даты или сделать ее функцией.
геокавель
GET-параметры недопустимы в качестве метода ввода в PHP . Вам нужно будет либо сделать это функцией и передать ввод в качестве параметров функции, либо получить ввод из $argvили STDIN.
Мего
@Mego Jeeze, дайте мне некоторое время , чтобы обновить свой ответ , так как ОП не указывается никаких требований для ввода - это просто достаточно , чтобы изменения $tв $argv[1]и теперь он считывает из ввода командной строки.
Ника
ОП, устанавливающая требования к вводу данных, не имеет значения; у нас есть список приемлемых по умолчанию методов ввода / вывода (которые я связал), чтобы авторам испытаний не приходилось указывать их при каждой проблеме.
Мего
2

JavaScript (ES6), 106 байт

s=>eval('q="030101001010";p=s.split`/`;for(d=i=p[1],m=p[0]-1;i--;d>n&&(m++,d-=n))n=31-q[m%=12];m+1+"/"+d')

объяснение

s=>
  eval(`              // use eval to enable for loop without needing to write {} or return
    q="030101001010"; // q = array of 31 - days in each month
    p=s.split\`/\`;   // p = array of [ month, day ]
    for(
      d=i=p[1],       // d = day
        m=p[0]-1;     // m = month - 1
      i--;            // loop for each day, this is more iterations than needed but extra
                      //     iterations do not affect the result and it's the shortest way
                      //     to guarantee all months have been subtracted from d, it also
                      //     ensures the loop runs at least once to get m % 12
      d>n&&(m++,d-=n) // if too many days, subtract the month's days and increment month
    )
      n=31-q[m%=12];  // n = number of days in month, get m % 12
    m+1+"/"+d         // return the result
  `)

Тестовое задание

user81655
источник
1

Неконкурентный ответ - Bash + coreutils, 55

date -d1-$[(${1%/*}-1)%12+1]-1+$[${1#*/}-1]day +%-m/%-d

«Функции анализа / форматирования даты все еще разрешены», - я предполагаю, что это означает, что dateутилита разрешена.

Ввод читается из командной строки, например:

$ ./rollovercal.sh 15/43
4/12
$ 

Это не конкурирует, потому что команда date расширяется до чего-то вроде этого, который добавляет количество дней:

date -d1-3-1+42day +%-m/%-d
Цифровая травма
источник
Это разрешено до тех пор, пока он не делает ничего похожего date.add(875)на увеличение даты на 875 дней. Это в основном то, что я собирался после.
геокавель
@ Geokavel О, я вижу. Полностью развернутая dateкоманда здесь date -d1-3-1+42day +%-m/%-d, так что она делает именно это. Я думаю, что это неконкурентный ответ :(
Цифровая травма