Kalendarz najazdu

17

Jest to zainspirowane jednym z pytań Downgoata w Sandbox, w którym zasugerowałem, aby uwzględnił 31 kwietnia jako dzień Pi dla osób korzystających z formatu dzień / miesiąc, tylko po to, aby poinformował mnie, że nie ma 31 kwietnia!

Biorąc pod uwagę ciąg daty w formacie miesiąc / dzień , który może być nieprawidłowy, wypisz prawidłową datę za pomocą najazdu. (Najpierw rollover miesiąc, następnie rollover dzień).

Przykłady:

„15/43” - oznacza to 43 dzień 15. miesiąca. Najpierw przechodzimy przez miesiąc do następnego roku, więc kończymy na 3 (marzec). Teraz, ponieważ marzec ma tylko 31 dni, przenosimy dodatkowe dni na kwiecień, więc podajemy rzeczywistą datę jako „4/12” (12 kwietnia).

„3/16” - To jest prawidłowa data (16 marca). Zwróć to, co jest.

„12/64” - Ach, tyle miłych wspomnień z 64 grudnia… Grudzień ma 31 dni, styczeń ma 31 dni, więc tak naprawdę mam na myśli „2/2” (2 lutego).

„19/99” - po pierwsze, 19 staje się 7 (lipiec). Lipiec ma 31 dni, sierpień ma 31 dni, wrzesień ma 30 dni, więc wynik to „10/7” (7 października).

„1/99999” - rok ma 365 dni. 99999 (mod 365) = 354. 354 dniem roku jest „12/20” .

„9999999/10” - Najwyraźniej 9999999 (mod 12) = 3, więc jest to „3/10” (10 marca).

Kryteria:

Miesiąc wejściowy jest liczbą całkowitą> 0. Dzień wejściowy jest liczbą całkowitą> 0. Rok nigdy nie musi być określany, ponieważ nie ma lat przestępnych do rozwiązania.

Aktualizacja:

Ponieważ uważam, że nadmiernie uprości to wyzwanie, funkcje kalendarza, takie jak te z klasy Java Calendar , są zakazane. Funkcje analizy / formatowania daty są jednak nadal dozwolone.

geokavel
źródło
1
Innym ważnym przypadkiem testowym byłby taki, który miałby wystarczającą liczbę dni, aby przejść przez ponad 8 lat, tak że odpowiedzi wykorzystujące wbudowane elementy muszą zwracać uwagę na wbudowane wykorzystujące lata przestępne.
Martin Ender,
Och, to odpowiedzi, że ... Właśnie miałem opublikować odpowiedź Mathematica, która korzysta z wbudowanego. : /
Martin Ender,
@Martin Przepraszamy za to;).
geokavel,
Dla porównania, rozwiązanie Mathematica nadal miało długość 90 bajtów (chociaż było to w dużej mierze zdominowane przez przetwarzanie łańcucha). Jeśli jednak chcesz dodać taki przypadek testowy, 1/99999powinieneś się poddać 12/19.
Martin Ender,

Odpowiedzi:

11

LabVIEW, 32 Prymitywy LabVIEW

Eumel
źródło
To było szybkie.
Addison Crump,
Czy możesz mnie zapewnić, że nie używasz tutaj żadnych funkcji kalendarza?
geokavel
Zaletą LabVIEW jest to, że jest w zasadzie taki, jak wygląda. Najpierw skanuje liczby z modułów ciągu 2, pudełko jest strukturą skrzynki przełączników, która daje 28, 30 lub 31, a następnie ponownie składa się w ciąg.
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;}

Edycja : Naprawiono do pracy w przypadkach takich jak 24/1, 36/1 itp. I trochę golfa. Dzięki za komentarze, jest kilka miejsc, które trochę zapisałem!

Nie golfowany:

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
źródło
Po pierwsze: Witamy w społeczności! Sądzę, że możesz zapisać niektóre bajty, przypisując słownik w pętli lub używając funkcji przełączania (tutaj jednak nie ma C # pro). Również bezpośrednie drukowanie „m +” / „+ d” może trochę pomóc. I na koniec (to może, ale nie musi działać) użycie argumentów char * zamiast łańcucha w argumentach.
Eumel,
Nie udaje się to w niektórych przypadkach testowych, np 24/1.
LegionMammal978,
@Eumel dzięki! Bezpośrednie drukowanie wykorzystuje Console.Writewięcej niż return, aw języku C # użyłbym go char[]jako zamiennika string, ale to ta sama ilość znaków i sprawia, że ​​dzielenie na /bardziej problematyczne. Ale twoja notatka w Słowniku doprowadziła mnie do znacznie lepszej wersji!
DrewJordan,
4

R, 208 182 bajtów

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="/")

Uzyskaj miesiąc, dzieląc przez 12, a następnie zapętlając, usuwając liczbę dni bieżącego miesiąca, aż otrzymasz liczbę ujemną., Odwróć ostatni krok i wydrukuj.

W wielu wierszach (należy użyć pliku i źródła):

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ódło
Oto wiadomość, którą otrzymuję, gdy próbuję uruchomić Twój program w R: pastebin.com/dPh1n64a
geokavel
Dziwne,
sprawdzę
Dostałem również tę wiadomość. Twój program wydaje się mieć problemy z niektórymi miesiącami. W przeciwnym razie działa. pastebin.com/g3BCUDi8
geokavel
Dziękujemy za opinię. Jestem w drodze, naprawię to
Tensibai,
1
@Tensibai tak masz rację, mój zły (powinienem pamiętać, że komunikat o błędzie mówi, że oczekuje „prawdziwego”).
plannapus
3

PHP> = 5,5, 181 bajtów

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 prawie obsługuje przechodzenie z samych instrukcji parsowania i formatowania. Na przykład:

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

Jednak gdy którakolwiek liczba staje się większa niż 100, PHP odrzuca jej analizę i zwraca błąd (prawdopodobnie z jakiegoś arbitralnego powodu). Tak więc teoria z tą odpowiedzią polega na sprowadzeniu jej z powrotem do miejsca, w którym PHP ją przeanalizuje, a następnie prześle date_create_from_format().

Nie golfowany:

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

Wypróbuj online

nickb
źródło
1
Musisz dać mi sposób na wprowadzenie ciągu daty lub uczynić go funkcją.
geokavel,
Parametry GET są niedopuszczalne jako metoda wprowadzania danych w PHP . Musisz albo ustawić tę funkcję i przekazać dane wejściowe jako parametry funkcji, albo uzyskać dane wejściowe z $argvlub STDIN.
Mego
@Mego Jeeze, daj mi trochę czasu na aktualizację mojej odpowiedzi, ponieważ OP nie określił żadnych wymagań dotyczących wprowadzania danych - wystarczy przejść $tna $argv[1]teraz i czyta się z wprowadzania z wiersza poleceń.
nickb
Wymagania określające PO dla danych wejściowych są nieistotne; mamy listę domyślnych akceptowalnych metod We / Wy (które połączyłem), aby autorzy wyzwań nie musieli określać ich przy każdym wyzwaniu.
Mego
2

JavaScript (ES6), 106 bajtów

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

Wyjaśnienie

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

Test

użytkownik 81655
źródło
1

Odpowiedź niekonkurencyjna - Bash + coreutils, 55

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

„Funkcje analizy / formatowania daty są jednak nadal dozwolone” - zakładam, że oznacza to, że datenarzędzie jest dozwolone.

Dane wejściowe są odczytywane z wiersza poleceń, np .:

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

Jest to niekonkurencyjne, ponieważ polecenie date rozwija się do czegoś takiego, co dodaje liczbę dni:

date -d1-3-1+42day +%-m/%-d
Cyfrowa trauma
źródło
Jest to dozwolone, pod warunkiem, że nie pozwala date.add(875)na zwiększenie daty o 875 dni. Po to przede wszystkim chciałem.
geokavel,
@geokavel och, rozumiem. Tutaj jest w pełni rozwinięte datepolecenie date -d1-3-1+42day +%-m/%-d, więc robi dokładnie to. Myślę, że to jest niekonkurencyjna odpowiedź :(
Digital Trauma