- Решение каждой задачи лежит в собственной гит ветке
Реализуйте алгоритм быстрой сортировки произвольных данных в функции
func qsort(n int,
less func(i, j int) bool,
swap func(i, j int)) {
...
}
В качестве параметров функция qsort
должна принимать:
-
n
— количество сортируемых записей, -
less
— функцию сравнения$i$ -той и$j$ -той записи, -
swap
— функцию обмена$i$ -той и$j$ -той записи.
Составьте программу qsort.go
, демонстрирующую работоспособность функции
qsort
.
Реализуйте алгоритмы перевода текста из UTF-32 в UTF-8, и обратно. Алгоритмы должны быть оформлены в виде двух функций:
func encode(utf32 []rune) []byte {
...
}
func decode(utf8 []byte) []rune {
...
}
Функция encode
принимает в качестве параметра текст в виде массива
кодовых точек и возвращает образ этого текста в UTF-8. Функция decode
выполняет обратное преобразование. Правила кодирования текста в UTF-8
приведены в таблице:
Код символа в Unicode | 1 | 2 | 3 | 4 |
---|---|---|---|---|
0 0000 0000 0000 0xxx xxxx | 0xxx xxxx | — | — | — |
0 0000 0000 0yyy yyxx xxxx | 110y yyyy | 10xx xxxx | — | — |
0 0000 zzzz yyyy yyxx xxxx | 1110 zzzz | 10yy yyyy | 10xx xxxx | — |
u uuzz zzzz yyyy yyxx xxxx | 1111 0uuu | 10zz zzzz | 10yy yyyy | 10xx xxxx |
Составьте программу utf8.go
, демонстрирующую работоспособность функций
decode
и encode
. Проверьте правильность результатов работы функций
с помощью встроенных средств Go.
Реализуйте алгоритм сложения натуральных чисел, представленных в виде
массива цифр в системе счисления по основанию
func add(a, b []int32, p int) []int32 {
...
}
Составьте программу add.go
, демонстрирующую работоспособность функции
add
.
Составьте программу gauss.go
, выполняющую решение системы линейных
алгебраических уравнений в рациональных числах методом Гаусса.
Формат входных данных:
Программа должна считывать из входного потока число
Формат результата работы программы:
Если система не имеет решения, следует выводить фразу «No solution
».
Если решение существует, программа должна печатать в выходной поток
Например, если на вход программы подаётся
3
-4 -1 8 2
7 -7 7 3
5 -1 -4 7
то на выходе мы получаем
377/21
214/7
274/21
Польская запись — это форма записи арифметических, логических и алгебраических выражений, в которой операция располагается слева от операндов. Выражения в польской записи могут обходиться без скобок, однако мы оставим скобки для наглядности.
Например, выражение
(* 5 (+ 3 4))
Пусть в нашем случае выражения состоят из чисел от 0
до 9
, круглых
скобок и трёх знаков операций: плюс, минус и звёздочка (умножить).
Требуется составить программу polish.go
, вычисляющую значение выражения.
Пусть выражения в польской записи состоят из имён переменных (от a
до z
),
круглых скобок и трёх знаков операций: #
, $
и @
(смысл операций
мы определять не будем).
Выражения могут содержать повторяющиеся подвыражения. Экономное вычисление таких выражений подразумевает, что повторяющиеся подвыражения вычисляются только один раз.
Требуется составить программу econom.go
, вычисляющую количество операций,
которые нужно выполнить для экономного вычисления выражения. Примеры работы
программы приведены в таблице:
Выражение | Количество операций |
---|---|
x |
0 |
($xy) |
1 |
($(@ab)c) |
2 |
(#i($jk)) |
2 |
(#($ab)($ab)) |
2 |
(@(#ab)($ab)) |
3 |
(#($a($b($cd)))(@($b($cd))($a($b($cd))))) |
5 |
(#($(#xy)($(#ab)(#ab)))(@z($(#ab)(#ab)))) |
6 |
Пусть идентификатор — это последовательность латинских букв и цифр, начинающаяся с буквы.
Известно, что в некоторой строке записаны идентификаторы, разделённые произвольным количеством пробелов. При этом строка может начинаться и заканчиваться произвольным количеством пробелов. Назовём такую строку предложением.
Лексический анализ предложения заключается в выделении из него последовательности записанных в нём идентификаторов. В результате лексического анализа получается массив целых чисел, каждое из которых соответствует одному из идентификаторов. Целые числа назначаются идентификаторам произвольно, но так, чтобы разным идентификаторам соответствовали разные числа, а равным идентификаторам — одинаковые числа.
Пример. Пусть дано предложение
alpha x1 beta alpha x1 y
Тогда на выходе лексического анализатора может получиться последовательность чисел
1 2 3 1 2 4
Здесь число 1
соответствует идентификатору alpha
, число 2
— идентификатору
x1
, число 3
— идентификатору beta
, а число 4
— идентификатору y
.
Необходимо разработать функцию lex, выполняющую лексический анализ предложения:
func lex(sentence string, array AssocArray) []int {
...
}
В качестве первого параметра функция lex
принимает предложение,
а второй параметр задаёт ассоциативный массив, который должен быть использован
внутри функции для хранения соответствия идентификаторов и целых чисел.
Ассоциативный массив, который можно передавать в функцию lex
, должен
реализовывать интерфейс AssocArray
:
type AssocArray interface {
Assign(s string, x int)
Lookup(s string) (x int, exists bool)
}
Метод Assign
добавляет в ассоциативный массив словарную пару.
Метод Lookup
выполняет поиск словарной пары по ключу и возвращает
два значения: x
и exists
. Если словарной пары с указанным ключом
в массиве нет, то exists
принимает значение false
. В противном случае
exists
равен true
, а x
— связанное с ключом значение.
Составьте программу lex.go
, демонстрирующую работоспособность функции
lex
. В качестве ассоциативных массивов для тестирования функции lex
нужно использовать список с пропусками и АВЛ-дерево.
Составьте программу arith.go
, вычисляющую значение скобочного арифметического
выражения.
Арифметическое выражение считывается из аргументов командной строки
и представляет собой строку, содержащую целые числа от 0 до 5/2
даёт 2
, а не 2.5
. Пробелы не несут никакого
смысла и должны игнорироваться программой.
Примеры выражений, которые могут быть поданы на вход программе:
-x * (x+10) * (128/x-5)
Length * Height * Depth
Грамматика для арифметических выражений записывается как
<E> ::= <E> + <T> | <E> - <T> | <T>.
<T> ::= <T> * <F> | <T> / <F> | <F>.
<F> ::= <number> | <var> | ( <E> ) | - <F>.
Здесь number
и var
обозначают множества
терминальных символов, соответствующих числам и именам переменных.
После удаления левой рекурсии получается LL(1)-грамматика
<E> ::= <T> <E'>.
<E'> ::= + <T> <E'> | - <T> <E'> | .
<T> ::= <F> <T'>.
<T'> ::= * <F> <T'> | / <F> <T'> | .
<F> ::= <number> | <var> | ( <E> ) | - <F>.
Алгоритм вычисления значения выражения должен быть разбит на две части: лексический анализатор и синтаксический анализатор.
Задачей лексического анализатора является разбиение арифметического
выражения на лексемы, то есть выделение в нём числовых констант, имён
переменных, знаков операций и круглых скобок. Пробелы во время лексического
анализа пропускаются. Каждая лексема представляется в виде экземпляра
структуры Lexem
:
type Lexem struct {
Tag
Image string
}
Здесь Image
— подстрока арифметического выражения, соответствующая
распознанной лексеме, а Tag
— целочисленный код, задающий тип лексемы:
type Tag int
const (
ERROR Tag = 1 << iota // Неправильная лексема
NUMBER // Целое число
VAR // Имя переменной
PLUS // Знак +
MINUS // Знак -
MUL // Знак *
DIV // Знак /
LPAREN // Левая круглая скобка
RPAREN // Правая круглая скобка
)
Значения кодов лексем образуют степени двойки, чтобы можно было эффективно
проверять принадлежность текущей лексемы некоторому множеству лексем.
Например, если lx
— переменная, в которой хранится текущая лексема,
то проверить, является ли она аддитивной арифметической операцией,
можно следующим образом:
if lx.Tag & (PLUS | MINUS) != 0 {
...
}
Лексический анализатор должен выполняться в отдельной go-программе, получающей на вход арифметическое выражение и канал лексем и отправляющей распознанные лексемы в этот канал:
func lexer(expr string, lexems chan Lexem) {
...
}
Синтаксический анализатор должен быть составлен методом рекурсивного спуска по приведённой LL(1)-грамматике.
Программа должна запрашивать у пользователя значения переменных, входящих
в выражение, и выводить в стандартный поток вывода значение выражения
или сообщение «error
», если выражение содержит синтаксическую
ошибку. Если некоторая переменная входит в выражение многократно,
её значение всё равно должно запрашиваться только один раз.
Составьте программу, выполняющую построение графа делителей натурального
числа
Вершинами графа делителей являются все делители числа
Число
Составьте программу, разделяющую кандидатов на две группы
для участия в экспедициях. Если такое разделение невозможно, программа
должна выводить сообщение «No solution
». В противном случае, программа
должна выводить номера кандидатов, принадлежащих первой группе. Первой
группой мы будем считать группу, в которой меньше кандидатов.
Естественно, хорошо написанная программа должна стремиться к тому, чтобы размеры групп не очень сильно отличались. Поэтому, если возможно несколько разбиений на группы, программа должна выбирать разбиение с минимальной разностью количеств кандидатов в группах. При этом в случае, если разбиений с минимальной разницей всё равно получается несколько, для определённости выбирается разбиение, в котором первая группа лексикографически меньше, чем первые группы остальных разбиений.
Программа должна считывать со стандартного потока ввода количество
кандидатов и матрицу размера
8
- - + - - - - -
- - - + - - - -
+ - - - - - - +
- + - - - + - -
- - - - - - - -
- - - + - - - -
- - - - - - - +
- - + - - - + -
программа должна выводить
1 2 6 8
Составьте программу, выполняющую поиск наибольшей компоненты связности в неориентированном мультиграфе. Наибольшей считается компонента, содержащая максимальное количество вершин. Если две или более компоненты содержат одинаковое количество вершин, то выбирается та из них, в которой больше рёбер. Если же и это не позволяет однозначно выбрать наибольшую компоненту, следует предпочесть компоненту, содержащую минимальную по номеру вершину.
Программа должна считывать со стандартного потока ввода количество вершин
графа
Программа должна формировать в стандартном потоке вывода описание графа в формате DOT. При этом вершины графа должны быть помечены своими номерами, и, кроме того, вершины и рёбра наибольшей компоненты должны быть раскрашены красным цветом.
Пример входных данных:
7
8
0 1
0 5
1 5
1 4
5 4
2 3
3 6
Программа должна использовать представление графа в виде списка инцидентности.
Составьте программу, определяющую количество мостов в неориентированном простом графе.
Программа должна считывать со стандартного потока ввода количество вершин
графа
Программа должна хранить граф в памяти в виде списков инцидентности.
Мы будем называть расстоянием от вершины
Составьте программу, выполняющую поиск всех вершин неориентированного простого
графа, равноудалённых от вершин
Программа должна считывать со стандартного потока ввода количество вершин графа
В результате работы программы в стандартном потоке вывода должна находиться отсортированная по возрастанию последовательность номеров вершин графа, равноудалённых от опорных вершин. Если таких вершин нет, программа должна выводить «минус».
Программа должна хранить граф в памяти в виде списков инцидентности.
Составьте программу, реализующую алгоритм Крускала для вычисления минимальной суммарной длины дорожек в парке аттракционов. Дорожки должны быть проложены таким образом, чтобы между любыми двумя аттракционами существовал маршрут.
Программа должна считывать со стандартного потока ввода количество аттракционов и их координаты. При этом координаты каждого аттракциона задаются парой целых чисел (в декартовой системе).
Программа должна выводить в стандартный поток вывода минимальную суммарную длину дорожек с точностью до двух знаков после запятой.
Например, для входных данных
12
2 4
2 5
3 4
3 5
6 5
6 6
7 5
7 6
5 1
5 2
6 1
6 2
программа должна выводить число 14.83
.
На строительном участке нужно создать телефонную сеть, соединяющую все бытовки. Для того, чтобы телефонные линии не мешали строительству, их решили проводить вдоль дорог. Составьте программу, реализующую алгоритм Прима для вычисления минимальной общей длины телефонных линий для указанной конфигурации участка. Граф конфигурации участка должен быть представлен в программе в виде списка инцидентности.
Программа должна считывать со стандартного потока ввода количество
бытовок
Программа должна выводить в стандартный поток вывода минимальную общую длину телефонных линий.
Например, для входных данных
7
10
0 1 200
1 2 150
0 3 100
1 4 170
1 5 180
2 5 100
3 4 240
3 6 380
4 6 210
5 6 260
программа должна выводить число 930
.
Пусть
База — это подмножество вершин орграфа, обладающее следующими свойствами:
- каждая вершина орграфа достижима, по крайней мере, из одной вершины базы;
- в базе нет вершин, достижимых из других вершин базы.
Очевидно, что в базе не может быть двух вершин, принадлежащих одной и той же компоненте сильной связности.
Также нетрудно доказать, что в ациклическом орграфе существует только одна база. Она состоит из всех вершин с полустепенью захода, равной 0.
С учётом вышесказанного поиск баз в орграфе можно проводить в следующем порядке:
- найти все компоненты сильной связности орграфа;
- построить его конденсацию;
- найти базу конденсации;
- из каждой компоненты сильной связности, образующей вершину базы конденсации, взять по одной вершине.
Составьте программу, вычисляющую базу заданного орграфа.
Программа должна считывать со стандартного потока ввода количество
вершин орграфа
Для обеспечения уникальности ответа из компоненты сильной связности, образующей вершину базы конденсации, следует брать вершину с минимальным номером.
Программа должна выводить в стандартный поток вывода номера вершин базы, отсортированные в порядке возрастания.
Например, для входных данных
22
33
0 8 1 3 1 10 2 11 2 13 3 14
4 6 4 16 5 17 6 19 8 1 8 9
9 0 9 2 10 1 10 4 11 12 12 2
12 4 13 5 13 12 14 15 15 3 15 6
16 4 16 7 17 7 17 18 18 5 19 6
20 21 21 18 21 20
программа должна выводить
0 20
Рассмотрим простой язык программирования. Программа на этом языке представляет собой последовательность функций. Каждая функция имеет фиксированное количество целочисленных формальных параметров и возвращает целое число. Телом функции является единственное выражение, позволяющее выполнять над параметрами и целыми числами арифметические операции, операции сравнения и тернарную операцию выбора, а также вызывать функции.
Например, функция вычисления факториала числа на нашем языке может быть записана как
fact(x) := x=0 ? 1 : x*fact(x-1);
Более сложный пример демонстрирует функцию fib
, вычисляющую
fib(n) := fibrec(1,1,n);
fibrec(a,b,n) := n=1 ? a : fibrec(b,a+b,n-1);
Приведём формальное описание нашего языка.
Пусть программа состоит из лексем, разделённых произвольным (возможно, нулевым) количеством пробелов или символов перевода строки. При этом лексема — это либо идентификатор (имя формального параметра или имя функции), либо числовая константа, либо специальный символ.
Идентификатор — это непустая последовательность латинских букв и десятичных
цифр, начинающаяся с буквы. В БНФ грамматики нашего языка идентификаторы будут
обозначаться нетерминалом <ident>
.
Числовая константа — это непустая последовательность десятичных цифр. В БНФ мы
будем использовать нетерминал <number>
для обозначения числовой константы.
Латинская буква не может располагаться в тексте программы непосредственно после
числовой константы.
Специальные символы нашего языка включают знаки арифметических операций («+
»,
«-
», «*
», «/
»), знаки оперций сравнения («=
», «<>
», «<
», «>
»,
«<=
», «>=
»), знаки тернарной операции («?
» и «:
»), а также круглые
скобки, запятую, точку с запятой и знак «:=
», отделяющий заголовок функции
от её тела.
Согласно грамматике нашего языка, программа — это последовательность функций:
<program> ::= <function> <program>.
Объявление функции начинается с имени функции, за которым в круглых скобках
следует список формальных параметров, знак «:=
» и выражение, кодирующее тело
функции. Заканчивается объявление функции точкой с запятой.
<function> ::= <ident> ( <formal-args-list> ) := <expr> ; .
Список формальных параметров представляет собой список имен параметров, разделённых запятыми:
<formal-args-list> ::= <ident-list> | .
<ident-list> ::= <ident> | <ident> , <ident-list>.
Выражение — это либо выражение выбора, использующее тернарную операцию в духе языка C, либо выражение сравнения:
<expr> ::=
<comparison_expr> ? <comparison_expr> : <expr>
| <comparison_expr>.
Выражение сравнения представляет собой либо сравнение двух арифметичеких выражений, либо просто одно арифметическое выражение:
<comparison_expr> ::=
<arith_expr> <comparison_op> <arith_expr>
| <arith_expr>.
<comparison_op> ::= = | <> | < | > | <= | >= .
Арифметическое выражение определяется следующими правилами грамматики:
<arith_expr> ::=
<arith_expr> + <term>
| <arith_expr> - <term>
| <term>.
<term> ::=
<term> * <factor>
| <term> / <factor>
| <factor>.
<factor> ::=
<number>
| <ident>
| <ident> ( <actual_args_list> )
| ( <expr> )
| - <factor>.
Список фактических параметров определяется как список выражений, разделённых запятыми:
<actual_args_list> ::= <expr-list> | .
<expr-list> ::= <expr> | <expr> , <expr-list>.
Предположим, что готовится к выходу вторая версия нашего языка, в которую
добавили модульность. Теперь мы можем оформить некоторый набор функций в виде
отдельного файла, откомпилировать этот файл и затем просто подключать его
к другим программам и модулям. Особенностью реализации модульности в нашем
языке будет невозможность циклического подключения модулей: например, нельзя
подключить модуль
Составьте программу, выполняющую оценку максимального числа модулей, на которые может быть разбита некоторая программа, написанная на нашем языке.
Программа должна считывать оцениваемую программу со стандартного потока ввода
и выводить в стандартный поток вывода максимальное количество модулей или слово
«error
», если программа содержит ошибки.
Обратите внимание на то, что перед разработкой синтаксического анализатора необходимо удалить из приведённой выше грамматики левую рекурсию и факторизовать часть правил, чтобы получилась LL(1)-грамматика.
Метод критичекого пути используется в управлении проектами для планирования расписания осуществляемых работ.
Работой мы будем называть составную часть проекта, имеющую название и продолжительность.
Говорят, что одна работа зависит от другой работы, если она не может начаться до завершения этой другой работы. Тем самым, на множестве работ определено отношение частичного порядка.
Сетевой график — это ациклический орграф, вершинами которого являются
работы, а дуги задают их частичный порядок, а именно: дуга исходит из вершины
Перед нами стоит задача определения минимально возможной продолжительности проекта при условии, что независимые работы можно неограниченно распараллеливать. Решение задачи сводится к поиску критического пути, а именно — пути в сетевом графике, имеющем максимальную сумму продолжительностей входящих в него работ.
Составьте программу, вычисляющую критический путь в сетевом графике. В случае,
если языком реализации программы выбран язык Java, то точкой входа в программу
должен являться метод main
класса Cpm
.
Формат входных данных Программа должна считывать описание сетевого графика из стандартного потока ввода. Описание состоит из предложений, разделённых точкой с запятой. Каждое предложение записывается как последовательность зависимых работ:
работа < работа < ... < работа
Знак «<
» в предложении обозначает описанное выше отношение частичного порядка
на множестве работ, т.е. для каждой пары соседних работ в предложении
справедливо, что работа, расположенная слева от «<
», предшествует работе,
расположенной справа.
Естественно, что одна и та же работа может несколько раз присутствовать
в описании. При этом её первое вхождение записывается как
«имя(продолжительность)
», а все последующие вхождения записываются просто
как «имя
». Здесь «имя
» — это идентификатор работы, представляющий собой
последовательность латинских букв и цифр, начинающуюся с буквы.
Продолжительность работы задаётся неотрицательным целым десятичным числом.
Формат выходных данных Программа должна выводить в стандартный поток вывода описание сетевого графика в виде орграфа в формате DOT. Вершины критического пути и соединяющие их дуги должны быть отмечены красным цветом. Если сетевой график содержит несколько критических путей, все они должны быть отмечены.
Учитывая, что формат входных данных не гарантирует того, что сетевой график получится ациклическим, программа должна уметь обрабатывать циклические зависимости работ. Такие работы по понятным причинам не могут быть никогда выполнены и, следовательно, не могут входить в критический путь.
Рассмотрим модель машинного языка, состоящую из трёх команд: ACTION
, JUMP
и BRANCH
. Пусть команда ACTION
обозначает любую инструкцию машинного языка,
после выполнения которой управление передаётся на следующую инструкцию,
а команды JUMP
и BRANCH
означают безусловный и условный переход,
соответственно. Тем самым, в нашей модели мы абстрагируемся от деталей
машинного языка, не касающихся передачи управления.
Пусть в первой строчке программы на нашем модельном языке записано количество
команд
метка команда операнд
Здесь метка — это уникальное целое число, а команда — это ACTION
, JUMP
или
BRANCH
. При этом команда ACTION
не имеет операнда, а команды JUMP
и BRANCH
имеют один операнд — метку команды, на которую нужно передать
управление. Подразумевается, что команда JUMP
всегда осуществляет переход
на указанную метку, а команда BRANCH
выполняет проверку некоторого условия,
от которого мы в нашей модели абстрагируемся, и передаёт управление
на указанную метку только в случае истинности этого условия.
Приведём пример программы на нашем модельном языке:
6
10 ACTION
20 ACTION
30 BRANCH 60
40 ACTION
50 ACTION
60 JUMP 20
Для любой программы можно построить управляющий граф
Отметим, что программа может содержать так называемые «мёртвые» команды, которые не достижимы из корня. Они в управляющий граф не включаются.
Пусть дана некоторая вершина
- подграф
$L$ включает вершину$h$ и ещё как минимум одну вершину; - вершина
$h$ доминирует над всеми остальными вершинами подграфа$L$ ; - любые две вершины подграфа
$L$ взаимно достижимы.
Если подграф
Нетрудно доказать два свойства натуральных циклов, позволяющих идентифицировать их в управляющем графе:
- вершина
$x$ управляющего графа$G$ является заголовком натурального цикла тогда и только тогда, когда в вершину$x$ входит хотя бы одна дуга, исходящая из вершины, над которой доминирует$x$ ; - вершина
$x$ не может быть заголовком сразу нескольких натуральных циклов.
Составьте программу, вычисляющую количество натуральных циклов в программе на модельном языке.
Пусть имеется некоторый набор формул, задающих зависимости между переменными.
Например, объём
V = S*h / 3
S = a * b
a, b = 10, 15
h = (a + b) / 2
Обратите внимание на то, что каждая формула состоит из левой и правой частей,
разделённых знаком «=
». Левая часть является списком переменных, а правая
часть — списком соответствующих этим переменным выражений. Переменные в левой
части и выражения в правой части разделяются запятыми.
Формулы могут быть записаны в любом порядке, но, если в них нет циклических зависимостей, их можно расположить в порядке, в котором нужно выполнять вычисления.
Составьте программу, осуществляющую топологическую сортировку формул.
Для решения задачи нужно построить орграф, вершинами которого являются формулы,
а дуги задают зависимости между ними. То есть, если формула
Формулы подаются в программу через стандартный потока ввода. Они отделяются друг от друга символом перевода строки. Выражения в составе формул содержат знаки четырёх арифметических операций, круглые скобки, десятичные числа и имена переменных. Имя переменной — это последовательность латинских букв и десятичных цифр, начинающаяся с буквы.
Программа должна выводить сообщение «syntax error
», если какая-нибудь формула
содержит синтаксическую ошибку, или если некоторая переменная присутствует
в левой части нескольких формул, или если не существует формулы для вычисления
какой-нибудь переменной.
Программа должна выводить сообщение «cycle
» в случае обнаружения циклической
зависимости формул. Для обнаружения циклической зависимости следует проверять
наличие обратных дуг при обходе графа в глубину. Напомним, что обратная дуга
ведёт в «серую» вершину.
Если ошибки в формулах не обнаружены, то программа должна выводить в стандартный поток вывода отсортированный набор формул. В случае существования нескольких вариантов взаимного расположения формул, требуется вывести любой из них.
Карта представляет собой целочисленную матрицу размера
Путь на карте — это последовательность элементов карты с координатами
-
$x$ -координаты элементов совпадают, а$y$ -координаты различаются на единицу; -
$y$ -координаты элементов совпадают, а$x$ -координаты различаются на единицу.
Длина пути — это сумма его элементов.
Например, пусть дана карта:
2 1 3
5 8 2
7 1 6
Тогда
Требуется составить программу, вычисляющую минимальную длину пути, соединяющего
точки
Программа должна считывать из входного потока размер
Программа должна выводить в выходной поток целое число — минимальную длину пути.
Например, для входных данных
5
1 7 7 9 1
8 5 0 6 0
4 1 2 9 8
4 1 5 7 6
5 6 8 8 7
программа должна выводить число 40.
В парке аттракционов построили лабиринт. Лабиринт состоит из
Владельцы лабиринта планируют устроить соревнование. Несколько участников
будут заброшены в комнату номер 1. Они должны будут добраться до комнаты
номер
Андрей готовится к участию в соревновании. Он пролетел на вертолёте
над парком аттракционов и зарисовал лабиринт. Необходимо составить
программу, которая поможет ему найти идеальный путь из комнаты
номер 1 в комнату номер
Первым делом программа считывает со стандартного потока ввода два
целых числа
Программа должна выводить в стандартный поток вывода длину
Например, для входных данных
4 6
1 2 1
1 3 2
3 4 3
2 3 1
2 4 4
3 1 1
программа должна выводить
2
1 3
Пусть на множестве входных сигналов инициального автомата Мили определено отношенеие строгого порядка.
Выполним обход диаграммы автомата в глубину от начального стостояния таким образом, что дуги, исходящие из каждого состояния, рассматриваются в порядке возрастания входных сигналов, которыми эти дуги помечены.
Если присвоить каждому состоянию автомата номер, равный позиции состояния в полученном в результате обхода предпорядке, то мы получим так называемую каноническую нумерацию состояний. При этом будем считать, что состояния нумеруются, начиная с нуля.
Составьте программу, выполняющую каноническую нумерацию состояний инициального автомата Мили.
Программа должна считывать из стандартного потока ввода количество состояний
автомата
Программа должны выводить в стандартный поток вывода описание автомата, эквивалентного исходному, в котором состояния пронумерованы канонически. Описание должно выводиться в том же формате, в котором исходный автомат поступает на вход программы.
Составьте программу, выполняющую визуализацию заданного инициального автомата Мили через graphviz.
Программа должна считывать из стандартного потока ввода количество состояний
автомата
Будем считать, что входными сигналами автомата являются "a"
, второй столбец — букве "b"
, и т.д.
Программа должна выводить в стандартный поток вывода описание диаграммы
автомата на языке DOT. При этом каждое состояние на диаграмме должно быть
представлено кружком с порядковым номером состояния внутри, а каждая дуга
должна иметь метку вида "x(y)", где
Например, для входных данных
4
3
0
1 3 3
1 1 2
2 2 2
1 2 3
x y y
y y x
x x x
x y y
программа должна выводить
digraph {
rankdir = LR
0 -> 1 [label = "a(x)"]
0 -> 3 [label = "b(y)"]
0 -> 3 [label = "c(y)"]
1 -> 1 [label = "a(y)"]
1 -> 1 [label = "b(y)"]
1 -> 2 [label = "c(x)"]
2 -> 2 [label = "a(x)"]
2 -> 2 [label = "b(x)"]
2 -> 2 [label = "c(x)"]
3 -> 1 [label = "a(x)"]
3 -> 2 [label = "b(y)"]
3 -> 3 [label = "c(y)"]
}
Пусть дан входной алфавит $X=\left\{ a,b\right\} $ и выходной алфавит
Назовём языком инициального автомата Мили
В качестве примера рассмотрим автомат Мили, изображённый на рисунке
Для последовательности входных сигналов
Составьте программу, вычисляющая множество слов автомата
Мили, длина которых не превышает числа
x xx xxx xxy xy xyx xyy
Программа должна считывать со стандартного потока ввода количество
состояний автомата
Например, для входных данных
4
0 1
0 2
1 3
3 3
- x
- y
- x
y z
0
4
программа должна выводить
x xx xxx xxxx xxxy xxy xxyx xxyy
xy xyx xyxx xyxy xyxz xyy xyyx xyyy
Составьте программу, выполняющую минимизацию заданного инициального автомата Мили.
Программа должна считывать из стандартного потока ввода количество состояний
автомата
Будем считать, что входными сигналами автомата являются "a"
, второй столбец — букве "b"
, и т.д.
Программа должна выводить в стандартный поток вывода описание диаграммы
минимизированного автомата на языке DOT. При этом каждое состояние на диаграмме
должно быть представлено кружком с каноническим порядковым номером
состояния внутри, а каждая дуга должна иметь метку вида "x(y)", где
Например, для входных данных
5
3
0
1 2 3
3 4 1
3 4 2
3 0 4
4 4 3
x x y
y x x
y x x
x x y
x y x
программа должна выводить описание автомата Мили, изображённого на рисунке
Составьте программу, определяющую, являются ли два инициальных автомата Мили эквивалентными.
Программа должна считывать из стандартного потока ввода сначала описание
первого автомата, а потом — описание второго автомата. Описание каждого
автомата представлено в следующем формате: количество состояний автомата
Программа должны выводить в стандартный поток вывода строку «EQUAL
», если
автоматы эквивалентны, и «NOT EQUAL
» — в противном случае.
Составьте программу, выполняющую постороение автомата Мура по автомату Мили, не имеющему преходящих состояний.
Программа должна считывать со стандартного потока ввода входной и выходной
алфавиты, количество состояний
Входной и выходной алфавиты представлены в стандартном потоке ввода
следующим образом: сначала идёт размер алфавита
Элемент
Программа должна выводить в стандартный поток вывода описание автомата Мура в формате DOT.
Например, для входных данных
4
00 01 10 11
2
0 1
2
0 0 0 1
0 1 1 1
0 1 1 0
1 0 0 1
программа должна выводить описание автомата Мура, изображённого на рисунке
Составьте программу, выполняющую детерминизацию заданного недетерминированного распознающего автомата.
Программа должна считывать со стандартного потока ввода количество
состояний
Каждый из M переходов описывается следующим образом: сначала идёт
номер исходного состояния, затем — номер целевого состояния, а за ними
следует символ, которым помечен переход. Состояния нумеруются
с нуля. Символ задаётся в виде строки, причём lambda
».
Элемент
Описанние детерминированного автомата на языке DOT должно выводиться
в стандартный поток вывода. При этом непринимающие состояния детерминированного
автомата должны иметь форму круга (атрибут «shape = circle
»), а принимающее —
форму двойного круга (атрибут «shape = doublecircle
»). Состояния
детерминированного автомата должны быть помечены отсортированной по возрастанию
последовательностью номеров соответствующих им состояний недетерминированного
автомата, взятой в квадратные скобки. Кроме того, если из одного состояния
в другое имеется сразу несколько переходов, то все эти переходы должны
изображаться одной дугой, помеченной списком символов, соответствующих этим
переходам. Символы в списке должны разделяться запятыми и располагаться
в порядке их первого появления во входных данных.
Например, для входных данных
6
10
0 5 x
0 5 y
0 1 lambda
1 2 lambda
1 3 lambda
1 4 lambda
3 3 x
4 4 y
5 5 z
5 1 lambda
0 0 1 1 1 0
0
программа должна выводить описание распознающего автомата, изображённого на рисунке