Zkouška PAL 8. ledna 2014

Vstup: množina slov, která mají být přijímána automatem; množina slov, která nemají být přijímána

Výstup: minimální nutný počet stavů automatu (DFA)

Ukázka řešení (12/12):

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <vector>
 
struct Input {
    unsigned letter_count;
    std::vector<std::vector<unsigned> > p; // přijímaná slova
    std::vector<std::vector<unsigned> > n; // nepřijímaná slova
 
    Input(): letter_count(0) {}
};
 
const int undefined_transition = -1;
 
struct Node {
    bool is_terminal;
    std::vector<int> transitions;
 
    explicit Node(unsigned transition_count)
      : is_terminal(false),
        transitions(transition_count, undefined_transition) {
    }
};
 
struct Graph {
    std::vector<Node> nodes;
 
    Graph(unsigned node_count, unsigned transition_count)
      : nodes(node_count, Node(transition_count)) {
    }
};
 
bool check(const Input &input, Graph &g) {
    for (unsigned node_pos = 0; node_pos < g.nodes.size(); ++node_pos) {
        g.nodes[node_pos].is_terminal = false;
    }
    // projdeme slova, která mají být přijímána
    for (unsigned i = 0; i < input.p.size(); ++i) {
        const std::vector<unsigned> &word = input.p[i];
 
        int node_pos = 0;
        bool skip = false;
        for (unsigned wp = 0; wp < word.size(); ++wp) {
            const unsigned letter = word[wp];
            node_pos = g.nodes[node_pos].transitions[letter];
            if (node_pos == undefined_transition) {
                // došli jsme v grafu někam, kde to ještě nemáme vygenerované
                // - toto slovo přeskočíme
                skip = true;
                break;
            }
        }
        if (skip) {
            continue;
        }
        g.nodes[node_pos].is_terminal = true;
    }
    // projdeme slova, která nemají být přijímána
    for (unsigned i = 0; i < input.n.size(); ++i) {
        const std::vector<unsigned> &word = input.n[i];
 
        int node_pos = 0;
        bool skip = false;
        for (unsigned wp = 0; wp < word.size(); ++wp) {
            const unsigned letter = word[wp];
            node_pos = g.nodes[node_pos].transitions[letter];
            if (node_pos == undefined_transition) {
                // došli jsme v grafu někam, kde to ještě nemáme vygenerované
                // - toto slovo přeskočíme
                skip = true;
                break;
            }
        }
        if (skip) {
            continue;
        }
        if (g.nodes[node_pos].is_terminal) {
            // toto slovo nemá být přijímáno, ale podle grafu je přijímáno,
            // takže tento graf není správný
            return false;
        }
    }
    // pokud vše prošlo, předpokládáme, že graf je
    // správný (automat přijímá co má a nepřijímá co nemá)
    return true;
}
 
bool dfa_exists_r(const Input &input, Graph &g, unsigned node_pos, unsigned trans_pos) {
    if (node_pos == g.nodes.size()) {
        return check(input, g);
    }
    if (trans_pos == input.letter_count) {
        return dfa_exists_r(input, g, node_pos + 1, 0);
    }
    if (!check(input, g)) {
        return false;
    }
    for (unsigned i = 0; i < g.nodes.size(); ++i) {
        g.nodes[node_pos].transitions[trans_pos] = i;
        if (dfa_exists_r(input, g, node_pos, trans_pos + 1)) {
            return true;
        }
    }
    g.nodes[node_pos].transitions[trans_pos] = undefined_transition;
    return false;
}
 
bool dfa_exists(unsigned node_count, const Input &input) {
    Graph g(node_count, input.letter_count);
    return dfa_exists_r(input, g, 0, 0);
}
 
std::vector<unsigned> read_word(unsigned &letter_count, std::vector<int> &map) {
    std::vector<unsigned> v;
    std::string line;
    getline(std::cin, line);
    for (unsigned k = 0; k < line.size(); ++k) {
        char c = line[k];
        if (c == '\n' || c == '\r') {
            break;
        }
        if (map.at(c) == -1) {
            map[c] = letter_count ++;
        }
        v.push_back(map[c]);
    }
    return v;
}
 
Input read_input() {
    Input input;
    std::vector<int> map(256, -1);
    std::string line;
    getline(std::cin, line);
    int p_count = atoi(line.c_str());
    for (int i = 0; i < p_count; ++i) {
        input.p.push_back(read_word(input.letter_count, map));
    }
    getline(std::cin, line);
    int n_count = atoi(line.c_str());
    for (int i = 0; i < n_count; ++i) {
        input.n.push_back(read_word(input.letter_count, map));
    }
    return input;
}
 
int main(int argc, char *argv[]) {
    try {
        Input input = read_input();
        for (int i = 1; i < 10; i++) {
            if (dfa_exists(i, input)) {
                std::cout << i << std::endl;
                break;
            }
        }
    } catch (const std::exception &e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}
courses/a4m33pal/zkouska2014_2.txt · Poslední úprava: 2025/01/03 18:29 (upraveno mimo DokuWiki)
Nahoru
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0