├── 1 ├── kross.png ├── situation_3.png ├── task2.jl ├── task3.jl ├── work4.jl ├── Лекция-1.md ├── Практика-1.md └── Список-задач-1.md ├── 2 ├── Лекция-2.md ├── Практика-2.md └── Список-задач-2.md ├── 3 ├── chess.png ├── Задачи 10-13.md ├── Лекция-3.md └── Практика-3.md ├── 4 ├── Задачи 14-25.md ├── Лекция-4.md ├── Модель памяти.png └── Практика-4.md ├── 5 ├── task13.jl ├── task14.jl ├── Задачи 26-28.md ├── Лекция-5.md ├── Практика-5.md ├── Черновик 5.1.md └── Черновик-5.2.md ├── 6 ├── oblique_lines.png ├── straight_lines.png ├── totask30.png ├── totask31.png ├── Задачи 28-31.md └── Лекция-6.md ├── 7 ├── task12.jl ├── task31.jl ├── task31.sit ├── Задачи 32-.md ├── Лекция-7.md ├── Практика-7.md └── Черновик.md ├── 8 ├── example_8.1.jl ├── example_8.1.sit ├── example_8.1.sit.png ├── example_8.2.jl ├── example_8.2.sit ├── example_8.2.sit.png ├── example_8.3.jl ├── example_8.3.sit ├── example_8.3.sit.png ├── functional_robot.jl ├── horizonside.jl ├── ignjre._trajectories_robot.jl ├── Лекция-8.md └── Практика-8.md ├── 9 ├── example_9.1.jl ├── example_9.1.sit ├── example_9.1.sit.png ├── example_9.2.jl ├── example_9.2.sit ├── example_9.2.sit.png ├── example_9.3.jl ├── example_9.3.sit ├── example_9.3.sit.png ├── functional_robot.jl └── Лекция-9.md ├── 10 ├── _chess_marker.jl ├── _example_10.1.jl ├── chess_marker.jl ├── example_10.1.jl ├── example_10.1.sit ├── example_10.1.sit.png ├── functional_robot.jl ├── horizonside.jl ├── interface_decart.jl ├── interface_robot_decart.jl ├── robot_decart.jl ├── type_decart.jl ├── Лекция-10.md ├── Практика-10.md └── Требуется.txt ├── 11 ├── horizontal_borders.sit ├── horizontal_borders.sit.png ├── interface_borders_area.jl ├── interface_fold_borders_counter.jl ├── interface_general_borders_counter.jl ├── max_area_borders.jl ├── num_borders.jl ├── num_horizon_borders.jl ├── num_rectangular_borders.jl ├── rectangular_borders.sit ├── rectangular_borders.sit.png └── Лекция-11.md ├── 12-15 ├── RobotTypes.jl ├── Test_RobotMaxTmpr.jl ├── Test_RobotPutmarker.jl ├── Test_around_action.jl ├── Test_iterate.jl ├── Zad_5.jl ├── example.jl ├── horizonside.jl ├── horizonside_robot.jl ├── labirint.sit.png ├── multi_horizonside.jl ├── plan_gran.jl ├── practica-4.1.jl ├── practica-4.2.jl ├── practica-4.3.jl ├── robot_types.jl ├── robot_types_1.jl ├── robot_types_2.jl ├── Лекция-12.md ├── Лекция-13.md ├── Лекция-14.md └── Лекция-15.md ├── GIT+GITHUB ├── github-new-repo-button.png ├── github-new-repo.png ├── Краткая_справка_по_git.md └── Организация_работы_на_базе_git.md └── README.md /1/kross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/1/kross.png -------------------------------------------------------------------------------- /1/situation_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/1/situation_3.png -------------------------------------------------------------------------------- /1/task2.jl: -------------------------------------------------------------------------------- 1 | function mark_frame_perimetr!(r::Robot) 2 | num_vert = moves!(r, Sud) 3 | num_hor = moves!(r, West) 4 | #УТВ: Робот - в Юго-Западном углу 5 | 6 | for side in (Nord, Ost, Sud, West) 7 | putmarkers!(r, side) 8 | end 9 | #УТВ: По всему периметру стоят маркеры 10 | 11 | moves!(r, Nord, num_vert) 12 | moves!(r, Ost, num_hor) 13 | #УТВ: Робот - в исходном положении 14 | end 15 | 16 | function moves!(r::Robot,side::HorizonSide) 17 | num_steps=0 18 | while isborder(r,side)==false 19 | move!(r,side) 20 | num_steps+=1 21 | end 22 | return num_steps 23 | end 24 | 25 | function moves!(r::Robot,side::HorizonSide,num_steps::Int) 26 | for _ in 1:num_steps # символ "_" заменяет фактически не используемую переменную 27 | move!(r,side) 28 | end 29 | end 30 | 31 | function putmarkers!(r::Robot, side::HorizonSide) 32 | while isborder(r,side)==false 33 | move!(r,side) 34 | putmarker!(r) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /1/task3.jl: -------------------------------------------------------------------------------- 1 | #= 2 | ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля 3 | 4 | РЕЗУЛЬТАТ: Робот - в исходном положении, и все клетки поля промакированы 5 | 6 | num_hor = переместить робота до упора на юг и вернуть число шагов 7 | num_vert = переместить робота на запад и вернуть число шагов 8 | 9 | side = Ost 10 | маркировать ряд в направлении side до упора 11 | wile isborder(r,Nord)==false 12 | move!(r,Nord) 13 | side = inverse(side) 14 | маркировать ряд в направлении side до упора 15 | end 16 | 17 | переместить робота до упора на юг 18 | переместить робота на запад 19 | 20 | movemens!(r,Ost,num_hor) 21 | movemens!(r,Nord,num_vert) 22 | 23 | =# 24 | 25 | 26 | #include("roblib.jl") 27 | 28 | function mark_all(r::Robot) 29 | nun_vert = get_num_steps_movements!(r,Sud) 30 | nun_hor = get_num_steps_movements!(r,West) 31 | #УТВ: Робот - в юго-западном углу 32 | 33 | side = Ost 34 | mark_row!(r,side) 35 | while isborder!(r,Nord)==false 36 | side=inverse(side) 37 | mark_row!(r,side) 38 | end 39 | #УТВ: Робот - у северной границы, в одном из углов 40 | 41 | movements!(r,Sud) 42 | movements!(r,West) 43 | #УТВ: Робот - в юго-западном углу 44 | 45 | movemens!(r,Ost,num_hor) 46 | movemens!(r,Nord,num_vert) 47 | end 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /1/work4.jl: -------------------------------------------------------------------------------- 1 | function pyramide(r::Robot) 2 | move_angle_left!(r) 3 | lenght = moves!(r, Ost) 4 | hight = moves!(r, Nord) 5 | move_angle_left!(r) 6 | j=lenght+1 7 | for i in 1:hight 8 | while j-i != 0 9 | putmarker!(r) 10 | move!(r,Ost) 11 | j-=1 12 | end 13 | putmarker!(r) 14 | j=lenght+1 15 | back(r) 16 | move!(r,Nord) 17 | end 18 | end 19 | 20 | function move_angle_left!(r::Robot) #перемещает в левый нижний угол 21 | for side in (Sud, West) 22 | while isborder(r, side) == false 23 | move!(r, side) 24 | end 25 | end 26 | end 27 | 28 | function moves!(r::Robot,side::HorizonSide) #возвращает кол-во шагов в опред направлении 29 | num_steps=0 30 | while isborder(r,side)==false 31 | move!(r,side) 32 | num_steps+=1 33 | end 34 | return num_steps 35 | end 36 | 37 | function back(r::Robot) #Возвращает робота в левую часть 38 | while isborder(r,West) == false 39 | move!(r,West) 40 | end 41 | end -------------------------------------------------------------------------------- /1/Практика-1.md: -------------------------------------------------------------------------------- 1 | # ПРАКТИКА 1 2 | 3 | - [ПРАКТИКА 1](#практика-1) 4 | - [Подготовка программного окружения для работы с Роботом](#подготовка-программного-окружения-для-работы-с-роботом) 5 | - [**Технология проектирования "сверху вниз"**](#технология-проектирования-сверху-вниз) 6 | - [Разбор задачи 2](#разбор-задачи-2) 7 | - [**Декомпозиция задачи на уровне псевдокода**](#декомпозиция-задачи-на-уровне-псевдокода) 8 | - [**Программный код главной функции**](#программный-код-главной-функции) 9 | - [**Реализация вспомогателных функций**](#реализация-вспомогателных-функций) 10 | - [**Запуск и отладка программного кода**](#запуск-и-отладка-программного-кода) 11 | 12 | ----------------------- 13 | 14 | [<< README](../README.md) 15 | 16 | ------------------------ 17 | 18 | ## Подготовка программного окружения для работы с Роботом 19 | 20 | См. [здесь](https://github.com/Vibof/HorizonSideRobots.jl/blob/master/content/setup.md) 21 | 22 | ## **Технология проектирования "сверху вниз"** 23 | 24 | Содержание этой технологии было разъяснено [в Лекции 1](Лекция-1.md). 25 | 26 | Для её практического усвоения продолжим решение задач. 27 | 28 | ## Разбор задачи 2 29 | 30 | (задача 1 была разобрана на лекции) 31 | 32 | ДАНО: Робот - в произвольной клетке поля (без внутренних перегородок и маркеров) 33 | 34 | РЕЗУЛЬТАТ: Робот - в исходном положении, и все клетки по периметру внешней рамки промакированы 35 | 36 | Перейдем к решению. 37 | 38 | ### **Декомпозиция задачи на уровне псевдокода** 39 | 40 | ```julia 41 | function mark_frame_perimetr!(r::Robot) 42 | дойти до самого Юга и вернуть сделанное число шагов 43 | дойти до самого Запада и вернуть сделанное число шагов 44 | #УТВ: Робот - в Юго-Западном углу 45 | 46 | for sidе - перебор всех 4-х сторон горизонта в ПРАВИЛЬНОМ порядке 47 | маркировать все клетки, кроме первой, в напраленнии side 48 | end 49 | #УТВ: По всему периметру прямоугольника стоят маркеры 50 | 51 | сделать уже известное число шагов на Север 52 | сделать уже известное число шагов на Восток 53 | #УТВ: Робот - в исходном положении 54 | end 55 | ``` 56 | 57 | ### **Программный код главной функции** 58 | 59 | Вот соответствующий код главной функции на Julia 60 | 61 | ```julia 62 | function mark_frame_perimetr!(r::Robot) 63 | num_vert = moves!(r, Sud) 64 | num_hor = moves!(r, West) 65 | #УТВ: Робот - в Юго-Западном углу 66 | 67 | for sidе in (Nord, Ost, Sud, West) 68 | putmarkers!(r, side) 69 | end 70 | #УТВ: По всему периметру стоят маркеры 71 | 72 | moves!(r, Nord, num_vert) 73 | moves!(r, Ost, num_hor) 74 | #УТВ: Робот - в исходном положении 75 | end 76 | ``` 77 | 78 | ### **Реализация вспомогателных функций** 79 | 80 | ```julia 81 | function moves!(r::Robot, side::HorizonSide) 82 | num_steps=0 83 | while isborder(r,side)==false 84 | move!(r,side) 85 | num_steps+=1 86 | end 87 | return num_steps 88 | end 89 | 90 | function moves!(r::Robot,side::HorizonSide,num_steps::Int) 91 | for _ in 1:numsteps # символ "_" заменяет фактически не используемую переменную 92 | move!(r,side) 93 | end 94 | end 95 | ``` 96 | 97 | Последние две функции имют одинаковые имена, но различаются количеством своих аргументов, поэтому `Julia` сумеет разобраться какую из них и когда надо вызывать. Это свойство языка называется **множественной диспетчеризацией**. Далеко не все языки программирования обладают этим свойством, например, в `Python` так сделать было бы нельзя. 98 | 99 | Следующая функция уже была нами реализована при решении самой первой задачи (см. пример, разбиравшийся на 1-ой леции). И мы могли бы этим сейчас воспользоваться, но для этого надо было бы эту функцию сначала поместить в отдельный библиотечный файл, в котрый мы могли бы помещать также и другие универсально полезные функции. А затем этот библиотечный файл можно было бы использовать в других файлах с помощью функции `include`. Но пока еще мы этого не сделали, то нам придется написать ее повторно (хотя, конечно, это не правильно). 100 | 101 | ```Julia 102 | function putmarkers!(r::Robot, side::HorizonSide) 103 | while isborder(r,side)==false 104 | move!(r,side) 105 | putmarker!(r) 106 | end 107 | end 108 | ``` 109 | 110 | ----------------- 111 | 112 | [<< к началу](#практика-1) 113 | 114 | ### **Запуск и отладка программного кода** 115 | 116 | Все эти определения должны быть помещены в отдельный файл (в этом файле мы и должны были сразу и писать их). Пусть этот файл называется "example-1.jl" 117 | 118 | Тогда, что бы приступить к отладке программы, необходимо поместить все наши определения в пространство имен REPL. Для этого из REPL следует выполнить функцию 119 | 120 | ```julia 121 | julia> include("examle-2.jl") 122 | ``` 123 | 124 | После этого определения всех функций из файла "example-2.jl" становятся известными в пространстве REPL, и поэтому любую из этих функций теперь можно вызвать на исполнение. В частности, вызов главной функции будет выглядеть так: 125 | 126 | ```julia 127 | julia> mark_frame_perimetr!(r) 128 | ``` 129 | 130 | И если после этого в программу придется вносить какие-либо изменения, то, после сохранения результатов редактирования, необходимо будет снова выполнить функцию include, а затем уже вызывать на исполнение нужную функцию из соответствующего файла. 131 | 132 | Но с самого начала, конечно, мы должны были еще сделать 133 | 134 | ```julia 135 | julia> using HorizonSideRobots 136 | 137 | julia> r=Robot(animate=true) 138 | ``` 139 | 140 | Модуль HorizonSideRobots экспортирует перечисление HorizonSide, содержащее символы Nord, Sud, Ost, West, и определения следующих функций: 141 | 142 | ```julia 143 | moves!(::Robot, ::HorizonSide) 144 | moves!(::Robot, ::HorizonSide, ::Int) 145 | find_border!(::Robot, ::HorizonSide, ::HorizonSide) 146 | inverse(::HorizonSide) 147 | putmarkers!(::Robot, ::HorizonSide) 148 | putmarkers!(r, direction_of_movement, direction_to_border) 149 | ``` 150 | 151 | После этого уже следует приступить к отладке программы. Для этого лучше всего придерживаться технологии отладки "снизу вверх", суть которой была изложена [здесь](https://github.com/Vibof/Robot/blob/master/example.md). 152 | 153 | ----------------- 154 | 155 | [<< к началу](#практика-1) 156 | -------------------------------------------------------------------------------- /1/Список-задач-1.md: -------------------------------------------------------------------------------- 1 | # CПИСОК ЗАДАЧ ДЛЯ САМОСТОЯТЕЛЬНОГО РЕШЕНИЯ 1 2 | 3 | 1. * ДАНО: Робот находится в произвольной клетке ограниченного прямоугольного поля без внутренних перегородок и маркеров. 4 | 5 | РЕЗУЛЬТАТ: Робот — в исходном положении в центре прямого креста из маркеров, расставленных вплоть до внешней рамки. 6 | 7 | Рассмотреть отдельно еще случай, когда изначально в некоторых клетках поля могут находиться маркеры. 8 | 9 | 2. * ДАНО: Робот - в произвольной клетке поля (без внутренних перегородок и маркеров) 10 | 11 | РЕЗУЛЬТАТ: Робот - в исходном положении, и все клетки по периметру внешней рамки промакированы 12 | 13 | 3. ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля 14 | 15 | РЕЗУЛЬТАТ: Робот - в исходном положении, и все клетки поля промакированы 16 | 17 | 4. ДАНО: Робот - Робот - в произвольной клетке ограниченного прямоугольного поля 18 | 19 | РЕЗУЛЬТАТ: Робот - в исходном положении, и клетки поля промакированы так: нижний ряд - полностью, следующий - весь, за исключением одной последней клетки на Востоке, следующий - за исключением двух последних клеток на Востоке, и т.д. 20 | 21 | 5. ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля, на котором могут находиться также внутренние прямоугольные перегородки (все перегородки изолированы друг от друга, прямоугольники могут вырождаться в отрезки) 22 | 23 | РЕЗУЛЬТАТ: Робот - в исходном положении и в углах поля стоят маркеры 24 | 25 | ----------------------- 26 | 27 | [<< README](../README.md) 28 | 29 | ------------------------ 30 | -------------------------------------------------------------------------------- /10/_chess_marker.jl: -------------------------------------------------------------------------------- 1 | interface_robot_chess(robot_decart) = 2 | # robot_decart = interface_robot_decart(...) 3 | ( 4 | isborder = robot_decart.isborder, 5 | putmarker! = () -> if iseven(sum(robot_decart.coordinates())) 6 | robot_decart.putmarker!() 7 | end, 8 | move! = robot_decart.move!, 9 | ) 10 | 11 | function chess_mark!(r::Robot) 12 | robot = interface_robot(r) 13 | decart = interface_decart((x=0,y=0)) 14 | 15 | robot_decart = interface_robot_decart(robot, decart) 16 | robot_chess = interface_robot_chess(robot_decart) 17 | line = interface_line(robot_chess.move!) 18 | trajectories = interface_trajectories(robot_chess) 19 | 20 | trajectories.snake!(Ost, Nord) do side 21 | robot_chess.putmarker!() 22 | line.movements!(robot_chess.putmarker!, side) 23 | end 24 | end 25 | 26 | 27 | -------------------------------------------------------------------------------- /10/_example_10.1.jl: -------------------------------------------------------------------------------- 1 | robot = interface_save_robot(robot) 2 | rectangular_borders = interface_rectangular_borders(robot) 3 | line = interface_line(rectangular_borders.move!) 4 | trajectories = interface_trajectories(robot) 5 | 6 | """ 7 | find_marker!() 8 | 9 | перемещает Робота, находящегося где-то на неограниченном поле без внутренних перегородок, в клетку с маркером 10 | """ 11 | find_marker!() = trajectories.spiral!(move_ifnomarker!) 12 | 13 | 14 | function move_ifnomarker!(side)::Bool 15 | #= 16 | Перемещает Робота в заданном направлении и возвращает true, если в клетке с Роботом нет маркера, 17 | в противном случае Робот остается на месте и возвращается false 18 | =# 19 | if robot.ismarker() 20 | return false 21 | end 22 | move_unlimited_line!(side) 23 | return true 24 | end 25 | 26 | function move_unlimited_line!(side) 27 | coordinate = 0 # - текущая координата Робота относительно начального положения 28 | num_steps = 1 # - текущее число шагов при поиске края перегородки 29 | orthogonal = right(side) # - текущее направление поиска края перегородки 30 | back_side = orthogonal # - первоначальное направление поиска края перегородки 31 | while robot.isborder(side) # поиск края полубесконечной прямолинейной перегородки 32 | line.movements!(orthogonal,num_steps) 33 | if orthogonal == back_side 34 | coordinate += num_steps 35 | else 36 | coordinate -= num_steps 37 | end 38 | num_steps+=1 39 | orthogonal=inverse(orthogonal) 40 | end 41 | #УТВ: Робот - за краем перегородки 42 | robot.move!(side) 43 | if coordinate > 0 44 | back_side = inverse(back_side) 45 | else 46 | coordinate = -coordinate 47 | end 48 | line.movements!(back_side,coordinate) 49 | #УТВ: Робот - в соседней, по отношению к исходной, позиции с другой стороны от перегородки 50 | end 51 | -------------------------------------------------------------------------------- /10/chess_marker.jl: -------------------------------------------------------------------------------- 1 | module ChessMarker 2 | export chess_mark! 3 | 4 | include("horizonside.jl") 5 | include("functional_robot.jl") 6 | include("interface_decart.jl") 7 | include("interface_robot_decart.jl") 8 | include("_chess_marker.jl") 9 | end 10 | 11 | #---------------Test: 12 | using .ChessMarker 13 | using HorizonSideRobots 14 | r=Robot(animate=true) 15 | 16 | chess_mark!(r) -------------------------------------------------------------------------------- /10/example_10.1.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Модуль FindMarker 3 | предназначени для решения задачи поиска маркера на неограниченном поле, содержащем прямолинейные полубесконечные перегородки 4 | или перегородки конечной длины 5 | 6 | экспортирует функцию 7 | find_marker! 8 | 9 | """ 10 | module FindMarker 11 | export find_marker! 12 | 13 | using HorizonSideRobots 14 | include("functional_robot.jl") 15 | include("horizonside.jl") 16 | 17 | robot = Robot("10/example_10.1.sit", animate=true) 18 | 19 | include("_example_10.1.jl") 20 | end 21 | 22 | # ------- Исполняемая часть файла 23 | 24 | using .FindMarker 25 | 26 | FindMarker.find_marker!() 27 | 28 | #= 29 | ВНИМАНИЕ!!!: если здесь не использовать префикс "FindMarker.", 30 | то при первом запуске файла все будет работать хорошо, но при последующих запусках, 31 | поскольку модуль FindMarker при этом будет импортироваться повторно, возникнут связанные с этим проблемы 32 | =# -------------------------------------------------------------------------------- /10/example_10.1.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 12 1 9 | temperature_map: 10 | 245 258 -148 425 -78 172 -84 467 331 288 -182 165 -206 336 -52 425 444 -165 -49 490 72 86 2 209 -173 207 -146 -235 199 278 463 64 -205 -110 -175 168 -20 309 69 361 116 198 85 423 326 474 159 364 320 458 -161 247 -70 209 338 68 252 -145 103 228 -38 -64 310 213 -270 -222 355 429 127 39 478 187 402 214 171 122 470 -69 -99 -168 120 311 414 485 202 481 129 -10 62 221 -162 -160 201 380 94 4 126 470 -139 358 76 343 -15 -171 114 457 168 -17 121 448 -202 248 5 -10 139 -188 33 -41 283 448 167 -243 -195 331 74 179 426 147 345 420 410 -88 -25 -92 485 147 156 491 268 352 65 202 120 450 11 | markers_map: 12 | (7, 6) 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 0 20 | 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | 28 | 3 29 | 3 30 | 31 | 0 32 | 33 | 3 34 | 2 35 | 36 | 37 | 38 | 1 39 | 1 40 | 41 | 42 | 43 | 0 44 | 1 45 | 46 | 47 | 0 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 0 2 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 0 67 | 68 | 0 69 | 1 70 | 1 71 | 1 72 | 1 73 | 1 74 | 75 | 76 | 77 | 2 78 | 79 | 2 80 | 81 | 82 | 83 | 0 84 | 85 | 86 | 87 | 3 88 | 3 89 | 3 90 | 91 | 92 | 3 93 | 94 | 95 | 0 96 | 97 | 98 | 1 99 | 100 | 101 | 102 | 103 | 1 104 | 105 | 1 106 | 107 | 0 108 | 109 | 110 | 111 | 112 | 113 | 3 114 | 3 115 | 116 | 117 | 118 | 119 | 0 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 1 128 | 129 | 130 | 131 | 0 132 | 133 | 134 | 135 | 136 | 137 | 138 | 0 139 | 140 | 141 | 142 | 2 143 | 144 | 145 | 146 | 147 | 148 | 149 | 2 150 | 151 | 152 | 153 | 154 | 2 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /10/example_10.1.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/10/example_10.1.sit.png -------------------------------------------------------------------------------- /10/horizonside.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | 3 | """ 4 | inverse(side::HorizonSide) 5 | 6 | -- возвращает сторону горизонта, противоположную заданной 7 | """ 8 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 9 | 10 | 11 | """ 12 | left(side::HorizonSide) 13 | 14 | -- возвращает сторону горизонта, следующую после заданной (в положительном направлении вращения) 15 | """ 16 | left(side::HorizonSide) = HorizonSide(mod(Int(side)+1, 4)) 17 | 18 | 19 | """ 20 | right(side::HorizonSide) 21 | 22 | -- возвращает сторону горизонта, предшествующую заданной (в положительном направлении вращения) 23 | """ 24 | right(side::HorizonSide) = HorizonSide(mod(Int(side)-1, 4)) 25 | 26 | 27 | """ 28 | inverse(side::NTuple) 29 | 30 | -- возвращает кортеж, содержащй стороны горизонта, противоположные заданным 31 | """ 32 | inverse(side::NTuple) = Tuple(inverse.(collect(side))) 33 | 34 | 35 | """ 36 | inverse(side::AbstractVector) 37 | 38 | -- возвращает вектор, сожержащий направления, противоположные заданным 39 | """ 40 | inverse(side::AbstractVector) = inverse.(side) -------------------------------------------------------------------------------- /10/interface_decart.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | 3 | function interface_decart(coord::NamedTuple{(:x,:y),Tuple{Int,Int}}) 4 | x = coord.x 5 | y = coord.y 6 | 7 | function coordinates!(side::HorizonSide) 8 | if side == Ost 9 | x+=1 10 | elseif side == West 11 | x-=1 12 | elseif side == Nord 13 | y+=1 14 | else 15 | y-=1 16 | end 17 | return (x=x,y=y) 18 | end 19 | 20 | coordinates() = (x=x,y=y) 21 | 22 | return (coordinates = coordinates, coordinates! = coordinates!) 23 | end 24 | 25 | #= 26 | #------------Тест: 27 | 28 | decart = interface_decart((x=0,y=0)) 29 | decart.coordinates() |> println # (x=0,y=0) 30 | decart.coordinates!(Nord) |> println # (x=0,y=1) 31 | 32 | =# -------------------------------------------------------------------------------- /10/interface_robot_decart.jl: -------------------------------------------------------------------------------- 1 | interface_robot_decart(robot, decart) = 2 | # robot = inteface_save_robot(...) 3 | # decart = interface_decart(...) 4 | ( 5 | move! = 6 | side -> if robot.move!(side) == true 7 | decart.coordinates!(side) 8 | true 9 | end, 10 | isborder = robot.isborder, 11 | putmarker! = robot.putmarker!, 12 | ismarker = robot.ismarker, 13 | temperature = robot.temperature, 14 | show! = robot.show!, 15 | set_situation! = robot.set_situation!, 16 | coordinates = decart.coordinates 17 | ) 18 | -------------------------------------------------------------------------------- /10/robot_decart.jl: -------------------------------------------------------------------------------- 1 | include("../8/horizonside.jl") 2 | function interface_decart(x,y) 3 | function decart(side::HorizonSide) 4 | if side == Ost 5 | x+=1 6 | elseif side == West 7 | x-=1 8 | elseif side == Nord 9 | y+=1 10 | else 11 | y-=1 12 | end 13 | (x=x,y=y) 14 | end 15 | decart() = (x=x,y=y) 16 | return (decart = decart,) 17 | end 18 | 19 | mutable struct RobotDecart <: AbstractRobot 20 | robot::Robot 21 | coordinates::NamedTuple{(:x,:y),NTuple{2,Int}} 22 | decart::NTuple{1,Functional} 23 | RobotDecart(robot::Robot,coordinates::NamedTuple{(:x,:y),NTuple{2,Int}}) = new(robot,coordinates,interface_decart(Tuple(coordinates)...)) 24 | end 25 | 26 | function move!(robot::RobotDecart,side) 27 | robot.coordinates = robot.decart(side) 28 | move!(AbstractRobot(robot), side) 29 | end -------------------------------------------------------------------------------- /10/type_decart.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | 3 | mutable struct Decart 4 | coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}} 5 | 6 | Decart(coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}}) = new(coordinates) 7 | end 8 | 9 | function coordinates!(decart::Decart, side::HorizonSide) 10 | if side == Ost 11 | decart.coordinates.x+=1 12 | elseif side == West 13 | decart.coordinates.x-=1 14 | elseif side == Nord 15 | decart.coordinates.y+=1 16 | else 17 | decart.coordinates.y-=1 18 | end 19 | 20 | return (x=decart.coordinates.x,y=decart.coordinates.y) 21 | end 22 | coordinates(decart::Decart) = decart.coordinates 23 | 24 | #------------Тест: 25 | decart = Decart((x=0,y=0)) 26 | coordinates(decart) |> println # (x=0,y=0) 27 | coordinates!(decart, Nord) |> println # (x=0,y=1) 28 | 29 | -------------------------------------------------------------------------------- /10/Практика-10.md: -------------------------------------------------------------------------------- 1 | # Задача о маркировке поля в шахматном порядке 2 | 3 | Пусть Робот находится в юго-западном углу ограниченного прямоугольного поля без внутренних перегородок. Требуется расставить маркеры на поле в шахматном порядке начиная с юго-западного угла. 4 | 5 | Для решения этой задачи мы можем воспользоваться имеющимися у нас обобщенными функциями, перемещающими Робота, а именно - функцией, перемещающй Робота по полю "змейкой". 6 | 7 | Решение задачи, с помощью этой функции, если бы маркеры надо было ставить в каждой клетке поля, выглядело бы так 8 | 9 | ```julia 10 | using HorizonSideRobots 11 | include("functional_robot.jl") 12 | robot = Robot(animate=true) 13 | save_robot = interface_save_robot(robot) 14 | robot = interface_line(save_robot.move!) 15 | 16 | #исполняема часть 17 | trajectories = interface_traectories(robot) 18 | traectoties.snake!(Ost, Nord) do side 19 | save_robot.putmarker!() 20 | save_robot.movements!(save_robot.putmarker!, side) 21 | end 22 | ``` 23 | 24 | Однако, маркеры надо ставить в шахматном порядке. Для этого можно, например, если во время движения Робота будут известны его текущие координаты, отсчитываемые от юго-западного угла, координаты которого будут (x=0, y=0), вычислять сумму этих координат, и если значение суммы будет четным, то ставить маркер. 25 | 26 | Но для этого потребуется сначала спроектировать исполнителя, который будет отличаться от обычного Робота тем, что, во-первых, в его интерфейс будет входить функция coords, с помощью которой можно будет получать значение текущих координат, во-вторых, при выполнении Роботом перемещения в соседнюю клетку в том или ином направлении, значение текущих координат будет автоматически отслеживаться (изменяться), и, в-терьх, команда putmarker!() этого робота должна будет устанавливать маркер только в случае, когда сумма текущих координат Робота четная. 27 | 28 | Такого узкоспециализированного исполнителя можно будет получить за два этапа. Сначала спроектировать исполнителя, который будет уметь только отслеживать и возвращать свои текущие координаты, а затем, на его базе спроектировать уже требуемого исполнителя, который будет ставить маркеры нужным образом. 29 | 30 | Первого из этих двух последних исполнителей назовем будем создавать с помощью функции высшего порядка `interface_robot_dekart`, определение которой находится в файле ["interface_robot_decart.jl"](interface_robot_decart.jl). 31 | Чтобы создать с помощью этой функции соответствующего исполнителя потребуется сделать следующие действия 32 | 33 | ```julia 34 | using HorizonSideRobots 35 | include("functional_robot.jl") 36 | include("interface_decart.jl") 37 | robot = Robot(...) # многоточия заменяют требуемые аргументы 38 | 39 | robot_decart = interface_robot_decart(interface_robot(robot), interface_decart((x=0,y=0))) 40 | ``` 41 | 42 | После чего исполнителем `robot_decart` можно будет командовать привычными командами, а также получать текущие значения координат с помощью инструкции `robot_decart.coordinates()` 43 | 44 | Теперь, имеея исполнителя `robot_decart` можно уже реализовать узкоспециализированного исполнителя, у которого инструкция putmarker!() будет переопределена так, чтобы маркер ставился только в случае, когда сумма текущих координат является четной. Функция высшего порядка, возвращающая интерфейс такого исполнителя находится в файле ["_chess_mark.jl"](_chess_mark.jl). 45 | 46 | Затем этот файл обернут в модуль `ChessMark`, находящийся в файле ["chess_mark.jl"](chess_marker.jl) 47 | 48 | Исполнить этот файл из REPL надо так 49 | 50 | ```julia 51 | include("10/chess_marker.jl") 52 | ``` 53 | -------------------------------------------------------------------------------- /10/Требуется.txt: -------------------------------------------------------------------------------- 1 | Рассмотреть еще вариант решения задачи о маркировеи в щахматном порядке с использованием типа RobotDecart (см. конец лекциии 10) 2 | 3 | файл robot_decart.jl - не используется -------------------------------------------------------------------------------- /11/horizontal_borders.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 11 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | true 7 | robot_position: 8 | 11 1 9 | temperature_map: 10 | 265 394 -19 30 -239 380 205 232 191 128 -41 -169 269 -200 417 456 466 -113 30 378 -138 378 267 219 498 -113 459 42 -142 492 301 171 -203 30 -149 288 -68 313 -139 163 -206 -161 -6 -19 -137 403 483 -209 -117 337 331 237 409 -267 256 283 -45 -19 37 99 -11 -53 25 337 426 120 223 -85 19 -64 192 159 -266 428 -71 453 134 142 480 476 7 375 362 267 313 -3 380 -25 -169 -246 302 -18 176 48 -269 478 372 172 353 452 -44 285 439 -66 56 194 -74 474 148 39 125 110 4 -123 -13 -20 443 117 312 -207 124 492 419 142 -23 -74 136 72 79 -121 -217 405 11 | markers_map: 12 | 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 2 30 | 31 | 32 | 33 | 34 | 0 35 | 36 | 37 | 38 | 39 | 40 | 2 41 | 42 | 43 | 44 | 2 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 2 62 | 63 | 64 | 0 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 2 73 | 74 | 2 75 | 76 | 77 | 2 78 | 79 | 80 | 81 | 82 | 83 | 2 84 | 85 | 86 | 0 87 | 88 | 89 | 0 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 2 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 0 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 0 119 | 0 2 120 | 121 | 122 | 0 123 | 124 | 125 | 126 | 127 | 128 | 129 | 0 2 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /11/horizontal_borders.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/11/horizontal_borders.sit.png -------------------------------------------------------------------------------- /11/interface_borders_area.jl: -------------------------------------------------------------------------------- 1 | """ 2 | interface_borders_area(robot, direct) 3 | 4 | -- robot - именованный кортеж функций (интерфейс), включающий функции: 5 | move!(side) (перемещает Робота на 1 клетку в заданном направлении), isborder(side) 6 | 7 | -- возвращает именованный кортеж функций (интерфейс), состоящий из 2х функций: 8 | move!(side), get_area() 9 | 10 | Функция get_area() возвращает значение площади прямоугольной перегородки, полученное при выполнении 11 | функции move!(side) 12 | 13 | Описание функции move!: 14 | 15 | ДАНО: в направлении direct от Робота перегородки нет 16 | side - направление перемещения, перпендикулярное направлению direct 17 | 18 | РЕЗУЛЬТАТ: в направлении direct от Робота ПОПРЕЖНЕМУ НЕТ перегородки, 19 | но Робот прошёл мимо очередной перегородки, если таковая имелась на его пути, 20 | а если таких перегородок не было, то он росто дошел до упора. 21 | При этом, если в направлении side имелась преграждающая путь перегородка, то Робот остался на месте. 22 | Если Робот сделал шаг, то возвращено true, если остался на месте, то возвращено false 23 | 24 | Во внешнюю (замыкаемую) переременную записывается при этом значение площади пройденной перегородки 25 | (если пройденной пергородки не было - Робот просто дошел до упора, то в этой переменной будет 0) 26 | """ 27 | function interface_borders_area(robot, direct) 28 | # robot = interface_save_robot(...) | interface_rectangular_borders(...) || .... 29 | 30 | size_direct = 0 31 | size_side = 0 32 | area = 0 33 | 34 | function move!(side) 35 | while !robot.isborder(direct) 36 | if robot.move!(side)==false # robot.move!(side)==true <=> перемещение состоялось (Робот не уперся во внешнюю рамку) 37 | area = 0 # ! нужно обнулить, т.к. не нулевое значение могло остаться после предыдущего вызова этой функции return false 38 | return false 39 | end 40 | end 41 | # УТВ: в направлении direct имеется перегородка 42 | 43 | while robot.isborder(direct) 44 | robot.move!(side) 45 | size_side+=1 46 | end 47 | #УТВ: Робот - стоит за этой перегородкой 48 | 49 | robot.move!(direct) 50 | while robot.isborder(inverse(side)) 51 | robot.move!(direct) 52 | size_direct += 1 53 | end 54 | for _ in 1:size_direct+1 55 | robot.move!(inverse(direct)) 56 | end 57 | # size_direct - определен, Робот - стоит за перегродкой в прежнем положении 58 | 59 | area = size_side*size_direct 60 | size_side, size_direct = 0, 0 61 | return true 62 | end 63 | 64 | return (move! = move!, get_area = ()-> area) 65 | end 66 | -------------------------------------------------------------------------------- /11/interface_fold_borders_counter.jl: -------------------------------------------------------------------------------- 1 | """ 2 | interface_fold_borders(robot, direct_borders) 3 | 4 | -- robot - именованный кортеж функций (интерфейс), включающий функции: 5 | move!(side) (перемещает Робота на 1 клетку в заданном направлении), isborder(side) 6 | 7 | -- direct_borders - главное направление движения, перпендикулярное складкам "змейки" 8 | 9 | -- возвращает именованный кортеж функций (интерфейс), состоящий из 2х функций: 10 | move!(side), get_num() 11 | 12 | Функция get_num() возвращает ОБЩЕЕ число перегородок, мимо которых прошел Робот с помощью 13 | функции move!(side) 14 | 15 | Описание функции move!: 16 | 17 | ДАНО: в направлении direct от Робота перегородки нет 18 | side - направление перемещения, перпендикулярное направлению direct 19 | 20 | РЕЗУЛЬТАТ: в направлении direct от Робота ПОПРЕЖНЕМУ НЕТ перегородки, 21 | но Робот прошёл мимо очередной перегородки, если таковая имелась на его пути, 22 | а если таких перегородок не было, то он росто дошел до упора. 23 | При этом, если в направлении side имелась преграждающая путь перегородка, то Робот остался на месте. 24 | Если Робот сделал шаг, то возвращено true, если остался на месте, то возвращено false 25 | 26 | Внешняя (замыкаемая) переременная увеличивается при этом 1, если была пройдена новая перегородка, или, в противном случае, 27 | её значение остаётся без изменения 28 | """ 29 | 30 | function interface_fold_borders_counter(robot, direct_borders) 31 | # robot = interface_save_robot(...) | interface_rectangular_borders(...) || .... 32 | num_borders = 0 33 | 34 | function move!(side) 35 | #= 36 | ДАНО: в направлении direct_borders от Робота перегородки нет 37 | side - направление перемещения, перпендикулярное направлению direct_borders 38 | РЕЗУЛЬТАТ: в направлении direct_borders от Робота ПОПРЕЖНЕМУ НЕТ перегородки, 39 | но Робот прошёл мимо очередной перегородки, если таковая имелась на его пути, 40 | а если таких перегородок не было, то он дошел до упора, 41 | или Робот остался на месте, если в направлении side имелась перегородка. 42 | Если Робот сделал шаг, то возвращено true, если остался на месте, то возвращено false 43 | =# 44 | while !robot.isborder(direct_borders) # || state==1 45 | if robot.move!(side)==false # robot.move!(side)==true <=> перемещение состоялось (Робот не уперся во внешнюю рамку) 46 | return false 47 | end 48 | end 49 | # УТВ: в направлении direct_borders имеется перегородка 50 | num_borders+=1 51 | while robot.isborder(direct_borders) 52 | robot.move!(side) 53 | end 54 | #УТВ: Робот - стоит за этой перегородкой 55 | return true 56 | end 57 | 58 | return (move! = move!, get_num = ()->num_borders) 59 | end 60 | -------------------------------------------------------------------------------- /11/interface_general_borders_counter.jl: -------------------------------------------------------------------------------- 1 | """ 2 | interface_fold_borders(robot, direct_borders) 3 | 4 | -- robot - именованный кортеж функций (интерфейс), включающий функции: 5 | count!() (перемещает Робота на 1 клетку в заданном направлении), isborder(side) 6 | 7 | -- direct - главное направление движения, перпендикулярное складкам "змейки" 8 | 9 | -- возвращает именованный кортеж функций (интерфейс), состоящий из 2х функций: 10 | count!(), get_num() 11 | 12 | Функция get_num() возвращает ОБЩЕЕ число перегородок, на которые наткнулся Робот (которые преграждают путь Роботу при движении по складкам) 13 | 14 | Описание функции count!: 15 | 16 | ДАНО: рядом с Роботом в направлении side находится перегородка 17 | (side - направление перемещения Робот по складке) 18 | 19 | РЕЗУЛЬТАТ: Робот в исходном положении и внешняя переменная с числом линейных перегородок, параллельных направлению direct, увеличено на 1, 20 | если перегородка Рядом с роботом является отрезком, и эта внешняя переменная осталась без изменения, в противном случае 21 | """ 22 | function interface_general_borders_counter(robot, direct) 23 | num_borders = 0 24 | 25 | function count!(side) 26 | if robot.move!(inverse(direct)) == false 27 | return 28 | end 29 | if robot.move!(side)==false # c этой вертикальной перегородкой Робот уже встречался (т.е. она уже посчитана) 30 | robot.move!(direct) 31 | return 32 | end 33 | #Робот - за вертикальной частью перегородки 34 | if !robot.isborder(direct) 35 | num_borders+=1 36 | end 37 | robot.move!(inverse(side)) 38 | robot.move!(direct) 39 | end 40 | 41 | return (count! = count!, get_num = ()->num_borders) 42 | end -------------------------------------------------------------------------------- /11/max_area_borders.jl: -------------------------------------------------------------------------------- 1 | module NumBorders 2 | export get_max_area! 3 | 4 | include("../10/horizonside.jl") 5 | include("../10/functional_robot.jl") 6 | include("interface_borders_area.jl") 7 | 8 | 9 | function get_max_area!(robot) 10 | robot = interface_save_robot(robot) 11 | 12 | borders_area = interface_borders_area(robot, Nord) 13 | rectangular_borders = interface_rectangular_borders(robot) 14 | trajectories = interface_trajectories(robot) 15 | 16 | max_area = 0 17 | 18 | trajectories.snake!(Ost, Nord) do side 19 | if robot.isborder(Nord) 20 | return false 21 | end 22 | while borders_area.move!(side) || rectangular_borders.move!(side) 23 | area = borders_area.get_area() 24 | if area > max_area 25 | max_area = area 26 | end 27 | end 28 | end 29 | 30 | return max_area 31 | end 32 | end # module NumBorders 33 | 34 | #-------Исполняемая часть файла 35 | 36 | using .NumBorders 37 | using HorizonSideRobots 38 | 39 | #robot = Robot("11/horizontal_borders.sit", animate=true) 40 | robot = Robot("11/rectangular_borders.sit", animate=true) 41 | get_max_area!(robot) |> println -------------------------------------------------------------------------------- /11/num_borders.jl: -------------------------------------------------------------------------------- 1 | module NumBorders 2 | export get_num_borders! 3 | 4 | include("../10/horizonside.jl") 5 | include("../10/functional_robot.jl") 6 | include("interface_fold_borders_counter.jl") 7 | include("interface_general_borders_counter.jl") 8 | 9 | function get_num_borders!(robot) 10 | robot = interface_save_robot(robot) 11 | 12 | horizont_borders_counter = interface_fold_borders_counter(robot, Nord) 13 | rectangular_borders = interface_rectangular_borders(robot) 14 | trajectories = interface_trajectories(robot) 15 | vertical_borders_counter = interface_general_borders_counter(robot, Nord) 16 | 17 | trajectories.snake!(Ost, Nord) do side 18 | if robot.isborder(Nord) 19 | return false 20 | end 21 | while horizont_borders_counter.move!(side) || (vertical_borders_counter.count!(side); rectangular_borders.move!(side)) 22 | end 23 | end 24 | 25 | return horizont_borders_counter.get_num() + vertical_borders_counter.get_num() 26 | end 27 | end # module NumBorders 28 | 29 | #-------Исполняемая часть файла: 30 | using .NumBorders 31 | using HorizonSideRobots 32 | 33 | #robot = Robot("11/horizontal_borders.sit", animate=true) 34 | robot = Robot("11/rectangular_borders.sit", animate=true) 35 | get_num_borders!(robot) |> println -------------------------------------------------------------------------------- /11/num_horizon_borders.jl: -------------------------------------------------------------------------------- 1 | module NumBorders 2 | export get_num_borders! 3 | 4 | include("../10/horizonside.jl") 5 | include("../10/functional_robot.jl") 6 | include("interface_fold_borders_counter.jl") 7 | 8 | function get_num_borders!(robot) 9 | robot = interface_save_robot(robot) 10 | 11 | horizont_borders_counter = interface_fold_borders_counter(robot, Nord) 12 | trajectories = interface_trajectories(robot) 13 | 14 | trajectories.snake!(Ost, Nord) do side 15 | if robot.isborder(Nord) 16 | return false 17 | end 18 | while horizont_borders_counter.move!(side) || robot.move!(side) 19 | end 20 | end 21 | 22 | return horizont_borders_counter.get_num() 23 | end 24 | end # module NumBorders 25 | 26 | #-------Исполняемая часть файла: 27 | using .NumBorders 28 | using HorizonSideRobots 29 | 30 | robot = Robot("11/horizontal_borders.sit", animate=true) 31 | 32 | get_num_borders!(robot) |> println 33 | -------------------------------------------------------------------------------- /11/num_rectangular_borders.jl: -------------------------------------------------------------------------------- 1 | module NumBorders 2 | export get_num_borders! 3 | 4 | include("../10/horizonside.jl") 5 | include("../10/functional_robot.jl") 6 | include("interface_fold_borders_counter.jl") 7 | 8 | function get_num_borders!(robot) 9 | robot = interface_save_robot(robot) 10 | 11 | horizont_borders_counter = interface_fold_borders_counter(robot, Nord) 12 | rectangular_borders = interface_rectangular_borders(robot) 13 | trajectories = interface_trajectories(robot) 14 | 15 | trajectories.snake!(Ost, Nord) do side 16 | if robot.isborder(Nord) 17 | return false 18 | end 19 | while horizont_borders_counter.move!(side) || rectangular_borders.move!(side) 20 | end 21 | end 22 | 23 | return horizont_borders_counter.get_num() 24 | end 25 | end # module NumBorders 26 | 27 | #-------Исполняемая часть файла: 28 | using .NumBorders 29 | using HorizonSideRobots 30 | 31 | robot = Robot("11/horizontal_borders.sit", animate=true) 32 | 33 | get_num_borders!(robot) |> println 34 | -------------------------------------------------------------------------------- /11/rectangular_borders.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 11 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | true 7 | robot_position: 8 | 11 1 9 | temperature_map: 10 | 265 394 -19 30 -239 380 205 232 191 128 -41 -169 269 -200 417 456 466 -113 30 378 -138 378 267 219 498 -113 459 42 -142 492 301 171 -203 30 -149 288 -68 313 -139 163 -206 -161 -6 -19 -137 403 483 -209 -117 337 331 237 409 -267 256 283 -45 -19 37 99 -11 -53 25 337 426 120 223 -85 19 -64 192 159 -266 428 -71 453 134 142 480 476 7 375 362 267 313 -3 380 -25 -169 -246 302 -18 176 48 -269 478 372 172 353 452 -44 285 439 -66 56 194 -74 474 148 39 125 110 4 -123 -13 -20 443 117 312 -207 124 492 419 142 -23 -74 136 72 79 -121 -217 405 11 | markers_map: 12 | 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 2 30 | 31 | 32 | 33 | 34 | 0 35 | 36 | 37 | 38 | 39 | 40 | 2 41 | 42 | 43 | 44 | 2 45 | 46 | 47 | 48 | 49 | 50 | 51 | 3 52 | 53 | 54 | 55 | 3 56 | 3 57 | 58 | 59 | 60 | 61 | 2 62 | 63 | 1 64 | 0 65 | 1 66 | 67 | 68 | 69 | 70 | 71 | 72 | 2 73 | 74 | 2 75 | 76 | 77 | 2 78 | 79 | 80 | 81 | 82 | 83 | 2 84 | 3 85 | 86 | 0 87 | 88 | 89 | 0 90 | 91 | 92 | 93 | 94 | 95 | 96 | 1 97 | 98 | 99 | 2 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 0 108 | 109 | 3 110 | 3 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 0 119 | 0 2 120 | 3 121 | 3 122 | 0 123 | 124 | 125 | 126 | 127 | 128 | 129 | 0 2 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /11/rectangular_borders.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/11/rectangular_borders.sit.png -------------------------------------------------------------------------------- /12-15/RobotTypes.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ИЕРАРХИЯ ИЕРАРХИЯ АБСТРАКТНЫХ И КОНКРЕТНЫХ ТИПОВ ТИПОВ: 3 | 4 | Any 5 | |___Decart (интерфейс: coordinates!, coordinates) 6 | | 7 | |___AbstractRobot (интерфейс: isborder, putmatker!, ismarker, temperature, show!) 8 | | 9 | |___AbstractRobotDecart (дополнительные функции: move!, coordinates) 10 | | 11 | |___RobotDecart{TypeRobot} - параметрический конкретный тип 12 | | 13 | |___OrtRobot{TypeRobot} (дополнительные/переопределенные функции: forvard!, isborder, rotation!) - параметрический конкретный тип 14 | | 15 | |___GranRobot{TypeRobot} (forvard!, isborder, coordinates, num_steps, num_rotatins, ort, around!) - параметрический конкретный тип 16 | 17 | """ 18 | module RobotTypes 19 | export AbstractRobot, AbstractRobotDecart, RobotDecart, OrtRobot, GranRobot, 20 | move!, isborder, putmatker!, ismarker, temperature, show!, forvard!, rotation!, num_steps, num_rotations, ort, around! 21 | 22 | using HorizonSideRobots 23 | include("horizonside.jl") 24 | include("robot_types.jl") 25 | end -------------------------------------------------------------------------------- /12-15/Test_RobotMaxTmpr.jl: -------------------------------------------------------------------------------- 1 | module Test_RobotMaxTmpr 2 | using HorizonSideRobots 3 | include("horizonside.jl") 4 | include("robot_types.jl") 5 | #include("RobotsTypes.jl") 6 | #using .RobotTypes 7 | 8 | mutable struct RobotMaxTmpr <: AbstractRobot 9 | robot::Robot 10 | max_temperature::Int 11 | end 12 | 13 | HorizonSideRobots.move!(robot::RobotMaxTmpr,side::HorizonSide) = begin 14 | move!(robot.robot, side) 15 | t = temperature(robot.robot) 16 | if t > robot.max_temperature 17 | robot.max_temperature = t 18 | end 19 | end 20 | 21 | robot = Robot("labirint.sit"; animate = true) 22 | robot = RobotMaxTmpr(robot, temperature(robot)) 23 | gran_robot = GranRobot{RobotMaxTmpr}(robot) 24 | 25 | around!(gran_robot) 26 | println(robot.max_temperature) 27 | end -------------------------------------------------------------------------------- /12-15/Test_RobotPutmarker.jl: -------------------------------------------------------------------------------- 1 | module Test_RobotPutmarker 2 | using HorizonSideRobots 3 | include("horizonside.jl") 4 | include("robot_types.jl") 5 | #include("RobotsTypes.jl") 6 | #using .RobotTypes 7 | 8 | struct RobotPutmarker <: AbstractRobot # - это просто тип-обертка, чтобы для этого типа можно было переопределить функцию move! 9 | robot::Robot 10 | end 11 | 12 | HorizonSideRobots.move!(robot::RobotPutmarker,side::HorizonSide) = begin 13 | move!(robot.robot,side) 14 | putmarker!(robot.robot) 15 | end 16 | 17 | #= 18 | robot = Robot("labirint.sit"; animate = true) 19 | gran_robot = GranRobot{RobotPutmarker}(RobotPutmarker(robot)) 20 | =# 21 | gran_robot = (Robot("labirint.sit"; animate = true) |> RobotPutmarker |> GranRobot{RobotPutmarker}) 22 | 23 | around!(gran_robot) 24 | end -------------------------------------------------------------------------------- /12-15/Test_around_action.jl: -------------------------------------------------------------------------------- 1 | module Test_around_action 2 | using HorizonSideRobots 3 | include("horizonside.jl") 4 | include("robot_types.jl") 5 | #include("RobotsTypes.jl") 6 | #using .RobotTypes 7 | 8 | gran_robot = (Robot("labirint.sit"; animate = true) |> GranRobot{Robot}) 9 | sum_tmprs=0 10 | around!(gran_robot)do 11 | global sum_tmprs 12 | sum_tmprs += temperature(gran_robot) 13 | end 14 | 15 | sum_tmprs/num_steps(gran_robot) |> println 16 | end 17 | -------------------------------------------------------------------------------- /12-15/Test_iterate.jl: -------------------------------------------------------------------------------- 1 | module Test_iterate 2 | using HorizonSideRobots 3 | include("horizonside.jl") 4 | include("robot_types.jl") 5 | #include("RobotsTypes.jl") 6 | #using .RobotTypes 7 | 8 | robot = Robot("labirint.sit", animate=true) 9 | 10 | around = GranRobot{Robot}(robot) 11 | for robot in around 12 | temperature(robot) |> println 13 | end 14 | end -------------------------------------------------------------------------------- /12-15/Zad_5.jl: -------------------------------------------------------------------------------- 1 | module Zad5 2 | using HorizonSideRobots 3 | include("robot_types.jl") 4 | include("horizonside.jl") 5 | include("horizonside_robot.jl") 6 | 7 | 8 | function start!(r::Robot) # главная функция, 9 | robot_path = RobotPath{Robot}(r) 10 | while !isborder(robot_path, Sud) || !isborder(robot_path, West) 11 | movements!(robot_path, Sud) 12 | movements!(robot_path, West) 13 | end 14 | #ygol!(r,Nord) 15 | #ygol!(r,Ost) 16 | #ygol!(r,Sud) 17 | #ygol!(r,West) 18 | movements_to_back!(robot_path) 19 | end 20 | 21 | end 22 | 23 | Zad5.start!(r) 24 | -------------------------------------------------------------------------------- /12-15/example.jl: -------------------------------------------------------------------------------- 1 | include("RobotTypes.jl") 2 | using .RobotTypes 3 | 4 | #------------------------------------------------------------------------------------------------------------------------- 5 | struct RobotPutmarker <: AbstractRobot 6 | robot::Robot 7 | end 8 | HorizonSideRobots.move!(robot::RobotPutmarker,side::HorizonSide) = begin 9 | move!(robot.robot,side) 10 | putmarker!(robot.robot) 11 | end 12 | 13 | #------------------------------------------------------------------------------------------------------------------------- 14 | mutable struct RobotMaxTmpr <: AbstractRobot 15 | robot::Robot 16 | max_temperature::Int 17 | end 18 | HorizonSideRobots.move!(robot::RobotMaxTmpr,side::HorizonSide) = begin 19 | move!(robot.robot, side) 20 | t = temperature(robot.robot) 21 | if t > robot.max_temperature 22 | robot.max_temperature = t 23 | end 24 | end 25 | #------------------------------------------------------------------------------------------------------------------------- 26 | 27 | function mark_gran!(robot) 28 | robot_putmarker = RobotPutmarker(robot) 29 | gran_robot = GranRobot{RobotPutmarker}(robot_putmarker) 30 | around!(gran_robot) 31 | end 32 | 33 | function max_tmpr_gran(robot) 34 | robot_max_tmpr = RobotMaxTmpr(robot, temperature(robot)) 35 | gran_robot = GranRobot{RobotMaxTmpr}(robot_max_tmpr) 36 | around!(gran_robot) 37 | return robot_max_tmpr.max_temperature 38 | end 39 | 40 | function sum_tmprs_gran(robot) 41 | gran_robot = GranRobot{Robot}(robot) 42 | sum_tmprs=0 43 | around!(gran_robot)do 44 | sum_tmprs += temperature(robot) 45 | end 46 | return sum_tmprs 47 | end 48 | 49 | #-==========================================ИСПОЛНЯЕМАЯ ЧАСТЬ ФАЙЛА======================================================== 50 | 51 | robot = Robot("labirint.sit"; animate = true) 52 | 53 | #= 54 | 55 | =# 56 | 57 | #= 58 | 59 | =# -------------------------------------------------------------------------------- /12-15/horizonside.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | 3 | """ 4 | inverse(side::HorizonSide) 5 | 6 | -- возвращает сторону горизонта, противоположную заданной 7 | """ 8 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 9 | 10 | 11 | """ 12 | left(side::HorizonSide) 13 | 14 | -- возвращает сторону горизонта, следующую после заданной (в положительном направлении вращения) 15 | """ 16 | left(side::HorizonSide) = HorizonSide(mod(Int(side)+1, 4)) 17 | 18 | 19 | """ 20 | right(side::HorizonSide) 21 | 22 | -- возвращает сторону горизонта, предшествующую заданной (в положительном направлении вращения) 23 | """ 24 | right(side::HorizonSide) = HorizonSide(mod(Int(side)-1, 4)) 25 | 26 | 27 | """ 28 | inverse(side::NTuple) 29 | 30 | -- возвращает кортеж, содержащй стороны горизонта, противоположные заданным 31 | """ 32 | inverse(side::NTuple) = Tuple(inverse.(collect(side))) 33 | 34 | 35 | """ 36 | inverse(side::AbstractVector) 37 | 38 | -- возвращает вектор, сожержащий направления, противоположные заданным 39 | """ 40 | inverse(side::AbstractVector) = inverse.(side) -------------------------------------------------------------------------------- /12-15/horizonside_robot.jl: -------------------------------------------------------------------------------- 1 | movements!(robot, side) = 2 | while !isborder(robot, side) 3 | move!(robot, side) 4 | end 5 | 6 | movements!(action::Function, robot, side) = 7 | while !isborder(robot, side) 8 | move!(robot, side) 9 | action() 10 | end 11 | 12 | #= 13 | movements(action::Function, condition::Function) = 14 | while condition() 15 | action() 16 | end 17 | 18 | movements(()->(move!(robot,side);putmarker!(robot)), ()->!isborder(robot,side)) 19 | =# 20 | 21 | movements!(robot, side, num_steps::Integer) = 22 | for _ in 1:num_steps 23 | move!(robot, side) 24 | end 25 | 26 | movements!(action::Function, robot, side, num_steps::Integer) = 27 | for _ in 1:num_steps 28 | move!(robot, side) 29 | action() 30 | end 31 | 32 | function get_num_movements!(robot, side) #countmovements!(robot,side) 33 | num_steps=0 34 | while !isborder(robot, side) 35 | move!(robot, side) 36 | num_steps+=1 37 | end 38 | return num_steps 39 | end 40 | 41 | 42 | function get_num_movements!(action::Function, robot, side) #countmovements!(::Function,robot,side) 43 | num_steps=0 44 | while !isborder(robot, side) 45 | move!(robot, side) 46 | action() 47 | num_steps+=1 48 | end 49 | return num_steps 50 | end 51 | -------------------------------------------------------------------------------- /12-15/labirint.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/12-15/labirint.sit.png -------------------------------------------------------------------------------- /12-15/multi_horizonside.jl: -------------------------------------------------------------------------------- 1 | inverse(sides::Vector) = sides .|> inverse 2 | 3 | inverse(sides::Tuple) = sides |> collect .|> inverse |> Tuple 4 | 5 | left(sides::Vector) = sides .|> left 6 | 7 | left(sides::Tuple) = sides |> collect .|> left |> Tuple 8 | 9 | right(sides::Vector) = sides .|> right 10 | 11 | right(sides::Tuple) = sides |> collect .|> right |> Tuple -------------------------------------------------------------------------------- /12-15/plan_gran.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | include("horizonside.jl") 3 | include("horizonside_robot.jl") 4 | include("robot_types.jl") 5 | 6 | #include("RobotTypes.jl") 7 | #using .RobotTypes 8 | 9 | 10 | function data_plan_gran(robot::TypeRobot, coords=(x=0,y=0)) where TypeRobot 11 | gran_robot = GranRobot{TypeRobot}(robot, coords) 12 | pre_ort=ort(gran_robot) # - ориентация Робота на предыдущем шаге при движении вдоль границы 13 | 14 | xdata=Float64[] 15 | ydata=Float64[] 16 | 17 | for robot in gran_robot 18 | cur_ort = ort(robot) 19 | if cur_ort in (left(pre_ort), right(pre_ort)) # Робот совершил поворот на 90 град (находится в углу) 20 | x, y = coordinates(robot) 21 | if (pre_ort, cur_ort) in ((Sud,Ost),(Ost,Sud)) 22 | dx, dy = 0.5, 0.5 23 | elseif (pre_ort, cur_ort) in ((Ost,Nord), (Nord,Ost)) 24 | dx, dy = -0.5, 0.5 25 | elseif (pre_ort, cur_ort) in ((Nord,West), (West,Nord)) 26 | dx, dy = -0.5, -0.5 27 | elseif (pre_ort, cur_ort) in ((Sud,West), (West,Sud)) 28 | dx, dy = 0.5, -0.5 29 | else 30 | error("Ошибка в выкладках!!!") 31 | end 32 | push!(xdata,x+dx) 33 | push!(ydata,y+dy) 34 | pre_ort=ort(robot) 35 | elseif cur_ort == inverse(pre_ort) # имел место РАЗВОРОТ (находится в "тупике") 36 | x, y = coordinates(robot) 37 | dx = dy = 0.5 38 | if (pre_ort, cur_ort) == (Sud,Nord) 39 | push!(xdata,x+dx) 40 | push!(ydata,y-dy) 41 | push!(xdata,x-dx) 42 | push!(ydata,y-dy) 43 | elseif (pre_ort, cur_ort) == (Ost,West) 44 | push!(xdata,x+dx) 45 | push!(ydata,y+dy) 46 | push!(xdata,x+dx) 47 | push!(ydata,y-dy) 48 | elseif (pre_ort, cur_ort) == (Nord,Sud) 49 | push!(xdata,x-dx) 50 | push!(ydata,y+dy) 51 | push!(xdata,x+dx) 52 | push!(ydata,y+dy) 53 | elseif (pre_ort, cur_ort) == (West,Ost) 54 | push!(xdata,x-dx) 55 | push!(ydata,y-dy) 56 | push!(xdata,x-dx) 57 | push!(ydata,y+dy) 58 | else 59 | error("Ошибка в выкладках!!!") 60 | end 61 | pre_ort=ort(robot) 62 | end 63 | 64 | end 65 | push!(xdata,xdata[1]) 66 | push!(ydata,ydata[1]) 67 | return xdata, ydata 68 | end 69 | 70 | function movements_to_ymin!(robot::TypeRobot) where TypeRobot 71 | gran_robot = GranRobot{TypeRobot}(robot) 72 | pre_ort=ort(gran_robot) # - ориентация Робота на предыдущем шаге при движении вдоль границы 73 | 74 | y_min = coordinates(gran_robot).y 75 | for robot in gran_robot 76 | y = coordinates(robot).y 77 | if y display 102 | 103 | robot_path=RobotPath{Robot}(robot) 104 | end_coords=movements_to_ymin!(robot_path) 105 | #УТВ: Робот - в самой нижней клетке возле лабиринта 106 | 107 | dy = get_num_movements!(robot_path,Sud) 108 | #УТВ: Робот - возле внешней рамки (на южной стороне) 109 | 110 | xdata, ydata = data_plan_gran(robot_path, (x=end_coords.x, y=end_coords.y - dy)) 111 | plot!(xdata,ydata; ratio=:equal, legend=false) |> display 112 | 113 | movements_to_back!(robot_path) 114 | #УТВ: Робот - в исходном положении 115 | 116 | show!(robot) 117 | -------------------------------------------------------------------------------- /12-15/practica-4.2.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | include("horizonside.jl") 3 | #------------------------------------------------------------------------------------------------------------------------- 4 | 5 | mutable struct Decart 6 | coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}} 7 | 8 | Decart(coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}}) = new(coordinates) 9 | end 10 | 11 | function coordinates!(decart::Decart, side::HorizonSide) 12 | x = decart.coordinates.x 13 | y = decart.coordinates.y 14 | if side == Ost 15 | x+=1 16 | elseif side == West 17 | x-=1 18 | elseif side == Nord 19 | y+=1 20 | else 21 | y-=1 22 | end 23 | decart.coordinates = (;x,y); #(x=x,y=y) 24 | end 25 | 26 | coordinates(decart::Decart) = decart.coordinates 27 | 28 | #-------------------------------------------------------------------------------------------------------------------------- 29 | 30 | 31 | #??? Чем же тогда этот тип отличатся от AbstractRobot 32 | abstract type AbstractTypeRobot 33 | #robot::TypeRobot - у всех производных типов предполагается наличие поля некоторого типа, у которого имеется поле robot::TypeRobot (TypeRobot вклютает интефес Robot) 34 | end 35 | 36 | #HorizonSideRobots.move!(robot::AbstractRobot, side) = move!(robot.robot, side) 37 | HorizonSideRobots.isborder(robot::AbstractTypeRobot, side) = HorizonSideRobots.isborder(robot.robot, side) 38 | HorizonSideRobots.putmarker!(robot::AbstractTypeRobot) = HorizonSideRobots.putmarker!(robot.robot) 39 | HorizonSideRobots.ismarker(robot::AbstractTypeRobot) = HorizonSideRobots.ismarker(robot.robot) 40 | HorizonSideRobots.temperature(robot::AbstractTypeRobot) = HorizonSideRobots.temperature(robot.robot) 41 | HorizonSideRobots.show!(robot::AbstractTypeRobot) = HorizonSideRobots.show!(robot.robot) 42 | 43 | #-------------------------------------------------------------------------------------------------------------------------------- 44 | abstract type AbstractOrtTypeRobot <: AbstractTypeRobot 45 | #robot::TypeRobot - наличие этих полей пердполагается у всех производных типов 46 | #ort::HorizonSide 47 | end 48 | 49 | #forvard!(robot::AbstractOrtTypeRobot) = HorizonSideRobots.move!(robot.robot.robot, robot.ort) 50 | forvard!(robot::AbstractOrtTypeRobot) = HorizonSideRobots.move!(robot.robot, robot.ort) 51 | 52 | function rotation!(robot::AbstractOrtTypeRobot, rotation::Function) 53 | # rotation = lift | right | inverse - функции из "horizonside.jl" 54 | robot.ort = rotation(robot.ort) 55 | end 56 | 57 | #isborder(robot::AbstractOrtTypeRobot, rotation::Function) = HorizonSideRobots.isborder(robot.robot.robot, rotation(robot.ort)) 58 | #isborder(robot::AbstractOrtTypeRobot) = HorizonSideRobots.isborder(robot.robot.robot, robot.ort) 59 | 60 | HorizonSideRobots.isborder(robot::AbstractOrtTypeRobot, rotation::Function) = HorizonSideRobots.isborder(robot.robot, rotation(robot.ort)) 61 | # rotation = lift | right | inverse - функции из "horizonside.jl" 62 | 63 | HorizonSideRobots.isborder(robot::AbstractOrtTypeRobot) = HorizonSideRobots.isborder(robot.robot, robot.ort) 64 | 65 | ort(robot::AbstractOrtTypeRobot) = robot.ort 66 | 67 | #-------------------------------------------------------------------------------------------------------------------------- 68 | 69 | include("horizonside.jl") 70 | 71 | mutable struct OrtTypeRobot{TypeRobot <: Union{AbstractTypeRobot, Robot}} <: AbstractOrtTypeRobot 72 | robot::TypeRobot 73 | ort::HorizonSide 74 | 75 | OrtTypeRobot{TypeRobot}(robot, ort) where TypeRobot = new(robot, ort) 76 | OrtTypeRobot{TypeRobot}(robot) where TypeRobot = OrtTypeRobot{TypeRobot}(robot, Nord) 77 | end 78 | 79 | #-------------------------------------------------------------------------------------------------------- 80 | 81 | mutable struct GranTypeRobot{TypeRobot <: Union{AbstractTypeRobot, Robot}} <: AbstractOrtTypeRobot 82 | robot::TypeRobot 83 | ort::HorizonSide 84 | 85 | decart::Decart 86 | num_steps::Int 87 | 88 | function GranTypeRobot{TypeRobot}(robot::TypeRobot) where {TypeRobot <: Union{AbstractTypeRobot, Robot}} 89 | # Надо развернуть Робота так, чтобы слева была граница и можно было бы сделать шаг вперед 90 | # Если рядом с Роботом вообще нет перегородок, или, наоборот, он ограничен со всех 4-х сторон, то тогода - прерывание 91 | if isa(robot, Robot) 92 | ort_robot = OrtTypeRobot{Robot}(robot) 93 | else 94 | ort_robot = OrtTypeRobot{Robot}(robot.robot) 95 | end 96 | 97 | n=0 98 | while !isborder(ort_robot) 99 | rotation!(ort_robot, left) 100 | n+=1 101 | if n > 3 102 | error("Рядом с Роботом нет перегородки ни с одной из сторон") 103 | end 104 | end 105 | #УТВ: Спереди от Робота перегородка 106 | n=0 107 | while isborder(ort_robot) 108 | rotation!(ort_robot, right) 109 | n+=1 110 | if n > 3 111 | error("Робот со всех сторон ограничен перегородками") 112 | end 113 | end 114 | #УТВ: слева от Робота - перегородка, спереди - свободно 115 | new(robot, ort(ort_robot), Decart((x=0,y=0)), 0) #, positive) 116 | end 117 | end # struct GranTypeRobot 118 | 119 | 120 | function move!(robot::GranTypeRobot) 121 | forvard!(robot) 122 | coordinates!(robot.decart, ort(robot)) 123 | print("*") 124 | if !isborder(robot, left) 125 | rotation!(robot, left) 126 | else 127 | while isborder(robot) 128 | rotation!(robot, right) 129 | end 130 | end 131 | #УТВ: Робот развернут так, чтобы следующий шаг вперед будет шагом вдоль границы 132 | print("*") 133 | robot.num_steps += 1 134 | end 135 | 136 | coordinates(robot::GranTypeRobot) = coordinates(robot.decart) 137 | num_steps(robot::GranTypeRobot) = robot.num_steps 138 | 139 | 140 | #------------------------------------------------------------------------------------------------------ 141 | 142 | function around(robot::GranTypeRobot{TypeRobot}) where {TypeRobot} # ??? <: AbstractDecartRobot} 143 | # Заставляет Робота, находящегося возле границы лабиринта, совершить ее полный обход и остановиться в исходном положении 144 | start_ort = ort(robot) 145 | start_coords = coordinates(robot) 146 | 147 | move!(robot) 148 | while coordinates(robot) != start_coords || ort(robot) != start_ort 149 | move!(robot) 150 | end 151 | end 152 | 153 | #---------------------------------------------------- 154 | 155 | struct RobotPutmarker <: AbstractTypeRobot 156 | robot::Robot 157 | end 158 | HorizonSideRobots.move!(robot::RobotPutmarker,side::HorizonSide) = begin 159 | HorizonSideRobots.move!(robot.robot,side) 160 | HorizonSideRobots.putmarker!(robot.robot) 161 | end 162 | #-==========================================ИСПОЛНЯЕМАЯ ЧАСТЬ ФАЙЛА======================================================== 163 | 164 | robot = Robot(animate=true) 165 | robot_putmarker = RobotPutmarker(robot) 166 | gran_robot = GranTypeRobot{RobotPutmarker}(robot_putmarker) -------------------------------------------------------------------------------- /12-15/practica-4.3.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | include("horizonside.jl") 3 | 4 | #= 5 | ------------------------------------------------------------------------------- 6 | АБСТРАКТНЫЕ ТИПЫ 7 | ------------------------------------------------------------------------------- 8 | =# 9 | abstract type AbstractRobot 10 | #robot::TypeRobot - наличие этого поля предполагается у всех производных типов (интерфес типа TypeRobot должен включать интерфейс типа Robot) 11 | end 12 | 13 | #HorizonSideRobots.move!(robot::AbstractRobot, side) = move!(robot.robot, side) 14 | HorizonSideRobots.isborder(robot::AbstractRobot, side) = isborder(robot.robot, side) 15 | HorizonSideRobots.putmarker!(robot::AbstractRobot) = putmarker!(robot.robot) 16 | HorizonSideRobots.ismarker(robot::AbstractRobot) = ismarker(robot.robot) 17 | HorizonSideRobots.temperature(robot::AbstractRobot) = temperature(robot.robot) 18 | HorizonSideRobots.show!(robot::AbstractRobot) = show!(robot.robot) 19 | #-------------------------------------------------------------------------------------------------------------------------- 20 | 21 | abstract type AbstractRobotDecart <: AbstractRobot 22 | #robot::Robot - наличие этих полей предполагается у всех производных типов 23 | #decart::Decart 24 | end 25 | 26 | coordinates(robot::AbstractRobotDecart) = coordinates(robot.decart) 27 | 28 | HorizonSideRobots.move!(robot::AbstractRobotDecart, side::HorizonSide) = begin 29 | move!(robot.robot, side) # - здесь требуется префикс "HorizonSideRobots." потому что в текущем пространстве 30 | coordinates!(robot.decart,side) 31 | end 32 | 33 | #-------------------------------------------------------------------------------------------------------------------------- 34 | 35 | abstract type AbstractOrtRobot <: AbstractRobot 36 | #robot::TypeRobot - наличие этих полей предполагается у всех производных типов (интерфес типа TypeRobot должен включать интерфейс типа Robot) 37 | #ort::HorizonSide 38 | end 39 | 40 | forvard!(robot::AbstractOrtRobot) = move!(robot.robot, robot.ort) 41 | 42 | function rotation!(robot::AbstractOrtRobot, rotation::Function) 43 | # rotation = left | right | inverse - функции из "horizonside.jl" 44 | robot.ort = rotation(robot.ort) 45 | end 46 | 47 | HorizonSideRobots.isborder(robot::AbstractOrtRobot, rotation::Function) = isborder(robot.robot, rotation(robot.ort)) 48 | # rotation = lift | right | inverse - функции из "horizonside.jl" 49 | 50 | HorizonSideRobots.isborder(robot::AbstractOrtRobot) = isborder(robot.robot, robot.ort) 51 | 52 | ort(robot::AbstractOrtRobot) = robot.ort 53 | 54 | #= 55 | ------------------------------------------------------------------------------- 56 | ИЕРАРХИЯ АБСТРАКТНЫХ ТИПОВ: 57 | 58 | Any 59 | |___AbstractRobot (функции: isborder, putmatker!, ismarker, temperature, show!) 60 | |___AbstractRobotDecart (дополнительные и переопределенные функции: move!, coordinates) 61 | | 62 | |___AbstractOrtRobot (дополнительные и переопределенные функции: forvard!, isborder, rotation!) 63 | -------------------------------------------------------------------------------------------------------------------------- 64 | КОНКРЕТНЫЕ ТИПЫ (в том числе - параметрические): 65 | ------------------------------------------------------------------------------------------------------------------------- 66 | =# 67 | mutable struct Decart 68 | coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}} 69 | 70 | Decart(coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}}) = new(coordinates) 71 | end 72 | 73 | function coordinates!(decart::Decart, side::HorizonSide) 74 | x = decart.coordinates.x 75 | y = decart.coordinates.y 76 | if side == Ost 77 | x+=1 78 | elseif side == West 79 | x-=1 80 | elseif side == Nord 81 | y+=1 82 | else 83 | y-=1 84 | end 85 | decart.coordinates = (;x,y); #(x=x,y=y) 86 | end 87 | 88 | coordinates(decart::Decart) = decart.coordinates 89 | 90 | #-------------------------------------------------------------------------------------------------------------------------- 91 | 92 | struct RobotDecart{TypeRobot} <: AbstractRobotDecart 93 | robot::TypeRobot 94 | decart::Decart 95 | 96 | RobotDecart{TypeRobot}(robot, coords) where TypeRobot = new(robot, Decart(coords)) 97 | RobotDecart{TypeRobot}(robot) where TypeRobot = RobotDecart(robot, (x=0, y=0)) 98 | end 99 | 100 | #-------------------------------------------------------------------------------------------------------------------------- 101 | 102 | mutable struct OrtRobot{TypeRobot} <: AbstractOrtRobot 103 | robot::TypeRobot 104 | ort::HorizonSide 105 | 106 | OrtRobot{TypeRobot}(robot, ort) where TypeRobot = new(robot, ort) 107 | OrtRobot{TypeRobot}(robot) where TypeRobot = OrtRobot{TypeRobot}(robot, Nord) 108 | end 109 | #-------------------------------------------------------------------------------------------------------------------------- 110 | 111 | mutable struct GranRobot{TypeRobot} 112 | robot::OrtRobot{TypeRobot} 113 | 114 | decart::Decart 115 | num_steps::Int 116 | 117 | function GranRobot{TypeRobot}(robot::TypeRobot) where TypeRobot 118 | # Надо развернуть Робота так, чтобы слева была граница и можно было бы сделать шаг вперед 119 | # Если рядом с Роботом вообще нет перегородок, или, наоборот, он ограничен со всех 4-х сторон, то тогода - прерывание 120 | ort_robot = OrtRobot{TypeRobot}(robot) 121 | n=0 122 | while !isborder(ort_robot) 123 | rotation!(ort_robot, left) 124 | n+=1 125 | if n > 3 126 | error("Рядом с Роботом нет перегородки ни с одной из сторон") 127 | end 128 | end 129 | #УТВ: Спереди от Робота перегородка 130 | n=0 131 | while isborder(ort_robot) 132 | rotation!(ort_robot, right) 133 | n+=1 134 | if n > 3 135 | error("Робот со всех сторон ограничен перегородками") 136 | end 137 | end 138 | #УТВ: слева от Робота - перегородка, спереди - свободно 139 | new(ort_robot, Decart((x=0,y=0)), 0) #, positive) 140 | end 141 | end # struct GranRobot{TypeRobot} 142 | 143 | 144 | function forvard!(robot::GranRobot) 145 | forvard!(robot.robot) 146 | coordinates!(robot.decart, ort(robot)) 147 | 148 | if !isborder(robot.robot, left) 149 | rotation!(robot.robot, left) 150 | else 151 | while isborder(robot.robot) 152 | rotation!(robot.robot, right) 153 | end 154 | end 155 | #УТВ: Робот развернут так, чтобы следующий шаг вперед будет шагом вдоль границы в положительном направлении 156 | 157 | robot.num_steps += 1 158 | end 159 | 160 | coordinates(robot::GranRobot) = coordinates(robot.decart) 161 | 162 | num_steps(robot::GranRobot) = robot.num_steps 163 | 164 | ort(robot::GranRobot) = ort(robot.robot) 165 | 166 | function around!(robot::GranRobot) 167 | # Заставляет Робота, находящегося возле границы лабиринта, совершить ее полный обход и остановиться в исходном положении 168 | start_ort = ort(robot) 169 | start_coords = coordinates(robot) 170 | 171 | forvard!(robot) 172 | while coordinates(robot) != start_coords || ort(robot) != start_ort 173 | forvard!(robot) 174 | #putmarker!(robot) 175 | end 176 | end 177 | 178 | #----------------------------------------------------------------------------------------------------------------- 179 | #= 180 | ИЕРАРХИЯ ИЕРАРХИЯ АБСТРАКТНЫХ И КОНКРЕТНЫХ ТИПОВ ТИПОВ: 181 | 182 | Any 183 | |___Decart (интерфейс: coordinates!, coordinates) 184 | |___AbstractRobot (интерфейс: isborder, putmatker!, ismarker, temperature, show!) 185 | | |___AbstractRobotDecart (дополнительные функции: move!, coordinates) 186 | | | 187 | | |___RobotDecart{TypeRobot} - параметрический конкретный тип 188 | | | 189 | | |___AbstractOrtRobot (дополнительные/переопределенные функции: forvard!, isborder, rotation!) 190 | | | 191 | | |___OrtRobot{TypeRobot} - параметрический конкретный тип 192 | | 193 | |___GranRobot{TypeRobot} (forvard!, coordinates, num_steps, ort, around!) 194 | =# 195 | #------------------------------------------------------------------------------------------------------------------------- 196 | 197 | #------------------------------------------------------------------------------------------------------------------------- 198 | struct RobotPutmarker <: AbstractRobot 199 | robot::Robot 200 | end 201 | HorizonSideRobots.move!(robot::RobotPutmarker,side::HorizonSide) = begin 202 | move!(robot.robot,side) 203 | putmarker!(robot.robot) 204 | end 205 | 206 | #------------------------------------------------------------------------------------------------------------------------- 207 | mutable struct RobotMaxTmpr <: AbstractRobot 208 | robot::Robot 209 | max_temperature::Int 210 | end 211 | HorizonSideRobots.move!(robot::RobotMaxTmpr,side::HorizonSide) = begin 212 | move!(robot.robot, side) 213 | t = temperature(robot.robot) 214 | if t > robot.max_temperature 215 | robot.max_temperature = t 216 | end 217 | end 218 | #------------------------------------------------------------------------------------------------------------------------- 219 | #-==========================================ИСПОЛНЯЕМАЯ ЧАСТЬ ФАЙЛА======================================================== 220 | 221 | robot = Robot("labirint.sit"; animate = true) 222 | #= 223 | robot_putmarker = RobotPutmarker(robot) 224 | gran_robot = GranRobot{RobotPutmarker}(robot_putmarker) 225 | around!(gran_robot) 226 | =# 227 | robot_max_tmpr = RobotMaxTmpr(robot, temperature(robot)) 228 | gran_robot = GranRobot{RobotMaxTmpr}(robot_max_tmpr) 229 | around!(gran_robot) 230 | robot_max_tmpr.max_temperature |> println -------------------------------------------------------------------------------- /12-15/robot_types_1.jl: -------------------------------------------------------------------------------- 1 | #Вспомогательный тип: 2 | mutable struct Decart 3 | coordinates::NamedTuple{(:x,:y), Tuple{Int,Int}} 4 | 5 | Decart(coordinates::NamedTuple{(:x,:y), Tuple{Int,Int}}) = new(coordinates) 6 | end 7 | 8 | function coordinates!(decart::Decart, side::HorizonSide) 9 | x = decart.coordinates.x 10 | y = decart.coordinates.y 11 | if side == Ost 12 | x += 1 13 | elseif side == West 14 | x -= 1 15 | elseif side == Nord 16 | y += 1 17 | else 18 | y -= 1 19 | end 20 | decart.coordinates = (;x,y); #(x=x,y=y) 21 | end 22 | 23 | coordinates(decart::Decart) = decart.coordinates 24 | 25 | #= 26 | --------------------------------------------------------------------------------------------------------------------------- 27 | АБСТРАКТНЫЕ ТИПЫ: 28 | --------------------------------------------------------------------------------------------------------------------------- 29 | =# 30 | abstract type AbstractRobot 31 | #robot::TypeRobot - наличие этого поля предполагается у всех производных типов (интерфес типа TypeRobot должен включать интерфейс типа Robot) 32 | end 33 | 34 | #HorizonSideRobots.move!(robot::AbstractRobot, side) = move!(robot.robot, side) 35 | HorizonSideRobots.isborder(robot::AbstractRobot, side) = isborder(robot.robot, side) 36 | HorizonSideRobots.putmarker!(robot::AbstractRobot) = putmarker!(robot.robot) 37 | HorizonSideRobots.ismarker(robot::AbstractRobot) = ismarker(robot.robot) 38 | HorizonSideRobots.temperature(robot::AbstractRobot) = temperature(robot.robot) 39 | HorizonSideRobots.show!(robot::AbstractRobot) = show!(robot.robot) 40 | #-------------------------------------------------------------------------------------------------------------------------- 41 | 42 | abstract type AbstractRobotDecart <: AbstractRobot 43 | #robot::Robot - наличие этих полей предполагается у всех производных типов 44 | #decart::Decart 45 | end 46 | 47 | coordinates(robot::AbstractRobotDecart) = coordinates(robot.decart) 48 | 49 | HorizonSideRobots.move!(robot::AbstractRobotDecart, side::HorizonSide) = begin 50 | move!(robot.robot, side) # - здесь требуется префикс "HorizonSideRobots." потому что в текущем пространстве 51 | coordinates!(robot.decart,side) 52 | end 53 | 54 | #= 55 | --------------------------------------------------------------------------------------------------------------------------- 56 | ИМЕЮЩАЯСЯ ИЕРАРХИЯ АБСТРАКТНЫХ ТИПОВ: 57 | Any 58 | |___AbstractRobot (функции: isborder, putmatker!, ismarker, temperature, show!) 59 | |___AbstractRobotDecart (дополнительные и переопределенные функции: move!, coordinates) 60 | --------------------------------------------------------------------------------------------------------------------------- 61 | =# 62 | 63 | #-------------------------------------------------------------------------------------------------------------------------- 64 | 65 | struct RobotDecart{TypeRobot} <: AbstractRobotDecart 66 | robot::TypeRobot 67 | decart::Decart 68 | 69 | RobotDecart{TypeRobot}(robot, coords) where TypeRobot = new(robot, Decart(coords)) 70 | RobotDecart{TypeRobot}(robot) where TypeRobot = RobotDecart(robot, (x=0, y=0)) 71 | end 72 | 73 | #-------------------------------------------------------------------------------------------------------------------------- 74 | 75 | mutable struct OrtRobot{TypeRobot} <: AbstractRobot 76 | robot::TypeRobot 77 | ort::HorizonSide 78 | 79 | OrtRobot{TypeRobot}(robot, ort) where TypeRobot = new(robot, ort) 80 | OrtRobot{TypeRobot}(robot) where TypeRobot = OrtRobot{TypeRobot}(robot, Nord) 81 | end 82 | 83 | forvard!(robot::OrtRobot) = move!(robot.robot, robot.ort) 84 | 85 | function rotation!(robot::OrtRobot, rotation::Function) 86 | # rotation = left | right | inverse - функции из "horizonside.jl" 87 | robot.ort = rotation(robot.ort) 88 | end 89 | 90 | HorizonSideRobots.isborder(robot::OrtRobot, rotation::Function) = isborder(robot.robot, rotation(robot.ort)) 91 | # rotation = left | right | inverse - функции из "horizonside.jl" 92 | 93 | HorizonSideRobots.isborder(robot::OrtRobot) = isborder(robot.robot, robot.ort) 94 | 95 | ort(robot::OrtRobot) = robot.ort 96 | 97 | #-------------------------------------------------------------------------------------------------------------------------- 98 | 99 | mutable struct GranRobot{TypeRobot} <: AbstractRobotDecart 100 | robot::OrtRobot{TypeRobot} 101 | decart::Decart 102 | num_steps::Int 103 | num_rotations::Int 104 | 105 | GranRobot{TypeRobot}(robot::TypeRobot) where TypeRobot = GranRobot{TypeRobot}(robot, (x=0, y=0)) 106 | 107 | function GranRobot{TypeRobot}(robot::TypeRobot, begin_coords) where TypeRobot 108 | # Надо развернуть Робота так, чтобы слева была граница и можно было бы сделать шаг вперед 109 | # Если рядом с Роботом вообще нет перегородок, или, наоборот, он ограничен со всех 4-х сторон, то тогода - прерывание 110 | ort_robot = OrtRobot{TypeRobot}(robot) 111 | n=0 112 | while !isborder(ort_robot) 113 | rotation!(ort_robot, left) 114 | n+=1 115 | if n > 3 116 | error("Рядом с Роботом нет перегородки ни с одной из сторон") 117 | end 118 | end 119 | #УТВ: Спереди от Робота перегородка 120 | n=0 121 | while isborder(ort_robot) 122 | rotation!(ort_robot, right) 123 | n+=1 124 | if n > 3 125 | error("Робот со всех сторон ограничен перегородками") 126 | end 127 | end 128 | #УТВ: слева от Робота - перегородка, спереди - свободно 129 | new(ort_robot, Decart((x=begin_coords.x,y=begin_coords.y)), 0, 0) #, positive) 130 | end 131 | end # struct GranRobot{TypeRobot} 132 | 133 | 134 | function forvard!(robot::GranRobot) 135 | #Перемещает Робота вдоль границы в положительном направлении в соседнюю клетку 136 | #и добавляет число сделанных при этом поворотов, с учетом их знака, к значению robot.num_rotations 137 | forvard!(robot.robot) 138 | coordinates!(robot.decart, ort(robot)) 139 | if !isborder(robot.robot, left) 140 | rotation!(robot.robot, left) 141 | robot.num_rotations += 1 142 | else 143 | while isborder(robot.robot) 144 | rotation!(robot.robot, right) 145 | robot.num_rotations -= 1 146 | end 147 | end 148 | #УТВ: Робот развернут так, чтобы следующий шаг вперед будет шагом вдоль границы в положительном направлении 149 | 150 | robot.num_steps += 1 151 | end 152 | 153 | HorizonSideRobots.isborder(robot::GranRobot) = isborder(robot.robot) 154 | HorizonSideRobots.isborder(robot::GranRobot, rotation::Function) = isborder(robot.robot, rotation) 155 | num_steps(robot::GranRobot) = robot.num_steps 156 | ort(robot::GranRobot) = ort(robot.robot) 157 | num_rotations(robot::GranRobot) = robot.num_rotations 158 | 159 | function around!(robot::GranRobot) 160 | # Заставляет Робота, находящегося возле границы лабиринта, совершить ее полный обход и остановиться в исходном положении 161 | start_ort = ort(robot) 162 | start_coords = coordinates(robot) 163 | 164 | forvard!(robot) 165 | while coordinates(robot) != start_coords || ort(robot) != start_ort 166 | forvard!(robot) 167 | #putmarker!(robot) 168 | end 169 | end 170 | 171 | function around!(action::Function, robot::GranRobot) 172 | # Заставляет Робота, находящегося возле границы лабиринта, совершить ее полный обход и остановиться в исходном положении, 173 | # выполняя после каждого шага action() 174 | start_ort = ort(robot) 175 | start_coords = coordinates(robot) 176 | 177 | forvard!(robot) 178 | action() 179 | while coordinates(robot) != start_coords || ort(robot) != start_ort 180 | forvard!(robot) 181 | action() 182 | end 183 | end 184 | #----------------------------------------------------------------------------- 185 | 186 | # Итератор для обхода границы: 187 | Base.iterate(robot::GranRobot) = begin 188 | start_coordinates = coordinates(robot) 189 | start_ort = ort(robot) 190 | forvard!(robot) 191 | return robot, (start_coordinates, start_ort) 192 | end 193 | 194 | Base.iterate(robot::GranRobot, state::Tuple) = begin 195 | if state == (coordinates(robot), ort(robot)) 196 | return nothing 197 | end 198 | forvard!(robot) 199 | return robot, state 200 | end 201 | -------------------------------------------------------------------------------- /12-15/robot_types_2.jl: -------------------------------------------------------------------------------- 1 | abstract type AbstractTryRobot <: AbstractRobot 2 | #robot::TypeRobot 3 | end 4 | 5 | HorizonSideRobots.move!(robot::AbstractTryRobot, side) = 6 | if isborder(robot, side) 7 | return false 8 | else 9 | move!(robot.robot, side) 10 | return true 11 | end 12 | 13 | movements!(robot::AbstractTryRobot, side) = 14 | while move!(robot, side)==true 15 | end 16 | 17 | movements!(robot::AbstractTryRobot, action::Function, side) = 18 | while move!(robot, side)==true 19 | action() 20 | end 21 | 22 | movements!(robot::AbstractTryRobot, side, num_steps::Integer) = 23 | for _ in 1:num_steps 24 | move!(robot, side) 25 | end 26 | 27 | function get_num_movements!(robot::AbstractTryRobot, side) 28 | num_steps=0 29 | while move!(robot, side)==true 30 | num_steps+=1 31 | end 32 | return num_steps 33 | end 34 | 35 | #--------------------------------------------------------------------------------------- 36 | struct TryRobot{TypeRobot <: Union{Robot,AbstractRobot}} <: AbstractTryRobot 37 | robot::TypeRobot 38 | end 39 | #----------------------------------------------------------------------------------------- 40 | 41 | struct RectangularBordersRobot{TypeRobot <: Union{Robot,AbstractRobot}} <: AbstractTryRobot 42 | robot::TypeRobot 43 | end 44 | 45 | function HorizonSideRobots.move!(side)::Bool 46 | # Перемещает Робота на один шаг в заданном направлении с обходом прямоугольной перегородки, если она стоит на пути 47 | num_steps = 0 48 | while isborder(robot, side) && !isborder(robot, left(side)) 49 | move!(robot, left(side)) #!!! 50 | num_steps+=1 51 | end 52 | #УТВ: Робот стоит за краем перегородки, которую пытался обойти в поперечном направлении, или в углу, если это была внешняя рамка 53 | 54 | ansver = move!(robot, side) 55 | if num_steps==0 # Робот не выполнял попытки обхода (перегородки на его пути не было) 56 | return ansver # == true 57 | end 58 | while isborder(robot, right(side)) 59 | if isborder(robot, side) 60 | ansver = false # Робот уперся в угол (перегородка не является прямоугольной!) 61 | while isborder(robot, right(side)) 62 | move!(robot, inverse(side)) 63 | end 64 | #УТВ: Робот возвращен на уровень переднего фронта перегородки 65 | break 66 | end 67 | #УТВ: перегородка, возможно, является прямоугольной 68 | move!(robot, side) 69 | end 70 | #УТВ: Робот прошел сбоку от перегородки за её пределы 71 | try_robot = TryRobot(robot) 72 | movements!(try_robot, right(side), num_steps) 73 | #УТВ: Робот возвращен на главную линию своего движения 74 | return ansver 75 | end 76 | 77 | #------------------------------------------------------------------ 78 | 79 | mutable struct SnakeRobot{TypeRobot <: Union{Robot, AbstractRobot}} <: AbstractRobot 80 | robot::TypeRobot 81 | fold_direct::HorizonSide 82 | genral_direct::HorizonSide 83 | is_begin_fold::Bool 84 | 85 | SnakeRobot{TypeRobot}(robot::TypeRobot, fold_direct, general_direct) where TypeRobot = new(robot,fold_direct, general_direct, true) 86 | end 87 | 88 | is_begin_fold(snake::SnakeRobot) = snake.is_begin_fold 89 | 90 | Base.iterate(snake::SnakeRobot) = begin 91 | return (snake, nothing) 92 | end 93 | 94 | Base.iterate(snake::SnakeRobot, ::Any) = begin 95 | if isborder(snake, fold_direct) 96 | if isborder(snake, general_direct) 97 | return nothing # змейка закончилась 98 | end 99 | move!(snake.robot, snake.general_direct) 100 | snake.fold_direct = inverse(snake.fold_direct) 101 | snake.is_begin_fold = true 102 | else 103 | move!(snake.robot, snake.fold_direct) 104 | snake.is_begin_fold = false 105 | end 106 | return snake, nothing 107 | end 108 | #------------------------------------------------------------------------------- 109 | 110 | mutable struct SpiralRobot{TypeRobot} <: AbstractRobot 111 | robot::TypeRobot 112 | side::HorizonSide 113 | max_num_steps::Int 114 | num_steps::Int 115 | num_rotations::Int 116 | SpiralRobot{TypeRobot}(robot) where TypeRobot = new(robot,Nord,1,0,0) 117 | end 118 | 119 | Base.iterate(::SpiralRobot) = begin 120 | move!(spiral.robot,spiral.side) 121 | spiral.num_steps += 1 122 | spiral.side = left(spiral.side) 123 | spiral.num_rotations += 1 124 | return (spiral, nothing) 125 | end 126 | 127 | Base.iterate(::SpiralRobot, ::Any) = begin 128 | if spiral.num_steps == spiral.max_num_steps 129 | spiral.side = left(spiral.side) 130 | spiral.num_rotations += 1 131 | end 132 | move!(spiral.robot,spiral.side) 133 | if iseven(spiral.num_rotations) 134 | spiral.max_num_steps += 1 135 | end 136 | return (spiral, nothing) 137 | end 138 | 139 | #-------------------------------------------------------------------------- 140 | 141 | struct RobotPath{TypeRobot<:Union{Robot,AbstractRobot}} <: AbstractRobot 142 | robot::TypeRobot 143 | path_sides::Vector{HorizonSide} 144 | path_num_steps::Vector{Int} 145 | RobotPath{TypeRobot}(robot) where TypeRobot = new(robot, HorizonSide[], Int[]) 146 | end 147 | 148 | """ 149 | move!(robot, side) 150 | 151 | -- перемещает Робота в заданном направлении в соседнюю клетку 152 | """ 153 | function HorizonSideRobots.move!(robot::RobotPath, side) 154 | if isempty(robot.path_sides) || robot.path_sides[end]!=side 155 | push!(robot.path_sides, side) 156 | push!(robot.path_num_steps, 1) 157 | else 158 | robot.path_num_steps[end] += 1 159 | end 160 | move!(robot.robot,side) # - то, что эта инструкция выполняется последней, - это может быть существенно, если функция move! возвращает значение (отличное от nothing), логическое, например 161 | end 162 | 163 | """ 164 | movements_to_back!(robot) 165 | 166 | -- возвращает Робота из конца своего маршрута в исходное положение 167 | """ 168 | movements_to_back!(robot) = 169 | for (i,side) in enumerate(reverse(robot.path_sides)) 170 | movements!(robot.robot, inverse(side), reverse(robot.path_num_steps)[i]) 171 | end 172 | #------------------------------------------------------------------------------------------ -------------------------------------------------------------------------------- /12-15/Лекция-12.md: -------------------------------------------------------------------------------- 1 | # Лекция 12 2 | 3 | ## Реализация исполнителя "Декарт" на основе соответствующей структуры 4 | 5 | Реализовать исполнителя "Декарт" можно было бы еще и на основе проектирования соответствующего пользовательского типа данных (следующий код находится в файле ["type_decart.jl"](type_decart.jl)) 6 | 7 | ```julia 8 | using HorizonSideRobots 9 | 10 | mutable struct Decart 11 | coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}} 12 | 13 | Decart(coordinates::NamedTuple{(:x,:y),Tuple{Int,Int}}) = new(coordinates) 14 | end 15 | 16 | function coordinates!(decart::Decart, side::HorizonSide) 17 | x = decart.coordinates.x 18 | y = decart.coordinates.y 19 | if side == Ost 20 | x+=1 21 | elseif side == West 22 | x-=1 23 | elseif side == Nord 24 | y+=1 25 | else 26 | y-=1 27 | end 28 | decart.coordinates = (;x,y); #(x=x,y=y) 29 | end 30 | 31 | coordinates(decart::Decart) = decart.coordinates 32 | ``` 33 | 34 | Функциональный нтерфейс в данном случае составляют две функции: `coordinates!(::Decart, ::HorizonSide)` и `coordinates(::Decart)` 35 | 36 | Протестировать эти функции можн, например, так: 37 | 38 | ```julia 39 | include("type_decart.jl") 40 | decart = Decart((x=0,y=0)) 41 | 42 | coordinates(decart) |> println # (x=0,y=0) 43 | coordinates!(decart, Nord) |> println # (x=0,y=1) 44 | ``` 45 | 46 | Стоить обратить внимание на полное соответствие данной реализации исполнителя "Декарт" с реализованной ранее в функциональном стиле (см. ["10/interface_decart.jl](../10/interface_decart.jl)). 47 | 48 | Важно также заметить, что в обоих случаях данные и работающие с ними функции представляют собой единое целое (исполнителя). Только в случае функционального программирования к функциям добавляются данные (функции замыкают эти данные), а в случае объектно-ориентированного стиля программирования, наоборот, к данным добавляются функции, получающие эти данные в иде аргументов. 49 | 50 | ## Реализация (создание) интерфейса исполнителя "Робот-Декарт" с помомощью структуры 51 | 52 | Ранее исполнитель "Робот-Декарт" был реализован в функциональном стиле, см. ["10/interface_robot_decart.jl"](../10/interface_robot_decart.jl) 53 | 54 | ```julia 55 | # в этом же файле выше был определен тип Decart 56 | 57 | using HorizonSideRobots 58 | 59 | struct RobotDecart 60 | robot::Robot # - АГРЕГИРОВАНИЕ объекта типа Robot (композиция типов) https://ru.wikipedia.org/wiki/Агрегирование(программирование) 61 | decart::Decart # - АГРЕГИРОВАНИЕ объекта типа Decart 62 | 63 | RobotDecart(robot, coords) = new(robot, Decart(coords)) 64 | RobotDecart(robot) = RobotDecart(robot, (x=0, y=0)) 65 | end 66 | 67 | HorizonSideRobots.move!(robot::RobotDecart, side) = begin # (move!(robot.robot, side); coodinates!(robot.decart,side)) 68 | move!(robot.robot, side) 69 | coodinates!(robot.decart,side) 70 | end 71 | HorizonSideRobots.isborder(robot::RobotDecart, side) = isborder(robot.robot, side) 72 | HorizonSideRobots.putmarker!(robot::RobotDecart) = putmarker!(robot.robot) 73 | HorizonSideRobots.ismarker(robot::RobotDecart) = ismarker(robot.robot) 74 | HorizonSideRobots.temperature(robot::RobotDecart) = temperature(robot.robot) 75 | HorizonSideRobots.show!(robot::RobotDecart) = show!(robot.robot) 76 | coordinates(robot::RobotDecart) = coordinates(robot.decart) 77 | 78 | Чтобы протестировать эти функции, можно сделать следующее: 79 | 80 | ```julia 81 | robot = Robot(animate=true) 82 | robot_decart = RobotDecart(robot) 83 | 84 | coordinates(robot_decart) |> println # (x=0, y=0) 85 | move!(robot_decart, Nord) 86 | coordinates(robot_decart) |> println # (x=0, y=1) 87 | ``` 88 | 89 | Но теперь, когда у нас создан объект `robot_decart` типа `RobotDecart`, мы снова можем воспользоваться определениями из файла ["functional_robot.jl"](functional_robot.jl), например: 90 | 91 | ```julia 92 | protected_robot = interface_protected_robot(robot_decart) 93 | line = interface_line(protectd_robot.move!) 94 | line.movements!(Ost) 95 | coordinates(robot_decart) |> println # - будут выведены координаты Робота, переместившегося до упора на восток 96 | ``` 97 | 98 | ## Исполнитель "Робот - счётчик числа маккеров" 99 | 100 | ```julia 101 | using HorizonSideRobots 102 | 103 | mutable struct RobotMarkersCounter 104 | robot::Robot # - АГРЕГИРОВАНИЕ (композиция) объекта типа Robot 105 | 106 | num_markers::Int 107 | RobotMakersCounter(robot, init_val) = new(robot, init_val) 108 | RobotMakersCounter(robot) = RobotDecart(robot, 0) 109 | end 110 | 111 | HorizonSideRobots.move!(robot::RobotMarkersCounter, side) = begin 112 | move!(robot.robot, side) 113 | if ismarker(robot.robot) 114 | robot.num_markers += 1 115 | end 116 | end 117 | HorizonSideRobots.isborder(robot::RobotMarkersCounter, side) = isborder(robot.robot, side) 118 | HorizonSideRobots.putmarker!(robot::RobotMarkersCounter) = putmarker!(robot.robot) 119 | HorizonSideRobots.ismarker(robot::RobotMarkersCounter) = ismarker(robot.robot) 120 | HorizonSideRobots.temperature(robot::RobotMarkersCounter) = temperature(robot.robot) 121 | HorizonSideRobots.show!(robot::RobotMarkersCounter) = show!(robot.robot) 122 | get_num_markers(robot::RobotMarkersCounter) = robot.num_markers 123 | ``` 124 | 125 | ```julia 126 | robot = Robot() 127 | if ismarker(robot) 128 | num_markers=1 129 | else 130 | num_markers=0 131 | end 132 | 133 | robot=RobotMakersCounter(robot, num_markers) 134 | .... 135 | 136 | num_markers = get_num_markers(robot) 137 | ``` 138 | 139 | ## Иерархия типов, абстрактные типы 140 | 141 | ```julia 142 | 143 | abstract type AbstractRobot 144 | #robot::Robot 145 | end 146 | 147 | #HorizonSideRobots.move!(robot::AbstractRobot, side) = move!(robot.robot, side) 148 | HorizonSideRobots.isborder(robot::AbstractRobot, side) = isborder(robot.robot, side) 149 | HorizonSideRobots.putmarker!(robot::AbstractRobot) = putmarker!(robot.robot) 150 | HorizonSideRobots.ismarker(robot::AbstractRobot) = ismarker(robot.robot) 151 | HorizonSideRobots.temperature(robot::AbstractRobot) = temperature(robot.robot) 152 | HorizonSideRobots.show!(robot::AbstractRobot) = show!(robot.robot) 153 | 154 | #----------------------------------- 155 | 156 | mutable struct RobotMarkersCounter <: AbstractRobot 157 | robot::Robot # - АГРЕГИРОВАНИЕ (композиция) объекта типа Robot 158 | 159 | num_markers::Int 160 | RobotMakersCounter(robot, init_val) = new(robot, init_val) 161 | RobotMakersCounter(robot) = RobotDecart(robot, 0) 162 | end 163 | 164 | HorizonSideRobots.move!(robot::RobotMarkersCounter, side) = begin 165 | move!(robot.robot, side) 166 | if ismarker(robot.robot) 167 | robot.num_markers += 1 168 | end 169 | end 170 | get_num_markers(robot::RobotMarkersCounter) = robot.num_markers 171 | 172 | #---------------------------------------------- 173 | 174 | struct RobotDecart <: AbstractRobot 175 | robot::Robot # - АГРЕГИРОВАНИЕ (композиция) объекта типа Robot 176 | decart::Decart # - АГРЕГИРОВАНИЕ объекта типа Decart 177 | 178 | RobotDecart(robot, coords) = new(robot, Decart(coords)) 179 | RobotDecart(robot) = RobotDecart(robot, (x=0, y=0)) 180 | end 181 | 182 | HorizonSideRobots.move!(robot::RobotDecart, side) = begin # (move!(robot.robot, side); coodinates!(robot.decart,side)) 183 | move!(robot.robot, side) 184 | coodinates!(robot.decart,side) 185 | end 186 | 187 | Decart.coordinates(robot::RobotDecart) = coordinates(robot.decart) 188 | 189 | #----------------------------------------------------------- 190 | ``` 191 | 192 | ## Исполнитель "Робот-Декарт + счетчик маркеров" 193 | 194 | ```julia 195 | mutable struct RobotDecartMarkersCounter <: AbstractRobot 196 | robot::RobotDecart # - АГРЕГИРОВАНИЕ (композиция) объекта типа RobotDecart 197 | 198 | num_markers::Int 199 | RobotDecartMakersCounter(robot, init_val) = new(robot, init_val) 200 | RobotDecartMakersCounter(robot) = RobotDecart(robot, 0) 201 | end 202 | 203 | HorizonSideRobots.move!(robot::RobotMarkersCounter, side) = begin 204 | move!(robot.robot, side) 205 | if ismarker(robot.robot) 206 | robot.num_markers += 1 207 | end 208 | end 209 | 210 | num_markers(robot::RobotDecartMarkersCounter) = robot.num_markers 211 | 212 | coordinates(robot::RobotDecartMarkersCounter) = coordinates(robot.robot) 213 | ``` 214 | 215 | ```julia 216 | robot = Robot() 217 | robot = RobotDecart(robot) 218 | num_markers = .... 219 | robot = RobotDecartMarkersCounter(robot, num_markers) 220 | 221 | ``` 222 | 223 | ## О построении иерархии пользовательских типов 224 | 225 | Если проектируется иерархия типов, то эта иерархия нуждается в тщательном продумывании с тем, чтобы она была удобна для проектирования новых типов, потребность в котрых будет возникать при решении новых задач. 226 | 227 | Так например, выше был спроектиирван конкретный тип `RobotDecart`, но умение отслеживать свои координаты может быть необходимо и для роботов других типов, имеющих какую-то дополнительную специализацию, и которых нам приходится проектировать. Поэтому было бы целесообразно спроектировать абстрактный тип `AbstractRobotDecart <: AdstractRobot` в интерфейсе которого бы содержалась бы функция `coordinates(::AbstractRobotDecart)`, возвращающая текущие значения координат, и у которого бы соответствующим образом была бы определена функция `move!(::AbstractRobotDecart)`. 228 | 229 | А именно, вместо: 230 | 231 | ```julia 232 | struct RobotDecart <: AbstractRobot 233 | .... 234 | end 235 | ``` 236 | 237 | определим абстрактный тип с двумя функциями (пополняющими наследуемый от типа `AbstractRobot` интерфейс): 238 | 239 | ```julia 240 | abstract type AdstractRobotDecart <: AbstractRobot 241 | #robot::Robot 242 | #decart::Decart 243 | end 244 | 245 | HorizonSideRobots.move!(robot::RobotDecart, side) = begin 246 | move!(robot.robot, side) 247 | coodinates!(robot.decart,side) 248 | end 249 | 250 | Decart.coordinates(robot::RobotDecart) = coordinates(robot.decart) 251 | ``` 252 | 253 | Тогда от этого типа могут быть определены конкретные, которые унаследуют от данного абстрактного типа его интерфейс. 254 | 255 | Например: 256 | 257 | ```julia 258 | struct RobotDecart <: AbstractRobot 259 | robot::Robot # - АГРЕГИРОВАНИЕ (композиция) объекта типа Robot 260 | decart::Decart # - АГРЕГИРОВАНИЕ объекта типа Decart 261 | 262 | RobotDecart(robot, coords) = new(robot, Decart(coords)) 263 | RobotDecart(robot) = RobotDecart(robot, (x=0, y=0)) 264 | end 265 | ``` 266 | 267 | Другой пример (см. ыше): 268 | 269 | ```julia 270 | mutable struct RobotDecartMarkersCounter <: AbstractRobotDecart 271 | robot::Robot # RobotDecart 272 | decart::Decart 273 | num_markers::Int 274 | RobotDecartMarkersCounter(robot, num_markers) = new(robot, Decart((x=0,y=0)), num_markers) #new(RobotDecart(robot), num_markers) 275 | end 276 | 277 | function move!(robot::RobotDecartMarkersCounter, side::HorizonSide) 278 | move!(robot.robot, side) 279 | if ismarker(robot) 280 | robot.num_markers += 1 281 | end 282 | return nothing 283 | end 284 | ``` 285 | 286 | Теперь, когда основная часть интерфеса оказалась унаследованной от типа `AbstractRobotDecart` оказалось достаточно только определить соответствующую структуру и только одну функцию `num_markers(robot::RobotDecartMarkersCounter)` 287 | -------------------------------------------------------------------------------- /12-15/Лекция-15.md: -------------------------------------------------------------------------------- 1 | # Лекция 15 2 | 3 | Рекурсия 4 | 5 | ```julia 6 | 7 | include("horizonside.jl") 8 | 9 | function move_recurs!(robot,side) 10 | if isborder(robot,side) 11 | move!(robot,right(side)) 12 | move_recurs!(robot,side) 13 | move!(robot,left(side)) 14 | else 15 | move!(robot,side) 16 | end 17 | end 18 | 19 | #move_recurs!(robot,Nord) 20 | 21 | function dist_double!(robot,side) 22 | if !isborder(robot,side) 23 | move!(robot,side) 24 | dist_double(robot,side) 25 | move!(robot,inverse(side)) 26 | move!(robot,inverse(side)) 27 | end 28 | end 29 | 30 | 31 | function move_symmetric!(robot,side) 32 | if !isborder(robot,inverse(side)) 33 | move!(robot,inverse(side)) 34 | move_symmetric!(robot,side) 35 | move!(robot,inverse(side)) 36 | else 37 | while !isborder(robot,side) 38 | move!(robot,side) 39 | end 40 | end 41 | end 42 | 43 | 44 | mark_labirint!(robot, index_side = -1) = 45 | if !ismarker(robot) 46 | putmarker!(robot) 47 | 48 | for side in HorizonSide.(setdiff!([0,1,2,3], index_side)) 49 | move!(robot,side) 50 | mark_labirint!(robot, Int(inverse(side))) 51 | move!(robot,inverse(side)) 52 | end 53 | end 54 | 55 | #---------------------------------------------------------------------- 56 | #= 57 | for side in HorizonSide.(0:3) 58 | ... 59 | end 60 | =# 61 | 62 | #----------------------------------------------------------------------- 63 | 64 | Base.iterate(side::HorizonSide) = (side, (Int(side), mod(Int(side)+1,4)) 65 | Base.iterate(side::HorizonSide, state) = 66 | if state[1] == state[2] 67 | return nothing 68 | else 69 | return HorizonSide(state), (state[1], mod(state[2]+1,4)) 70 | end 71 | 72 | #= 73 | Теперь можно будет присать так: 74 | 75 | for side if HorizonSide(0) # | HorizonSide(1) | HorizonSide(2) | HorizonSide(3) 76 | ... 77 | end 78 | 79 | А также можно будет использовать функцию setdiff!(Set(HorizonSide.(0:3)), inverse(robot.input_side)) 80 | =# 81 | 82 | struct RobotLabirinTracker{TypeRobot} <: AbstractDecartRobot 83 | robot::TypeRobot 84 | decart::Decart 85 | markered_positions::Set{Tuple{Int,Int}} 86 | RobotLabirinTracker{TypeRobot}(robot::TypeRobot) where TypeRobot = new(roobot, Decart(), Set{Tuple{Int,Int}}()) 87 | end 88 | 89 | setmarker!(robot) = push!(robot.markered_positions, coordinates(robot) 90 | ismarkered(robot::RobotLabirinTracker) = (coordinates(robot.robot_decart) in robot.markered_positions) 91 | 92 | function tracke!(action::Function, robot::RobotLabirinTracker) 93 | if !ismarkered(robot) 94 | setmarker!(robot) 95 | for side in HorizonSide(0) 96 | tracke!(action, robot.robot_decart, side) 97 | end 98 | end 99 | end 100 | 101 | function tracke!(action::Function, robot::RobotLabirinTracker, side) 102 | if !ismarkered(robot) 103 | setmarker!(robot) 104 | for side in setdiff!(Set(HorizonSide.(0:3)), inverse(robot.input_side)) 105 | tracke!(action, robot.robot_decart, side) 106 | end 107 | end 108 | end 109 | 110 | #= 111 | #Base.iterate(robot::RobotLabirinTracker) = (move!(robot,nothing) ???????? 112 | #Base.iterate(robot::RobotLabirinTracker, state) = (robot,nothing) ???????? 113 | =# 114 | ``` 115 | 116 | Пример косвенной рекурсии -------------------------------------------------------------------------------- /2/Список-задач-2.md: -------------------------------------------------------------------------------- 1 | # CПИСОК ЗАДАЧ ДЛЯ САМОСТОЯТЕЛЬНОГО РЕШЕНИЯ 2 2 | 3 | 6. * ДАНО: На ограниченном внешней прямоугольной рамкой поле имеется ровно одна внутренняя перегородка в форме прямоугольника. Робот - в произвольной клетке поля между внешней и внутренней перегородками. 4 | РЕЗУЛЬТАТ: Робот - в исходном положении и по всему периметру внутренней перегородки поставлены маркеры. 5 | 6 | 7. ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля (без внутренних перегородок) 7 | 8 | РЕЗУЛЬТАТ: Робот - в исходном положении, в клетке с роботом стоит маркер, и все остальные клетки поля промаркированы в шахматном порядке 9 | 10 | 8. ДАНО: Робот - рядом с горизонтальной перегородкой (под ней), бесконечно продолжающейся в обе стороны, в которой имеется проход шириной в одну клетку. 11 | РЕЗУЛЬТАТ: Робот - в клетке под проходом 12 | 13 | 9. ДАНО: Где-то на неограниченном со всех сторон поле и без внутренних перегородок имеется единственный маркер. Робот - в произвольной клетке поля. 14 | РЕЗУЛЬТАТ: Робот - в клетке с тем маркером. 15 | 16 | ----------------------- 17 | 18 | [<< README](../README.md) 19 | 20 | ------------------------ -------------------------------------------------------------------------------- /3/chess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/3/chess.png -------------------------------------------------------------------------------- /3/Задачи 10-13.md: -------------------------------------------------------------------------------- 1 | 10. ДАНО: Робот - в юго-западном углу поля, на котором расставлено некоторое количество маркеров 2 | 3 | РЕЗУЛЬТАТ: Функция вернула значение средней температуры всех замаркированных клеток 4 | 5 | 6 | 11. ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля, на котором могут находиться также внутренние прямоугольные перегородки (все перегородки изолированы друг от друга, прямоугольники могут вырождаться в отрезки) 7 | 8 | РЕЗУЛЬТАТ: Робот - в исходном положении, и в 4-х приграничных клетках, две из которых имеют ту же широту, а две - ту же долготу, что и Робот, стоят маркеры. 9 | 10 | 12. На прямоугольном поле произвольных размеров расставить маркеры в виде "шахматных" клеток, начиная с юго-западного угла поля, когда каждая отдельная "шахматная" клетка имеет размер n x n клеток поля (n - это параметр функции). Начальное положение Робота - произвольное, конечное - совпадает с начальным. Клетки на севере и востоке могут получаться "обрезанными" - зависит от соотношения размеров поля и "шахматных" клеток. (Подсказка: здесь могут быть полезными две глобальных переменных, в которых будут содержаться текущие декартовы координаты Робота относительно начала координат в левом нижнем углу поля, например) 11 | 12 | 13. ДАНО: Робот - в произвольной клетке ограниченного прямоугольной рамкой поля без внутренних перегородок и маркеров. 13 | 14 | РЕЗУЛЬТАТ: Робот - в исходном положении в центре косого креста (в форме X) из маркеров. 15 | 16 | (Подсказка: решение будет подобно решению задачи 1, если направление премещения Робота задавать кортежами пары значений типа HorizonSide) 17 | -------------------------------------------------------------------------------- /3/Практика-3.md: -------------------------------------------------------------------------------- 1 | # ПРАКТИКА 3 2 | 3 | - [ПРАКТИКА 3](#практика-3) 4 | - [**Разбор решения задачи 5**](#разбор-решения-задачи-5) 5 | - [**Возможный вариант решения задачи 5**](#возможный-вариант-решения-задачи-5) 6 | - [**Улучшенный вариант решения задачи 5**](#улучшенный-вариант-решения-задачи-5) 7 | - [**Разбор решения задачи 8**](#разбор-решения-задачи-8) 8 | - [**Первый вариант решения задачи 8**](#первый-вариант-решения-задачи-8) 9 | - [**Второй вариант решения задачи 8**](#второй-вариант-решения-задачи-8) 10 | - [**Разбор решения задачи 9**](#разбор-решения-задачи-9) 11 | 12 | ## **Разбор решения задачи 5** 13 | ДАНО: Робот - в произвольной клетке ограниченного прямоугольного поля, на котором могут находиться также внутренние прямоугольные перегородки (все перегородки изолированы друг от друга, прямоугольники могут вырождаться в отрезки) 14 | 15 | РЕЗУЛЬТАТ: Робот - в исходном положении и в углах поля стоят маркеры 16 | 17 | ### **Возможный вариант решения задачи 5** 18 | ```julia 19 | function mark_angles(r) 20 | num_steps=[] 21 | while isborder(r,Sud)==false || isborder(r,West) # Робот - не в юго-западном углу 22 | push!(num_steps, moves!(r, West)) # - добавляется в конец массива новый элемент 23 | push!(num_steps, moves!(r, Sud)) 24 | end 25 | # УТВ: Робот - в юго-западном углу и в num_steps - закодирован пройденный путь 26 | for side in (Nord,Ost,Sud,West) 27 | moves!(r,side) # возвращаемый результат игнорируется 28 | putmarker!(r) 29 | end 30 | # УТВ: Маркеры поставлены и Робот - в юго-западном углу 31 | for (i,n) in enumerate(reverse!(num_steps)) # встроенная функция reverse! переворачивает массив задом на перед 32 | side = isodd(i) ? Ost : Nord # odd - нечетный 33 | moves!(r,side,n) 34 | end 35 | #УТВ: Робот - в исходном положении 36 | end 37 | 38 | #= 39 | Последний цикл в этой функции эквивалентен следующему: 40 | 41 | i=0 42 | for n in reverse!(num_steps) 43 | i+=1 44 | side = isodd(i) ? Ost : Nord # odd - нечетный 45 | moves!(r,side,n) 46 | end 47 | 48 | =# 49 | 50 | # перемещает Робота в заданном направлении до упора и возвращает число сделанных шагов 51 | function moves!(r,side) 52 | num_steps=0 53 | while isborder(r,side)==false 54 | move!(r,side) 55 | num_steps+=1 56 | end 57 | return num_steps 58 | end 59 | 60 | # Перемещает Робота в заданном направлении на заданное число шагов 61 | moves!(r,side,num_steps) = for _ in 1:num_steps move!(r,side) end 62 | ``` 63 | ЗАМЕЧАНИЕ. 64 | Имя последней функции moves! отличается одной буквой от имени стандартной команды Робота move!. 65 | Но, в принципе, эту функцию мы могли бы тоже назвать move!, но тогда пришлось бы написать так 66 | ```julia 67 | HorizonSideRobots.move!(r,side,num_steps)=for _ in 1:num_steps move!(r,side) end 68 | ``` 69 | Это ознало бы, что мы переопределяем страндартную команду Робота move! (но для другого числа аргументов). В этом случае язык Julia требует, чтобы при таком переопределении использовалось расширенное имя с префиксом "HorizonSideRobots.", определяюшим принадлежность соответствующему модулю. 70 | 71 | Ну или можно было бы это переопределение сделать еще и так: 72 | ```julia 73 | import HorizonSideRobots.move! 74 | move!(r,side,num_steps)=for _ in 1:num_steps move!(r,side) end 75 | ``` 76 | 77 | Но в данном случае не стали делать такого переопределения. 78 | 79 | -------------------------- 80 | [<< к началу](#практика-3) 81 | 82 | -------------------------- 83 | ### **Улучшенный вариант решения задачи 5** 84 | 85 | Однако в главной функцию можно было бы выполнить еще дополнительную декомпозици: 86 | 87 | ```julia 88 | function mark_angles(r) 89 | num_steps = through_rectangles_into_angle(r,(Sud,West)) 90 | # УТВ: Робот - в юго-западном углу и в num_steps - закодирован пройденный путь 91 | for side in (Nord,Ost,Sud,West) 92 | moves!(r,side) # возвращаемый результат игнорируется 93 | putmarker!(r) 94 | end 95 | # УТВ: Маркеры поставлены и Робот - в юго-западном углу 96 | move!(r,(Ost,Nord),num_steps) 97 | #УТВ: Робот - в исходном положении 98 | end 99 | ``` 100 | Здесь выделены еще две новые вспомогательные функции through_rectangles_into_angle, сome_back, котрые, вообще-то, имеют достаточно универсальный характер, и могут пригодиться в будущем (если их поместить в библиотечный файл). 101 | 102 | Вот код этих новых функций, с соответствующими описаниями, как это положено для библиотечных функций, чтобы можно было получать по этим функциям информацию с использованием встроенной системы помощи: 103 | ```julia 104 | """ 105 | through_rectangles_into_angle(r,angle::NTuple{2,HorizonSide}) 106 | 107 | -- Перемещает Робота в заданный угол, прокладывая путь межу внутренними прямоугольными перегородками и возвращает массив, содержащий числа шагов в каждом из заданных направлений на этом пути 108 | """ 109 | function through_rectangles_into_angle(r,angle::NTuple{2,HorizonSide}) 110 | num_steps=[] 111 | while isborder(r,angle[1])==false || isborder(r,angle[2]) # Робот - не в юго-западном углу 112 | push!(num_steps, moves!(r, angle[2])) 113 | push!(num_steps, moves!(r, angle[1])) 114 | end 115 | return num_steps 116 | end 117 | 118 | """ 119 | moves!(r,sides,num_steps::Vector{Int}) 120 | 121 | -- перемещает Робота по пути, представленного двумя последовательностями, sides и num_steps 122 | -- sides - содержит последовательность направлений перемещений 123 | -- num_steps - содержит последовательность чисел шагов в каждом из этих направлений, соответственно; при этом, если длина последовательности sides меньше длины последовательности num_steps, то предполагается, что последовательность sides должна быть продолжена периодически 124 | """ 125 | function moves!(r,sides,num_steps::Vector{Int}) 126 | for (i,n) in enumerate(reverse!(num_steps)) 127 | moves!(r, sides[mod(i-1, length(sides))+1], n) # - это не рекурсия (не вызов функцией самой себя), это вызов другой, ранее определенной функции 128 | # выражение индекса массива mod(i-1, length(sides))+1 обеспечисвает периодическое продолжение последовательности из вектора sides до длины вектора num_steps 129 | end 130 | end 131 | ``` 132 | 133 | Здесь важно понять, что определяемая здесь функция moves!(r,sides,num_steps::Vector{Int}) и ранее определенная функция moves!(r,side,num_steps) имеют разные сигнатуры: в первом случае параметр num_steps имеет тип Vector{Int}, а во втором - третий параметр num_steps явно не аннотирован, т.е. фактически его тип - Any. Таким образом, здесь будет действовать множественная диспетчеризация, т.е. на основании этого различия Julia будет знать, какой код должен быть исполнен в том или ином случае. 134 | 135 | -------------------------- 136 | [<< к началу](#практика-3) 137 | 138 | -------------------------- 139 | ## **Разбор решения задачи 8** 140 | ДАНО: Робот - рядом с горизонтальной перегородкой (под ней), бесконечно продолжающейся в обе стороны, в которой имеется проход шириной в одну клетку. 141 | РЕЗУЛЬТАТ: Робот - в клетке под проходом 142 | 143 | ### **Первый вариант решения задачи 8** 144 | 145 | В этом варианте используются установка маркеров 146 | ```julia 147 | function find_passage(r) 148 | side=Ost 149 | while isborder(r,Nord)==true # прохода сверху нет 150 | putmarker!(r) 151 | move_by_markers!(r,side) 152 | side=inverse(side) 153 | end 154 | end 155 | 156 | move_by_markers!(r,side) = while ismarker(r) move!(r,side) end 157 | 158 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2,4)) 159 | ``` 160 | ### **Второй вариант решения задачи 8** 161 | 162 | В этом варианте вместо маркеров используется переменная-счетчик числа шагов 163 | 164 | ```julia 165 | function find_passage(r) 166 | n=0; side=Ost 167 | while isborder(r,Nord)==true # прохода сверху нет 168 | n+=1 169 | move!(r,side,n) 170 | side=inverse(side) 171 | end 172 | end 173 | 174 | move!(r,side,num_steps)=for _ in 1:num_steps move!(r,side) end 175 | 176 | inverse(side::HorizonSide)=HorizonSide(mod(Int(side)+2,4)) 177 | ``` 178 | 179 | -------------------------- 180 | [<< к началу](#практика-3) 181 | 182 | -------------------------- 183 | ## **Разбор решения задачи 9** 184 | 185 | ДАНО: Где-то на неограниченном со всех сторон поле и без внутренних перегородок имеется единственный маркер. Робот - в произвольной клетке поля. 186 | РЕЗУЛЬТАТ: Робот - в клетке с тем маркером. 187 | 188 | ```julia 189 | function find_marker(r) 190 | num_steps_max=1 191 | side=Nord 192 | while ismarker(r)==false 193 | for _ in 1:2 194 | find_marker(r,side,num_steps_max) 195 | side=next(side) 196 | end 197 | num_steps_max+=1 198 | end 199 | end 200 | 201 | function find_marker(r,side,num_steps_max) 202 | for _ in 1:num_steps_max 203 | if ismarker(r) 204 | return nothing 205 | end 206 | move!(r,side) 207 | end 208 | end 209 | 210 | next(side::HorizonSide)=HorizonSide(mod(Int(side)+1,4)) 211 | ``` 212 | 213 | -------------------------- 214 | [<< к началу](#практика-3) 215 | 216 | -------------------------- 217 | -------------------------------------------------------------------------------- /4/Задачи 14-25.md: -------------------------------------------------------------------------------- 1 | ЗАДАЧИ 14-26 2 | Задачи 14-18 аналогичны задачам 1-5, но дополнительно на поле могут находиться внутрение перегородки прямоугольной формы, среди которых могут быть и вырожденые прямоугольники (отрезки), эти внутренние перегородки изолированы друг от друга и от внешней рамки. 3 | 4 | Пояснение. На самом деле, если задачи 1-5 были уже решены, то для решения задач 14-18 требуется всго лишь подправить некоторые ранее разработанные вспомогательные функции так, что бы они сталтали учитывать возможность наличия внутренних перегородок прямоугольной формы. 5 | 6 | 19. Эта задача аналогична задаче 9, но дополнительно на неограниченном поле могут находиться изолированные прямолинейные перегородки, в том числе и неограниченно продолжающиеся в одну из своих сторон. 7 | 8 | 20. Посчитать число всех горизонтальных прямолинейных перегородок (вертикальных - нет) 9 | 10 | 21. Подсчитать число и вертикальных и горизонтальных прямолинейных перегородок (прямоугольных - нет) 11 | 22. Подсчитать число прямоугольных перегородок (отрезков нет) 12 | 23. Подсчитать число и прямоугольных и прямолинейных (вертикальных и горизонтальных) 13 | 14 | 24. Найти площадь наибольшей прямоугольной перегородки 15 | 16 | 25. Найти прямоугольную перегородку, включая внешнюю рамку, с наибольшей средней температурой клеток периметра 17 | 18 | ЗАМЕЧАНИЕ. Список получился довольно большой, поэтому если не хватит времени на полное решение всех этих задач, то желательно хотя бы продумать их решение, оформив результ в виде псевдокода. -------------------------------------------------------------------------------- /4/Модель памяти.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/4/Модель памяти.png -------------------------------------------------------------------------------- /5/task13.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Рассмотрим задачу 13: 3 | ДАНО: Робот - в произвольной клетке ограниченного прямоугольной рамкой поля без внутренних перегородок и маркеров. 4 | 5 | РЕЗУЛЬТАТ: Робот - в исходном положении в центре косого креста (в форме X) из маркеров. 6 | 7 | Решение могло бы быть, например, таким. 8 | =# 9 | 10 | 11 | #= 12 | Если в эту функцию дополнительно передавать кортеж направлений, то, если не аннотировать тип этого дополнительного параметра, эта функция получилась бы обобщенной 13 | =# 14 | function mark_kross_x(r::Robot) 15 | for side in ((Nord,Ost),(Sud,Ost),(Sud,West),(Nord,West)) 16 | putmarkers!(r,side) 17 | move_by_markers!(r,inverse(side)) 18 | end 19 | putmarker!(r) 20 | end 21 | 22 | # Если не аннотировать тип параметра side, то эта функция стала бы обобщенной 23 | putmarkers!(r::Robot, side::NTuple{2,HorizonSide}) = 24 | while isborder(r,side)==false 25 | move!(r,side) 26 | end 27 | 28 | # Этот метод функции isborder дает ее специализацию для типа NTuple{2,HorizonSide} по параметру side 29 | isborder(r::Robot,side::NTuple{2,HorizonSide}) = (isborder(r,side[1]) || isborder(r,side[2])) 30 | 31 | #Этот метод функции HorizonSideRobots.move! дает ее специализацию типа NTuple{2,HorizonSide} по параметру side 32 | HorizonSideRobots.move!(r::Robot,side::NTuple{2,HorizonSide}) = for s in side move!(r,s) end 33 | 34 | #= 35 | Если не аннотировать тип параметра side, то эта функция стала бы обобщенной (но специализация для типа HorizonSide сохранилась бы) 36 | =# 37 | move_by_markers!(r::Robot,side::NTuple{2,HorizonSide}) = while ismarker(r) move!(r,side) end 38 | 39 | # Этот метод функции inverse дает ее специализацию для типа NTuple{2,HorizonSide} по параметру side 40 | inverse(side::NTuple{2,HorizonSide}) = (inverse(side[1]), inverse(side[2])) 41 | 42 | 43 | #------------------------------------------- 44 | function mark_kross(r::Robot, sides) 45 | for side in sides 46 | putmarkers!(r,side) 47 | move_by_markers!(r,inverse(side)) 48 | end 49 | putmarker!(r) 50 | end 51 | 52 | putmarkers!(r::Robot,side) = while isborder(r,side)==false move!(r,side) end 53 | move_by_markers!(r::Robot,side) = while ismarker(r) move!(r,side) end 54 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 55 | ``` 56 | 57 | Если этот код, с определениями этих 4-х функций находится в отдельном файле, то тогда при решении задачи 13 мы могли бы его использовать без всяких изменений, воспользовавшись функцией `include`. Но при этом, уже в новом файле с решением задачи 13, нам пришлось бы дополнительно дать еще следующие три определения, специализирующих нужным образом соответствующие функции: 58 | ```julia 59 | isborder(r::Robot,side::NTuple{2,HorizonSide}) = (isborder(r,side[1] || isborder(r,side[2])) 60 | HorizonSideRobots.move!(r::Robot,side::NTuple{2,HorizonSide}) = for s in side move!(r,s) end 61 | inverse(side::NTuple{2,HorizonSide}) = (inverse(side[1]),inverse(side[2])) 62 | ``` 63 | В результате ранее определенная (обобщенная) функция mark_kross(r::Robot,sides) решала бы и задачу 13. 64 | 65 | Больше того, если бы потребовалось, например, расставить маркеры еще и в форме 8-конечного креста, то уже вообще ничего программировать бы не потребовалось, достаточно было бы просто вызвать функцию `mark_kross` с фактическим параметром в позиции side имеющем значение 8-элементного кортежа `(Nord,(Nord-Ost),Ost,(Sud,Ost),Sud,(Sud,West),West,(Nord,West))`. Заметим, что тип этого кортежа есть `Tuple`, а не NTuple, т.к. составляющие его элементы имеют разный тип. 66 | 67 | Можно было бы даже совсем отказатьса от аннотирования типа аргумента `side` (с мыслью о том, что вдруг года-нибудь понадобится понимать под side что-нибудь отличное от того, что мы понимаем сейчас; например, в принципе, в какой-то другой ситуации направление может задаваться и словами "лево", "право"): 68 | ```julia 69 | isborder(r::Robot,side) = (isborder(r,side[1] || isborder(r,side[2])) 70 | HorizonSideRobots.move!(r::Robot,side) = for s in side move!(r,s) end 71 | inverse(side) = (inverse(side[1]),inverse(side[2])) 72 | ``` 73 | И это делало бы последние три функции тоже обобщенными (правда мы пока точно не знаем, когда потенциал такого обобщения сможет быть реализованным, но мы сделали так на всякий случай, а вдруг это пригодится). 74 | 75 | Исходя из всего сказанного, можно предположить, что на всякий случай и от аннотации типа аргумента r в определениях наших обобщенных функций лучше отказаться ([см. еще ниже](#принцип-аннотирования-тпов-аргуметов-функции)). 76 | 77 | В итоге получаем следующий обобщенный код (теперь уже и по аргументу r) 78 | 79 | ```julia 80 | function mark_kross(r,sides) 81 | for side in sides 82 | putmarkers!(r,side) 83 | move_by_markers!(r,inverse(side)) 84 | end 85 | putmarker!(r) 86 | end 87 | 88 | putmarkers!(r,side) = while isborder(r,side)==false move!(r,side) end 89 | move_by_markers!(r,side) = while ismarker(r) move!(r,side) end 90 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 91 | ``` 92 | 93 | А при решении задачи 13 дополнительно к этому получим 94 | ```julia 95 | isborder(r::Robot,side::NTuple{2,HorizonSide}) = (isborder(r,side[1] || isborder(r,side[2])) 96 | HorizonSideRobots.move!(r::Robot,side::NTuple{2,HorizonSide}) = for s in side move!(r,s) end 97 | inverse(side::NTuple{2,HorizonSide}) = (inverse(side[1]),inverse(side[2])) 98 | ``` 99 | ЗАМЕЧАНИЕ. 100 | Может показаться, что отказ от аннотирования типов аргументов функций существенно снизит надежность программного кода из-за того, что теперь возможны ошибки, связанные с передачей фанкциям параметров не тех типов, которые требуются. Однако на практике это не так, ткого рода ошибки быстро обнаруатся, как только дело дойдет до выполения узкоспециализированных методов в "глубине" функции. Просто стек выводимых сообщений об ошибках будет теперь получаться несколько длиннее, но до истинных причин такого рода ошибок "докопаваться" все-равно будет не так уж и сложно. 101 | 102 | Таким образом, в файл roblib.jl имеет смысл помещать определения функций в как можно более обобщенном виде, что расширит сферу их применимости. 103 | -------------------------------------------------------------------------------- /5/task14.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Задача 14 3 | ДАНО: Робот находится в произвольной клетке ограниченного прямоугольного поля, на котром возможны внутренние перегородки прямоугольной формы (некоторые прямоугольники могут вырождаться в отрезки) и в некоторых клетках изначально могут находиться маркеры. 4 | 5 | РЕЗУЛЬТАТ: Робот — в исходном положении в центре прямого креста из маркеров, расставленных вплоть до внешней рамки (кроме этих маркеров на поле могут находиться и какие-то другие). 6 | 7 | # На поле возможны внутренние перегородки ПРЯМОУГОЛЬНОЙ формы (допускаются и вырожденные прпямоугольники, т.е. - отрезки) 8 | =# 9 | function mark_kross(r) 10 | for side in (Nord, West, Sud, Ost) 11 | num_steps = putmarkers!(r,side) 12 | movements!(r,inverse(side), num_steps) # в Практика-4 эту функция не очень удачно было названа просто move! Новое предложенное имя подчеркивает, что шагов может быть много 13 | end 14 | end 15 | 16 | 17 | """ 18 | putmarkers!(r::Robot,side::HorizonSide) 19 | 20 | -- Перемещает Робота в заданном направлении до упора, и после каждого шага ставит маркер и возвращает число сделанных шагов 21 | """ 22 | function putmarkers!(r::Robot,side::HorizonSide) 23 | num_steps=0 24 | while move_if_possible!(r, side) == true 25 | putmarker!(r) 26 | num_steps += 1 27 | end 28 | return num_steps 29 | end 30 | 31 | #= 32 | Если 33 | move_if_possible!(r, side) = 34 | if isborder(r,side)==false 35 | move!(r,side) 36 | return true 37 | else 38 | return false 39 | end 40 | 41 | movements!(r::Robot, side::HorizonSide, num_steps::Int) = for _ in 1:num_steps move!(r,side) 42 | 43 | то мы имеем просто решение задачи 1. 44 | 45 | Но чтобы получить решение задачи 14 потребуется переопределить функциии move_is_posible и movements!(::Robor,::HorizonSide,::Int), 46 | так, чтобы они могли обходить все встречающиеся на пути изолированные внутренние перегородоки прямоугольной формы. 47 | =# 48 | 49 | # Перемещает робота в заданном направлении, если это возможно, и возвращает true, 50 | # если перемещение состоялось; в противном случае - false. 51 | function move_if_possible!(r::Robot, direct_side::HorizonSide)::Bool 52 | orthogonal_side = left(direct_side) 53 | reverse_side = inverse(orthogonal_side) 54 | num_steps=0 55 | while isborder(r,direct_side) == true 56 | if isborder(r, orthogonal_side) == false 57 | move!(r, orthogonal_side) 58 | num_steps += 1 59 | else 60 | break 61 | end 62 | end 63 | #УТВ: Робот или уперся в угол внешней рамки поля, или готов сделать шаг (или несколько) в направлении 64 | # side 65 | 66 | if isborder(r,direct_side) == false 67 | move!(r,direct_side) 68 | while isborder(r,reverse_side) == true 69 | move!(r,direct_side) 70 | end 71 | result = true 72 | else 73 | result = false 74 | end 75 | for _ in 1:num_steps 76 | move!(r,reverse_side) 77 | end 78 | return result 79 | end 80 | 81 | # Делает заданное число шагов в заданном направлении, при необходимости обходя внутренние перегородки. 82 | # При этом величина одного "шага" может быть больше 1 и равна "толщине" встретившейся прямоугольной 83 | # перегородки 84 | movements!(r::Robot, side::HorizonSide, num_steps::Int) = 85 | for _ in 1:num_steps 86 | move_if_possible!(r,side) # - в данном случае возможность обхода внутренней перегородки гарантирована 87 | end 88 | 89 | 90 | """ 91 | inverse(side::HorizonSide) 92 | 93 | -- возвращает сторону горизонта, противоположную заданной 94 | """ 95 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 96 | 97 | 98 | """ 99 | left(side::HorizonSide) 100 | 101 | -- возвращает сторону горизонта, следующую после заданной (в положительном направлении вращения) 102 | """ 103 | left(side::HorizonSide) = HorizonSide(mod(Int(side)+1, 4)) 104 | 105 | 106 | """ 107 | right(side::HorizonSide) 108 | 109 | -- возвращает сторону горизонта, предшествующую заданной (в положительном направлении вращения) 110 | """ 111 | right(side::HorizonSide) = HorizonSide(mod(Int(side)-1, 4)) 112 | -------------------------------------------------------------------------------- /5/Задачи 26-28.md: -------------------------------------------------------------------------------- 1 | ЗАДАЧИ 26-28 2 | 3 | 26. Расставить маркеры в "полосочку" (через n пустых "полосок"). Причем "полосочки" могут быть, в одном случае, "прямыми", а в другом - косыми. 4 | 5 | ![Пряые полосы](straight_lines.png) 6 | ![Косые полосы](oblique_lines.png) 7 | 8 | Требуется написать **обобщенную функцию** (см. [лекцию 5](Лекция-5.md)), которая бы могла расставлять маркеры как по "прямым" (горизонтальным или вертикальнымм), так и по наклонным линиям (наклоны могут быть или в одну сторону или в другую), в соответствии со следующим описанием функции: 9 | ```julia 10 | """ 11 | zebra_mark(r, along_side, across_side, num_passes, num_start_passes=0) 12 | 13 | Расставляет параллельные полосы из маркеров с заданным промежутком между ними и с задаеным промежутком между стартовым углом и первой полосой, и возвращает робота в исходное положение 14 | 15 | -- r - cсылка на Робота 16 | -- along_side - начальное направление вдоль полосы маркеров (оно должно инвертироваться от полосы к полосы) 17 | -- across_side - направление поперек полос с маркерами 18 | -- num_passes - число пустых полос в промежутке между полосами с маркерами 19 | -- num_start_passes - число пустых полос в промежутке между стартовым углом и первой полосой с маркерами 20 | 21 | При этом стартовый угол определяется значениями along_side, across_side 22 | """ 23 | ``` 24 | Считать, что внутренних перегородок на поле нет. 25 | 26 | УКАЗАНИЕ. 27 | Напишите сначала программу, имея ввиду, что полосы из маркеров на поле должны быть именно горизонтальными или вертикалными, но соблюдая при этом общие принципы написания обобщенного кода, следуя рекомендациям из [лекции 5](Лекция-5.md). А затем попробуйте использовать полученный код и для случая наклонных полос. 28 | 29 | 27. Отдельно рассмотреть случай, когда в предыдущей задаче на поле могут быть внутренние прямоугольные изолированные перегородки. 30 | 31 | 28. Реализовать поиск маркера на неограниченном поле при наличии прямолинейных перегородок, в том числе полубесконечных 32 | 33 | 34 | -------------------------------------------------------------------------------- /5/Практика-5.md: -------------------------------------------------------------------------------- 1 | - [Создание библиотечного файла roblib.jl](#создание-библиотечного-файла-roblibjl) 2 | - [Пример, когда желание иметь универсальный код приводит к необходимости, некоторые вспомогательные функции распределять по нескольким отдельным файлам](#пример-когда-желание-иметь-универсальный-код-приводит-к-необходимости-некоторые-вспомогательные-функции-распределять-по-нескольким-отдельным-файлам) 3 | 4 | ## Создание библиотечного файла roblib.jl 5 | 6 | Подытожим результаты всей предыдущей работы по решению задач. 7 | 8 | У нас уже накопилось не мало вспомогательных функции, которые встречались из задачи в задачу. 9 | 10 | Поэтому эти функции являются претендентами на включение их в состав специальной библиотеки, например, - в файл `librob.jl` 11 | 12 | Вспомним их еще раз. 13 | 14 | ```julia 15 | #Cодержимое файла roblib.jl 16 | 17 | """ 18 | movements!(r::Robot, side::HorizonSide, num_steps::Int) 19 | 20 | -- Перемещает Робота в заданном направлении на заданное число шагов 21 | """ 22 | movements!(r::Robot, side::HorizonSide, num_steps::Int) = for _ in 1:num_steps move!(r,side) 23 | 24 | """ 25 | movements!(r::Robot, side::HorizonSide) 26 | 27 | -- Перемещает Робота в заданном направлении до упора 28 | """ 29 | movements!(r::Robot, side::HorizonSide) = while isborder(r,side)==false move!(r,side) end 30 | 31 | 32 | """ 33 | get_num_movements!(r::Robot, side::HorizonSide) 34 | 35 | -- Перемещает Робота в заданном направлении до упора и возвращает сделанное число шагов 36 | """ 37 | function get_num_movements!(r::Robot, side::HorizonSide) 38 | num_steps = 0 39 | while isborder(r,side)==false 40 | move!(r,side) 41 | num_steps += 1 42 | end 43 | return num_steps 44 | end 45 | 46 | """ 47 | inverse(side::HorizonSide) 48 | 49 | -- Возвращает направление, противоположное заданному 50 | """ 51 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 52 | 53 | """ 54 | left(side::HorizonSide) 55 | 56 | -- Возвращает направление, следующее, если отсчитывать против часовой стредки, по отношению к заданному 57 | """ 58 | left(side::HorizonSide) = HorizonSide(mod(Int(side)+1, 4)) 59 | # - прежде было имя next, но все-таки будет существенно удобнее, если его заменить на lef (это будет яснее) 60 | 61 | """ 62 | right(side::HorizonSide) 63 | 64 | -- Возвращает направление, предыдущее, если отсчитывать против часовой стредки, по отношению к заданному 65 | """ 66 | right(side::HorizonSide) = HorizonSide(mod(Int(side)-1, 4)) 67 | ``` 68 | 69 | Для того, чтобы иметь возможность пользоваться встроенной системой помощи все библиотечные функции следует предварять описаниями в виде многостирочного комментария, заключамого в тройные кавычки """....""". Тогда, после выполнения вклчения `include(имя_файла)` в REPL можно будет получить информацию о любой функции (с описанием) из данного файла: 70 | 71 | ```julia 72 | julia>? имя_функции 73 | ``` 74 | 75 | В результате, все функции, составляющие нашу библиотеку, могли бы быть использованы во всех рассматривавшихся задачах (1-25) с помощью выполнения включения `include("roblib.jl")` в файлы с новыми программами. 76 | 77 | ## Пример, когда желание иметь универсальный код приводит к необходимости, некоторые вспомогательные функции распределять по нескольким отдельным файлам 78 | 79 | Однако встречались и функции с одинаковыми именами, которые в разных задачах приходилось переопределять, потомучто требовалось учитывать специфику каждой задачи. 80 | А именно, вспомним [задачу 14](../4/Задачи%2014-25.md), которая есть аналог [задачи 1](../lecture-1/Список-задач-1.md), но ее уловие допускает наличие на поле внутренних перегодок прямоугольной формы. Решение этой задачи было разобрано в [Практика 4](../4/Практика-4.md) (напомним, там требовалось расставить маркеры в форме прямого креста). 81 | 82 | Сравнивая оба решения мы видим, что следующий код: 83 | 84 | ```julia 85 | function mark_kross(r) 86 | for side in (Nord, West, Sud, Ost) 87 | num_steps = putmarkes!(r,side) 88 | movements!(r,inverse(side), num_steps) # тут шибочно было: move!(...) 89 | end 90 | end 91 | 92 | function putmarkers!(r::Robot,side::HorizonSide) 93 | num_steps=0 94 | while move_if_possible!(r, side) == true 95 | putmarker!(r) 96 | num_steps += 1 97 | end 98 | return num_steps 99 | end 100 | 101 | movements!(r::Robot, side::HorizonSide, num_steps::Int) = 102 | for _ in 1:num_steps 103 | move_if_posible!(r,side) # - в данном случае возможность обхода внутренней перегородки гарантирована 104 | end 105 | ``` 106 | 107 | может давать решение как задачи 1, так и задачи 14 - тут все зависит от того, как будет реализована вспомогательная функция `move_if_posible!(::Robot, ::HorizonSide)`. 108 | 109 | Eсли 110 | 111 | ```julia 112 | move_if_possible!(r::Robot, side::HorizonSide) = 113 | if isborder(r,side)==false 114 | move!(r,side) 115 | return true 116 | else 117 | return false 118 | end 119 | ``` 120 | 121 | то получим решение задачи 1. Кстати говоря, это определение можно было бы записать и в одну строчку 122 | 123 | ```julia 124 | move_if_possible!(r::Robot, side::HorizonSide) = !isborder(r,side) ? (move!(r,side); true) : false 125 | ``` 126 | 127 | где `(move!(r,side); true)` - это не кортеж, в кортеже элементы разделяются запятой, это программный блок, и это эквивалентно `begin move!(r,side); true end`. 128 | 129 | Соответственно в случае задачи 14, эта функция будет уже иметь другую реализацию: 130 | 131 | ```julia 132 | """ 133 | move_if_possible!(r::Robot, side::HorizonSide)::Bool 134 | 135 | -- Перемещает Робота в заданном направлении на 1 шаг и возвращает true - это, если мешающей перегородки нет, 136 | 137 | или, если её можно обойти; имеется ввиду, что изолированная перегородка прямоугольной формы. 138 | 139 | В противном случае Робот остается на месте и функция возвращает false. 140 | """ 141 | function move_if_possible!(r::Robot, direct_side::HorizonSide)::Bool 142 | orthogonal_side = left(direct_side) 143 | reverse_side = inverse(orthogonal_side) 144 | num_steps=0 145 | while isborder(r,direct_side) == true 146 | if isborder(r, orthogonal_side) == false 147 | move!(r, orthogonal_side) 148 | num_steps += 1 149 | else 150 | break 151 | end 152 | end 153 | #УТВ: Робот или уперся в угол внешней рамки поля, или готов сделать шаг (или несколько) в направлении 154 | # side 155 | 156 | if isborder(r,direct_side) == false 157 | move!(r,direct_side) 158 | while isborder(r,reverse_side) == true 159 | move!(r,direct_side) 160 | end 161 | result = true 162 | else 163 | result = false 164 | end 165 | for _ in 1:num_steps 166 | move!(r,reverse_side) 167 | end 168 | return result 169 | end 170 | ``` 171 | 172 | (конечно решение задачи 14 включает в себя и решение задачи 1, но если известно, что внутренних перегородок на поле нет, то решение, относящееся к более общему случаю будет содержать в себе лишние проверки, котрые иногда могут быть желательны). 173 | 174 | Возникает вопрос, а как воспользоваться замеченным сходством двух алгоритмов, так чтобы не кодировать посути одно и тоже дважды. 175 | 176 | **Решение может состоять в том, чтобы эти две разные реализации функции move_if_possible! поместить в разные файлы, и подключать к файлу с главной функцией тот или иной из них с помощью функции include, в зависимости от решаемой задачи.** 177 | 178 | Однако возможен и другой способ решения данной проблемы, основанный на так называемом обобщенном подходе к программированию. 179 | -------------------------------------------------------------------------------- /5/Черновик 5.1.md: -------------------------------------------------------------------------------- 1 | ----------------- 2 | ДОПОЛНЕНИЕ. 3 | Чтобы реализовать новый метод функции `inverse`, потребуется сделать так: 4 | ```julia 5 | inverse(side) = typeof(side)(inverse.(collect(side))) 6 | ``` 7 | Здесь, во-первых, использована встроенная функция `collect`, преобразующая любой итерируемый объект (в данном слусае кортеж) в одномерный массив (вектор). 8 | 9 | Во-вторых, точка в выражении `функция.(одномерный_массив)` означает, что формируется другой одномерный массив, путем примения данной функции (в нашем случау inverse) к каждому элементу исходного массива. 10 | 11 | Наконец, в-третьих, typeof(side) - даёт тип переменной side, так что typeof(side)(...) - это есть преобразование (приведение) аргумента во вторых скобках (замененного здесь на ...) к этому типу. 12 | 13 | --------------------------- 14 | ----------------------------------------------------------- 15 | ----------------------------------------------------------- 16 | ----------------------------------------------------------- 17 | 18 | ## Обновленное сожержимое библиотечного файла roblib.jl 19 | 20 | ```julia 21 | 22 | HorizonSideRobots.move!(r::Robot,side::NTuple{HorizonSide}) = 23 | 24 | movements!(r, side, num_steps::Integer) = for _ in 1:num_steps move!(r,side) 25 | # тип Integer - это абстрактный тип, включающий все целые типы 26 | 27 | movements!(r, side) = while isborder(r,side)==false move!(r,side) end 28 | 29 | function get_num_movements!(r, side) 30 | num_steps = 0 31 | while isborder(r,side)==false 32 | move!(r,side) 33 | num_steps += 1 34 | end 35 | return num_steps 36 | end 37 | 38 | # Делает заданное число шагов в заданном направлении, при необходимости обходя внутренние перегородки. 39 | # При этом величина одного "шага" может быть больше 1 и равна "толщине" встретившейся прямоугольной 40 | # перегородки 41 | movements!(r::Robot, side::HorizonSide, num_steps::Integer) = 42 | for _ in 1:num_steps 43 | move_if_posible!(r,side) # - в данном случае возможность обхода внутренней перегородки гарантирована 44 | end 45 | #??? нужно ли обобщать эту функцию??? 46 | 47 | # Перемещает робота в заданном направлении, если это возможно, и возвращает true, 48 | # если перемещение состоялось; в противном случае - false. 49 | function move_if_possible!(r::Robot, side::HorizonSide)::Bool 50 | orthogonal_side = next(side) 51 | reverse_side = reverse(orthogonal_side) 52 | num_steps=0 53 | while isborder(direct_side) == true 54 | if isborder(r, orthogonal_side) == false 55 | move(r, orthogonal_side) 56 | num_steps += 1 57 | else 58 | break 59 | end 60 | end 61 | #УТВ: Робот или уперся в угол внешней рамки поля, или готов сделать шаг (или несколько) в направлении 62 | # side 63 | if isborder(r,side) == false 64 | while isborder(r,reverse_side) == true 65 | move!(r,side) 66 | end 67 | result = true 68 | else 69 | result = false 70 | end 71 | move!(r,reverse_side) 72 | return result 73 | end 74 | #??? нужно ли обобщать эту функцию??? 75 | 76 | 77 | inverse(side::HorizonSide) = 78 | left(side::HorizonSide) = # прежде было имя next, но все-таки его лучше заменить!!! 79 | right(side::HorizonSide) = 80 | 81 | ``` 82 | 83 | ---------------------------- 84 | 85 | 86 | Надо бы порешать еще задачи, можно такие. 87 | 88 | 89 | 90 | Это уже, наверное, материал для Лекции 6-7 91 | ### Элементы функционального программирования 92 | 93 | ### Пользовательские абстрактные и конкретные типы 94 | - Наследование и агрегирование (композиция) 95 | - Отсутствие множественного наследования 96 | - Отсутствие возможности наследования от конкретных типов 97 | #### Система типов Julia 98 | 99 | ### OOП как альтернатива функциональному программированию 100 | 101 | ### Примеры: Обобщенный (Абстрактный) Робот и различные специализированные роботы 102 | 103 | #### Обобщенный Робот 104 | 105 | - api Обобщенного Робота 106 | 107 | 108 | #### Пример Рробота-установшика маркеров, 109 | 110 | #### Пример Робота-установщик маркеров в шахматном порядке 111 | 112 | #### Пример Робота-счетика числа маркеров и т.п., 113 | 114 | #### Пример Робота-умеющего обходить прямоугольные перегородки 115 | 116 | #### Пример Робота-умеющего определять свои декартовы координаты 117 | 118 | 119 | -------------------------------------------------------------------------------- /5/Черновик-5.2.md: -------------------------------------------------------------------------------- 1 | ------------------------------------------------ 2 | ------------------------------------------------ 3 | 4 | ДАЛЕЕ, ВРОДЕ КАК, НИЧЕГО ОСОБЕННО ЦЕННОГО НЕТ 5 | 6 | ------------------------------------------------ 7 | 8 | В предыдущих примерах на использование множественной диспетчеризацию, мы описывали типы аргументов функций как можно более точно. Однако, как правило, так поступать не следует, потому что это будет ограничивать область применеия функций. 9 | 10 | Например, мы определили один из методов функции move! так 11 | ```julia 12 | move!(r::Robot, sides::Tuple{HorizonSide}) 13 | ``` 14 | но могли бы определить и так 15 | ```julia 16 | move!(r::Robot,sides::Tuple) 17 | ``` 18 | Теперь второй аргумент имеет более общий тип - это кортеж (Tuple) каких-угодно значений. 19 | Можно было бы возразить, что какие-угодно значения нам не нужны, у нас есть только Nord, Sud, Ost и West. Но, на самом деле, не исключено, что когда-нибудь могут понадобиться и направления на северо-восток, северо-запад, юго-восток, юго-запад, которые будут определяться кортежами двух соответствующих значений: (Nord,Ost), (Nord, West), (Sud,Ost), (Sud,West) (и мы в этом совсем скоро убедимся). И тогда замена Tuple{HorizonSide} на Tuple, может оказаться оправданной. 20 | Но остается еще проблема, при описании sides::Tuple мы можем задать последовательность направлений в виде кортежа направлений, но не можем - в виде массива направлений. Чтобы расширить наши возможности в этом направлении, следовало бы описать функцию вообще без аннотирования типа ее второго аргумента 21 | ```julia 22 | move!(r::Robot, sides) 23 | ``` 24 | На самом деле это просто означает, что sides::Any, где `Any` - это абстрактный тип, стоящий во лаве всей иерархии типов языка Julia. Фактически это означает, что тип второго аргумента может быть любой, за исключением типа HorizonSide, т.к. для этого случая имеется определение отдельного метода функции. При этом говорят, что функция имеет специализацию для типа HorizonSide. 25 | 26 | Точно также, определяя новые методы для функции move!, на самом деле стоит отказаться и от аннотирования первого аргумента: 27 | ```julia 28 | move!(r::Robot, side::HorizonSide) # - имеет максимальную специализацию по обоим аргументам 29 | move!(r, side, num_steps) # - тип всех аргументов Any 30 | move!(r, sides) # - тип всех аргументов Any 31 | ``` 32 | 33 | Какую выгоду из этого мы сумеем извлечь - это мы увидим дальше. Но пока просто будем следовать общему принципу: без явной необходимости не сужать специализацию функций. 34 | 35 | Иногда такое сужение специализации нежелательно, потому что приведет к ограничению общности функции, а иногда - просто потому, что точное описание типа может оказаться слишком громоздким. 36 | 37 | ### Примеры разработки обобщенных функций 38 | Рассмотрим еще раз, разобранную ранее, [задачу 13](../4/Практика-4.md). 39 | ДАНО: Робот - в произвольной клетке ограниченного прямоугольной рамкой поля без внутренних перегородок и маркеров. 40 | 41 | РЕЗУЛЬТАТ: Робот - в исходном положении в центре косого креста (в форме X) из маркеров. 42 | 43 | **Решение** 44 | Следуя технологии "сверху вниз", запишем псевдокод 45 | ```julia 46 | for side in ((Nord,Ost),(Nord,West),(Sud,West),(Sud,Ost)) 47 | ставить маркеры в направлении side до упора 48 | вернуться в обратном направлении по маркерам в исходное положение 49 | end 50 | ``` 51 | Или придумывая подходящиее заголовки для соответствующих подпрограмм, получаем 52 | ```julia 53 | function mark_krest(r,sides) 54 | for side in sides 55 | putmarkers!(r,side) # ставит маркеры в заданном напралении до упора 56 | moves_by_markers!(r,inverse(side)) 57 | end 58 | putmarker!(r) 59 | end 60 | 61 | """ 62 | inverse(s::HorizonSide) 63 | 64 | -- возвращает направление, противоположное заданному 65 | """ 66 | inverse(s::HorizonSide)=HorizonSide(mod(Int(s)+2,4)) 67 | 68 | """ 69 | inverse(side) 70 | 71 | -- side - кортеж или вектор, содержащий направления типа Union{HorizonSide, NTuple{2, HorizonSide}} 72 | """ 73 | inverse(side)=typeof(side)((inverse.(collect(side)))) 74 | 75 | """ 76 | putmarkers(r,side) 77 | 78 | -- 79 | """ 80 | putmarkers(r,side) = 81 | while isborder(r,side) == true 82 | move!(r,side) 83 | putmarker!(r) 84 | end 85 | 86 | """ 87 | isborder(r,side) 88 | 89 | -- r - ссылка на Робота 90 | 91 | -- side - итерируемый объект, содержащий значения направлений типа HorizonSize (но формально тут этого ограничения нет) 92 | 93 | -- возвращает true, если хотя бы для с одного из направлений в side рядом с роботом имеется перегородка 94 | """ 95 | function isborder(r,side) 96 | for s in side 97 | if isborder(r,s)==true return end 98 | end 99 | return false 100 | end 101 | 102 | """ 103 | move!(r,sides) 104 | 105 | -- r - ссылка на Робота 106 | 107 | -- sides - итерируемый объект, содержащий значения направлений (например, типа HorizonSize) 108 | 109 | -- последовательно перемещает робота в направлениях из sides 110 | """ 111 | move!(r,side) = for s in side move!(r,s) end 112 | 113 | 114 | """ 115 | moves_by_markers!(r,side) 116 | 117 | -- перемещает Робота r в заданном направлении side, до тех пор пока Робот находится в клетке с маркером 118 | 119 | -- side::Union{HorizonSide,Ntuple{2,HorizonSide} 120 | """ 121 | moves_by_markers!(r,side) = 122 | while ismarker(r,side) 123 | move!(r, side) 124 | end 125 | end 126 | ``` 127 | 128 | ### Пример практического использования множественной диспетчеризации 129 | 130 | И так, у Робота есть команда move!(::Robot, ::HorizonSide), которая перемещает его ровно на одну клетку в заданном направлении, в предположении, конечно, что этому не помешает перегородка. Если же наличествует перегородка на пути, то произойдет фатальная ошибка времени выполнения. 131 | 132 | А что если понадобится команда сделать шаг "по диагонали", на северо-восток, юго-восток, и т.д. Какждый такой шаг реализуется за 2 стандартных шага Робота, поэтому соответствующий параметр новой функции, которая это будет реализовывать, задается кортежем (Tuple) вида (Nor,Ost), (Sud,Ost), и т.д. 133 | Но как назвать саму эту функцию? Если использовать множественную диспетчерезацию, то имя этой новой команды может быть тоже move!, что было бы логично (и даже очень желательно, если иметь целью программировать обобщенно, о чем несколько слов здесь будет сказано далее). Для этого только потребуется нужным образом аннотировать тип соответствующего параметра: 134 | ```julia 135 | move!(r::Robot,side::Tuple{HorizonSide}) = for s in side move!(r,s) end 136 | ``` 137 | Теперь можно будет командовать, например, так: 138 | ```julia 139 | move!(r,(Nord,Ost)) 140 | ``` 141 | 142 | Но можно также и 143 | ```julia 144 | move!(r,(Nord,Sud)) 145 | ``` 146 | но это, скорее всего, бессмысленная команда, т.к. если на пути не было перегородки, то робот просто останется на месте, а если была - то произойдет фатальная ошибка времени выполнения. 147 | 148 | Однако возможно будет скомандовать еще и так, например, 149 | ```julia 150 | move!(r,(Nord,Nord,Sud,Nord)) 151 | ``` 152 | или 153 | ```julia 154 | move!(r,[Nord,Nord,Sud,Nord]) 155 | ``` 156 | и такая возможность может оказаться очень даже полезной. 157 | 158 | Но тут возможен еще такой "фокус". 159 | Мы определили тип аргумента side как Tuple{HorizonSide}, т.е. кортеж (произвольной длины) значений типа HorizonSide. Таким кортежем является, например, (Nord,Nord,Sud,Nord), который содержит в себе некоторый "путь" для Робота. А что если бы мы захотели задать такой путь: ((Nord,Ost),(Sud,West),(Sud,Ost)), то чтобы заставить Робота пройти этот путь, уже нельзя будет воспользоваться функцией move!(::Robot,::Tuple{HorizonSide}), потому что этому не соответствует тип ее вторго параметра. Но предвидя такую задачу, мы могли бы аннотировать этот аргумент так 160 | ```julia 161 | move!(r::Robot,side::Tuple) = for s in side move!(r,s) end 162 | ``` 163 | Теперь тип аргумента side есть кортеж (произвольной длины) каких угодно значений, в том числе допусимыми будут и значения вида (Nord,Ost),(Sud,West),(Sud,Ost). 164 | 165 | Это есть небольшая иллюстрация касающаяся **обобщенного программирования**. 166 | 167 | Можно даже было бы вообще не аннотировать аргументы этой функции: 168 | ```julia 169 | move!(r,side) = for s in side move!(r,s) end 170 | ``` 171 | и тем самым повысить степень ее обобщенности. 172 | 173 | Где достигаемая таким способ обобщенность может пригодиться, часто заранее даже не известно. 174 | Но в рассмативаемом случае сразу можно сказать, где она будет полезна. В самом деле, теперь последовательность направлений может быть представлена не только кортежем соответствующих значений, но и вектором этих значений, например: [(Nord,Ost),(Sud,West),(Sud,Ost)], или - [Nord,Nord,Sud,Nord]. 175 | 176 | На самом деле, не явно типы аргуметнов нашей последней функции аннотированы, можно считать, типом Any. Any - это абстрактный тип, стоящий на вершине иерархии всех типов Julia. 177 | 178 | Но для того, чтобы работала множественная диспетчеризация достаточно, чтобы в одном случае был один тип, в нашем случае HorizonSide, а в другом - тип может быть и Any (важно, что какой-то другой). 179 | -------------------------------------------------------------------------------- /6/oblique_lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/6/oblique_lines.png -------------------------------------------------------------------------------- /6/straight_lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/6/straight_lines.png -------------------------------------------------------------------------------- /6/totask30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/6/totask30.png -------------------------------------------------------------------------------- /6/totask31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/6/totask31.png -------------------------------------------------------------------------------- /6/Задачи 28-31.md: -------------------------------------------------------------------------------- 1 | # Задача 28-31 2 | 3 | 28. В [лекции 6](Лекция-6.md) был спроектирован модуль `StartBack` с двумя функциями `move_to_start!` и `move_to_back!`, с помощью которых робот может быть перемещен из начального положения в стартовый угол, а затетем, после решения основной задачи и возвращения в стартовый угол, перемещен в исходное положение. Однако в реализации этих функций не было предусмотрено наличие внутренних перегородок на поле. 4 | Требуется, модернизировать этот модуль так, чтобы его можно было бы использовать и при решении задач, услия которых предполагает возможность наличия на поле внутренних изолированных перегородок прямоугольной формы (некоторые такие прямоугольники могут вырождаться в отрезки). 5 | 6 | 29. Начертить в отдельном графическом окне план расположения перегородок, считая, что точка центра поля совпадает с началом координат, оси координат параллельны линям широты и долготы, и что размер клетки поля на чертеже равен 1. 7 | Вначале Робот находится в произвольной клетке поля, в конце он снова в исходном положени. 8 | 9 | Указание: использовать графическую библиотеку `Plots.jl` 10 | Для этого ее надо сначала скачать с github.com 11 | 12 | ```julia 13 | julia>] 14 | pkg> add Plots.jl 15 | ``` 16 | 17 | А после этого её можно будет импортировать: 18 | 19 | ```julia 20 | julia> using Plots 21 | ``` 22 | 23 | Чтобы построить график плоской ломаной линии, декартовы координаты узловых точек которой находятся, например, в векторах `xdata` и `ydata`, в этом пакете предусмотрена функция `plot`. 24 | После ее вызова с соответствующими фактическими параметрами 25 | 26 | ```julia 27 | p=plot(xdata,ydata) 28 | ``` 29 | 30 | в памяти компьюиера буддет создан объект p с данными графика. Отобразтися ли при этом график в графическом окне или нет - это зависит от того, где было исполнено `p=plot(xdata,ydata)`. Если непосредственно в REPL, то график отобразится, если - в теле какой-либо функции, вызываемой из REPL, то для того чтобы график отобразился требуется чтобы функия возвращала (в REPL) значение p (в функции должно быть return p). Если же `p=plot(xdata,ydata)` было исполнено в какой-дибо подпрограмме, вызываемой главной функцией, то необходимо, чтобы эта подпрограмма возвращала в вызывающуюю ее функцию объект p, а та, в свою очередь, должна возвратить его в REPL. Без этого график не отобразится. 31 | 32 | Если требуется в уже построеннный график добавить еще одну кривую, то для этого предусмотрена функция `plot!`. Пусть например переменные `xdata` и `ydata` содержат массивы координат нового графика, который требуется добавить к уже существующему в объекте p, тогда следует выполнить: 33 | 34 | ```julia 35 | plot!(p, xdata,ydata) 36 | ``` 37 | 38 | Более полную информацию по графическому пакету Plots можно найти [здесь](https://docs.juliaplots.org/latest/tutorial/) 39 | 40 | 30. На прямоугольном поле имеются прямолинейные горизонталные перегородки, которые на западе гарантированно не касаются внешней рамки, а на востоке такие касания возможны. Изначально Робот находится в произвольной клетке, в результате все поле должно быть замаркировано, и Робот должен находиться в исходном положении. Постараться минимизировать число шагов Робота. 41 | 42 | ![Пример обстановки](totask30.png) 43 | 44 | 31. Робот находится где-то внутри лабиринта, граница которого обладает следующим свойством: любая горизонтальная прямая пересекает границу ровно 2 раза (а произвольная вертикальная прямая пересекает ее любое четное число раз). 45 | Требуется подсчитать число имеющихся на поле маркеров (функция должна это число возвращать) и возвратить Робота в исходное положение. 46 | 47 | ![Пример обстановки](totask31.png) -------------------------------------------------------------------------------- /7/task12.jl: -------------------------------------------------------------------------------- 1 | module Decart 2 | using HorizonSideRobots 3 | #= 4 | Предполагается, что в пространстве имен Main определена функция inverse, например, путем вставки из файла "roblib.jl" 5 | =# 6 | export init, move!, get_coord 7 | 8 | X_COORD=0 9 | Y_COORD=0 10 | 11 | function init(x=0,y=0) 12 | global X_COORD, Y_COORD 13 | X_COORD=0 14 | Y_COORD=0 15 | end 16 | 17 | function move!(r,side) 18 | global X_COORD, Y_COORD 19 | if side==Nord 20 | Y_COORD+=1 21 | elseif side==Sud 22 | Y_COORD-=1 23 | elseif side==Ost 24 | X_COORD+=1 25 | else # side==West 26 | X_COORD-=1 27 | end 28 | HorizonSideRobots.move!(r,side) 29 | end 30 | 31 | det_coord()=( X_COORD, Y_COORD) 32 | end # module 33 | 34 | 35 | using .Decart 36 | 37 | 38 | #= 39 | Теперь модуль Decart, можно испоьзовать, например, так: 40 | 41 | Decart.init() 42 | r = Robot() 43 | Decart.move!(r,Nord) 44 | x,y = Decart.get_coord() 45 | =# 46 | 47 | 48 | function mark_chess(r::Robot,n::Int) 49 | #УТВ: Робот - в юго-западном углу 50 | Decart.init() 51 | side=Ost 52 | mark_row(r,side,n) 53 | while isborder(r,Nord)==false 54 | Decart.move!(r,Nord) 55 | side = inverse(side) 56 | mark_row(r,side,n) 57 | end 58 | end 59 | 60 | function mark_row(r::Robot,size::HorizonSide, n::Integer) 61 | putmarker_chess!(r,n) 62 | while isborder!(r,side)==false 63 | Decart.move!(r,side) 64 | putmarker_chess!(r,n) 65 | end 66 | end 67 | 68 | 69 | function putmarker_chess!(r::Robot,n::Integer) 70 | x,y = Decart.get_coord() 71 | x = mod(x,2n) 72 | y = mod(y,2n) 73 | if (x in 0:n && y in 0:n) || (x in n+1:2n && y in n+1:2n) 74 | putmarker!(r) 75 | end 76 | end 77 | -------------------------------------------------------------------------------- /7/task31.jl: -------------------------------------------------------------------------------- 1 | #= 2 | ЗАДАЧА 31. 3 | Робот находится где-то внутри лабиринта, граница которого обладает следующим свойством: любая горизонтальная 4 | прямая пересекает границу ровно 2 раза (а произвольная вертикальная прямая пересекает ее любое четное число раз). 5 | 6 | Требуется подсчитать число имеющихся на поле маркеров (функция должна это число возвращать) и 7 | возвратить Робота в исходное положение. 8 | =# 9 | 10 | function get_num_markers_lab(robot) 11 | #УТВ: Робот - в произвольной клетке лабиринта 12 | 13 | num_steps, side_steps = move_to_start!(robot, (Sud,West)) 14 | num_steps=reverse(num_steps) 15 | side_steps=reverse(side_steps) 16 | #УТВ: Робот - в юго-западном углу 17 | 18 | side = Ost 19 | num_markers = get_num_markers!(robot, side) 20 | #ИНВАРИАНТ: Робот - в "начале" ряда 21 | while is_move_posible!(robot, Nord, side) == true 22 | move!(robot, Nord) 23 | movements!(robot,side) 24 | side = inverse(side) 25 | num_markers += get_num_markers!(robot, side) 26 | end 27 | #УТВ: Маркеры посчитаны, Робот где-то у северной границы в углу 28 | 29 | move_to_start!(robot, (Sud,West)) 30 | #УТВ: Робот - снова в юго-западном углу 31 | 32 | for (i,n) in enumerate(num_steps) 33 | movements!(robot, side_steps[i], n) 34 | end 35 | #УТВ: Робот - в исходном положении 36 | return num_markers 37 | end 38 | 39 | function get_num_markers!(robot, side) 40 | #= 41 | ДАНО: Робот - в начале ряда, side - направление перемещения 42 | РЕЗУЛЬТАТ: Робот - в противоположном конце ряда и возвращено число маркеров, имеющихся в этом ряду 43 | =# 44 | nun_markers = ismarker(robot) ? 1 : 0 45 | while !isborder(robot,side) 46 | move!(robot,side) 47 | ismarker(robot) && num_markers += 1 # - это тоже самое, что и if ismarker(robot) num_markers += 1 end 48 | end 49 | return num_markers 50 | end 51 | 52 | 53 | function is_move_posible!(robot, move_side, find_side) 54 | #= 55 | ДАНО: Робот - в одном из концов ряда 56 | -- find_side - направление к противоположному концу ряда 57 | -- move_side - направление для перемещения в следующий ряда 58 | РЕЗУЛЬТАТ: 59 | Проверена возможность переместить Робота (но не перемещет его) в направлении move_side, 60 | при необходимости выполнив смещение Робота в направлении find_side на некоторое количество шагов 61 | 62 | Если перемещение в направлении move_side возможно, то Робот остановится возле первого возможного прохода, 63 | и тогда будет возвращено - true; 64 | в противном случае будет возвращено - false, и Робот окажется у противоположного конца ряда. 65 | =# 66 | while isborder(robot, move_side) 67 | if !isborder(robot, find_side) 68 | move!(robot, find_side) 69 | else 70 | return false 71 | end 72 | end 73 | return true 74 | end 75 | 76 | 77 | function move_to_start(robot, start_side::Tuple) 78 | #= 79 | Перемещает Робота из произвольной клетки в угол, заданный кортежем из двух ортогональных направлений start_side, 80 | и возвращает два массива равной длины: 81 | первый массив содержит числа сделанных шагов в направлениях, содержащихся во втором массиве, в естественном порядке 82 | =# 83 | num_steps = Int[] 84 | side_steps = HorizoSide[] 85 | while !isborder(robot,start_side[2]) || is_posible!(robot, start_side[1], inverse(start_side[2]), num_steps, side_steps) # <=> Робот - не в стартовом углу 86 | for i in 1:2 87 | push!(num_steps, get_num_movements!(robot,start_side[i])) 88 | push!(side_steps, start_side[i]) 89 | end 90 | end 91 | return num_steps, side_steps 92 | end 93 | 94 | 95 | function is_move_posible!(robot, move_side, find_side, num_steps::Vector, side_steps::Vector) 96 | #= 97 | ДАНО: Робот - в одном из концов ряда 98 | -- find_side - направление к противоположному концу ряда 99 | -- move_side - направление для перемещения в следующий ряда 100 | -- num_steps, side_steps - внешние массивы, которые додны быть пополнены новыми элементами 101 | РЕЗУЛЬТАТ: 102 | Проверена возможность переместиться в направлении move_side, при необходимости сместившись 103 | в направлении find_side на некотое количество шагов 104 | Если перемещение возможно, то Робот остановится возле первого возможного прохода, и будет возвращено - true 105 | В противном случае будет возвращено - false, и Робот окажется у противоположного конца ряда 106 | 107 | При этом во внешние массивы num_steps, side_steps добавлены число сделанных при поиске прохода шагов и 108 | направление поиска, соответственно 109 | =# 110 | num=0 111 | while isborder(robot, move_side) 112 | if !isborder(robot, find_side) 113 | num += 1 114 | move!(robot,find_side) 115 | else 116 | push!(num_steps, num) 117 | push!(side_steps, find_side) 118 | return false 119 | end 120 | end 121 | push!(num_steps, num) 122 | push!(side_steps, find_side) 123 | 124 | return true 125 | end -------------------------------------------------------------------------------- /7/task31.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 11 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 3 8 9 | temperature_map: 10 | 491 166 -249 438 301 -196 394 360 423 -28 59 190 92 99 83 177 40 1 -137 274 245 463 490 298 392 373 158 67 43 -262 -151 -157 -98 -159 -187 140 166 -66 419 308 226 183 68 167 94 -163 236 371 341 272 129 275 93 294 114 -177 466 186 -133 -264 272 485 278 364 442 -115 193 -73 -136 230 233 74 383 -104 176 236 68 -105 477 -118 -75 259 419 476 62 -100 421 402 -31 -160 -270 0 468 -44 -217 -157 190 458 -46 168 10 301 122 406 223 -248 419 -82 300 429 -41 -19 104 152 -130 -262 14 151 195 42 276 -69 -109 -136 -219 -130 75 -132 11 -24 443 457 11 | markers_map: 12 | (4, 3)(10, 8)(2, 2)(8, 9)(2, 10)(5, 9)(4, 7)(7, 5)(4, 8)(4, 9)(8, 4) 13 | borders_map: 14 | 15 | 16 | 17 | 3 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 2 26 | 1 2 27 | 2 28 | 2 29 | 30 | 31 | 3 32 | 33 | 2 34 | 1 2 35 | 36 | 37 | 0 38 | 0 39 | 0 40 | 0 41 | 42 | 0 43 | 1 44 | 0 45 | 0 2 46 | 47 | 2 48 | 49 | 0 50 | 0 51 | 0 52 | 53 | 0 54 | 55 | 0 2 56 | 2 57 | 58 | 59 | 0 2 60 | 61 | 0 2 62 | 63 | 1 0 64 | 65 | 2 66 | 2 67 | 68 | 0 69 | 70 | 0 71 | 0 2 3 72 | 73 | 0 2 74 | 75 | 76 | 77 | 0 2 78 | 2 79 | 80 | 2 81 | 82 | 83 | 84 | 0 2 85 | 86 | 1 0 2 87 | 88 | 0 89 | 0 2 90 | 91 | 2 92 | 93 | 94 | 95 | 1 96 | 97 | 0 2 98 | 99 | 1 100 | 2 101 | 102 | 2 103 | 104 | 105 | 3 106 | 107 | 2 108 | 109 | 0 110 | 3 111 | 2 112 | 113 | 114 | 0 3 115 | 116 | 0 2 117 | 3 118 | 2 3 119 | 120 | 0 121 | 0 2 122 | 2 123 | 124 | 125 | 126 | 0 3 127 | 0 128 | 129 | 130 | 131 | 0 3 132 | 0 133 | 1 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /7/Задачи 32-.md: -------------------------------------------------------------------------------- 1 | еще раз прорешать ранее решенные задачи, но записывать соответствующий программный код, придерживаясь функционального или смешанного функционально-императивного стиля. -------------------------------------------------------------------------------- /7/Практика-7.md: -------------------------------------------------------------------------------- 1 | # Практика 7 2 | 3 | - [Практика 7](#практика-7) 4 | - [Улучшение структуры програмного кода в полученном ранее решение задачи 12 за счет ввынесение за пределы модуля "лишних" функций](#улучшение-структуры-програмного-кода-в-полученном-ранее-решение-задачи-12-за-счет-ввынесение-за-пределы-модуля-лишних-функций) 5 | - [Разбор задачи 31](#разбор-задачи-31) 6 | - [Задание на улучшение структуры програмного кода решения задачи 31](#задание-на-улучшение-структуры-програмного-кода-решения-задачи-31) 7 | 8 | ## Улучшение структуры програмного кода в полученном ранее решение задачи 12 за счет ввынесение за пределы модуля "лишних" функций 9 | 10 | Ранее, в [Практика 4](../4/Практика-4.md) было разобрано решение задачи 12. 11 | 12 | Вот полученный там программный код. 13 | 14 | ```julia 15 | module NNChessMarker 16 | using HorizonSideRobots 17 | import Main.inverse 18 | #= 19 | Предполагается, что в пространстве имен Main определена функция inverse, например, путем вставки из файла "roblib.jl" 20 | =# 21 | export mark_chess 22 | 23 | X_COORDINATE=0 24 | Y_COORDINATE=0 25 | 26 | CELL_SIZE = 0 # - размер "шахматной" клеки 27 | 28 | function mark_chess(r::Robot,n::Int) 29 | global CELL_SIZE 30 | CELL_SIZE = n # инициализация глобальной переменной 31 | 32 | #УТВ: Робот - в юго-западном углу 33 | side=Ost 34 | mark_row(r,side) 35 | while isborder(r,Nord)==false 36 | move_decart!(r,Nord) 37 | side = inverse(side) 38 | mark_row(r,side) 39 | end 40 | end 41 | 42 | function mark_row(r::Robot,size::HorizonSide) 43 | putmarker_chess!(r) 44 | while isborder!(r,side)==false 45 | move_decart!(r,side) 46 | putmarker_chess!(r) 47 | end 48 | end 49 | 50 | function putmarker_chess!(r) 51 | if (mod(X_COORDINATE, 2*CELL_SIZE) in 0:CELL_SIZE-1) 52 | && (mod(Y_COORDINATE, 2*CELL_SIZE) in 0:CELL_SIZE-1) 53 | putmarker!(r) 54 | end 55 | end 56 | 57 | function move_decart!(r,side) 58 | global X_COORD, Y_COORD 59 | if side==Nord 60 | Y_COORD+=1 61 | elseif side==Sud 62 | Y_COORD-=1 63 | elseif side==Ost 64 | X_COORD+=1 65 | else # side==West 66 | X_COORD-=1 67 | end 68 | move!(r,side) 69 | end 70 | 71 | end 72 | ``` 73 | 74 | 75 | Однако этом коде идея модульного программирования не была доведена до идеала (сознательно). В прошлый раз целью было просто демонстрировалось использование глобальных переменных. 76 | 77 | И теперь мы можем его критически рассмотреть. Его недостаток в том, что наш модуль получился "размазанным" по всей программе. 78 | 79 | И это не хорошо, поскольку следует стремиться концентрировать в модуле (информационно связанном) минимальный набор функций, которые действительно составляют единое целое с глобальными переменными. 80 | 81 | Такой информационно связанный модуль будет получаться более универсальным, пригодным для повторных применений в других задачах. 82 | 83 | Также такой модуль будет проще отлаживать, поскольку часть лишних функций будет выведена за его пределы. 84 | 85 | Вот, что получится, если следовать указанному принципу. 86 | 87 | ```julia 88 | module Decart 89 | using HorizonSideRobots 90 | #= 91 | Предполагается, что в пространстве имен Main определена функция inverse, например, путем вставки из файла "roblib.jl" 92 | =# 93 | export init, move!, get_coord 94 | 95 | X_COORD=0 96 | Y_COORD=0 97 | 98 | function init(x=0,y=0) 99 | global X_COORD, Y_COORD 100 | X_COORD=0 101 | Y_COORD=0 102 | end 103 | 104 | function move!(r,side) 105 | global X_COORD, Y_COORD 106 | if side==Nord 107 | Y_COORD+=1 108 | elseif side==Sud 109 | Y_COORD-=1 110 | elseif side==Ost 111 | X_COORD+=1 112 | else # side==West 113 | X_COORD-=1 114 | end 115 | HorizonSideRobots.move!(r,side) 116 | end 117 | 118 | det_coord()=( X_COORD, Y_COORD) 119 | end # module 120 | ``` 121 | 122 | Тогда если код с этим модулем поместить в отдельный файл " Decart.jl" , например (или можно былобы его добавить в наш библиотечный модуль "roblib.jl"), то файл с главной функцией мог бы выглядеть, например, так: 123 | 124 | ```julia 125 | include("roblib.jl") 126 | include("Decart.jl") 127 | 128 | using .Decart 129 | 130 | function mark_chess(r::Robot,n::Int) 131 | #УТВ: Робот - в юго-западном углу 132 | Decart.init() 133 | side=Ost 134 | mark_row(r,side,n) 135 | while isborder(r,Nord)==false 136 | Decart.move!(r,Nord) 137 | side = inverse(side) 138 | mark_row(r,side,n) 139 | end 140 | end 141 | 142 | function mark_row(r::Robot,size::HorizonSide, n::Integer) 143 | putmarker_chess!(r,n) 144 | while isborder!(r,side)==false 145 | Decart.move!(r,side) 146 | putmarker_chess!(r,n) 147 | end 148 | end 149 | 150 | 151 | function putmarker_chess!(r::Robot,n::Integer) 152 | x,y = Decart.get_coord() 153 | x = mod(x,2n) 154 | y = mod(y,2n) 155 | if (x in 0:n && y in 0:n) || (x in n+1:2n && y in n+1:2n) 156 | putmarker!(r) 157 | end 158 | end 159 | ``` 160 | 161 | ## Разбор задачи 31 162 | ```julia 163 | #= 164 | ЗАДАЧА 31. 165 | Робот находится где-то внутри лабиринта, граница которого обладает следующим свойством: любая горизонтальная 166 | прямая пересекает границу ровно 2 раза (а произвольная вертикальная прямая пересекает ее любое четное число раз). 167 | 168 | Требуется подсчитать число имеющихся на поле маркеров (функция должна это число возвращать) и 169 | возвратить Робота в исходное положение. 170 | =# 171 | 172 | function get_num_markers_lab(robot) 173 | #УТВ: Робот - в произвольной клетке лабиринта 174 | 175 | num_steps, side_steps = move_to_start!(robot, (Sud,West)) 176 | num_steps=reverse(num_steps) 177 | side_steps=reverse(side_steps) 178 | #УТВ: Робот - в юго-западном углу 179 | 180 | side = Ost 181 | num_markers = get_num_markers!(robot, side) 182 | #ИНВАРИАНТ: Робот - в "начале" ряда 183 | while is_move_posible!(robot, Nord, side) == true 184 | move!(robot, Nord) 185 | movements!(robot,side) 186 | side = inverse(side) 187 | num_markers += get_num_markers!(robot, side) 188 | end 189 | #УТВ: Маркеры посчитаны, Робот где-то у северной границы в углу 190 | 191 | move_to_start!(robot, (Sud,West)) 192 | #УТВ: Робот - снова в юго-западном углу 193 | 194 | for (i,n) in enumerate(num_steps) 195 | movements!(robot, side_steps[i], n) 196 | end 197 | #УТВ: Робот - в исходном положении 198 | return num_markers 199 | end 200 | 201 | function get_num_markers!(robot, side) 202 | #= 203 | ДАНО: Робот - в начале ряда, side - направление перемещения 204 | РЕЗУЛЬТАТ: Робот - в противоположном конце ряда и возвращено число маркеров, имеющихся в этом ряду 205 | =# 206 | nun_markers = ismarker(robot) ? 1 : 0 207 | while !isborder(robot,side) 208 | move!(robot,side) 209 | ismarker(robot) && num_markers += 1 # - это тоже самое, что и if ismarker(robot) num_markers += 1 end 210 | end 211 | return num_markers 212 | end 213 | 214 | 215 | function is_move_posible!(robot, move_side, find_side) 216 | #= 217 | ДАНО: Робот - в одном из концов ряда 218 | -- find_side - направление к противоположному концу ряда 219 | -- move_side - направление для перемещения в следующий ряда 220 | РЕЗУЛЬТАТ: 221 | Проверена возможность переместить Робота (но не перемещет его) в направлении move_side, 222 | при необходимости выполнив смещение Робота в направлении find_side на некоторое количество шагов 223 | 224 | Если перемещение в направлении move_side возможно, то Робот остановится возле первого возможного прохода, 225 | и тогда будет возвращено - true; 226 | в противном случае будет возвращено - false, и Робот окажется у противоположного конца ряда. 227 | =# 228 | while isborder(robot, move_side) 229 | if !isborder(robot, find_side) 230 | move!(robot, find_side) 231 | else 232 | return false 233 | end 234 | end 235 | return true 236 | end 237 | 238 | 239 | function move_to_start(robot, start_side::Tuple) 240 | #= 241 | Перемещает Робота из произвольной клетки в угол, заданный кортежем из двух ортогональных направлений start_side, 242 | и возвращает два массива равной длины: 243 | первый массив содержит числа сделанных шагов в направлениях, содержащихся во втором массиве, в естественном порядке 244 | =# 245 | num_steps = Int[] 246 | side_steps = HorizoSide[] 247 | while !isborder(robot,start_side[2]) || is_posible!(robot, start_side[1], inverse(start_side[2]), num_steps, side_steps) # <=> Робот - не в стартовом углу 248 | for i in 1:2 249 | push!(num_steps, get_num_movements!(robot,start_side[i])) 250 | push!(side_steps, start_side[i]) 251 | end 252 | end 253 | return num_steps, side_steps 254 | end 255 | 256 | 257 | function is_move_posible!(robot, move_side, find_side, num_steps::Vector, side_steps::Vector) 258 | #= 259 | ДАНО: Робот - в одном из концов ряда 260 | -- find_side - направление к противоположному концу ряда 261 | -- move_side - направление для перемещения в следующий ряда 262 | -- num_steps, side_steps - внешние массивы, которые додны быть пополнены новыми элементами 263 | РЕЗУЛЬТАТ: 264 | Проверена возможность переместиться в направлении move_side, при необходимости сместившись 265 | в направлении find_side на некотое количество шагов 266 | Если перемещение возможно, то Робот остановится возле первого возможного прохода, и будет возвращено - true 267 | В противном случае будет возвращено - false, и Робот окажется у противоположного конца ряда 268 | 269 | При этом во внешние массивы num_steps, side_steps добавлены число сделанных при поиске прохода шагов и 270 | направление поиска, соответственно 271 | =# 272 | num=0 273 | while isborder(robot, move_side) 274 | if !isborder(robot, find_side) 275 | num += 1 276 | move!(robot,find_side) 277 | else 278 | push!(num_steps, num) 279 | push!(side_steps, find_side) 280 | return false 281 | end 282 | end 283 | push!(num_steps, num) 284 | push!(side_steps, find_side) 285 | 286 | return true 287 | end 288 | ``` 289 | 290 | ## Задание на улучшение структуры програмного кода решения задачи 31 291 | 292 | 1. По аналогии с тем, как это было сделано в [лекции 6](../6/Лекция-6.md) в подразделе "Задача перемещения Робота в стартовый угол и обратно" разработайте информационно связанный модуль StartBack, позволяющий перемещать Робота в стартовый угол, а потом, после решения основной задачи и возвращения в стартовый угол, вернуть его в исходное положение. И используйте этот модуль в решении задачи 32. 293 | 294 | 2. Попробуюте написать модуль StartBack так, чтобы он годился и для решения задачи 32, и для решения предыдущих задач. -------------------------------------------------------------------------------- /7/Черновик.md: -------------------------------------------------------------------------------- 1 | 2 | ```julia 3 | putmatkers!(robot, side) = movements!(robot, side) 4 | move!(robot,side) = begin HorizonSideRobots.move!(robot,side); putmarker!(robot) end 5 | ``` 6 | 7 | В результате последнего определения в текущем пространстве имен появится новое определение функции `move!`, а в пространстве имен `HorizonSideRobots` остается прежнее. Плохо в этом решении также то, что для его реализации мы были вынуждены держать в голове внутреннее устройство функции `movements!(robot, side)`, помнить что в ней используется функция с именем `move!`, которую теперь надо переопределить. Тут еще хуже то, что при таком подходе получается, что поведение функции `movements!(robot, side)` завистит от контекста, и это идет в разрез с желанием рассматривать функции как независимые элементы для построения программы. 8 | 9 | Но пока что в этом нет ни какого функционального программирования, мы определили обычные функции, т.е. это не функции высшего порядка. 10 | 11 | От указанных недостатков можно избавиться, например, если использовать функции высшего порядка, следующим образом: 12 | 13 | ```julia 14 | function putmarkers!(robot) 15 | move!() = begin move!(robot,side); putmarker!(robot) end 16 | return side -> movements!(move!, ()->!isborder(robot, side)) 17 | end 18 | ``` 19 | 20 | где ранее было определено: 21 | 22 | ```julia 23 | movements!(move!::Function, move_condition::Function) = while move_condition() move() end 24 | ``` 25 | 26 | Полученная функция не выполняет ни каких реальных действий, она только возвращает замыкание своего аргумента, т.е. значение функционального типа (функцию). 27 | 28 | Получаемое с ее помощью замыкакние является функцией одного аргумента (мы его называем для ясности `side`, но это просто формальный параметр замыкания). 29 | 30 | Теперь, чтобы совершить нужные нужные действия, эту получаемую функцию потребуется вызваать с нужным фактическим параметром (`side`), т.е. 31 | 32 | ```julia 33 | #= 34 | Предполагается, что определено конкретное значение переменной side, а переменная robot содержит ссылку на конкретного Робота 35 | =# 36 | 37 | func=putmarkers!(robot) 38 | func(side) 39 | ``` 40 | 41 | Но то же самое можно было бы сделать и без использования промежуточной переменной func: 42 | 43 | ```julia 44 | putmarkers!(robot)(side) # это тоже самое, что и (putmarkers!(robot))(side) 45 | ``` 46 | 47 | Теперь сделаем для нашего решения "обертку", что бы получить соответствующую функцию (обычную) с аргументами `robot` и `side`, которую можно было бы в последствии использовать многократно: 48 | 49 | 50 | ```julia 51 | function putmarkers!(robot,side) 52 | function putmarkers!(robot) # возвращает замыкание своего аргумента 53 | 54 | function move_to_border(side) 55 | movements!(()->!isborde(robot,s)) do 56 | move!(robot,side) 57 | putmarker!(robot) 58 | end 59 | end 60 | 61 | return move_to_border 62 | end 63 | 64 | return putmarkers!(robot)(side) 65 | # возвращается результат вызова замыкания аргумента robot на исполнение с фактическим параметром side 66 | end 67 | ``` 68 | -------------------------------------------------------------------------------- /8/example_8.1.jl: -------------------------------------------------------------------------------- 1 | #= Решение задачи 4 в функциональном стиле 2 | ДАНО: Робот - Робот - в произвольной клетке ограниченного прямоугольного поля 3 | 4 | РЕЗУЛЬТАТ: Робот - в исходном положении, и клетки поля промакированы так: 5 | нижний ряд - полностью, 6 | следующий - весь, за исключением одной последней клетки на Востоке, 7 | следующий - за исключением двух последних клеток на Востоке, 8 | и т.д. 9 | =# 10 | 11 | module MarkTrapz 12 | export mark_trapz! 13 | 14 | using HorizonSideRobots 15 | include("horizonside.jl") 16 | include("functional_robot.jl") 17 | 18 | 19 | function mark_trapz!(robot, num_steps::Integer) 20 | #= 21 | Расставляет маркеры в форме прямоугольной трапеции (или треугольника - как получится), 22 | при условии, что изначально Робот находится в юго-западном углу 23 | 24 | robot - интерфейс (именованный кортеж), содержащий функции: move!, isborder 25 | =# 26 | line = interface_line(robot.move!) 27 | trajectories = interface_trajectories(robot) 28 | 29 | putmarkers!(side, num_steps) = line.movements!(robot.putmarker!, side, num_steps) 30 | 31 | trajectories.snake!(Ost, Nord) do fold_direct 32 | (fold_direct==Ost) && robot.putmarker!() 33 | putmarkers!(fold_direct, num_steps) 34 | (fold_direct==West) && (num_steps -= 2) 35 | return true 36 | end 37 | end 38 | 39 | function mark_trapz!(robot) 40 | #УТВ: Робот - юго-западном углу 41 | robot = interface_protected_robot(robot) 42 | line = interface_line(robot.move!) 43 | 44 | num_steps = line.get_num_movements!(Ost) 45 | line.movements!(West) 46 | mark_trapz!(robot, num_steps) 47 | #УТВ: маркеры расставлены требуемым образом 48 | end 49 | 50 | end # module 51 | 52 | #---------------------Исполняемая часть файла 53 | 54 | using HorizonSideRobots 55 | using .MarkTrapz 56 | 57 | robot = Robot(animate=true) 58 | MarkTrapz.mark_trapz!(robot) 59 | 60 | 61 | 62 | #= 63 | ВНИМАНИЕ!!!: если здесь не использовать префикс "MarkTrapz.", 64 | то при первом запуске файла все будет работать хорошо, но при последующих запусках, 65 | поскольку модуль MarkTrapz при этом будет импортироваться повторно, возникнут связанные с этим проблемы 66 | =# -------------------------------------------------------------------------------- /8/example_8.1.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 11 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | true 7 | robot_position: 8 | 12 1 9 | temperature_map: 10 | 422 336 319 491 307 118 443 -258 68 -7 311 320 -68 117 475 373 309 -231 389 -107 251 10 466 177 334 223 74 -236 256 276 -186 53 -97 -68 451 246 -227 482 -146 -273 -25 187 -158 192 -258 405 -179 -29 -232 384 -227 10 -227 -90 440 -30 460 -175 427 322 381 490 492 20 -271 295 -201 -4 49 214 371 -159 85 372 342 309 426 -40 -190 212 287 -116 462 396 71 -260 1 226 463 -190 -157 49 -206 102 218 194 351 333 -115 345 269 70 -31 321 338 493 357 344 366 -248 304 328 367 -139 412 418 206 281 -154 90 -45 -131 -230 -201 19 -92 309 -172 -237 22 70 396 11 | markers_map: 12 | 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /8/example_8.1.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/8/example_8.1.sit.png -------------------------------------------------------------------------------- /8/example_8.2.jl: -------------------------------------------------------------------------------- 1 | module MarkersCounter 2 | export markers_counter! 3 | 4 | using HorizonSideRobots 5 | include("horizonside.jl") 6 | include("functional_robot.jl") 7 | 8 | function markers_counter!(robot) 9 | # Робот - в юго-западном углу 10 | robot = interface_protected_robot(robot) 11 | line = interface_line(robot.move!) 12 | trajectories = interface_trajectories(robot) 13 | 14 | counter() = if robot.ismarker() num_markers+=1 end 15 | 16 | num_markers = 0 17 | trajectories.labirint_snake!(Ost, Nord) do side 18 | counter() 19 | line.movements!(counter, side) 20 | return true 21 | end 22 | 23 | return num_markers 24 | end 25 | 26 | end # module MarkersCounter 27 | 28 | #-------------------------- Исполняемая часть файла 29 | 30 | using HorizonSideRobots 31 | using .MarkersCounter 32 | 33 | robot = Robot("8/example_8.2.sit", animate=true) 34 | MarkersCounter.markers_counter!(robot) |> println 35 | -------------------------------------------------------------------------------- /8/example_8.2.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 11 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 11 2 9 | temperature_map: 10 | 11 -137 -195 264 -198 468 487 244 -74 -234 148 425 171 -51 193 -130 246 92 -261 99 -94 308 -56 269 392 42 222 262 496 -219 387 8 74 101 -124 72 287 420 393 -157 111 317 -122 438 100 241 -74 -107 -65 472 420 128 287 449 338 119 7 17 272 342 159 304 -136 -226 -174 -100 355 40 206 215 -29 -163 470 -9 61 416 -174 228 394 116 292 185 1 -251 78 177 -116 -228 51 169 338 285 155 388 197 -1 192 305 -256 474 -229 38 369 215 -120 -263 -167 -204 203 273 177 421 37 239 -222 -193 423 273 162 267 234 360 66 441 10 -117 -105 425 -229 -252 -69 113 11 | markers_map: 12 | (8, 7)(3, 7)(11, 6)(9, 10)(5, 5)(5, 6)(5, 4)(5, 8)(8, 10)(11, 7) 13 | borders_map: 14 | 15 | 3 16 | 3 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 3 25 | 26 | 27 | 0 2 28 | 29 | 0 30 | 31 | 32 | 33 | 3 34 | 35 | 36 | 0 2 37 | 38 | 2 39 | 40 | 0 2 41 | 42 | 1 0 2 43 | 44 | 2 45 | 2 46 | 47 | 1 0 2 48 | 2 49 | 50 | 2 51 | 52 | 0 2 53 | 54 | 0 2 55 | 3 56 | 57 | 0 2 58 | 3 59 | 0 60 | 2 61 | 62 | 2 63 | 64 | 0 65 | 3 0 2 66 | 67 | 2 68 | 1 69 | 70 | 71 | 72 | 73 | 0 74 | 2 75 | 76 | 0 77 | 78 | 79 | 2 80 | 81 | 82 | 83 | 0 84 | 85 | 0 86 | 2 87 | 88 | 89 | 90 | 91 | 92 | 3 2 93 | 94 | 95 | 0 96 | 2 97 | 98 | 99 | 0 100 | 101 | 102 | 3 103 | 2 104 | 105 | 0 106 | 107 | 0 108 | 109 | 0 110 | 111 | 0 112 | 3 2 113 | 114 | 0 115 | 0 2 116 | 117 | 0 118 | 119 | 1 0 2 120 | 2 121 | 122 | 2 123 | 2 124 | 2 125 | 2 126 | 127 | 1 128 | 2 129 | 3 130 | 131 | 0 2 132 | 3 133 | 0 134 | 135 | 1 136 | 137 | 1 138 | 139 | 140 | 141 | 142 | 1 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /8/example_8.2.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/8/example_8.2.sit.png -------------------------------------------------------------------------------- /8/example_8.3.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Модуль FindMarker экспортирует функцию find_marker! 3 | осуществляющей поиск маркера на неограниченном поле при отсутствии на нём перегородок 4 | """ 5 | module FindMarker 6 | export find_marker! 7 | 8 | using HorizonSideRobots 9 | include("horizonside.jl") 10 | include("functional_robot.jl") 11 | 12 | 13 | """ 14 | find_marker!() 15 | 16 | перемещает Робота, находящегося где-то на неораниченном поле без внутренних перегородок, в клетку с маркером 17 | """ 18 | function find_marker!(robot) 19 | robot = interface_protected_robot(robot) 20 | 21 | function move_ifnomarker!(side)::Bool 22 | if robot.ismarker() 23 | return false 24 | end 25 | robot.move!(side) # - return true 26 | end 27 | 28 | trajectories = interface_trajectories(robot) 29 | trajectories.spiral!(move_ifnomarker!) 30 | end 31 | end 32 | 33 | # ------- Исполняемая часть файла 34 | using HorizonSideRobots 35 | using .FindMarker 36 | robot = Robot("8/example_8.3.sit"; animate=true) 37 | FindMarker.find_marker!(robot) 38 | -------------------------------------------------------------------------------- /8/example_8.3.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 12 1 9 | temperature_map: 10 | 245 258 -148 425 -78 172 -84 467 331 288 -182 165 -206 336 -52 425 444 -165 -49 490 72 86 2 209 -173 207 -146 -235 199 278 463 64 -205 -110 -175 168 -20 309 69 361 116 198 85 423 326 474 159 364 320 458 -161 247 -70 209 338 68 252 -145 103 228 -38 -64 310 213 -270 -222 355 429 127 39 478 187 402 214 171 122 470 -69 -99 -168 120 311 414 485 202 481 129 -10 62 221 -162 -160 201 380 94 4 126 470 -139 358 76 343 -15 -171 114 457 168 -17 121 448 -202 248 5 -10 139 -188 33 -41 283 448 167 -243 -195 331 74 179 426 147 345 420 410 -88 -25 -92 485 147 156 491 268 352 65 202 120 450 11 | markers_map: 12 | (7, 6) 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /8/example_8.3.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/8/example_8.3.sit.png -------------------------------------------------------------------------------- /8/functional_robot.jl: -------------------------------------------------------------------------------- 1 | #Предварительно требуется: 2 | #include("horizonside.jl") 3 | 4 | """ 5 | interface_protected_robot(robot) 6 | 7 | Возвращает кортеж замыканий переменной robot, содержащий функции: 8 | ( 9 | move! = (side)->(if isborder(robot,side) false else move!(robot,side); true end), 10 | isborder = (side)->isborder(robot,side), 11 | putmarker! = ()->putmarker!(robot), 12 | ismarker = ()->ismarker(robot), 13 | temperature = ()->temperature(robot), 14 | show! = ()->show!(robot), 15 | ) 16 | """ 17 | interface_protected_robot(robot) = ( 18 | move! = (side)->(if isborder(robot,side) false else move!(robot,side); true end), 19 | isborder = (side)->isborder(robot,side), 20 | putmarker! = ()->putmarker!(robot), 21 | ismarker = ()->ismarker(robot), 22 | temperature = ()->temperature(robot), 23 | show! = ()->show!(robot), 24 | ) #--------------------------------------------- 25 | 26 | """ 27 | interface_line(move!::Function) 28 | 29 | Получает функцию move!(side)::Bool, выполняющую перемещение Робота в ближайшую доступную клетку в направлении side и возвращающую true, 30 | если доступная клетка существует, и оставляющую Робота на месте и возвращающую false - в противном случае 31 | 32 | возвращает кортеж функций: 33 | 34 | movements!(side) - перемещает Робота "до упора" в заданном направлении 35 | movements!(side, num_steps::Integer) - перемещает Робота в заданном направлении на заданное число шагов 36 | movements!(action!::Function, side) - перемещает Робота "до упора" в заданном направлении 37 | movements!(action!::Function, side, num_steps::Integer) - перемещает Робота в заданном направлении на заданное число шагов 38 | 39 | get_num_movements!(side) - перемещает Робота "до упора" в заданном направлении и возвращает число сделанных шагов 40 | get_num_movements!(action!::Function, side) - перемещает Робота "до упора" в заданном направлении и возвращает число сделанных шагов 41 | 42 | при этом в соответствующих случаях здесь после каждого шага выполняется action!() 43 | 44 | """ 45 | interface_line(move!::Function) = begin 46 | movements!(side) = while move!(side)==true end 47 | movements!(side, num_steps::Integer) = for _ in 1:num_steps move!(side) end 48 | movements!(action::Function, side) = while move!(side)==true action() end 49 | movements!(action!::Function, side, num_steps::Integer) = for _ in 1:num_steps move!(side); action!() end 50 | 51 | function get_num_movements!(side) 52 | num_steps=0 53 | while move!(side)==true 54 | num_steps+=1 55 | end 56 | return num_steps 57 | end 58 | 59 | function get_num_movements!(action::Function, side) 60 | num_steps=0 61 | while move!(side)==true 62 | action() 63 | num_steps+=1 64 | end 65 | return num_steps 66 | end 67 | 68 | return (movements! = movements!, get_num_movements! = get_num_movements!) 69 | end # interface_line----------------------------------------------- 70 | 71 | """ 72 | interface_trajectories(robot) 73 | 74 | -- robot - именованный кортеж, содержащий интерфейс Робота, включающий функции 75 | move!, isborder 76 | -- Возвращает интерфейс, содержащий функции: 77 | 78 | snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 79 | 80 | Осуществляет проход Робота по рядам "змейкой" (в местах разворота возможны самоналожения траектории, и последняя складка может получиться полностью наложена на предыдущую) 81 | -- move_fold!(::HorizonSide) - функция, перемещающая Робота по очередной "складке змейки", и возвращающая логическое значение: 82 | если возвращает false, то - это сигнал, чтобы движение "змейкой" было остановлено 83 | -- fold_direct - направление перемещения по (самой первой) "складке" 84 | -- general_direct - направление перемещения от "складки" к "складке" 85 | 86 | labirint_snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 87 | 88 | Осуществляет проход Робота по рядам простого лабиринта "змейкой". 89 | Под простым лабиринтом понимается лабиринт который пересекается горизонтальными пярмыми ровно два раза. 90 | При этом в местах разворота возможны самоналожения траектории (последняя складка будет получиться полностью наложеннной на предыдущую), 91 | но функция move_fold! отвечает только за одноразовый проход по складке (самоналожения могут возникать только при попытках перемещения на новую склажку). 92 | -- move_fold!(::HorizonSide) - функция, перемещающая Робота по очередной "складке змейки", и, ВОЗМОЖНО, возвращающая логическое значение: 93 | если возвращает false, то - это сигнал, чтобы движение "змейкой" было остановлено 94 | (в принципе, move_fold!(...) может возвращать и любое другое значение, не обязательно типа Bool, например - nothing, 95 | но тогда "змейка" будет пройдена до самого конца) 96 | -- fold_direct - направление перемещения по (самой первой) "складке" 97 | -- general_direct - направление перемещения от "складки" к "складке" 98 | 99 | comb!(there_and_back!::Function, clove_direct::HorizonSide, general_direct::HorizonSide) 100 | 101 | -- Осуществляет проход Роботом по рядам "гребенкой" 102 | -- there_and_back!(::HorizonSide) - функция, перемещающая Робота по очередному "зубчику гребёнки", от его начала до конца и обрантно, и 103 | возвращающая логическое значение: если возвращает false, то - это сигнал, чтобы движение "гребенкой" было остановлено 104 | -- clove_direct - направления, определяющие направление перемещения по самому первому "зубчику" 105 | -- general_direct - направление перемещения от "зубчика" к "зубчику" 106 | 107 | spiral!(move_act!::Function) 108 | 109 | Перемещает Робота по раскручивающейся в положительном направлении спирали (первый шаг - на север) до момента наступления 110 | некотрого события, определяемого функцией move_act!(::HorizonSide) 111 | -- move_act!(::HorizonSide)::Bool - функция перемещающая Робота в заданном направлении на 1 шаг (и, возможно, делающая что-то еще), и 112 | возвращая логическое значение: если возвращается false, то - это сигнал, чтобы движение "змейкой" было остановлено. 113 | """ 114 | interface_trajectories(robot) = begin 115 | 116 | function snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 117 | if move_fold!(fold_direct)==false return end 118 | while !robot.isborder(general_direct) 119 | robot.move!(general_direct) 120 | fold_direct = inverse(fold_direct) 121 | if move_fold!(fold_direct)==false return end 122 | end 123 | end # function snake! 124 | 125 | function labirint_snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 126 | function to_next_fold!(general_direct)::Bool 127 | # перемещающает Робота в начало следующей "складки", если это возможно 128 | prew_direct = fold_direct 129 | fold_direct = inverse(fold_direct) # - внешняя переменная 130 | while robot.isborder(general_direct) 131 | if !robot.isborder(fold_direct) 132 | robot.move!(fold_direct) #!!! 133 | else return false # прохода в направлении general_direct нигде нет 134 | end 135 | end 136 | #УТВ: в направлении general_direct нет перегородки 137 | robot.move!(general_direct) #!!! 138 | while !robot.isborder(prew_direct) 139 | robot.move!(prew_direct) #!!! 140 | end 141 | return true 142 | end # function to_next_fold! 143 | 144 | if move_fold!(fold_direct)==false return end 145 | while to_next_fold!(general_direct)==true 146 | if move_fold!(fold_direct)==false return end 147 | end 148 | end # function labirint_snake! 149 | 150 | function spiral!(move_act!::Function) 151 | function next_round!(side, max_num_steps::Integer) # - на очереном витке увеличивает длину сегмента спирали 152 | if side in (Sud, Nord) max_num_steps+=1 end 153 | return max_num_steps 154 | end 155 | 156 | function move_direct!(move_act!::Function, side, max_num_steps::Integer) 157 | # перемещает Робота в заданном направлении не более чем на max_num_steps шагов с помощью функции move_act!(side) 158 | num_steps=0 159 | while (num_steps <= max_num_steps) 160 | if move_act!(side) == false return false end 161 | num_steps+=1 162 | end 163 | return true 164 | end 165 | side = Nord 166 | max_num_steps = 1 167 | while move_direct!(move_act!, side, max_num_steps) == true 168 | max_num_steps = next_round!(side, max_num_steps) 169 | side=left(side) 170 | end 171 | end # function spiral! 172 | 173 | function comb!(there_and_back!::Function, clove_direct::HorizonSide, general_direct::HorizonSide) 174 | 175 | function to_next_clove(general_direct) 176 | if !robot.isborder(general_direct) 177 | robot.move!(general_direct) 178 | return true 179 | else 180 | return false 181 | end 182 | end 183 | 184 | there_and_back!(clove_direct) 185 | while to_next_clove(general_direct) && there_and_back!(clove_direct) 186 | end 187 | end # function comb! 188 | 189 | return (snake! = snake!, labirint_snake! = labirint_snake!, comb! = comb!, spiral! = spiral!) 190 | end # interface_trajectories------------------------------------------------ -------------------------------------------------------------------------------- /8/horizonside.jl: -------------------------------------------------------------------------------- 1 | using HorizonSideRobots 2 | 3 | """ 4 | inverse(side::HorizonSide) 5 | 6 | -- возвращает сторону горизонта, противоположную заданной 7 | """ 8 | inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 9 | 10 | 11 | """ 12 | left(side::HorizonSide) 13 | 14 | -- возвращает сторону горизонта, следующую после заданной (в положительном направлении вращения) 15 | """ 16 | left(side::HorizonSide) = HorizonSide(mod(Int(side)+1, 4)) 17 | 18 | 19 | """ 20 | right(side::HorizonSide) 21 | 22 | -- возвращает сторону горизонта, предшествующую заданной (в положительном направлении вращения) 23 | """ 24 | right(side::HorizonSide) = HorizonSide(mod(Int(side)-1, 4)) 25 | 26 | 27 | """ 28 | inverse(side::NTuple) 29 | 30 | -- возвращает кортеж, содержащй стороны горизонта, противоположные заданным 31 | """ 32 | inverse(side::NTuple) = Tuple(inverse.(collect(side))) 33 | 34 | 35 | """ 36 | inverse(side::AbstractVector) 37 | 38 | -- возвращает вектор, сожержащий направления, противоположные заданным 39 | """ 40 | inverse(side::AbstractVector) = inverse.(side) -------------------------------------------------------------------------------- /8/ignjre._trajectories_robot.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Определенные в этом файле функции контекстно зависимы от интерфейса: 3 | move!(::Any), isborder(::Any) 4 | - это часть командного интерфейса Робота 5 | =# 6 | 7 | using HorizonSideRobots 8 | 9 | """ 10 | snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 11 | 12 | Осуществляет проход Робота по рядам "змейкой" (в местах разворота возможны самоналожения траектории, и последняя складка может получиться полностью наложена на предыдущую) 13 | -- move_fold!(::HorizonSide) - функция, перемещающая Робота по очередной "складке змейки", и возвращающая логическое значение: 14 | если возвращает false, то - это сигнал, чтобы движение "змейкой" было остановлено 15 | -- fold_direct - направление перемещения по (самой первой) "складке" 16 | -- general_direct - направление перемещения от "складки" к "складке" 17 | """ 18 | 19 | function snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 20 | if move_fold!(fold_direct)==false 21 | return 22 | end 23 | 24 | while !isborder(general_direct) 25 | move!(general_direct) 26 | fold_direct = inverse(fold_direct) 27 | if move_fold!(fold_direct)==false 28 | return 29 | end 30 | end 31 | end 32 | 33 | 34 | """ 35 | labirint_snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 36 | 37 | Осуществляет проход Робота по рядам простого лабиринта "змейкой". 38 | Под простым лабиринтом понимается лабиринт который пересекается горизонтальными пярмыми ровно два раза. 39 | При этом в местах разворота возможны самоналожения траектории (последняя складка будет получиться полностью наложеннной на предыдущую), 40 | но функция move_fold! отвечает только за одноразовый проход по складке (самоналожения могут возникать только при попытках перемещения на новую склажку). 41 | -- move_fold!(::HorizonSide) - функция, перемещающая Робота по очередной "складке змейки", и возвращающая логическое значение: 42 | если возвращает false, то - это сигнал, чтобы движение "змейкой" было остановлено 43 | -- fold_direct - направление перемещения по (самой первой) "складке" 44 | -- general_direct - направление перемещения от "складки" к "складке" 45 | """ 46 | function labirint_snake!(move_fold!::Function, fold_direct::HorizonSide, general_direct::HorizonSide) 47 | 48 | function to_next_fold!(general_direct)::Bool 49 | # перемещающает Робота в начало следующей "складки", если это возможно 50 | prew_direct = fold_direct 51 | fold_direct = inverse(fold_direct) # - внешняя переменная 52 | while isborder(general_direct) 53 | if !isborder(fold_direct) 54 | move!(fold_direct) 55 | else 56 | return false # прохода в направлении general_direct нигде нет 57 | end 58 | end 59 | #УТВ: в направлении general_direct нет перегородки 60 | move!(general_direct) 61 | while !isborder(prew_direct) 62 | move!(prew_direct) 63 | end 64 | return true 65 | end 66 | 67 | if move_fold!(fold_direct)==false 68 | return 69 | end 70 | 71 | while to_next_fold!(general_direct)==true 72 | if move_fold!(fold_direct)==false 73 | return 74 | end 75 | end 76 | end 77 | 78 | #inverse(side::HorizonSide) = HorizonSide(mod(Int(side)+2, 4)) 79 | 80 | """ 81 | comb!(there_and_back!::Function, clove_direct::HorizonSide, general_direct::HorizonSide) 82 | 83 | -- Осуществляет проход Роботом по рядам "гребенкой" 84 | -- there_and_back!(::HorizonSide) - функция, перемещающая Робота по очередному "зубчику гребёнки", от его начала до конца и обрантно, и 85 | возвращающая логическое значение: если возвращает false, то - это сигнал, чтобы движение "гребенкой" было остановлено 86 | -- clove_direct - направления, определяющие направление перемещения по самому первому "зубчику" 87 | -- general_direct - направление перемещения от "зубчика" к "зубчику" 88 | """ 89 | function comb!(there_and_back!::Function, clove_direct::HorizonSide, general_direct::HorizonSide) 90 | function to_next_clove(general_direct) 91 | if !isborder(general_direct) 92 | move!(general_direct) 93 | return true 94 | else 95 | return false 96 | end 97 | end 98 | 99 | there_and_back!(clove_direct) 100 | while to_next_clove(general_direct) && there_and_back!(clove_direct) 101 | end 102 | end 103 | 104 | #------------------ 105 | """ 106 | spiral!(move_act!::Function) 107 | 108 | Перемещает Робота по раскручивающейся в положительном направлении спирали (первый шаг - на север) до момента наступления 109 | некотрого события, определяемого функцией move_act!(::HorizonSide) 110 | -- move_act!(::HorizonSide)::Bool - функция перемещающая Робота в заданном направлении на 1 шаг (и, возможно, делающая что-то еще), и 111 | возвращая логическое значение: если возвращается false, то - это сигнал, чтобы движение "змейкой" было остановлено. 112 | """ 113 | function spiral!(move_act!::Function) 114 | function next_round!(side, max_num_steps::Integer) 115 | # - на очереном витке увеличивает длину сегмента спирали 116 | if side in (Sud, Nord) 117 | max_num_steps+=1 118 | end 119 | return max_num_steps 120 | end 121 | 122 | function move_direct!(move_act!::Function, side, max_num_steps::Integer) 123 | # перемещает Робота в заданном направлении не более чем на max_num_steps шагов с помощью функции move_act!(side) 124 | num_steps=0 125 | while (num_steps <= max_num_steps) 126 | if move_act!(side) == false 127 | return false 128 | end 129 | num_steps+=1 130 | end 131 | return true 132 | end 133 | 134 | side = Nord 135 | max_num_steps = 1 136 | 137 | while move_direct!(move_act!, side, max_num_steps) == true 138 | max_num_steps = next_round!(side, max_num_steps) 139 | side=left(side) 140 | end 141 | end 142 | 143 | #left(side::HorisonSide) = HorizonSide(mod(side(Int)+1, 4)) 144 | -------------------------------------------------------------------------------- /8/Практика-8.md: -------------------------------------------------------------------------------- 1 | # Примеры решения задач в функциональном стиле 2 | 3 | Прежде всего программныый код, разработанный в лекции поместим разместим в файле ["functional_robot.jl"](functional_robot.jl) 4 | 5 | ## Решение задачи о расстановке маркеров на ограниченном рамкой поле в форме прямоугольной трапеции 6 | 7 | ```julia 8 | ДАНО: Робот - Робот - в произвольной клетке ограниченного прямоугольного поля 9 | 10 | РЕЗУЛЬТАТ: Робот - в исходном положении, и клетки поля промакированы так: 11 | нижний ряд - полностью, 12 | следующий - весь, за исключением одной последней клетки на Востоке, 13 | следующий - за исключением двух последних клеток на Востоке, 14 | и т.д. 15 | ``` 16 | 17 | В результате на поле должна получиться такая обстановка: !["example_8.1.sit.png"](example_8.1.sit.png). 18 | 19 | Соответствующий программный код содержится в файле ["example_8.1.jl"](example_8.1.jl). 20 | 21 | Чтобы исполнить содержащийся в этом файле код достаточно будет просто вставить этот файл в REPL: 22 | 23 | ```julia 24 | julia> include("8/example_8.1.jl") 25 | ``` 26 | 27 | (при условии, что файл "8/example_8.1.jl" находится в текущей директории). 28 | 29 | Следует обратить внимание на то, что определения функций в этом файле обернуты в модуль. Это делается для того, чтобы не "засорять" пространство имен REPL лишними определениями. 30 | 31 | ## Решение задачи о подсчете числа маркеров внутри простого лабиринта 32 | 33 | Под простым лабиринтом понимается лабиринт который любая горизонтальная прямая пересекает ровно два раза (если пересекает), а вертикальная прямая может мересекать его любое число раз, например: !["example_8.2.sit.png"](example_8.2.sit.png). 34 | 35 | Пусть Робот находился в юго-западном углу такого лабиринта, и требуется подсчитать число всех маркеров, находящихся внутри него. 36 | 37 | Программный код c решением находится в файле ["example_8.2.jl"](example_8.2.jl). 38 | 39 | Чтобы исполнить код, содержащийся в этом файле, достаточно просто вставить этот файл в REPL: 40 | 41 | ```julia 42 | julia> include("8/example_8.2.jl") 43 | ``` 44 | 45 | (при условии, что файл "8/example_8.2.jl" и заранее подготовленный файл с обстановкой "8/example_8.2.sit" находятся в текущей директории). 46 | 47 | ## Решение задачи о поиске маркера на неограниченном поле 48 | 49 | При отсутствии на поле внутренних перегородок решение этой задачи содержится в файле ["еxample_8.3.jl"](example_8.3.jl) 50 | 51 | Чтобы исполнить код, содержащийся в этом файле "example_8.3.jl", достаточно просто вставить этот файл в REPL: 52 | 53 | ```julia 54 | julia> include("8/example_8.3.jl") 55 | ``` 56 | 57 | (при условии, что файл "8/example_8.3.jl" и заранее подготовленный файл с обстановкой "8/example_8.3.sit" находятся в текущей директории). -------------------------------------------------------------------------------- /9/example_9.1.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Модуль содержит определение функции markers_counter!(), 3 | возвращающей число маркеров внутри простого лабирина, содержащего внутри себя изолированные 4 | пергородки прямоугольной формы. 5 | Требуется, чтобы изначально Робот находился в левом нижнем углу лабиринта. 6 | В исходное положение Робот не возвращается 7 | """ 8 | module MarkersCounter 9 | export markers_counter! 10 | 11 | using HorizonSideRobots 12 | include("../8/horizonside.jl") 13 | include("functional_robot.jl") 14 | 15 | function markers_counter!(robot) 16 | # Робот - в юго-западном углу 17 | robot = interface_protected_robot(robot) 18 | rectangular_borders = interface_rectangular_borders(robot) 19 | line = interface_line(rectangular_borders.move!) 20 | trajectories = interface_trajectories(robot) 21 | 22 | counter() = if robot.ismarker() num_markers+=1 end 23 | 24 | num_markers = 0 25 | trajectories.labirint_snake!(Ost, Nord) do side 26 | counter() 27 | line.movements!(counter, side) 28 | return true 29 | end 30 | 31 | return num_markers 32 | end 33 | 34 | end # module MarkersCounter 35 | 36 | #-------------------------- Исполняемая часть файла 37 | 38 | using HorizonSideRobots 39 | using .MarkersCounter 40 | 41 | robot = Robot("9/example_9.1.sit", animate=true) 42 | MarkersCounter.markers_counter!(robot) |> println 43 | -------------------------------------------------------------------------------- /9/example_9.1.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 11 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 11 2 9 | temperature_map: 10 | 11 -137 -195 264 -198 468 487 244 -74 -234 148 425 171 -51 193 -130 246 92 -261 99 -94 308 -56 269 392 42 222 262 496 -219 387 8 74 101 -124 72 287 420 393 -157 111 317 -122 438 100 241 -74 -107 -65 472 420 128 287 449 338 119 7 17 272 342 159 304 -136 -226 -174 -100 355 40 206 215 -29 -163 470 -9 61 416 -174 228 394 116 292 185 1 -251 78 177 -116 -228 51 169 338 285 155 388 197 -1 192 305 -256 474 -229 38 369 215 -120 -263 -167 -204 203 273 177 421 37 239 -222 -193 423 273 162 267 234 360 66 441 10 -117 -105 425 -229 -252 -69 113 11 | markers_map: 12 | (11, 7)(3, 7)(5, 5)(5, 6)(11, 9)(5, 8)(5, 4)(9, 8)(8, 10)(9, 5) 13 | borders_map: 14 | 15 | 3 16 | 3 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 3 25 | 26 | 27 | 0 2 28 | 29 | 0 30 | 31 | 32 | 33 | 3 34 | 35 | 36 | 0 2 37 | 38 | 2 39 | 40 | 0 2 41 | 42 | 1 0 2 43 | 44 | 2 45 | 2 46 | 47 | 1 0 2 48 | 2 49 | 50 | 2 51 | 52 | 0 2 53 | 54 | 0 2 55 | 3 56 | 57 | 0 2 58 | 3 59 | 0 60 | 2 61 | 62 | 2 63 | 64 | 0 65 | 3 0 2 66 | 67 | 2 68 | 1 69 | 70 | 3 71 | 72 | 73 | 0 74 | 2 75 | 76 | 77 | 78 | 79 | 80 | 81 | 2 82 | 83 | 1 2 84 | 85 | 0 86 | 2 87 | 88 | 1 89 | 1 3 90 | 1 91 | 1 92 | 3 2 93 | 2 94 | 3 95 | 2 96 | 2 97 | 98 | 99 | 0 100 | 1 101 | 102 | 1 3 103 | 2 104 | 105 | 0 106 | 107 | 1 108 | 109 | 0 110 | 111 | 0 112 | 3 2 113 | 114 | 0 115 | 0 2 116 | 117 | 0 118 | 119 | 1 0 2 120 | 2 121 | 122 | 2 123 | 2 124 | 2 125 | 2 126 | 127 | 1 128 | 2 129 | 3 130 | 131 | 0 2 132 | 3 133 | 0 134 | 135 | 1 136 | 137 | 1 138 | 139 | 140 | 141 | 142 | 1 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /9/example_9.1.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/9/example_9.1.sit.png -------------------------------------------------------------------------------- /9/example_9.2.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Модуль FindMarker экспортирует функцию find_marker! 3 | осуществляющей поиск маркера на неограниченном поле при возможном наличии на нём перегородок в виде отрезков 4 | """ 5 | module FindMarker 6 | export find_marker! 7 | 8 | using HorizonSideRobots 9 | include("../8/horizonside.jl") 10 | include("functional_robot.jl") 11 | 12 | 13 | """ 14 | find_marker!() 15 | 16 | перемещает Робота, находящегося где-то на неораниченном поле без внутренних перегородок, в клетку с маркером 17 | """ 18 | function find_marker!(robot) 19 | robot = interface_protected_robot(robot) 20 | rectangular_borders = interface_rectangular_borders(robot) 21 | 22 | function move_ifnomarker!(side)::Bool 23 | if robot.ismarker() 24 | return false 25 | end 26 | rectangular_borders.move!(side) # - return true 27 | end 28 | 29 | trajectories = interface_trajectories(robot) 30 | trajectories.spiral!(move_ifnomarker!) 31 | end 32 | end 33 | 34 | # ------- Исполняемая часть файла 35 | using HorizonSideRobots 36 | using .FindMarker 37 | robot = Robot("9/example_9.2.sit"; animate=true) 38 | FindMarker.find_marker!(robot) 39 | -------------------------------------------------------------------------------- /9/example_9.2.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 10 2 9 | temperature_map: 10 | 245 258 -148 425 -78 172 -84 467 331 288 -182 165 -206 336 -52 425 444 -165 -49 490 72 86 2 209 -173 207 -146 -235 199 278 463 64 -205 -110 -175 168 -20 309 69 361 116 198 85 423 326 474 159 364 320 458 -161 247 -70 209 338 68 252 -145 103 228 -38 -64 310 213 -270 -222 355 429 127 39 478 187 402 214 171 122 470 -69 -99 -168 120 311 414 485 202 481 129 -10 62 221 -162 -160 201 380 94 4 126 470 -139 358 76 343 -15 -171 114 457 168 -17 121 448 -202 248 5 -10 139 -188 33 -41 283 448 167 -243 -195 331 74 179 426 147 345 420 410 -88 -25 -92 485 147 156 491 268 352 65 202 120 450 11 | markers_map: 12 | (7, 6) 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 3 33 | 2 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 1 43 | 1 44 | 45 | 46 | 0 47 | 3 48 | 49 | 50 | 51 | 0 52 | 53 | 54 | 55 | 56 | 57 | 2 58 | 59 | 60 | 1 61 | 62 | 63 | 0 64 | 1 65 | 1 66 | 1 67 | 68 | 69 | 3 70 | 3 71 | 72 | 0 73 | 74 | 75 | 0 76 | 77 | 78 | 79 | 80 | 1 81 | 82 | 83 | 2 84 | 85 | 86 | 87 | 0 88 | 89 | 2 90 | 91 | 92 | 93 | 2 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 0 103 | 104 | 105 | 106 | 0 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 0 117 | 118 | 0 119 | 120 | 121 | 122 | 123 | 124 | 125 | 3 126 | 127 | 2 128 | 129 | 130 | 3 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 1 139 | 2 140 | 141 | 1 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /9/example_9.2.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/9/example_9.2.sit.png -------------------------------------------------------------------------------- /9/example_9.3.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Модуль FindMarker экспортирует функцию 3 | find_marker! 4 | осуществляющую поиск маркера на неограниченном поле, на которм могут находиться 5 | конечные или полубесконечные прямолинейные перегородки 6 | """ 7 | module FindMarker 8 | export find_marker! 9 | 10 | using HorizonSideRobots 11 | include("../8/horizonside.jl") 12 | include("functional_robot.jl") 13 | 14 | """ 15 | find_marker!(robot::Robot) 16 | 17 | перемещает Робота, находящегося где-то на неограниченном поле без внутренних перегородок, 18 | в клетку с маркером 19 | """ 20 | function find_marker!(robot::Robot) 21 | robot = interface_protected_robot(robot) 22 | line = interface_line(robot.move!) 23 | 24 | 25 | function move_ifnomarker!(side)::Bool 26 | if robot.ismarker() 27 | return false 28 | end 29 | move_unlimited_line!(side) 30 | return true 31 | end 32 | 33 | function move_unlimited_line!(side) 34 | coordinate = 0 # - текущая координата Робота относительно начального положения 35 | num_steps = 1 # - текущее число шагов при поиске края перегородки 36 | orthogonal = right(side) # - текущее направление поиска края перегородки 37 | back_side = orthogonal # - первоначальное направление поиска края перегородки 38 | while robot.isborder(side) # поиск края полубесконечной прямолинейной перегородки 39 | line.movements!(orthogonal,num_steps) 40 | if orthogonal == back_side 41 | coordinate += num_steps 42 | else 43 | coordinate -= num_steps 44 | end 45 | num_steps+=1 46 | orthogonal=inverse(orthogonal) 47 | end 48 | #УТВ: Робот - за краем перегородки 49 | robot.move!(side) 50 | if coordinate > 0 51 | back_side = inverse(back_side) 52 | else 53 | coordinate = -coordinate 54 | end 55 | line.movements!(back_side,coordinate) 56 | #УТВ: Робот - в соседней, по отношению к исходной, позиции с другой стороны от перегородки 57 | end 58 | 59 | trajectories = interface_trajectories(robot) 60 | trajectories.spiral!(move_ifnomarker!) 61 | end 62 | end 63 | 64 | # ------- Исполняемая часть файла 65 | 66 | using HorizonSideRobots 67 | using .FindMarker 68 | robot = Robot("9/example_9.3.sit"; animate=true) 69 | FindMarker.find_marker!(robot) 70 | -------------------------------------------------------------------------------- /9/example_9.3.sit: -------------------------------------------------------------------------------- 1 | frame_size: 2 | 12 12 3 | coefficient: 4 | 1.0 5 | is_framed: 6 | false 7 | robot_position: 8 | 12 1 9 | temperature_map: 10 | 245 258 -148 425 -78 172 -84 467 331 288 -182 165 -206 336 -52 425 444 -165 -49 490 72 86 2 209 -173 207 -146 -235 199 278 463 64 -205 -110 -175 168 -20 309 69 361 116 198 85 423 326 474 159 364 320 458 -161 247 -70 209 338 68 252 -145 103 228 -38 -64 310 213 -270 -222 355 429 127 39 478 187 402 214 171 122 470 -69 -99 -168 120 311 414 485 202 481 129 -10 62 221 -162 -160 201 380 94 4 126 470 -139 358 76 343 -15 -171 114 457 168 -17 121 448 -202 248 5 -10 139 -188 33 -41 283 448 167 -243 -195 331 74 179 426 147 345 420 410 -88 -25 -92 485 147 156 491 268 352 65 202 120 450 11 | markers_map: 12 | (7, 6) 13 | borders_map: 14 | 15 | 16 | 17 | 18 | 19 | 0 20 | 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | 28 | 3 29 | 3 30 | 31 | 0 32 | 33 | 3 34 | 2 35 | 36 | 37 | 38 | 1 39 | 1 40 | 41 | 42 | 43 | 0 44 | 1 45 | 46 | 47 | 0 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 0 2 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 0 67 | 68 | 0 69 | 1 70 | 1 71 | 1 72 | 1 73 | 1 74 | 75 | 76 | 77 | 2 78 | 79 | 2 80 | 81 | 82 | 83 | 0 84 | 85 | 86 | 87 | 3 88 | 3 89 | 3 90 | 91 | 92 | 3 93 | 94 | 95 | 0 96 | 97 | 98 | 1 99 | 100 | 101 | 102 | 103 | 1 104 | 105 | 1 106 | 107 | 0 108 | 109 | 110 | 111 | 112 | 113 | 3 114 | 3 115 | 116 | 117 | 118 | 119 | 0 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 1 128 | 129 | 130 | 131 | 0 132 | 133 | 134 | 135 | 136 | 137 | 138 | 0 139 | 140 | 141 | 142 | 2 143 | 144 | 145 | 146 | 147 | 148 | 149 | 2 150 | 151 | 152 | 153 | 154 | 2 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /9/example_9.3.sit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/9/example_9.3.sit.png -------------------------------------------------------------------------------- /GIT+GITHUB/github-new-repo-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/GIT+GITHUB/github-new-repo-button.png -------------------------------------------------------------------------------- /GIT+GITHUB/github-new-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vibof/ProgrammingManual/056d60b01b9a0465cba0ff08b3128077ba59c5e0/GIT+GITHUB/github-new-repo.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Руководство по программированию 2 | ____________ 3 | 4 | ## 0 5 | 6 | ### [Лекция - Работа с GIT](GIT+GITHUB/Краткая_справка_по_git.md) 7 | 8 | ### [Практика - организация работы с GIT](GIT+GITHUB/Организация_работы_на_базе_git.md) 9 | ## 1 10 | 11 | ------------- 12 | ### [Лекция 1](1/Лекция-1.md) 13 | 14 | - О целях и содержании курса 15 | - О языке программирования Juliа 16 | - О исполнителе "Робот на клетчатом поле со сторонами горизонта" 17 | - Технология проектирования 18 | - Пример решения в плохом стиле 19 | - Пример достаточно хорошо структурированного кода 20 | - Технология проектирования «сверху вниз» 21 | - Отладка программы по технологии «снизу вверх» 22 | - О составлении описаний функций 23 | - Функции и файлы 24 | - Аннотирование аргументов функции 25 | 26 | ### [Практика 1](1/Практика-1.md) 27 | 28 | - Подготовка программного окружения для работы с Роботом 29 | - Технология проектирования "сверху вниз" 30 | - Разбор задачи 2 31 | - Декомпозиция задачи на уровне псевдокода 32 | - Программный код главной функции 33 | - Реализация вспомогателных функций 34 | - Запуск и отладка программного кода 35 | 36 | ### [Задачи 1-5](1/Список-задач-1.md) 37 | 38 | ----------------- 39 | 40 | [<< к началу](#руководство-по-программированию) 41 | 42 | ----------------- 43 | 44 | ## 2 45 | 46 | ----------------- 47 | ### [Лекция 2](2/Лекция-2.md) 48 | 49 | - Уточнение понятия алгоритма 50 | - Что такое "правильная программа" 51 | - Языки программирования и трансляция программы в машиный код 52 | - Классификация трансляторов 53 | - Устройство и алгоритм работы компьютера 54 | 55 | ### [Практика 2](2/Практика-2.md) 56 | 57 | - Разбор задачи 6 58 | - Декомпозиция задачи и соответствующий псевдокод 59 | - Полученный полный программный код 60 | - Запуск и отладка программного кода 61 | - О самодокументировании библиотечных функций 62 | - Создание библиотечного файла 63 | - Пример получения помощи в REPL по функциям из библиотечного файла 64 | 65 | ### [Задачи 6-9](2/Список-задач-2.md) 66 | 67 | ----------------- 68 | 69 | [<< к началу](#руководство-по-программированию) 70 | 71 | ----------------- 72 | 73 | ## 3 74 | 75 | ------------------ 76 | 77 | ### [Лекция 3](3/Лекция-3.md) 78 | 79 | - Статическая и динамическая типизация 80 | - Вывод типа 81 | - Cсылки на объекты 82 | - Автоматическая сборка "мусора" 83 | - Mножественная диспетчеризация 84 | - Глобальные переменные модуля 85 | - Пример программы, использующей глобальную переменную 86 | - Цель инкапсуляции данных и функций в модуль 87 | - Замечание о использовании глобальных переменных 88 | - Рекомендация по отладке модуля 89 | - Локальные переменные функций 90 | - Пример программы, использующей функции с локальными переменными 91 | - Пример не слишком удачного выбора решения с использования глобальных переменных 92 | - Функции с аргументами, передача параметров в функцию "по значению" и "по ссылке" 93 | 94 | ### [Практика 3](3/Практика-3.md) 95 | 96 | - Разбор решения задачи 5 97 | - Возможный вариант решения 98 | - Улучшенный вариант решения 99 | - Разбор решения задачи 8 100 | - Первый вариант решения 101 | - Второй вариант решения 102 | - Разбор решения задачи 9 103 | 104 | ### [Задачи 10-13](3/Задачи%2010-13.md) 105 | 106 | ----------------- 107 | 108 | [<< к началу](#руководство-по-программированию) 109 | 110 | ----------------- 111 | 112 | ## 4 113 | 114 | ---------- 115 | 116 | ### [Лекция 4](4/Лекция-4.md) 117 | 118 | - Использование программами компьютерной памяти 119 | - Простейшие приемы доказательства и контроля правильности программного кода 120 | - Промежуточные утверждения 121 | - Циклы 122 | - Cвойство цикла с предусловием 123 | - Инвариант цикла и метод доказательства правильности цикллического алгоритма 124 | - Пример использования инварианта в доказательстве правильности алгоритма: замаркировать ряд от начала до конца 125 | - Опасность и нежелательность цикла с постусловием 126 | - Пример: алгоритм подсчёта числа перегородок в ряду 127 | - Метод переменной состояния 128 | - Альтернативный способ 129 | 130 | ------------------------------ 131 | 132 | ### [Пракика 4](4/Практика-4.md) 133 | 134 | --------------------------- 135 | - Разбор задачи 11 136 | - Разбор задачи 12 137 | - Разбор задачи 13 138 | - Разбор задачи 14 139 | - Разбор задачи 16 140 | 141 | ### [Задачи 14-25](4/Задачи%2014-25.md) 142 | 143 | ----------------- 144 | 145 | [<< к началу](#руководство-по-программированию) 146 | 147 | ----------------- 148 | 149 | ## 5 150 | 151 | ### [Лекция 5](5/Лекция-5.md) 152 | 153 | - Обобщенное программирование 154 | - Иерархия типов Julia, конкретные и абстрактные типы 155 | - Пример разработки обобщенной функции 156 | - Принцип аннотирования тпов аргуметов функции 157 | 158 | ### [Практика 5](5/Практика-5.md) 159 | 160 | - Создание библиотечного файла roblib.jl 161 | - Пример, когда желание иметь универсальный код приводит к необходимости, некоторые вспомогательные функции распределять по нескольким отдельным файлам 162 | 163 | ### [Задачи 26-28](5/Задачи%2026-28.md) 164 | 165 | 166 | ---------------------------- 167 | [<< к началу](#руководство-по-программированию) 168 | 169 | ----------------- 170 | 171 | 172 | ## 6 173 | 174 | ### [Лекция 6](6/Лекция-6.md) 175 | 176 | - Ленивые логические операции && и || 177 | - Разбор задачи 26 178 | - Модульное программирование 179 | - Задача перемещения Робота в стартовый угол и обратно 180 | - Еще раз о задаче 7 с точки зрения модульного программирования 181 | - Вложенные функции 182 | 183 | ### [Задачи 28-31](6/Задачи%2028-31.md) 184 | 185 | ----------------------- 186 | 187 | [<< к началу](#руководство-по-программированию) 188 | 189 | ----------------- 190 | 191 | 192 | ## 7 193 | 194 | ### [Лекция 7](7/Лекция-7.md) 195 | 196 | - Элементы функционального программирования 197 | - Функции, как объекты первого класса 198 | - Анонимные функции 199 | - Функции высших порядков 200 | - Замыкания (closure) 201 | - Замыкание, возвращаемое из функции 202 | - Стандартная функция высшего порядка map 203 | - do-синтаксис 204 | - Каррирование 205 | - Операция композиции функций 206 | - Операция направления потока данных на "вход" функции 207 | 208 | ### [Практика 7](7/Практика-7.md) 209 | 210 | - Улучшение структуры програмного кода в полученном ранее решение задачи 12 за счет ввынесение за пределы модуля "лишних" функций 211 | - Разбор задачи 31 212 | - Задание на улучшение структуры програмного кода решения задачи 31 213 | 214 | ----------------------- 215 | 216 | [<< к началу](#руководство-по-программированию) 217 | 218 | ----------------- 219 | 220 | ## 8 221 | 222 | ### [Лекция 8](8/Лекция-8.md) 223 | 224 | ### [Практика 8](8/Практика-8.md) 225 | 226 | ----------------------- 227 | 228 | [<< к началу](#руководство-по-программированию) 229 | 230 | ----------------- 231 | 232 | ## 9 233 | 234 | ### [Лекция 9](9/Лекция-9.md) 235 | 236 | Обобщенное программирование в функциональном стиле (продолжение) 237 | 238 | ----------------------- 239 | 240 | [<< к началу](#руководство-по-программированию) 241 | 242 | ----------------- 243 | 244 | ## 10 245 | 246 | ### [Лекция 10](10/Лекция-10.md) 247 | 248 | ### [Практика 10](10/Практика-10.md) 249 | 250 | ## 11 251 | 252 | ### [Лекция 11](11/Лекция-11.md) 253 | 254 | ## 12 255 | 256 | ### [Лекция 12](12-15/Лекция-12.md) 257 | 258 | ## 13 259 | 260 | ### [Лекция 13](12-15/Лекция-13.md) 261 | 262 | ## 14 263 | 264 | ### [Лекция 14](12-15/Лекция-14.md) 265 | 266 | ## 15 267 | 268 | ### [Лекция 15](12-15/Лекция-15.md) --------------------------------------------------------------------------------