Dziwny zegarek: rozwiązanie zagadki

https://xpil.eu/k42

Postawiona niedawno zagadka o zdegenerowanym zegarku, który pokazuje tylko bieżącą godzinę oraz numer roku (w formie GG:MM:SS RRRR) jest niezbyt ambitna - w sam raz na szybką sesję z kartką i ołówkiem podczas porannej toalety, a jeżeli ktoś umie policzyć w rozumie do dwudziestu bez zdejmowania butów to nawet kartka i ołówek mogą okazać się zbędne.

Mówiąc "poranna toaleta" mam na myśli poranną kupę, nie poranne ablucje, chociaż oczywiście niczego nie narzucam. Jak mawiał kiedyś mój świętej pamięci wujek: "od porannej kupy się nie wymigasz, zrobisz ją choćby wieczorem". Wujek jakoś nie zapisał się złotymi zgłoskami w żadnych annałach, dalibóg nie wiem dlaczego.

Zaczniemy od tego, że w wyrażeniu GG:MM:SS pierwsze G, M oraz S muszą być mniejsze od szóstki (nie ma, przykładowo, godziny 12:64), a także samo G musi być mniejsze od trójki. A więc pozostają nam tutaj cyfry 0-5. Z tym, że ponieważ aktualnie mamy rok 2022 i będziemy próbować pozostać w bieżącym stuleciu, eliminujemy zero i dwójkę, czyli możemy roboczo przyjąć, że GG musi zaczynać się od 1, a MM i SS od 3, 4 lub 5.

Skoro bieżący rok zaczyna się od 20, najmniejsza wartość roku z przyszłości z unikalnymi cyframi to 2031. Odpada, bo (jak wyjaśniłem powyżej) "zjada" za dużo cyferek 0-5. Dla GG:MM:SS musimy pozostawić co najmniej trzy cyfry spośród 1, 3, 4, 5. Szybkie przemyślenia pokazują nam, że najmniejszy numer roku, który da się tu uzyskać to 2036 - każdy z poprzednich (większych od 2022) ma albo zdublowaną cyfrę, albo zużywa więcej niż jedną cyfrę z listy 1, 3, 4, 5.

A więc znamy już rok (2036), pozostały nam cyfry 1, 4, 5, 7, 8, 9, z których łatwo zbudować minimalną możliwą godzinę: 17:48:59. Tak więc poprawna odpowiedź brzmi: 17:48:59 2036.

Jakby się ktoś chciał przyczepić, skoro pytanie brzmi "Kiedy w najbliższej przyszłości pojawi się blablabla...", to odpowiedź powinna brzmieć "pierwszego stycznia 2036 roku o godzinie 17:48:59", ale może się nikt nie przyczepi.

(Dopisane w ostatniej chwili: jednak się ktoś przyczepił 🙂 )

A co z pytaniem bonusowym, które brzmiało podobnie tylko dotyczyło możliwie najpóźniejszej takiej daty z przeszłości?

Rok 2019 to ostatni rok w tym tysiącleciu (przed 2022), którego numer składa się z unikalnych cyfr. Ale zużywa on zero, jedynkę i dwójkę, z których przynajmniej jedna jest potrzebna do GG. Czyli - odpada. Wszystkie numery lat, które jednocześnie zużywają 0, 1, 2 odpadają, zatem nie możemy pozostać w drugim tysiącleciu.

A więc najlepszy kandydat na rok to 1987, potem już są duble aż do 2013.

Skoro 1987, to na część GG:MM:SS mamy do dyspozycji cyfry 0, 2, 3, 4, 5, 6. Szukamy czasu możliwie najpóźniejszego, a więc godzina 23. Pozostają 0, 4, 5, 6, więc minuta 56 i sekunda 40. Czyli po raz ostatni sytuacja taka miała miejsce w 1987 roku o godzinie 23:56:40 (31 grudnia, oczywiście, ale o to już w zagadce nie pytają).

A jak Wam poszło? Nader płodnie...

1Jeszcze tego samego dnia pod wieczór swoje rozwiązanie nadesłał Rozie. Zaliczam na pomarańczowo, bo choć odpowiedź jest poprawna (choć po drodze wkradł się niewielki błąd logiczny: "prawidłowa najbardziej istotna cyfra minut i sekund to 0-6" - powinno być "0-5"), to brak odpowiedzi na pytanie bonusowe.

2Nazajutrz wczesnym popołudniem swoją odpowiedź nadesłał Rzast. Odpowiedź na pytanie główne jak najbardziej poprawna, niestety Rzast machnął się o jedną sekundę w odpowiedzi na pytanie bonusowe 🙂 Zaliczam na pomarańczowo.

3Dzień później nadeszły dwie kolejne odpowiedzi. Najpierw Cichy rozwiązał zadanie w trymiga i z minimum zbędnej gadaniny (szczególnie wzruszyła mnie tutaj kwiecistość opisu problemu bonusowego):

4... a w chwilę potem nadeszło rozwiązanie Waldka, który jako pierwszy przyczepił się (i słusznie!) do niejednoznaczności pytania, bo dana godzina pojawia się w każdym roku więcej niż raz:

5Rafał podszedł do zagadnienia z innej strony i zamiast się głowić, napisał sobie prostą pętelkę, która sprawdziła wszystkie daty między rokiem 1000 a 2999 i mu wyszło. Prawidłowo - zaliczam, choć na sam kod PHP patrzę z lekkim przerażeniem. Ale, jak mawiają lokalni, don't fix if it ain't broken 🙂

$r1 = 1;
$r2 = 0;
$r3 = 0;
$r4 = 0;
$g1 = 0;
$g2 = 0;
$m1 = 0;
$m2 = 0;
$s1 = 0;
$s2 = 0;

echo 'start<br/>';
while ($r1 < 3) {
    $ciag = $g1 . $g2 .':'. $m1 . $m2 .':'. $s1 . $s2 .'-'. $r1 . $r2 . $r3 . $r4;
    $rok = $r1 . $r2 . $r3 . $r4;
    if (!($r1 != $r2 && $r2 != $r3 && $r3 != $r4 && $r1 != $r3 && $r1 != $r4 && $r2 != $r4)) {

        next_year();
    } else {

        if (preg_match('/0{1}/', $ciag) && preg_match('/1{1}/', $ciag) &&
            preg_match('/9{1}/', $ciag) && preg_match('/2{1}/', $ciag) &&
            preg_match('/3{1}/', $ciag) && preg_match('/4{1}/', $ciag) &&
            preg_match('/5{1}/', $ciag) && preg_match('/6{1}/', $ciag) &&
            preg_match('/7{1}/', $ciag) && preg_match('/8{1}/', $ciag)) {
            echo $ciag . '<br/>';
        }




        $s2++;
        if ($s2 > 9) {
            $s2 = 0;
            $s1++;
            if ($s1 > 5) {
                $s1 = 0;
                $m2++;
                if ($m2 > 9) {
                    $m2 = 0;
                    $m1++;
                    if ($m1 > 5) {
                        $m1 = 0;
                        $g2++;
                        if (($g2 > 9) || ($g1>1 && $g2>3)) {
                            $g2 = 0;
                            $g1++;
                            if ($g1 > 2) {
                                $g1 = 0;
                                $g2 = 0;
                                next_year();
                            }
                        }
                    }
                }
            }
        }
    }
}
echo 'koniec';

function next_year() {
    global $r1, $r2, $r3, $r4;
    $r4++;
    if ($r4 > 9) {
        $r4 = 0;
        $r3++;
        if ($r3 > 9) {
            $r3 = 0;
            $r2++;
            if ($r2 > 9) {
                $r2 = 0;
                $r1++;
            }
        }
    }
}

Piszę w dotnecie już trzecie stulecie, bo kto się w pehapie połapie?

6W ślady Rafała poszło paru innych zawodników, którzy nadesłali swoje rozwiązania w postaci skryptów. Butter na ten przykład zrobił tak:

import itertools

h1 = [0, 1, 2]  # godziny - 1 cyfra
h2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
m = [0, 1, 2, 3, 4, 5]  # minuty - pierwsza cyfra


res = ''
for rok in range(2022, 3000):
    if res != '':
        break

    r_ = str(rok)
    print('ROK ', r_)
    if len(set(r_)) == 4:
        cyfryWRoku = [int(c) for c in r_]
        h1_1 = [x for x in h1 if x not in cyfryWRoku]
        h2_1 = [x for x in h2 if x not in cyfryWRoku]
        m2_1 = [x for x in m if x not in cyfryWRoku]

        for element in itertools.product(h1_1, h2_1, m2_1, h2_1, m2_1, h2_1):
            s = set(element)
            s = s.union(set(cyfryWRoku))
            # print(element, r_)
            if len(s) == 10:
                time_ = ''.join([str(x) for x in element])
                if int(time_[0:2]) < 24:
                    res = '{0}:{1}:{2} {3}'.format(
                        time_[0:2], time_[2:4], time_[4:6], r_)
                    break

print('Wynik: ', res)

# 17:48:59 2036

7Potem ponownie odezwał się Rozie, który dodał brakującą poprzednio odpowiedź na pytanie bonusowe. Zaliczam, tym razem na zielono.

8W dalszej kolejności, tak dla odmiany, odezwał się znów Rozie, który tym razem zamiast siedzieć jak pambuk przykazał na kibelku i rozwiązywać zagadkę za pomocą szarej masy międzyusznej, zasiadł za Die Tastatur i wyprodukował skrypt w Pythonie. Niestety skrypt Roziego rozjechał się w praniu (czytaj: mój formularz do wysyłania rozwiązań nie poradził sobie z kodem), odtworzyłem jego zgrubną logikę z resztek, które się przedostały. Pomysł w zasadzie mniej więcej ten sam co u Buttera powyżej, tylko leniwsze podejście, dzięki któremu kod jest dużo krótszy i czytelniejszy, ale czas wykonania dziesięć razy dłuższy (Butter: 37 milisekund, Rozie: 0.37 sekund):

from itertools import permutations

for i in permutations([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]):
    year = i[0] * 1000 + i[1] * 100 + i[2] * 10 + i[3]
    if year<2100 and year > 2022:
        hour = i[4] * 10 + i[5]
        if hour<=23:
            minute = i[6] * 10 + i[7]
            if minute<=59:
                second = i[8] * 10 + i[9]
                if second<=59:
                    print(year, hour, minute, second)
                    break

9Potem swój skrypt (również, dla odmiany, w Pythonie) podesłał Krzysiek, jednak w odróżnieniu od poprzedników, których kod był na tyle prosty, że udało mi się go odrestaurować po nieludzkim potraktowaniu przez formularz, tutaj poległem. Ale wyniki dał dobre. Zaliczam.

Wiedziony ciekawością podesłałem jeszcze do Roziego zapytanie o oryginalny kod - okazało się, że był on nieco dłuższy od tego, co zaprezentowałem powyżej i generuje wszystkie unikalne kombinacje cyfr (będące zarazem numerem roku i godziną), a więc wyników trzeba się doszukać na wyjściu:

https://xpil.eu/k42

6 komentarzy

  1. Huh, widzę, że te bonusy to takie obowiązkowe. 😉 Może lepiej byłoby w takim razie pytać na zasadzie pytanie 1, pytanie 2? Bo tak to człowiek zadowolony, że przy porannej kawie rozpykał, w zasadzie w pamięci, a potem pomarańczowo.

    1. Co do kodu i jego zmasakrowania, to najwidoczniej sposób podany dla komentarzy działa inaczej przy odpowiedziach. Nic to, na przyszłość postaram się korzystać z gist. I kolorowanie będzie, i mi nie zniknie AKA kontrola wersji. Tylko nie wiem czy nie będzie można podglądnąć przed zakończeniem. Ale w sumie to problem psującego sobie zabawę…

      1. Zgadza się. Formularz odpowiedzi na zagadki obsługiwany jest przez wtyczkę Forminator, a komentarze – natywnie. Stąd też trick z kodem tam nie działa.

    2. Na początku dałem ci zielony, ale potem Rzastowi dałem pomarańcz za pomyłkę w bonusowym i pomyślałem sobie, że on się przynajmniej zabrał za rozwiązywanie bonusowego a ty nie, więc cię zdegradowałem. Aha, od razu uprzedzam, pomarańczowy nie upoważnia cię do medalu z ziemniaka, co najwyżej z brukwi pastewnej 🙂

Leave a Comment

Komentarze mile widziane.

Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]

Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.