Mała Delta
Jak opisać ładny język?
Przyjmijmy, że słowem będzie dla nas dowolny ciąg liter. Nie tylko taki, który da się wymówić albo którego znaczenie jest objaśnione w słowniku. Zupełnie dowolny ciąg, złożony z jednej litery, kilku lub nawet długości całej encyklopedii.
Możemy wziąć także bardzo wyjątkowy ciąg o długości zero, nazywany słowem pustym. Niektórzy zajmują się też nieskończonymi słowami, ale to inna historia. Dla nas każde słowo ma długość będącą liczbą całkowitą nieujemną.

A właściwie jakie litery dopuszczamy? Czy pozwalamy tylko na alfabet angielski,
czy akceptujemy wszelkie ogonki, kropki, kreślenia i akcenty? Otóż możemy
ustalić, co nam się podoba, ale trzeba to zrobić na początku zabawy. Czyli
zaczynamy od wybrania alfabetu – zestawu znaków, z których będziemy
składać słowa. Może to być alfabet angielski, może być polski, może być
zbiór egipskich hieroglifów albo nawet zestaw
. Na przykład
komputery, wczytując program, pracują zwykle na słowach nad alfabetem
złożonym z małych i dużych liter, cyfr i kilku znaków specjalnych (np. kropka,
podkreślenie). A zapisując dane, używają dwuliterowego alfabetu: 0 i 1.
Wszystkie znaki w alfabecie, jakkolwiek by one nie wyglądały, będziemy
nazywać literami.
Jeśli mamy wybrany alfabet, to umiemy budować słowa, więc możemy
też tworzyć języki. Językiem będzie dla nas po prostu zbiór słów
zbudowanych z liter wybranego alfabetu. Może być skończony, tak jak zbiór
wszystkich słów języka polskiego albo język nad alfabetem
złożony z czterech słów
i
albo też język
złożony tylko ze słowa pustego. Ale może być nieskończony. Dla dowolnego
alfabetu możemy mianowicie wziąć zbiór wszystkich słów, które da się
poskładać z jego liter. Poza jednym wyjątkiem – kiedy alfabet ma zero
liter i jedyne słowo nad nim to słowo puste – tak utworzony język jest
nieskończony.
Przyjrzyjmy się najprostszemu przypadkowi, który ma szanse być ciekawy:
alfabetowi złożonemu z jednej litery
. Możemy napisać słowo
jednoliterowe
, dwuliterowe
, trzyliterowe
Wszystkie słowa, czyli pełny język nad tym alfabetem, to ciągi powtórzeń
litery
. Słowo puste, oznaczane tradycyjnie
, możemy
rozumieć jako ,,zero powtórzeń litery
”. Ale są też inne języki
nieskończone nad tym alfabetem, mniejsze od pełnego, czyli będące
jego podzbiorami. Na przykład język słów o parzystej długości
, język słów o nieparzystej długości
, język słów o długościach będących
liczbami pierwszymi, język słów o długościach podzielnych przez 157,
język słów o długościach będących sześcianami liczb nieparzystych
Mamy mnóstwo możliwości. A jeśli weźmiemy większy alfabet,
chociażby dwuliterowy
i
, to pojawią się takie przykłady, jak
język słów mających na początku
liter
, a dalej tyle samo
liter
:

język słów zawierających dokładnie jedną literę
:

czy język słów zawierających przynajmniej dwa razy więcej liter
niż
:
![]() |
Podaliśmy tylko po kilka krótkich słów, ale na pewno, Czytelniku, umiesz te listy przedłużyć, a pewnie też znaleźć algorytm wypisywania słów z każdego z podanych języków, tak żeby żadnego nie pominąć.
Trudno się spodziewać, aby wszystkie języki były tak samo interesujące.
Pewnie, na przykład, częściej umiemy wykazać jakieś ciekawe własności
języka określonego, jak wyżej, jakąś regułą niż losowego zbioru słów.
Dobrym sposobem opisywania porządnych języków są wzory składające się
z liter wybranego alfabetu, trzech symboli
,
i
,
o których za chwilę opowiemy, i, jak zwykle, nawiasów dla zaznaczenia
kolejności działań. Takie wzory na konstrukcję języka nazywają się
wyrażeniami regularnymi, a języki, które za ich pomocą można opisać, to
języki regularne. Są to najporządniejsze z interesujących języków – zwykle,
żeby język wyrażał coś ciekawego, musi mieć bardziej skomplikowaną
strukturę. Nie zawsze: budowa lekserów (części kompilatorów) jest oparta na
językach regularnych, ale już parsery, wykonujące kolejny po analizie
leksykalnej krok kompilacji, używają języków opisanych bardziej złożonymi
,,równaniami” niż wyrażenia regularne.
Zajmijmy się naszymi regułami. Można się domyślić, że
oznacza
sumowanie dwóch języków, czyli wrzucenie do jednego języka wszystkich
słów z obu danych zbiorów. Dalej,
to też operacja na dwóch
językach – nowy język to sklejenia wszystkich słów z pierwszego języka ze
wszystkimi z drugiego. Kropkę w zapisie najczęściej się pomija, tak jak znak
mnożenia w arytmetyce. Na przykład,

Natomiast
to operacja na jednym języku. Nowy język składa się ze
wszystkich sklejeń dowolnej długości słów z podanego języka. Czyli,
na przykład, zbiór wszystkich słów złożonych z litery
zapisuje się
jako
, a zbiór wszystkich słów z liter
,
i
to
.
Teraz jeszcze trzeba się przyzwyczaić do tego, że symboli
,
i
będziemy używać nie tylko do języków, ale też do wyrażeń opisujących
języki. Czyli przez
rozumiemy zastosowanie
operacji
do języka
. Nawiasy klamrowe
wokół pojedynczych słów będziemy dla wygody opuszczać, więc ostatecznie
wyrażenie opisujące pełny język nad alfabetem
to po prostu
,
a wyrażenie dla pełnego języka nad alfabetem
,
,
to
.
A wyrażenia dla innych języków? Zacznijmy od alfabetu jednoliterowego
i słów o parzystej długości. Każde takie słowo można podzielić na
pary
, czyli jest ono sklejeniem pewnej liczby słów
. Wobec
tego odpowiednim wyrażeniem regularnym jest
. Ponieważ
obejmuje też możliwość sklejenia zera słów z danego języka, to
nie musimy się osobno martwić o słowo puste.
Teraz słowa o długości nieparzystej. Jeśli obetniemy pierwszą literę
z takiego słowa, to zostanie słowo o parzystej długości, czyli ten język powstaje
przez sklejanie litery
ze słowami z języka z poprzedniego przykładu.
Wystarczy więc dokleić literę
do opisanego wyżej wyrażenia:
. A gdybyśmy napisali
? Jak widać, jeden język
może być opisywany przez wiele wyrażeń regularnych.
Z pewnością już wiesz, Czytelniku, że język słów o długości
podzielnej przez 157 jest opisywany przez wyrażenie
, gdzie
zastępuje, oczywiście, odpowiednio długi ciąg, i potrafisz podać
wyrażenie dla języka słów o długościach dających resztę 19 z dzielenia
przez 91. Co z wyrażeniem dla słów o długościach będących liczbami
pierwszymi? Lepiej będzie poszukać dowodu, że takie wyrażenie nie istnieje
Język nad alfabetem
,
złożony ze słów z dokładnie jedną
literą
konstruujemy tak:
najpierw piszemy pewną liczbę liter
(może zero), później
wstawiamy
i kończymy ciągiem
(znów może pustym).
Czyli początek i koniec zapisujemy jako
, a całe wyrażenie to
Możemy też opisać zbiór słów (nad dwuliterowym
alfabetem), w których żadna litera nie występuje trzy razy pod rząd.
Ten warunek oznacza, że litery
i
występują blokami
co najwyżej dwuelementowymi. Weźmy słowo zaczynające się i kończące
literą
. Wtedy początek to
lub
. Jeśli słowo się na tym
nie kończy, to dalej mamy
lub
, potem znów
lub
i ta sytuacja może się powtarzać. Wobec tego słowa z naszego
języka zaczynające się i kończące
są opisywane wyrażeniem
. Pozostałe trzy przypadki: słowa zaczynające
się
i kończące
, zaczynające i kończące
oraz
zaczynające
i kończące
możemy opisać podobnie i dodać
wyrażenia definiujące cztery części języka:
![]() |
Jak opisać język zawierający trzy kolejne wystąpienia pewnej litery?
A język słów o nieparzystej długości? Albo język słów, w których
litera
pojawia się nieparzystą liczbę razy? Można rozważać alfabet
dwuliterowy, a można większy. Podpowiemy jeszcze, że wyrażeń dla
pozostałych przykładów z poprzedniej strony nie ma sensu szukać
nawet w długie zimowe wieczory. Ale warto pomyśleć nad dowodem,
że ich nie ma.