Zadanie pochodzi z konkursu Cody autorstwa CodestHQ. Jeśli chcecie zagrać - nie psujcie sobie zabawy czytaniem ;)
Problem jest prosty - trzeba wypisać na następujący tekst:
Ruby was released in 1995!
Większość z nas zrobi to w najprostszy możliwy sposób:
Ale teraz pojawia się utrudnienie - kod źródłowy musi spełniać następujące wyrażenie regularne: [a-zA-Z.\n ]. Czyli innymi słowy może składać się tylko z małych i wielkich liter, kropki, znaku nowej linii i spacji.
Pierwsze pytanie - jak możemy wypisać każdy znak na ekran bez jego używania?
Odpowiedź jest dosyć oczywista - każda litera ma sobie odpowiadający kod ascii.
Zatem jeżeli dodamy do siebie odpowiednio wiele liczb, a następnie zamienimy to na znak (metodą .chr) - dostaniemy pożądaną literkę!
Zatem nasze rozwiązanie wyglądałoby następująco:
Teraz co prawda pozbyliśmy się cudzosłowów i znaku wykrzynika - jednak wciąż używamy liczb. Skąd zatem je wziąć, skoro nie wolno ich nam użyć?
Inspiracją i pewną podpowiedzią może być konstrukcja liczb naturalnych von Neumanna. Czyli:
Tłumacząc to na język programowania, potrzebować będziemy pustej tablicy (nasz “zbiór pusty”), a potem jakiejś metody na dodawanie jej do samej siebie (krok indukcyjny).
Użyjmy zatem konstrukcji liczb naturalnych Von Neumanna w Ruby, do uzyskania potrzebnych nam liczb naturalnych przy pomocy samych tablic (i trzech prostych metod). Zaczniemy od zdefiniowania dwóch metod, które są odpowiednikiem kroku bazowego i kroku indukcyjnego z definicji.
(metoda .dup w metodzie b ma znaczenie czysto kosmetyczne. Bez niej zamiast ładnych zbiorów pustych tablic, dostaniemy tablice rekurencyjne, które nie będą odpowiadać liczbom naturalnym, a do tego wyświetlają się mniej ładnie. Do tego utrudniają zauważenie analogii z konstrukcją Von Neumanna. Natomiast liczba elementów się zgadza, stąd zadanie byłoby poprawne także wtedy)
I wtedy, odpowiednio:
Skonstruowaliśmy właśnie liczby naturalne, używając konstrukcji Von Neumanna w Ruby, przy pomocy tablicy i dwóch prostych metod. Całkiem nieźle, prawda?
Teraz brakuje nam tylko ostatniego klocka tej układanki - metody, która przyjmie całą daną tablicę, sprawdzi ile ona ma elementów, a następnie zwróci odpowiedni znak z tablicy ascii.
Żeby na przykład uzyskać ! musimy wykonać naszą konstrukcję 33 razy, a następnie dodać nasze zero na końcu, zamianę na znak i wypisanie na początku.
Intuicyjnie - c to zero, a każde kolejne b jest odpowiednikiem dodania do niego jedynki. Proste jak drut ;)
Finalne rozwiązanie wypisujące na ekran Ruby was released in 1995! wygląda następująco:
(linie są bardzo długie, bo nie wolno przecież użyć nam symbolu \, które pozwoliłby złamać)
A efekt:
(rozwiązanie wygrało nagrodę jako jedno z pięciu najciekawszych w konkursie Cody)