# Pary dat. Rozwiązanie zagadki kalendarzowej

https://xpil.eu/ywu

Zagadka jest całkiem prosta i da się ją - przy odrobinie cierpliwości - rozwiązać bez pomocy komputerów. Ja - z braku cierpliwości - napisałem sobie oczywiście prosty skrypt w Pythonie:

import pandas as pd
from pprint import pprint

dates = pd.date_range(start="2023-01-01", end="2023-12-31")
solution = set()

for d1 in dates:
for d2 in dates:
if (sorted([d1.month, d1.day]) == sorted([d2.month+d2.day, d2.month*d2.day])):
pprint(solution)
print(len(solution))

Wynik:

{((1, 1), (1, 2)),
((1, 1), (2, 1)),
((1, 2), (2, 3)),
((1, 2), (3, 2)),
((1, 3), (3, 4)),
((1, 3), (4, 3)),
((1, 4), (4, 5)),
((1, 4), (5, 4)),
((1, 5), (5, 6)),
((1, 5), (6, 5)),
((1, 6), (6, 7)),
((1, 6), (7, 6)),
((1, 7), (7, 8)),
((1, 7), (8, 7)),
((1, 8), (8, 9)),
((1, 8), (9, 8)),
((1, 9), (9, 10)),
((1, 9), (10, 9)),
((1, 10), (10, 11)),
((1, 10), (11, 10)),
((1, 11), (11, 12)),
((1, 11), (12, 11)),
((1, 12), (12, 13)),
((2, 1), (2, 3)),
((2, 1), (3, 2)),
((2, 2), (4, 4)),
((2, 3), (5, 6)),
((2, 3), (6, 5)),
((2, 4), (6, 8)),
((2, 4), (8, 6)),
((2, 5), (7, 10)),
((2, 5), (10, 7)),
((2, 6), (8, 12)),
((2, 6), (12, 8)),
((2, 7), (9, 14)),
((2, 8), (10, 16)),
((2, 9), (11, 18)),
((2, 10), (12, 20)),
((3, 1), (3, 4)),
((3, 1), (4, 3)),
((3, 2), (5, 6)),
((3, 2), (6, 5)),
((3, 3), (6, 9)),
((3, 3), (9, 6)),
((3, 4), (7, 12)),
((3, 4), (12, 7)),
((3, 5), (8, 15)),
((3, 6), (9, 18)),
((3, 7), (10, 21)),
((3, 8), (11, 24)),
((3, 9), (12, 27)),
((4, 1), (4, 5)),
((4, 1), (5, 4)),
((4, 2), (6, 8)),
((4, 2), (8, 6)),
((4, 3), (7, 12)),
((4, 3), (12, 7)),
((4, 4), (8, 16)),
((4, 5), (9, 20)),
((4, 6), (10, 24)),
((4, 7), (11, 28)),
((5, 1), (5, 6)),
((5, 1), (6, 5)),
((5, 2), (7, 10)),
((5, 2), (10, 7)),
((5, 3), (8, 15)),
((5, 4), (9, 20)),
((5, 5), (10, 25)),
((5, 6), (11, 30)),
((6, 1), (6, 7)),
((6, 1), (7, 6)),
((6, 2), (8, 12)),
((6, 2), (12, 8)),
((6, 3), (9, 18)),
((6, 4), (10, 24)),
((6, 5), (11, 30)),
((7, 1), (7, 8)),
((7, 1), (8, 7)),
((7, 2), (9, 14)),
((7, 3), (10, 21)),
((7, 4), (11, 28)),
((8, 1), (8, 9)),
((8, 1), (9, 8)),
((8, 2), (10, 16)),
((8, 3), (11, 24)),
((9, 1), (9, 10)),
((9, 1), (10, 9)),
((9, 2), (11, 18)),
((9, 3), (12, 27)),
((10, 1), (10, 11)),
((10, 1), (11, 10)),
((10, 2), (12, 20)),
((11, 1), (11, 12)),
((11, 1), (12, 11)),
((12, 1), (12, 13))}
95

Widać, że jest 95 różnych par dat spełniających warunki zagadki.

A jak Wam poszło?

1Cichemu wyszło 126. Nie zaliczam.

2Waldek stwierdził za pomocą kilku formuł w Excelu, że 96. Blisko, ale nie zaliczam. Nota bene nie do końca rozumiem Waldkowe formuły - a konkretnie to nie widzę gdzie ma zdefiniowane podwójne permutacje dat (trzeba sprawdzić wszystkie możliwe pary). A może metoda Waldka jest poprawna i się chłop po prostu walnął o 1, na przykład licząc podwójnie parę 2 lutego i 4 kwietnia? No nie wiem.

3Butter jako pierwszy nadesłał poprawne rozwiązanie, uzyskane za pomocą skryptu w Pythonie. Gratuluję wygranej.

from datetime import date, timedelta
res = []
_date = date(2023,1,1)
delta = timedelta(days = 1)

for x in range(365):
d1 = {
"day" :_date.day,
"month" : _date.month,
"date" :_date}
res.append(d1)

_date += delta

wynik = 0
for x in res:
suma    = x['day'] + x['month']
iloczyn = x['day'] * x['month']
szuk = [ pos for pos in res if ((pos['day'] == suma) and pos['month'] == iloczyn) or ((pos['day'] == iloczyn) and (pos['month'] == suma)) ]
if len(szuk) >0:
wynik += len(szuk)
wynik_print = '{0:02d}-{1:02d} --> '.format(x['day'],x['month'])
for px in szuk:
wynik_print += ' {0:02d}-{1:02d} '.format(px['day'],px['month'])
print(wynik_print)
print('---------')
print(wynik)

Skrypt Buttera (powyżej) jest nieco bardziej skomplikowany od mojego, ale z drugiej strony nie wymaga używania niestandardowych bibliotek i w dodatku wyświetla wyniki w bardziej elegancki sposób:

01-01 -->  02-01  01-02
02-01 -->  03-02  02-03
03-01 -->  04-03  03-04
04-01 -->  05-04  04-05
05-01 -->  06-05  05-06
06-01 -->  07-06  06-07
07-01 -->  08-07  07-08
08-01 -->  09-08  08-09
09-01 -->  10-09  09-10
10-01 -->  11-10  10-11
11-01 -->  12-11  11-12
12-01 -->  13-12
01-02 -->  03-02  02-03
02-02 -->  04-04
03-02 -->  06-05  05-06
04-02 -->  08-06  06-08
05-02 -->  10-07  07-10
06-02 -->  12-08  08-12
07-02 -->  14-09
08-02 -->  16-10
09-02 -->  18-11
10-02 -->  20-12
01-03 -->  04-03  03-04
02-03 -->  06-05  05-06
03-03 -->  09-06  06-09
04-03 -->  12-07  07-12
05-03 -->  15-08
06-03 -->  18-09
07-03 -->  21-10
08-03 -->  24-11
09-03 -->  27-12
01-04 -->  05-04  04-05
02-04 -->  08-06  06-08
03-04 -->  12-07  07-12
04-04 -->  16-08
05-04 -->  20-09
06-04 -->  24-10
07-04 -->  28-11
01-05 -->  06-05  05-06
02-05 -->  10-07  07-10
03-05 -->  15-08
04-05 -->  20-09
05-05 -->  25-10
06-05 -->  30-11
01-06 -->  07-06  06-07
02-06 -->  12-08  08-12
03-06 -->  18-09
04-06 -->  24-10
05-06 -->  30-11
01-07 -->  08-07  07-08
02-07 -->  14-09
03-07 -->  21-10
04-07 -->  28-11
01-08 -->  09-08  08-09
02-08 -->  16-10
03-08 -->  24-11
01-09 -->  10-09  09-10
02-09 -->  18-11
03-09 -->  27-12
01-10 -->  11-10  10-11
02-10 -->  20-12
01-11 -->  12-11  11-12
01-12 -->  13-12
---------
95

4Rozie nadesłał swoje rozwiązanie nazajutrz rano. Z jakiegoś powodu wyszło mu 48:

days_month_count = {
1: 31,
2: 29,
3: 31,
4: 30,
5: 31,
6: 30,
7: 31,
8: 31,
9: 30,
10: 31,
11: 30,
12: 31,
}

possible = set()
created = set()

for month in range(1, 13):
for day in range(1, days_month_count[month]):
new_day1 = month * day
new_month1 = month + day
new_day2 = month + day
new_month2 = month * day

count = 0
for to_check in created:
if to_check in possible:
print(to_check)
count += 1

print(count)

5Pod wieczór przyszło rozwiązanie Piotra - nie dość, że poprawne, to jeszcze zrobione algorytmem w SQL. Szacun!

with __numbers AS (select * from(values(1),(2),(3),(4),(5),(6)) as n(num)),
_numbers as (select a.* from __numbers a cross join __numbers),
numbers as (select row_number() over(order by a.num) rownum from _numbers a),
longmonthdays as (select rownum day from numbers where rownum <= 31),
shortmonthdays as (select rownum day from numbers where rownum <= 30),
februarydays as (select rownum day from numbers where rownum <= 28),
shortmonths as (select * from (values(4),(6),(9),(11)) as n(month)),
longmonths as (select * from (values (1),(3),(5),(7),(8),(10),(12)) as n(month)),
february as (select 2 as month),
longdates as (select day.*,month.* from longmonthdays day cross join longmonths month),
shortdates as (select day.*, month.* from shortmonthdays day cross join shortmonths month),
februarydates as (select day.*, month.* from februarydays day cross join february month),
alldates as (
select day, month from longdates
union all select day, month from shortdates
union all select day, month from februarydates
),
datecombinations AS (
select
a.day [my day],
a.month [my month],
b.day [friend day],
b.month [friend month]
from
alldates a
inner join alldates b on a.day + a.month = b.month
and a.day * a.month = b.day
union
select
a.day [my day],
a.month [my month],
b.day [friend day],
b.month [friend month]
from
alldates a
inner join alldates b on a.day * a.month = b.month
and a.day + a.month = b.day
)
select
row_number() over(
order by
[my day]
) num,
[my day],
[my month],
[friend day],
[friend month]
from
datecombinations
order by 2, 1

6Rozie zorientował się, że jego poprzednie rozwiązanie miało pewne wady i nadesłał nowe, lepsze. Też mu wyszło 48, ale dużo szybciej i bardziej elegancko:

mm = [1, 2, 3, 4, 6, 12] # possible month after multiplication
ms = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] # possible month after addition

solutions = set()
for m in mm:
for n in ms:
if m * n < 31 and m + n < 13:
solutions.add((m * n, m + n))
if m + n < 31 and m * n < 13:
solutions.add((m + n, m * n))
print(len(solutions))

Wydaje mi się, że Rozie próbuje tu rozwiązać inne zadanie niż przedstawione w zagadce...

P.S. Dzięki dla Waldka za przypomnienie mi o terminach - faktycznie kompletnie wyleciało mi z głowy, żeby opublikować odpowiedź. Swoją drogą mam żelazną zasadę nie publikowania zagadki zanim nie przygotuję wpisu z odpowiedzią, więc ten tutaj po prostu wisiał sobie na zapleczu i czekał na publikację. Kwestia paru kliknięć 🙂

7P.S.2. Aha, całkiem zapomniałem o tym, że w międzyczasie - zresztą za namową znajomego - spróbowałem rozwiązać tę zagadkę za pomocą popularnego ostatnio ChatGPT. Oto rezultaty:

Jak widać do osobliwości technologicznej jeszcze daleko 🙂

https://xpil.eu/ywu

## 9 komentarzy

1. Waldek pisze:

“licząc podwójnie parę 2 lutego i 4 kwietnia”

Tak było, tzn tak jest. Rzeczywiście popełniłem niegodny błąd i czuję się wstrętnie.
Przyznam, że szukałem haczyków w tej zagadce i sprawdzałem na różne sposoby wiele z nich (np. datę 29 lutego). Przeoczyłem jednak oczywiste. Tak mi wstyd…
Naprawdę.

2. Waldek pisze:

“Swoją drogą mam żelazną zasadę nie publikowania zagadki zanim nie przygotuję wpisu z odpowiedzią, więc ten tutaj po prostu wisiał sobie na zapleczu i czekał na publikację”.

Znaczy – znałeś nasze odpowiedzi, zanim my je uzyskaliśmy:

Bądź uwielbiony, miłosierny Boże, Wszechmocny Stwórco, dobry nasz Panie.
Cześć Ci oddajem w najgłębszej pokorze, w Bóstwa Twojego tonąc oceanie.

1. Jakiś hymn czy dwa, spoko, ale aż takie rymy to mi się jednak nie należą.

Chodziło mi bardziej o to, że zanim opublikuję zagadkę, mam już przygotowany wpis z odpowiedzią. Natomiast ponumerowane po kolei zgłoszenia czytelników dopisuję na bieżąco później.

Zresztą w tym akurat przypadku między nadejściem odpowiedzi numer 6 a publikacją wpisu minęło całkiem sporo czasu, więc wszystko się zgadza.

1. Waldek pisze:

Te peany to tylko drobny żarto-uśmiech ściągnięty z jakiejś przypadkowej strony religio-wyznawców. Tak poza tym to, rzecz jasna, nie możesz być Bogiem, gdyż zapomniałeś o dacie publikacji rozwiązania. Bóg by nie zapomniał…

1. W jednej z książek Pratchetta była bogini odpowiedzialna za blokowanie się chochli w szufladzie. Ja mogę być bogiem od zapominania. Panteon teraz jest pełen najróżniejszego dziwactwa 🙂

3. Waldek pisze:

Jeśli już o bogach i bóstwach: Bardzo, ale to najbardziej bardzo spodobał mi się cytat:
“If you broke down holy water into hydrogen and oxygen you could make a holy hydrogen bomb”.
Kilka cytatów z twojej strony już wcześniej mi się podobało (z siedem razy nawet się śmiałem), ale ten przebija wszystko. To jest KWINTESENCJA. Trzeba tylko spojrzeć w głąb. W głąb bomby wodorowej. Serdecznie pozdrawiam…

4. Ech, machnąłem się w warunku poprawności miesiąca i w niektórych przypadkach zaliczyło mi daty z miesiącami większymi od 12 – nie wiem, jakim cudem udało mi się tego nie zauważyć w wynikach. Po poprawieniu wyszło już dobrze.

5. Nie tylko liczyłem co innego, niż przedstawione w zagadce, ale dodatkowo z błędem. Chodzi oczywiście o linię

for day in range(1, days_month_count[month]):


Za mało o 1 w górnym zakresie.

I tak, policzyłem po prostu ile unikalnych dat można utworzyć przez mnożeniododawanie.

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.