+ upd
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
void optimize(std::map<char, std::vector<std::string>>& map) {
|
||||||
|
std::set<char> exist;
|
||||||
|
std::stack<char> stack;
|
||||||
|
|
||||||
|
|
||||||
|
stack.push('S');
|
||||||
|
exist.insert('S');
|
||||||
|
|
||||||
|
while (!stack.empty()) {
|
||||||
|
char now = stack.top();
|
||||||
|
stack.pop();
|
||||||
|
|
||||||
|
for (const auto& str : map[now]) {
|
||||||
|
for (const auto& c : str) {
|
||||||
|
if (!('A' <= c && c <= 'Z')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (exist.find(c) == exist.end()) {
|
||||||
|
exist.insert(c);
|
||||||
|
stack.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = map.begin();
|
||||||
|
while (it != map.end()) {
|
||||||
|
if (exist.find(it->first) == exist.end()) {
|
||||||
|
it = map.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// std::vector<std::pair<char, std::string>> mas;
|
||||||
|
std::map<char, std::vector<std::string>> map;
|
||||||
|
char left;
|
||||||
|
std::string right;
|
||||||
|
|
||||||
|
while (std::cin >> left >> right) {
|
||||||
|
// mas.push_back(std::make_pair(left, right));
|
||||||
|
map[left].push_back(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
optimize(map);
|
||||||
|
|
||||||
|
// for (const auto& rule : mas) {
|
||||||
|
// if (map.find(rule.first) != map.end()) {
|
||||||
|
// std::cout << rule.first << " " << rule.second << std::endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (const auto& rules : map) {
|
||||||
|
for (const auto& rule : rules.second) {
|
||||||
|
std::cout << rules.first << " " << rule << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
На стандартный поток ввода программе подаётся выражение в польской записи. Выражение может содержать имена переменных и бинарные операции +, -, *, /. Имя переменной — это строчная латинская буква. Элементы ввода могут разделяться произвольным количеством пробельных символов.
|
||||||
|
|
||||||
|
Напечатайте введённое выражение в инфиксной записи. Для сохранения приоритетов бинарные операции заключите в скобки. Выражение напечатайте в одной строке текста без пробельных символов.
|
||||||
|
Examples
|
||||||
|
Input
|
||||||
|
|
||||||
|
abc++
|
||||||
|
|
||||||
|
Output
|
||||||
|
|
||||||
|
(a+(b+c))
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
bool is_operation(char c) {
|
||||||
|
return c == '+' || c == '-' || c == '*' || c == '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char c;
|
||||||
|
std::stack<std::string> stack;
|
||||||
|
|
||||||
|
while (std::cin >> c) {
|
||||||
|
if (is_operation(c)) {
|
||||||
|
std::string r = stack.top();
|
||||||
|
stack.pop();
|
||||||
|
|
||||||
|
std::string l = stack.top();
|
||||||
|
stack.pop();
|
||||||
|
|
||||||
|
stack.push("(" + l + c + r + ")");
|
||||||
|
} else {
|
||||||
|
stack.push(std::string(1, c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << stack.top() << std::endl;
|
||||||
|
|
||||||
|
stack.pop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
// Разбор журналов
|
||||||
|
|
||||||
|
// Реализуйте класс CFGrammar, который используется для представления контекстно-свободной грамматики и вычисления множеств First и Follow для её нетерминалов. Терминалами грамматики считаются строчные символы латинского алфавита, а нетерминалами - заглавные символы латинского алфавита.
|
||||||
|
|
||||||
|
// 1) У класса должен быть реализован метод add_rule(char, const std::string&) для добавления нового правила в грамматику. Первый аргумент представляет нетерминал, из которого выводится правило, и может иметь значения от "А" до "Z". Второй аргумент представляет само правило, выводимое из данного нетерминала и может быть строкой (возможно, пустой), состоящей из допустимых терминалов и нетерминалов.
|
||||||
|
|
||||||
|
// 2) У класса должен быть реализован метод get_first(), который возвращает ассоциативный массив (map или unordered_map), ключами которого являются нетерминалы грамматики, а значениями - множество символов, входящих в First от этого нетерминала. Допустимыми элементами множества являются терминалы и специальный символ '_' для обозначения пустой цепочки (эпсилон).
|
||||||
|
|
||||||
|
// 3) У класса должен быть реализован метод get_follow(), который возвращает ассоциативный массив (map или unordered_map), ключами которого являются нетерминалы грамматики, а значениями - множество символов, входящих в Follow от этого нетерминала. Допустимыми элементами множества являются терминалы и специальный символ '$' для обозначения конца строки.
|
||||||
|
|
||||||
|
// 4) У класса должен быть реализован метод is_ll1(), который возвращает true, если грамматика удовлетворяет критерию LL(1) и false в противном случае.
|
||||||
|
|
||||||
|
// После подстановки решения студента, следующий код должен работать и выдавать ожидаемый результат (см. пример ввода и вывода):
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <regex>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
bool is_terminal(char c) { return c >= 'a' && c <= 'z'; }
|
||||||
|
bool is_non_terminal(char c) { return c >= 'A' && c <= 'Z'; }
|
||||||
|
|
||||||
|
std::string set_to_canonical_string(const auto& set_of_chars, char special_symbol) {
|
||||||
|
std::string result;
|
||||||
|
bool has_special_symbol = false;
|
||||||
|
for (char c : set_of_chars) {
|
||||||
|
if (is_terminal(c))
|
||||||
|
result += c;
|
||||||
|
else
|
||||||
|
has_special_symbol = true;
|
||||||
|
}
|
||||||
|
std::sort(result.begin(), result.end());
|
||||||
|
if (has_special_symbol)
|
||||||
|
result += special_symbol;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here goes your submission
|
||||||
|
|
||||||
|
class CFGrammar {
|
||||||
|
private:
|
||||||
|
std::unordered_map<char, std::vector<std::string>> rules;
|
||||||
|
std::unordered_map<char, std::set<char>> first;
|
||||||
|
std::unordered_map<char, std::set<char>> follow;
|
||||||
|
|
||||||
|
void compute_first() {
|
||||||
|
bool changed;
|
||||||
|
do {
|
||||||
|
changed = false;
|
||||||
|
for (const auto& [non_terminal, productions] : rules) {
|
||||||
|
for (const auto& production : productions) {
|
||||||
|
bool nullable = true;
|
||||||
|
for (char symbol : production) {
|
||||||
|
if (is_terminal(symbol)) {
|
||||||
|
if (first[non_terminal].insert(symbol).second) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
nullable = false;
|
||||||
|
break;
|
||||||
|
} else if (is_non_terminal(symbol)) {
|
||||||
|
for (char c : first[symbol]) {
|
||||||
|
if (c != '_' && first[non_terminal].insert(c).second) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (first[symbol].count('_') == 0) {
|
||||||
|
nullable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nullable && first[non_terminal].insert('_').second) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_follow() {
|
||||||
|
follow.begin()->second.insert('$');
|
||||||
|
bool changed;
|
||||||
|
do {
|
||||||
|
changed = false;
|
||||||
|
for (const auto& [non_terminal, productions] : rules) {
|
||||||
|
for (const auto& production : productions) {
|
||||||
|
std::set<char> trailer = follow[non_terminal];
|
||||||
|
for (auto it = production.rbegin(); it != production.rend(); ++it) {
|
||||||
|
char symbol = *it;
|
||||||
|
if (is_non_terminal(symbol)) {
|
||||||
|
for (char c : trailer) {
|
||||||
|
if (follow[symbol].insert(c).second) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (first[symbol].count('_') == 1) {
|
||||||
|
trailer.insert(first[symbol].begin(), first[symbol].end());
|
||||||
|
trailer.erase('_');
|
||||||
|
} else {
|
||||||
|
trailer = first[symbol];
|
||||||
|
}
|
||||||
|
} else if (is_terminal(symbol)) {
|
||||||
|
trailer = { symbol };
|
||||||
|
} else {
|
||||||
|
trailer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add_rule(char non_terminal, const std::string& production) {
|
||||||
|
rules[non_terminal].push_back(production);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<char, std::set<char>> get_first() {
|
||||||
|
if (first.empty()) {
|
||||||
|
compute_first();
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<char, std::set<char>> get_follow() {
|
||||||
|
if (follow.empty()) {
|
||||||
|
compute_first();
|
||||||
|
compute_follow();
|
||||||
|
}
|
||||||
|
return follow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ll1() {
|
||||||
|
for (const auto& [non_terminal, productions] : rules) {
|
||||||
|
std::set<char> seen;
|
||||||
|
for (const auto& production : productions) {
|
||||||
|
std::set<char> first_set;
|
||||||
|
bool nullable = true;
|
||||||
|
for (char symbol : production) {
|
||||||
|
if (is_terminal(symbol)) {
|
||||||
|
first_set.insert(symbol);
|
||||||
|
nullable = false;
|
||||||
|
break;
|
||||||
|
} else if (is_non_terminal(symbol)) {
|
||||||
|
first_set.insert(first[symbol].begin(), first[symbol].end());
|
||||||
|
if (first[symbol].count('_') == 0) {
|
||||||
|
nullable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nullable) {
|
||||||
|
first_set.insert(follow[non_terminal].begin(), follow[non_terminal].end());
|
||||||
|
}
|
||||||
|
for (char c : first_set) {
|
||||||
|
if (seen.count(c)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seen.insert(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::string line;
|
||||||
|
std::regex rule_regex("^([A-Z])\\s*->\\s*([a-zA-Z]*)$");
|
||||||
|
|
||||||
|
CFGrammar grammar;
|
||||||
|
while (std::getline(std::cin, line)) {
|
||||||
|
std::smatch m;
|
||||||
|
if (std::regex_match(line, m, rule_regex)) {
|
||||||
|
grammar.add_rule(m[1].first[0], m[2]);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<char, std::string>> sorted_first;
|
||||||
|
for (auto& entry : grammar.get_first())
|
||||||
|
sorted_first.emplace_back(entry.first, set_to_canonical_string(entry.second, '_'));
|
||||||
|
std::sort(sorted_first.begin(), sorted_first.end());
|
||||||
|
|
||||||
|
std::cout << "First:" << std::endl;
|
||||||
|
for (auto& entry : sorted_first)
|
||||||
|
std::cout << entry.first << ": " << entry.second << std::endl;
|
||||||
|
|
||||||
|
std::vector<std::pair<char, std::string>> sorted_follow;
|
||||||
|
for (auto& entry : grammar.get_follow())
|
||||||
|
sorted_follow.emplace_back(entry.first, set_to_canonical_string(entry.second, '$'));
|
||||||
|
std::sort(sorted_follow.begin(), sorted_follow.end());
|
||||||
|
|
||||||
|
std::cout << "Follow:" << std::endl;
|
||||||
|
for (auto& entry : sorted_follow)
|
||||||
|
std::cout << entry.first << ": " << entry.second << std::endl;
|
||||||
|
|
||||||
|
std::cout << "is LL(1): " << (grammar.is_ll1() ? "Yes" : "No") << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Примеры
|
||||||
|
Входные данные
|
||||||
|
|
||||||
|
S -> ABC
|
||||||
|
A -> aA
|
||||||
|
A ->
|
||||||
|
B -> b
|
||||||
|
B -> C
|
||||||
|
C -> c
|
||||||
|
|
||||||
|
Результат работы
|
||||||
|
|
||||||
|
First:
|
||||||
|
A: a_
|
||||||
|
B: bc
|
||||||
|
C: c
|
||||||
|
S: abc
|
||||||
|
Follow:
|
||||||
|
A: bc
|
||||||
|
B: c
|
||||||
|
C: c$
|
||||||
|
S: $
|
||||||
|
is LL(1): Yes
|
||||||
|
*/
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
# Хуй знает что тут
|
||||||
|
|
||||||
|
## Задания
|
||||||
|
|
||||||
|
### Первое задание
|
||||||
|
|
||||||
|
```plain
|
||||||
|
L1 = {1^n 0^m 1^m 0^n | n, m > 0}
|
||||||
|
r = {(), a^m b^(n+m)} // выдать на выходе вместо 1010 aabb
|
||||||
|
```
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - 1A0
|
||||||
|
A - 1A0 | 0B1
|
||||||
|
B - 0B1 | _
|
||||||
|
```
|
||||||
|
|
||||||
|
Переводим в другую грамматику (в скобках моменты печати слова)
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - 1A(b)0
|
||||||
|
A - 1A(b)0 | 0(a)B(b)1
|
||||||
|
B - 0(a)B(b)1 | _
|
||||||
|
```
|
||||||
|
|
||||||
|
### Второе задание
|
||||||
|
|
||||||
|
```plain
|
||||||
|
L1 = {(c/d)a^n b^n | n> 0}
|
||||||
|
r = {(L1), 1^2n 0^(k+n) | k = |d|}
|
||||||
|
```
|
||||||
|
|
||||||
|
Описание языка:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - cS | dS | aAb
|
||||||
|
A - aAb | _
|
||||||
|
```
|
||||||
|
|
||||||
|
Преобразование
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - cS | dS(0) | a(11)A(0)b
|
||||||
|
A - a(11)A(0)b | _
|
||||||
|
```
|
||||||
|
|
||||||
|
### Третье задание
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - bA
|
||||||
|
A - aC
|
||||||
|
B - aBb | _
|
||||||
|
C - Bba | _
|
||||||
|
```
|
||||||
|
|
||||||
|
```plain
|
||||||
|
r = {(), b^k a ^ m, k = |b|, m = |a|}
|
||||||
|
```
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - (b)bA
|
||||||
|
A - aC(a)
|
||||||
|
B - (b)aBb(a) | _
|
||||||
|
C - (b)Bba(a) | _
|
||||||
|
```
|
||||||
|
|
||||||
|
## Перевод в польско-инверсную запись
|
||||||
|
|
||||||
|
```plain
|
||||||
|
E - T {+T}
|
||||||
|
T - F {*F<*>}
|
||||||
|
F - a<a>|b<b>|(E)
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void E() {
|
||||||
|
T();
|
||||||
|
while(c == '+') {gc(); T(); cout << '+';}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
из `a+a*b` получим `aab*+`
|
||||||
|
|
||||||
|
### Задача
|
||||||
|
|
||||||
|
(тут был граф)
|
||||||
|
|
||||||
|
описывающая грамматика:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - ccCa
|
||||||
|
C - cCd | B
|
||||||
|
B - b
|
||||||
|
```
|
||||||
|
|
||||||
|
грамматика, которая перевернёт:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
S - cc<a>C<cc>a
|
||||||
|
C - c<d>C<c>d | B
|
||||||
|
B - b<b>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Переводы записей
|
||||||
|
|
||||||
|
```plain
|
||||||
|
1) s = i * (--a+b++)
|
||||||
|
|
||||||
|
&s i &a -# &b #+ + * = ;
|
||||||
|
<!-- * (+ #+ -->
|
||||||
|
```
|
||||||
|
|
||||||
|
```plain
|
||||||
|
2) x = (a + b, a * b);
|
||||||
|
|
||||||
|
&x a b + ; a b * = ;
|
||||||
|
```
|
||||||
|
|
||||||
|
Переход в какое-то место программы: _,!
|
||||||
|
|
||||||
|
B, _, !F - переход по лжи (B == False)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (B) p1; else pe;
|
||||||
|
B 7 !F p1 8 ! p2
|
||||||
|
1 2 3 4 5 6 7 8
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
1) if ((x+1) > y) x = y; else y = (x-y) * 3;
|
||||||
|
2) while (i < 9) {s = 3 + f(i), i++;}
|
||||||
|
3) do {x = z = (x + y + 5) * b - 3/f; b++;} while(-x+y>0);
|
||||||
|
4) for (i = 0; i < n; i++) {a = b - c;}
|
||||||
|
```
|
||||||
|
|
||||||
|
```plain
|
||||||
|
if ((x+1) > y) x = y; else y = (x-y) * 3;
|
||||||
|
|
||||||
|
x 1 + y > !F 18 &x y = ; 22 ! &y x y - 3 * = ;
|
||||||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||||
|
```
|
||||||
|
|
||||||
|
```plain
|
||||||
|
while (i < 9) {s = 3 + f(i), i++;}
|
||||||
|
|
||||||
|
i 9 < 17 !F &s 3 i f = ; &i #+ ; 1 !
|
||||||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
||||||
|
```
|
||||||
|
|
||||||
|
``` plain
|
||||||
|
do {x = z = (x + y + 5) * b - 3/f; b++;} while(-x+y>0);
|
||||||
|
|
||||||
|
|
||||||
|
&a a b < _ !F a _ ! b = ;
|
||||||
|
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user