Перекидання календаря


17

На це надихає одне з питань Downgoat у Sandbox, де я запропонував йому включити 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 (мод 365) = 354. Днем 354 року є "12/20" .

"9999999/10" - Мабуть, 9999999 (моди 12) = 3, тож це "3/10" (10 березня).

Критерії:

Місячний місяць введення - ціле число> 0. День введення - це ціле число> 0. Рік ніколи не потрібно вказувати, тому що таких високосних років не потрібно.

Оновлення:

Як я думаю, це надто спростило б виклик, функції календаря, такі як у класі Java Calendar , заборонені. Функції розбору / форматування дат все ж дозволені.



1
Ще один важливий тестовий випадок - це такий, у якого достатньо днів, щоб прокрутити більше 8 років, таким чином, щоб відповіді, в яких використовуються вбудовані модулі, повинні звернути увагу на ті вбудовані модулі, які використовують високосні роки.
Мартін Ендер

О, це відповідає, що ... Я ось-ось збирався опублікувати відповідь Mathematica, яка використовує вбудований. : /
Мартін Ендер

@Martin Вибачте за це;).
геокавель

Для довідки, рішення Mathematica все ще було 90 байт (хоча в цьому масово переважала обробка рядків). Якщо ви хочете все-таки додати такий тестовий випадок, я думаю, що я 1/99999повинен поступитися 12/19.
Мартін Ендер

Відповіді:


11

Це було швидко.
Аддісон Кримп

Чи можете ви запевнити, що тут не використовуються функції календаря?
геокавель

Хороша річ у LabVIEW полягає в тому, що це в основному те, що вона виглядає. Перша річ сканує числа з модулів рядка 2, поле - це структура корпусу комутатора, яка видає 28,30 або 31, а потім знову збирається як рядок.
Евмель

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 і т. Д. І небагато гольфу. Дякую за коментарі, є кілька місць, де я трохи заощадив!

Безумовно:

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;
}

Перш за все: Ласкаво просимо до громади! Я б припустив, що ви можете зберегти кілька байт, призначивши словник у циклі або скориставшись функцією перемикання (хоча тут немає C # pro). Також безпосередньо може надрукувати безпосередньо друк ´m + “/„ + d´. І останнє (це може чи не може працювати), використовуючи char * замість рядка в аргументах.
Евмель

Це не вдається в певних тестових випадках, наприклад 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="/")

Це повідомлення, яке я отримую при спробі запустити вашу програму на R: pastebin.com/dPh1n64a
geokavel

Дивно, що я повторно перевірятимусь
Тенсібай

Я також отримав це повідомлення. Здається, у вашої програми є проблеми з деякими місяцями. Інакше працює. pastebin.com/g3BCUDi8
geokavel

дякую за відгуки Я фактично в дорозі, я виправлю це
Тенсібай

1
@Tensibai так, ти маєш рацію, моє погано (я повинен був пам’ятати, що повідомлення про помилку говорить про те, що воно очікує «справжнє»).
планнапус

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().

Безголовки:

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");

Спробуйте в Інтернеті


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
  `)

Тест


1

Неконкурентна відповідь - Bash + coreutils, 55

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

"Функції аналізу / форматування дати все ще дозволені", - я припускаю, що це означаєdate утиліта дозволена.

Введення зчитується з командного рядка, наприклад:

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

Це не є змагальним, оскільки команда дата розширюється на щось подібне, що додає кількість днів:

date -d1-3-1+42day +%-m/%-d

Це дозволяється до тих пір, поки він не робить нічого подібного date.add(875)до збільшення дати на 875 днів. Це в основному те, що я йшов після.
geokavel

@geokavel ой, бачу. Тут повністю розширена dateкоманда date -d1-3-1+42day +%-m/%-d, тож вона робить саме це. Я думаю, це відповідь, що не конкурує :(
Digital Trauma
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.