• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Konwersja Gramatyki bezkontekstowej do Postaci Normalnej Chomskyego

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
840 wizyt
pytanie zadane 22 marca 2017 w C i C++ przez kopcowanie Nowicjusz (120 p.)

Dzień dobry,

piszę zamianę Gramatyki bezkontekstowej do postaci normalnej Chomskyego, znalazłem opis na Wikipedii - Konwersja Wikipedia i próbuję to zaimplementować, jednak przy drugim kroku mój program daje nieprawidłowe rezultaty, a trzeciego kroku nie rozumiem.

Na angielskiej wikipedii opis konwersji jest o wiele bardziej rozbudowany - Angielska wersja.

Moje pytanie - czy ktoś ma/mógłby podzielić się implementacją w C/C++ tego algorytmu żeby można było poczytać i krok po kroku prześledzić?

Tutaj zamieszczam przykładowy input:

S:bA|aB
A:bAA|aSb|a
B:aaBB|b

1 odpowiedź

+1 głos
odpowiedź 22 marca 2017 przez event15 Szeryf (93,790 p.)
komentarz 23 marca 2017 przez kopcowanie Nowicjusz (120 p.)
edycja 23 marca 2017 przez kopcowanie
#include <iostream>

using namespace std;

int symbol_nieterminalny(string produkcja) {
    for(unsigned i=0; i<produkcja.size(); ++i) {
        if (produkcja[i] >= 97 && produkcja[i] <= 122) {
            return i;
        }
    }
    return -1;
}

int znak_podzialu(string produkcja) {
    for(unsigned i=0; i<produkcja.size(); ++i) {
        if (produkcja[i] == '|') {
            return i;
        }
    }
    return -1;
}

int regula_lancuchowa(string produkcja) {
    for(unsigned i=0; i<produkcja.size(); ++i) {
        if (produkcja[i] >= 65 && produkcja[i] <= 90 && produkcja[i] != produkcja[0]) {
            return i;
        }
    }
    return -1;
}

string pobierz_regule(unsigned liczba_zmiennych, string *tablica_produkcji, char symbol_startowy) {
    for(unsigned i=0; i<liczba_zmiennych; ++i) {
        if(tablica_produkcji[i][0] == symbol_startowy) {
            return tablica_produkcji[i].substr(3, tablica_produkcji[i].length());
        }
    }
    return "";
}

unsigned dodaj_regule(unsigned liczba_zmiennych, string *tablica_produkcji, string regula) {
    for(unsigned i=0; i<liczba_zmiennych; ++i) {
        if(tablica_produkcji[i] == regula) {
            return liczba_zmiennych;
        }
    }
    tablica_produkcji[liczba_zmiennych] = regula;
    return ++liczba_zmiennych;
}

void wyswietl(unsigned liczba_zmiennych, string *tablica_produkcji) {
    for(unsigned i=0; i<liczba_zmiennych; ++i) {
        cout<<tablica_produkcji[i]<<endl;
    }
    cout<<endl;
}

int main() {
    string badane_slowo; unsigned liczba_zmiennych; string *tablica_produkcji;
    badane_slowo = "baa";
    liczba_zmiennych = 3;
    tablica_produkcji = new string[liczba_zmiennych*100];
    tablica_produkcji[0] = "S->bA|aB";
    tablica_produkcji[1] = "A->bAA|aSb|a";
    tablica_produkcji[2] = "B->aaBB|b";

    /**
     * Zastąpienie symboli terminalnych, symbolami nieterminalnymi
     */
    unsigned limit = liczba_zmiennych;
    for(unsigned i=0; i<limit; ++i) {
        while(symbol_nieterminalny(tablica_produkcji[i]) != -1) {
            int pozycja = symbol_nieterminalny(tablica_produkcji[i]);
            char znak = tablica_produkcji[i][pozycja];
            tablica_produkcji[i][pozycja] = znak-48;
            string regula = " -> ";
            regula[0] = znak-48;
            regula[3] = znak;
            liczba_zmiennych = dodaj_regule(liczba_zmiennych, tablica_produkcji, regula);
        }
    }

    wyswietl(liczba_zmiennych, tablica_produkcji);

    /**
     * Odpowiednie wydzielenie produkcji
     */
    for(unsigned i=0; i<liczba_zmiennych; ++i) {
        while(znak_podzialu(tablica_produkcji[i]) != -1) {
            int pozycja = znak_podzialu(tablica_produkcji[i]);
            string regula = tablica_produkcji[i].substr(0, pozycja);
            liczba_zmiennych = dodaj_regule(liczba_zmiennych, tablica_produkcji, regula);
            string czesc1 = tablica_produkcji[i].substr(0, 3);
            string czesc2 = tablica_produkcji[i].substr(pozycja+1, tablica_produkcji[i].length());
            tablica_produkcji[i] = czesc1 + czesc2;
        }
    }

    wyswietl(liczba_zmiennych, tablica_produkcji);


    /**
     * Eliminacja reguł łańcuchowych
     */
    for(unsigned i=0; i<liczba_zmiennych; ++i) {
        int pozycja = regula_lancuchowa(tablica_produkcji[i]);
        if (pozycja == -1) {
            continue;
        }
        char symbol_startowy = tablica_produkcji[i][pozycja];
        string regula = pobierz_regule(liczba_zmiennych, tablica_produkcji, symbol_startowy);
        string czesc1 = tablica_produkcji[i].substr(0, pozycja);
        string czesc2 = tablica_produkcji[i].substr(pozycja + 1, tablica_produkcji[i].length());
        tablica_produkcji[i] = czesc1 + regula + czesc2;
    }

    wyswietl(liczba_zmiennych, tablica_produkcji);


    return 0;
}

/*
void CFG::toCNF(){
    /*
     * add a variable for every terminal
     *
    std::map<std::string, std::vector<std::string> >::iterator it;
    for (unsigned int i = 0; i< terminals_.size(); i++){
        variables_.push_back(utilities::lowToUp(terminals_[i]));
        for (it = rules_.begin(); it != rules_.end(); it++){
            for (unsigned int e = 0; e < it->second.size(); e++){
                it->second[e] = utilities::replacestring(it->second[e], terminals_[i],
                                                         utilities::lowToUp(terminals_[i]));
            }
        }

    }
    /*
     * now we need to eleminate all replacement rules; greater then 3;
     *
    std::map<std::string, std::vector<std::string> > newmap;
    std::string newvar = "A";
    for (it = rules_.begin(); it != rules_.end(); it++){
        // dla każdej produkcji w tablicy produkcji
        for (unsigned int t = 0; t < it->second.size(); t++){
            // dla każdej zasady w produkcji
            if (it->second[t].size() <= 2){
                newmap[it->first].push_back(it->second[t]);
            }
            else if(it->second[t].length() > 2){
                std::string ruler = it->second[t];
                std::string firstvar = it->first;
                while (ruler.length() > 2){
                    bool invar = true;
                    while(invar){
                        invar = false;
                        for (unsigned int r; r < variables_.size(); r++){
                            if(variables_[r] == newvar){
                                newvar = utilities::nextstring(newvar);
                                invar = true;
                            }
                        }
                    }
                    std::string back = ruler.substr(0,1) + newvar;
                    newmap[firstvar].push_back(back);
                    ruler = ruler.substr(1);
                    firstvar = newvar;
                    variables_.push_back(firstvar);
                }
            }
        }
    }
    rules_ = newmap;
}
/* */

 

Bardzo dziękuję za te linki.​​ Piszę program na podstawie, kodu zamieszczonego pod mainem(znalezionego w tych adresach) oraz linków do wikipedii. Kod na którym bazuję biorę stąd: https://github.com/TREK-TMS-BB/TMS-BB/blob/56d1f9a5972ed4e2aaf8b011a08a2d2538d9b3c2/src/CFG.cpp

Zawiesiłem się jednak w kroku "Eliminacja reguł łańcuchowych". 

Podobne pytania

0 głosów
1 odpowiedź 245 wizyt
pytanie zadane 3 września 2020 w Rozwój zawodowy, nauka, praca przez Monand Nowicjusz (160 p.)
+4 głosów
10 odpowiedzi 1,204 wizyt
+2 głosów
4 odpowiedzi 516 wizyt

93,187 zapytań

142,201 odpowiedzi

322,012 komentarzy

62,514 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 2365p. - dia-Chann
  2. 2326p. - Łukasz Piwowar
  3. 2315p. - Łukasz Eckert
  4. 2269p. - Tomasz Bielak
  5. 2006p. - Michal Drewniak
  6. 2006p. - rucin93
  7. 2005p. - Łukasz Siedlecki
  8. 1964p. - CC PL
  9. 1946p. - Adrian Wieprzkowicz
  10. 1901p. - Mikbac
  11. 1744p. - rafalszastok
  12. 1734p. - Anonim 3619784
  13. 1586p. - Dawid128
  14. 1520p. - Marcin Putra
  15. 1480p. - ssynowiec
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...