Przeskocz do treści

Delta mi!

Mała Delta

Jak opisać ładny język?

Maria Donten-Bury

o artykule ...

  • Publikacja w Delcie: listopad 2010
  • Publikacja elektroniczna: 20-12-2010
  • Wersja do druku [application/pdf]: (173 KB)

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ą.

obrazek

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 math . 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 math złożony z czterech słów math i math 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  math. Możemy napisać słowo jednoliterowe  math, dwuliterowe  math, trzyliterowe math Wszystkie słowa, czyli pełny język nad tym alfabetem, to ciągi powtórzeń litery  math. Słowo puste, oznaczane tradycyjnie  math, możemy rozumieć jako ,,zero powtórzeń litery  math”. 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 math, język słów o nieparzystej długości math, 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 math Mamy mnóstwo możliwości. A jeśli weźmiemy większy alfabet, chociażby dwuliterowy math i  math, to pojawią się takie przykłady, jak język słów mających na początku math liter  math, a dalej tyle samo liter  math:

display-math

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

display-math

czy język słów zawierających przynajmniej dwa razy więcej liter  math niż  math:

display-math

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 mathmath  i  math , 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 math  oznacza sumowanie dwóch języków, czyli wrzucenie do jednego języka wszystkich słów z obu danych zbiorów. Dalej, math  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,

pict

Natomiast math 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  math zapisuje się jako  math , a zbiór wszystkich słów z liter mathmath i  math to  math .

Teraz jeszcze trzeba się przyzwyczaić do tego, że symboli mathmath  i  math będziemy używać nie tylko do języków, ale też do wyrażeń opisujących języki. Czyli przez math rozumiemy zastosowanie operacji  math do języka math. Nawiasy klamrowe wokół pojedynczych słów będziemy dla wygody opuszczać, więc ostatecznie wyrażenie opisujące pełny język nad alfabetem  math to po prostu  math , a wyrażenie dla pełnego języka nad alfabetem mathmathmath to  math .

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  math, czyli jest ono sklejeniem pewnej liczby słów  math. Wobec tego odpowiednim wyrażeniem regularnym jest  math . Ponieważ math 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ę  math z takiego słowa, to zostanie słowo o parzystej długości, czyli ten język powstaje przez sklejanie litery  math ze słowami z języka z poprzedniego przykładu. Wystarczy więc dokleić literę  math do opisanego wyżej wyrażenia: math . A gdybyśmy napisali math? 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  math , gdzie math 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 math

Język nad alfabetem mathmath złożony ze słów z dokładnie jedną literą  math konstruujemy tak:
najpierw piszemy pewną liczbę liter  math (może zero), później wstawiamy  math i kończymy ciągiem  math (znów może pustym). Czyli początek i koniec zapisujemy jako  math , a całe wyrażenie to math 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 math i  math występują blokami co najwyżej dwuelementowymi. Weźmy słowo zaczynające się i kończące literą  math. Wtedy początek to math lub  math. Jeśli słowo się na tym nie kończy, to dalej mamy math lub  math, potem znów math lub  math i ta sytuacja może się powtarzać. Wobec tego słowa z naszego języka zaczynające się i kończące  math są opisywane wyrażeniem math . Pozostałe trzy przypadki: słowa zaczynające się  math i kończące  math, zaczynające i kończące  math oraz zaczynające  math i kończące  math możemy opisać podobnie i dodać wyrażenia definiujące cztery części języka:

(a+ aa)[(b + bb)(a + aa)]∗ +[(b + bb)(a +aa)] ∗+
                                          ∗                    ∗
               + (b+ bb)[(a + aa)(b + bb)]  +[(a + aa)(b + bb)] .

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  math 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.