init commit

This commit is contained in:
2025-04-13 21:48:15 +03:00
commit 23255e9121
192 changed files with 12200 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
// #include <iostream>
// #include <array>
// #include <cstdint>
class BlackHole {
int mass;
public:
BlackHole(size_t mass) : mass(mass) {}
size_t get_mass() const {
return mass;
}
template <typename T>
void consume(T* arg) {
if (arg == nullptr) {
std::cout << "There is nothing to consume" << std::endl;
return;
}
size_t arg_mass = sizeof(*arg);
if (std::is_const<T>::value) {
std::cout << "Black hole consumed " << arg_mass << " const bytes" << std::endl;
} else {
std::cout << "Black hole consumed " << arg_mass << " non-const bytes" << std::endl;
}
mass += arg_mass;
delete arg;
return;
}
void consume(void* arg) {
throw std::runtime_error("Black hole has tried to consume void");
return;
}
void consume(const void* arg) {
throw std::runtime_error("Black hole has tried to consume void");
return;
}
void consume(BlackHole* arg) {
if (arg == this) {
throw std::runtime_error("Black hole has tried to consume itself");
return;
}
size_t arg_mass = arg->get_mass();
if (std::is_const<BlackHole>::value) {
std::cout << "Black hole consumed " << arg_mass << " const bytes" << std::endl;
} else {
std::cout << "Black hole consumed " << arg_mass << " non-const bytes" << std::endl;
}
mass += arg_mass;
delete arg;
return;
}
void consume(const BlackHole* arg) {
if (arg == this) {
throw std::runtime_error("Black hole has tried to consume itself");
return;
}
size_t arg_mass = arg->get_mass();
if (std::is_const<BlackHole>::value) {
std::cout << "Black hole consumed " << arg_mass << " const bytes" << std::endl;
} else {
std::cout << "Black hole consumed " << arg_mass << " non-const bytes" << std::endl;
}
mass += arg_mass;
delete arg;
return;
}
template <typename T>
void consume(T arg) {
throw std::runtime_error("Black hole has tried to consume non-pointer");
return;
}
~BlackHole() = default;
};
/*
Требуется реализовать класс BlackHole.
1) Конструктор класса должен принимать аргумент типа size_t, задающий массу чёрной дыры.
2) У класса должен быть метод get_mass() возвращающий текущую массу.
3) У класса должен быть шаблонный метод consume(arg), предназначенный для "поглощения" указателей (см. ниже) и способный принимать аргументы любых типов.
Вызов consume должен вести себя следующим образом.
1) Он должен выбрасывать исключение типа runtime_error (тексты исключений следует взять из примера вывода ниже) в следующих ситуациях:
- При передаче ему аргумента, не являющегося указателем
- Если переданный указатель указывает на void (константный или неконстантный)
- Если чёрная дыра пытается поглотить саму себя
2) Если в качестве аргумента передан нулевой указатель, следует напечатать "There is nothing to consume" и ничего не делать.
3) Если ни одно из выше перечисленных условий не сработало, то аргумент считается корректным указателем и для него нужно выполнить следующие действия:
- Определить "массу" аргумента. Для BlackHole масса определяется через вызов get_mass(), для остальных - через размер указываемого типа в байтах.
- Напечатать "Black hole consumed N non-const bytes", где вместо N нужно подставить массу аргумента. Если в качестве аргумента передан указатель на константный тип, то вместо non-const следует печатать const.
- Добавить массу аргумента к текущей массе чёрной дыры.
- Удалить аргумент через вызов delete.
При подстановке решения студента, следующий код должен работать:
*/
// int main() {
// BlackHole hole(100);
// std::cout << "The initial mass is " << hole.get_mass() << " bytes" << std::endl;
// hole.consume(new int64_t);
// hole.consume(const_cast <const int64_t*>(new int64_t));
// hole.consume(new int32_t);
// hole.consume(static_cast<char*>(nullptr));
// hole.consume(new BlackHole{ 50 });
// hole.consume(new std::array<char, 64>);
// try {
// hole.consume(5);
// }
// catch (std::runtime_error& err) {
// std::cout << "Error: " << err.what() << std::endl;
// }
// try {
// hole.consume(&hole);
// }
// catch (std::runtime_error& err) {
// std::cout << "Error: " << err.what() << std::endl;
// }
// try {
// hole.consume((void*) nullptr);
// }
// catch (std::runtime_error& err) {
// std::cout << "Error: " << err.what() << std::endl;
// }
// std::cout << "The total mass is: " << hole.get_mass() << " bytes" << std::endl;
// return 0;
// }
+105
View File
@@ -0,0 +1,105 @@
#include <iostream>
#include <fstream>
#include <regex>
#include <string>
#include <map>
#include <set>
/*
Количество слов
Напишите программу, которая для заданного ДКА и заданной максимальной длины N выводит общее количество слов не длинее N, допускаемых данным ДКА.
На вход программе подаётся описание ДКА в виде непустых строк следующих следующих видов.
1) Переход из состояния номер 1 в состояние номер 2 по символу "a":
[1] a [2]
2) Обозначение того, что состояние номер 3 является допускающим:
[[3]]
3) Явное объявление состояния под номером 4 (например, на случай если оно не фигурирует ни в каких переходах и не является допускающим):
[4]
После описания ДКА идёт пустая строка, за ней число N.
Номера состояний - это целые неотрицательные числа, в алфавит ДКА входят только строчные символы латинского алфавита.
Число N не может быть больше 100, а ответ помещается в тип size_t.
Начальным состоянием считается то, которое было первым объявлено в описании ДКА (либо в явном виде, либо при описании перехода).
Примеры
Входные данные в файле noMore.in
[0] a [1]
[1] a [0]
[1] b [0]
[[0]]
4
Результат работы в файле noMore.out
7
*/
int main() {
std::regex state_declaration_pattern(R"(\[(\d+)\])");
std::regex transition_pattern(R"(\[(\d+)\]\s*([a-z])\s*\[(\d+)\])");
std::regex accepting_state_pattern(R"(\[\[(\d+)\]\])");
std::map<int, std::map<char, int>> state_transitions;
std::set<int> accepting_states;
int start_state = -1;
std::ifstream Input("noMore.in");
std::string line;
while (std::getline(Input, line)) {
std::smatch match_result;
if (start_state == -1 && std::regex_match(line, match_result, state_declaration_pattern)) {
start_state = std::stoi(match_result[1].str());
} else if (std::regex_match(line, match_result, transition_pattern)) {
start_state = start_state == -1 ? std::stoi(match_result[1].str()) : start_state;
state_transitions[std::stoi(match_result[1].str())][match_result[2].str()[0]] = std::stoi(match_result[3].str());
} else if (std::regex_match(line, match_result, accepting_state_pattern)) {
accepting_states.insert(std::stoi(match_result[1].str()));
} else if (line.empty()) {
break;
}
}
int max_length;
Input >> max_length;
Input.close();
size_t total_count = 0;
std::vector<std::map<int, size_t>> dp_table(max_length + 1);
dp_table[0][start_state] = 1;
for (int length = 1; length <= max_length; ++length) {
for (const auto& [current_state, count] : dp_table[length - 1]) {
for (const auto& [transition_char, next_state] : state_transitions[current_state]) {
dp_table[length][next_state] += count;
}
}
}
for (int length = 0; length <= max_length; ++length) {
for (const auto& [state, count] : dp_table[length]) {
if (accepting_states.count(state)) {
total_count += count;
}
}
}
std::ofstream Output("noMore.out");
Output << total_count << std::endl;
Output.close();
return 0;
}
+117
View File
@@ -0,0 +1,117 @@
#include <iostream>
#include <fstream>
#include <regex>
#include <string>
#include <map>
#include <set>
/*
Количество слов
Напишите программу, которая для заданного ДКА и заданной максимальной длины N выводит общее количество слов не длинее N, допускаемых данным ДКА.
На вход программе подаётся описание ДКА в виде непустых строк следующих следующих видов.
1) Переход из состояния номер 1 в состояние номер 2 по символу "a":
[1] a [2]
2) Обозначение того, что состояние номер 3 является допускающим:
[[3]]
3) Явное объявление состояния под номером 4 (например, на случай если оно не фигурирует ни в каких переходах и не является допускающим):
[4]
После описания ДКА идёт пустая строка, за ней число N.
Номера состояний - это целые неотрицательные числа, в алфавит ДКА входят только строчные символы латинского алфавита.
Число N не может быть больше 100, а ответ помещается в тип size_t.
Начальным состоянием считается то, которое было первым объявлено в описании ДКА (либо в явном виде, либо при описании перехода).
Примеры
Входные данные в файле noMore.in
[0] a [1]
[1] a [0]
[1] b [0]
[[0]]
4
Результат работы в файле noMore.out
7
*/
int main() {
std::ifstream inputFile("noMore.in");
std::string line;
std::regex firstLinePattern(R"(\[(\d+)\])");
std::regex subsequentLinePattern(R"(\[(\d+)\]\s*([a-z])\s*\[(\d+)\])");
std::regex finalLinePattern(R"(\[\[(\d+)\]\])");
std::regex emptyLinePattern(R"(\s*)");
std::regex numLinePattern(R"(\d+)");
// Read the first line
int start_num = -1;
std::map<int, std::map<char, int>> transitions;
std::set<int> final_states;
int n = 0;
// Read subsequent lines
while (std::getline(inputFile, line)) {
std::smatch match;
if (std::regex_match(line, match, firstLinePattern)) {
if (start_num == -1) {
start_num = std::stoi(match[1].str());
}
} else if (std::regex_match(line, match, subsequentLinePattern)) {
if (start_num == -1) {
start_num = std::stoi(match[1].str());
}
int fromState = std::stoi(match[1].str());
char symbol = match[2].str()[0];
int toState = std::stoi(match[3].str());
transitions[fromState][symbol] = toState;
} else if (std::regex_match(line, match, finalLinePattern)) {
final_states.insert(std::stoi(match[1].str()));
} else if (std::regex_match(line, match, emptyLinePattern)) {
continue;
} else if (std::regex_match(line, match, numLinePattern)) {
n = std::stoi(match[0].str());
} else {
break;
}
}
inputFile.close();
size_t ans = 0;
std::vector<std::map<int, size_t>> dp(n + 1);
dp[0][start_num] = 1;
for (int k = 1; k <= n; ++k) {
for (const auto& [state, count] : dp[k - 1]) {
for (const auto& [symbol, nextState] : transitions[state]) {
dp[k][nextState] += count;
}
}
}
for (int k = 0; k <= n; ++k) {
for (const auto& [state, count] : dp[k]) {
if (final_states.count(state)) {
ans += count;
}
}
}
std::ofstream outputFile("noMore.out");
outputFile << ans << std::endl;
outputFile.close();
return 0;
}
+110
View File
@@ -0,0 +1,110 @@
#include <iostream>
#include <cstring>
int increment_counter() {
static int counter = 0;
return counter++;
}
struct Data {
public:
int value;
Data(int x = 42) : value(x) {}
Data(const Data& data) {
value = data.value;
}
~Data() {
// std::cout << "~Data() called " << std::endl;
increment_counter();
}
Data& operator=(const Data& data) {
value = data.value;
return *this;
}
friend std::ostream& operator<<(std::ostream& os, const Data data) {
os << data.value;
return os;
}
};
class DataBuffer {
Data* addr;
size_t size_buf;
friend void std::swap(DataBuffer& a, DataBuffer& b);
public:
DataBuffer(size_t size) {
// std::cout << "called11!" << std::endl;
size_buf = size;
addr = new Data[size_buf];
}
DataBuffer(const DataBuffer& data_buf) = delete;
const DataBuffer& operator=(const DataBuffer& data_buf) = delete;
DataBuffer(DataBuffer&& data_buf) noexcept : addr(data_buf.addr), size_buf(data_buf.size_buf) {
// std::cout << "Move constructor called!" << std::endl;
data_buf.addr = nullptr;
data_buf.size_buf = 0;
}
DataBuffer& operator=(DataBuffer&& data_buf) noexcept {
// std::cout << "Move assignment operator called!" << std::endl;
if (this != &data_buf) {
delete[] addr;
addr = data_buf.addr;
size_buf = data_buf.size_buf;
data_buf.addr = nullptr;
data_buf.size_buf = 0;
}
return *this;
}
~DataBuffer() {
// std::cout << "called1!" << std::endl;
delete[] addr;
}
size_t size() const {
return size_buf;
}
Data& operator[](const size_t ind) {
return addr[ind];
}
const Data& operator[](const size_t ind) const {
return addr[ind];
}
};
namespace std {
template<>
void swap<DataBuffer>(DataBuffer& a, DataBuffer& b) {
std::swap(a.addr, b.addr);
std::swap(a.size_buf, b.size_buf);
}
}
void print_buffer(const DataBuffer& buffer) {
for (size_t i = 0; i < buffer.size(); i++)
std::cout << "buffer[" << i << "] == " << buffer[i] << std::endl;
}
int main() {
{
DataBuffer buffer_1{ 5 }, buffer_2{ 3 };
std::cout << "buffer_1.size() == " << buffer_1.size() << std::endl;
std::cout << "buffer_2.size() == " << buffer_2.size() << std::endl;
for (size_t i = 0; i < buffer_2.size(); i++)
buffer_2[i] = i + 1;
std::cout << "buffer_1[0] == " << buffer_1[0].value << std::endl;
std::cout << "buffer_2[0] == " << buffer_2[0].value << std::endl;
std::swap(buffer_1, buffer_2);
// DataBuffer buffer_copy = buffer_1; // forbidden!
std::cout << "buffer_1.size() == " << buffer_1.size() << std::endl;
std::cout << "buffer_2.size() == " << buffer_2.size() << std::endl;
print_buffer(buffer_1);
}
std::cout << "~Data() called " << increment_counter() << " times" << std::endl;
return 0;
}
+45
View File
@@ -0,0 +1,45 @@
#include <iostream>
class C
{
unsigned long long x = 0;
bool last = false;
public:
C() {
if (std::cin >> x) {
return;
}
last = true;
}
~C() {
if (last) {
return;
}
std::cout << x << " ";
}
};
void
f() {
C c;
if (std::cin.eof()) {
return;
}
f();
return;
}
int
main() {
f();
std::cout << std::endl;
return 0;
}
+81
View File
@@ -0,0 +1,81 @@
/*
Сортировка
Необходимо реализовать функцию filter_sort, которая принимает контейнер с произвольным доступом к элементам и три лямбда-функции. Первая лямбда задаёт критерий фильтрации элементов контейнера, вторая - порядок первичной сортировки элементов, третья - вторичной сортировки. Файл с решением должен содержать только реализацию шаблонной функции filter_sort. Тип элементов контейнера при тестировании может быть любым.
После подстановки вашей реализации, приведенный ниже код должен работать (при тестировании код отличается) и выдавать для примера ввода ниже пример вывода ниже:
*/
#include <iostream>
#include <vector>
#include <string>
#include <optional>
#include <algorithm>
#include <iterator>
struct Student {
std::string full_name;
int group_no;
void print() const {
std::cout << group_no << " " << full_name << std::endl;
}
static std::optional<Student> read() {
Student student;
if (!(std::cin >> student.group_no))
return {};
std::cin >> std::ws;
if (!std::getline(std::cin, student.full_name))
return {};
return student;
}
};
// Your filter_sort is here!
template <class T, class Filter, class PSort, class SSort>
void filter_sort(T& mas, Filter filter, PSort psort, SSort ssort) {
auto it = std::remove_if(mas.begin(), mas.end(), [filter](auto a) { return !filter(a); });
std::stable_sort(mas.begin(), it, [ssort](auto a, auto b) { return ssort(a, b); });
std::stable_sort(mas.begin(), it, [psort](auto a, auto b) { return psort(a, b); });
mas.erase(it, mas.end());
}
int main() {
std::vector<Student> students;
while (auto student = Student::read())
students.push_back(*student);
filter_sort(students, // the container
[](Student& stud) { return stud.group_no >= 0; }, // filter
[](Student& stud_1, Student& stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort
[](Student& stud_1, Student& stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort
);
for (auto& student : students)
student.print();
return 0;
}
/*
Примеры
Входные данные
-100 Иванов Иван
300 Забугоркина Афродита
0 Смирнова Настя
0 Смирнова Анастасия
Результат работы
0 Смирнова Анастасия
0 Смирнова Настя
300 Забугоркина Афродита
*/
+90
View File
@@ -0,0 +1,90 @@
/*
Сортировка
Необходимо реализовать функцию filter_sort, которая принимает контейнер с произвольным доступом к элементам и три лямбда-функции. Первая лямбда задаёт критерий фильтрации элементов контейнера, вторая - порядок первичной сортировки элементов, третья - вторичной сортировки. Файл с решением должен содержать только реализацию шаблонной функции filter_sort. Тип элементов контейнера при тестировании может быть любым.
После подстановки вашей реализации, приведенный ниже код должен работать (при тестировании код отличается) и выдавать для примера ввода ниже пример вывода ниже:
*/
// #include <iostream>
// #include <vector>
// #include <string>
// #include <optional>
// #include <algorithm>
// #include <iterator>
// struct Student {
// std::string full_name;
// int group_no;
// void print() const {
// std::cout << group_no << " " << full_name << std::endl;
// }
// static std::optional<Student> read() {
// Student student;
// if (!(std::cin >> student.group_no))
// return {};
// std::cin >> std::ws;
// if (!std::getline(std::cin, student.full_name))
// return {};
// return student;
// }
// };
// Your filter_sort is here!
template <typename Container, typename Filter, typename PrimarySort, typename SecondarySort>
void filter_sort(Container& container, Filter filter, PrimarySort primary_sort, SecondarySort secondary_sort) {
auto it = std::remove_if(container.begin(), container.end(), [=](auto& item) { return !filter(item); });
container.erase(it, container.end());
std::stable_sort(container.begin(), container.end(), [=](auto item1, auto item2) { return secondary_sort(item1, item2); });
std::stable_sort(container.begin(), container.end(), [=](auto item1, auto item2) { return primary_sort(item1, item2); });
return;
}
// int main() {
// std::vector<Student> students;
// while (auto student = Student::read())
// students.push_back(*student);
// filter_sort(students, // the container
// [](Student& stud) { return stud.group_no >= 0; }, // filter
// // [](const Student stud_1, const Student stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort
// [](Student& stud_1, Student& stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort
// // [](const Student stud_1, const Student stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort
// [](Student& stud_1, Student& stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort
// );
// // filter_sort(students, // the container
// // [](Student& stud) { return stud.group_no >= 0; }, // filter
// // [](Student& stud_1, Student& stud_2) { return stud_1.group_no < stud_2.group_no; }, // primary sort
// // [](Student& stud_1, Student& stud_2) { return stud_1.full_name < stud_2.full_name; } // secondary sort
// // );
// for (auto& student : students)
// student.print();
// return 0;
// }
/*
Примеры
Входные данные
-100 Иванов Иван
300 Забугоркина Афродита
0 Смирнова Настя
0 Смирнова Анастасия
Результат работы
0 Смирнова Анастасия
0 Смирнова Настя
300 Забугоркина Афродита
*/
+137
View File
@@ -0,0 +1,137 @@
// #include <iostream>
// #include <type_traits>
// class ASTNode;
// class NodeOwner {
// ASTNode* node = nullptr;
// public:
// explicit NodeOwner(ASTNode* node) : node(node) {}
// NodeOwner(const NodeOwner&) = delete;
// NodeOwner& operator=(const NodeOwner&) = delete;
// NodeOwner(NodeOwner&& other) { std::swap(node, other.node); }
// NodeOwner& operator=(NodeOwner&& other) { std::swap(node, other.node); return *this; }
// ASTNode* operator->() { return node; }
// const ASTNode* operator->() const { return node; }
// operator bool() const { return (bool)node; }
// ~NodeOwner();
// };
/*
Реализации классов ASTNode, ASTNumberNode, ASTPlusNode и ASTMinusNode.
Реализации операторов operator+ и operator-.
*/
class ASTNode {
public:
virtual void print() {}
virtual int get_value() { return 0; }
virtual ~ASTNode() {}
};
class ASTNumberNode : ASTNode {
int value;
public:
ASTNumberNode(int value) : value(value) {}
static NodeOwner create(int value = 0) {
return NodeOwner(new ASTNumberNode(value));
}
void print() {
std::cout << value;
}
int get_value() {
return value;
}
~ASTNumberNode() = default;
};
class ASTPlusNode : ASTNode {
NodeOwner left, right;
public:
ASTPlusNode(NodeOwner left, NodeOwner right) : left(std::move(left)), right(std::move(right)) {}
static NodeOwner create(NodeOwner left, NodeOwner right) {
return std::move(NodeOwner(new ASTPlusNode(std::move(left), std::move(right))));
}
void print() {
std::cout << "(";
left->print();
std::cout << " + ";
right->print();
std::cout << ")";
}
int get_value() {
return left->get_value() + right->get_value();
}
~ASTPlusNode() = default;
};
class ASTMinusNode : ASTNode {
NodeOwner left, right;
public:
ASTMinusNode(NodeOwner left, NodeOwner right) : left(std::move(left)), right(std::move(right)) {}
static NodeOwner create(NodeOwner left, NodeOwner right) {
return std::move(NodeOwner(new ASTMinusNode(std::move(left), std::move(right))));
}
void print() {
std::cout << "(";
left->print();
std::cout << " - ";
right->print();
std::cout << ")";
}
int get_value() {
return left->get_value() - right->get_value();
}
~ASTMinusNode() = default;
};
NodeOwner operator+(NodeOwner left, NodeOwner right) {
return std::move(NodeOwner(ASTPlusNode::create(std::move(left), std::move(right))));
}
NodeOwner operator-(NodeOwner left, NodeOwner right) {
return std::move(NodeOwner(ASTMinusNode::create(std::move(left), std::move(right))));
}
// NodeOwner::~NodeOwner() {
// if (node)
// delete node;
// }
// int main() {
// // static_assert(std::is_same::value, "ASTNumberNode::create() must return NodeOwner value");
// // static_assert(std::is_same::value, "ASTPlusNode::create() must return NodeOwner value");
// // static_assert(std::is_same::value, "(NodeOwner + NodeOwner) must return NodeOwner value");
// auto expr_1 = ASTPlusNode::create(
// ASTNumberNode::create(1),
// ASTMinusNode::create(
// ASTNumberNode::create(2),
// ASTNumberNode::create(3)
// )
// );
// expr_1->print();
// std::cout << " = " << expr_1->get_value() << std::endl;
// auto expr_2 = ASTNumberNode::create(4) - ASTNumberNode::create(5) + ASTNumberNode::create(6);
// expr_2->print();
// std::cout << " = " << expr_2->get_value() << std::endl;
// return 0;
// }
+69
View File
@@ -0,0 +1,69 @@
// #include <iostream>
// #include <memory>
// #include <list>
// #include <vector>
// struct Element {
// int value;
// Element(int value) : value(value) {}
// };
// Реализация функции make_safe_vector()
template <typename T>
std::vector<std::unique_ptr<Element>> make_safe_vector(T&& container) {
std::vector<std::unique_ptr<Element>> result;
for (auto& el : container)
result.emplace_back(std::move(el));
container.clear();
return result;
}
// int main() {
// std::vector<Element*> unsafe_vector;
// unsafe_vector.emplace_back(new Element(0));
// unsafe_vector.emplace_back(new Element(42));
// unsafe_vector.emplace_back(new Element(900));
// auto safe_vector_1 = make_safe_vector(unsafe_vector);
// unsafe_vector.push_back(new Element(99));
// auto safe_vector_2 = make_safe_vector(safe_vector_1);
// auto safe_vector_3 = make_safe_vector(std::list<Element*>{new Element(1), new Element(2), new Element(3)});
// std::cout << "unsafe_vector: " << std::endl;
// for (auto& el : unsafe_vector) {
// std::cout << el->value << std::endl;
// delete el;
// }
// std::cout << "safe_vector_1: " << std::endl;
// for (auto& el : safe_vector_1)
// std::cout << el->value << std::endl;
// std::cout << "safe_vector_2: " << std::endl;
// for (auto& el : safe_vector_2)
// std::cout << el->value << std::endl;
// std::cout << "safe_vector_3: " << std::endl;
// for (auto& el : safe_vector_3)
// std::cout << el->value << std::endl;
// }
/*
unsafe_vector:
99
safe_vector_1:
safe_vector_2:
0
42
900
safe_vector_3:
1
2
3
*/
+72
View File
@@ -0,0 +1,72 @@
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <algorithm>
#include <fstream>
int main() {
std::map<int, std::map<char, int>> trans;
std::set<int> accept_states;
int init_state = -1;
std::ifstream Input("noMore.in");
std::string str;
while (std::getline(Input, str)) {
if (str.empty()) break;
if (str.find("[[") != std::string::npos) {
int state;
sscanf(str.c_str(), "[[%d]]", &state);
accept_states.insert(state);
if (init_state == -1) {
init_state = state;
}
} else if (std::count(str.begin(), str.end(), '[') == 2) {
int left_state, right_state;
char symbol;
sscanf(str.c_str(), "[%d] %c [%d]", &left_state, &symbol, &right_state);
if (init_state == -1) {
init_state = left_state;
}
trans[left_state][symbol] = right_state;
} else {
int state;
sscanf(str.c_str(), "[%d]", &state);
if (init_state == -1) {
init_state = state;
}
}
}
int N;
Input >> N;
std::vector<std::map<int, size_t>> dp(N + 1);
dp[0][init_state] = 1;
for (int k = 1; k <= N; ++k) {
for (auto& [state, count] : dp[k - 1]) {
for (auto& [symbol, right_state] : trans[state]) {
dp[k][right_state] += count;
}
}
}
size_t ans = 0;
for (int k = 0; k <= N; ++k) {
for (auto& [state, count] : dp[k]) {
if (accept_states.count(state)) {
ans += count;
}
}
}
std::ofstream Output("noMore.out");
Output << ans << std::endl;
Output.close();
Input.close();
return 0;
}