Форум сайта python.su
RomantegЯ увидел, что весь путь состоит из повторяющихся кусков. Один кусок включает в себя действия: закрасить первую клетку; пропустить ряд клеток; остановиться. Дальше я увидел, что “пропустить ряд клеток” вырастает на одну клетку после каждого куска. Дальше я ввёл эту переменную nn, которая и следит за тем, сколько клеток нужно пропустить в куске. А дальше можно было использовать range(), но range() есть не во всех языках, поэтому я решил range() заменить на счётчик пройденных клеток и назвал его n. Таким образом, на каждом куске счётчик пропущенных клеток обнуляется, а количество клеток, которые надо пропустить, наращивается на одну клетку. И когда счётчик на куске достигает количества пропускаемых клеток, кусок завершается остановкой и цикл переходит к следующему куску. В следующем куске устанавливается: сколько клеток надо в нём пропустить; счётчик пройденных клеток куска устанавливается в ноль; первая клетка куска закрашивается. И дальше всё повторяется, как в предыдущем куске.
Не могу понять принцип как вы пришли к такому решению, что нужно использовать зависимость n от nn и что nn задает границу, а затем n еще и сбрасывается… наверное, это приходит с опытом.
RomantegДа, ты видишь этот путь целиком, а нужно его раскладывать на одинаковые кусочки. Потом для кусочка надо писать программку, а потом эту программку повторять. И чтобы видеть, из каких одинаковых кусочков состоит якобы неразделимая и целостная сущность, нужно тренироваться. Человек состоит из частей тела. Человек состоит из тканей. Человек состоит из клеток. Человек состоит из атомов. Вот это разделение целостной сущности на составляющие части. То есть делить можно по-разному. Когда делаешь программу, делить целостную сущность нужно на максимальные одинаковые куски. Если ты поделишь путь из клеток на клетки, то ты ничего не получишь. Но если ты поделишь путь из клеток на повторяющиеся фрагменты пути, то ты можешь для одного фрагмента пути написать алгоритм, а потом в цикле вызывать его. И путь будет обрабатываться одинаковыми порциями.
наверное, это приходит с опытом.
Отредактировано py.user.next (Март 11, 2020 06:56:41)
Офлайн
py.user.next
Почему мы делаем вот так, а не как у тебя, - потому что это декомпозиция.
Какой принцип у декомпозиции:
1)
Нужно выделить максимальные действия, максимальные структуры и всё записать для них;
2)
Когда на них всё работает, мы спускаемся в полученные функции и проводим с ними то же самое действие - ищем всё максимальное уже на новом уровне и записываем всё для максимального;
3)
Когда для этого второго уровня всё работает, мы снова спускаемся в полученные функции (на третий уровень) и проводим там то же самое действие по поиску максимальных действий и структур;
4)
Это продолжается, пока разбивать ничего не останется, - элементы станут простейшими.
Эта декомпозиция приводит к тому, что у тебя всё получается ясно и выстроено.
А если же ты вот это всё не соблюдаешь, то у тебя получается вот такое дробление, где уже ничего поймёшь, что происходит.
Если бы функция fill_up_down() получилась слишком большой и запутанной, то её можно было бы дальше разбивать. Но так как она короткая (до 25 строк) и функционально-прочная по Майерсу (отвечает точно на вопрос “что делает эта функция?”), то мы её оставляем в таком виде. Если бы она была на полстраницы или делала бы десяток несвязанных между собой действий, то мы бы должны были её разбить на несколько разных функций, которые и короткие, и функционально-прочные. Проверяем “Что делает эта функция?”, ответ - она закрашивает клетки сверху и снизу от текущей, если это возможно сделать. Всё, ответ точный, значит функция фунционально-прочная по Майерсу.
while not wall_is_on_the_right(): if not wall_is_above(): move_up() fill_cell() move_down() if not wall_is_beneath(): move_down() fill_cell() move_up() move_right() else: if not wall_is_above(): move_up() fill_cell() move_down() if not wall_is_beneath(): move_down() fill_cell() move_up()
#!/usr/bin/python3 from pyrob.api import * def fill_cells(): for i in range(27): move_right() fill_cell() move_down() for i in range(27): fill_cell() move_left() move_down() @task(delay=0.01) def task_4_3(): pass for i in range(6): fill_cells() move_right() if __name__ == '__main__': run_tasks()
Офлайн
lapimaxЯ её сделал с подпрограммой (с функцией), потому что так легко было сделать. Но по курсу Тимофея в 13-ой задаче ещё подпрограммы нельзя использовать. Подпрограммы начинаются в 24-ой задаче. Но всё равно, всё к этому идёт. Без подпрограмм ничего не пишется. Так что у тебя вариант даже правильнее, если его до ума довести (убрать else ветку) и сделать всё без подпрограмм. Но я думаю, что до первого действия - действия подготовки к циклу - ты бы не додумался, потому что это надо знать из теории про предусловие цикла (хотя я там эту часть не описал, а в книжке оно есть). То есть перед выполнением цикла нужно соблюсти предусловие выполнения цикла. И для этого мы делаем подготовительный шаг перед тем, как начать выполнять цикл. Этот шаг можно делать и после цикла, но обычно мы его делаем до цикла. А зачем его делать, этот подготовительный шаг? А затем, что поле может оказаться ширины 1 (это теория, но она реальна) и твой цикл на самом первом шаге может сказать “там справа уже есть стена, и поэтому делать ничего не нужно” и таким образом оставить клетку незакрашенной, которую надо закрасить.
Чтобы вы понимали, вот так у меня была сделана изначально 13 задача:
lapimaxЭто ошибка. Какой ширины поле? Если не сказано, что поле точно ширины 29, то значит, что оно может быть ширины 1 и может быть ширины 1000. Поэтому и программу нужно писать так, что поле может быть как такой, так и такой ширины и при этом программа сработает правильно.
К слову, 20 задачу решил вот так:for i in range(27):
Отредактировано py.user.next (Март 19, 2020 03:52:13)
Офлайн
DevilDemonnfrom pyrob.api import * @task(delay=0.15) def task_9_3(): # Check size x = 0 while not wall_is_on_the_right(): move_right() x += 1 else: move_left(x) ############ base = x while x > 1: for i in range (x): move_right() if not i == x-1: fill_cell() for i in range (x): move_down() if not i == x-1: fill_cell() for i in range (x): move_left() if not i == x-1: fill_cell() for i in range (x): move_up() if not i == x-1: fill_cell() move_down() move_right() x -= 2 else: move_down(int(base/2)) move_left(int(base/2)) if __name__ == '__main__': run_tasks()[/quote]
Классное решение! Я до такой логики сравнения не додумался, к сожалению.
И немного изменил ваш вариант.a = 0 while not wall_is_on_the_right(): move_right() a += 1 else: move_left(a) while a > 1: for c in range(a): move_right() if c != a - 1: fill_cell() for c in range(a): move_down() if c != a - 1: fill_cell() for c in range(a): move_left() if c != a - 1: fill_cell() for c in range(a): move_up() if c != a - 1: fill_cell() move_right() move_down() a -= 2 while not wall_is_on_the_left(): move_left() while not wall_is_beneath(): move_down()
Отредактировано Romanteg (Март 19, 2020 11:53:06)
Офлайн
py.user.nextМожете тогда объяснить, как тогда решить 20 задачу не прибегая к подпрограмме(как сделал я)?
Подпрограммы начинаются в 24-ой задаче.
py.user.nextЯ понимаю, о чем вы говорите. Пытался найти другой способ, который подразумевал бы эту гибкость, но мне не удалось. При решении прошлых задач, достигнуть такой гибкости можно было благодаря циклу while и командам стены и/или закрашенной клетки.
Это ошибка. Какой ширины поле? Если не сказано, что поле точно ширины 29, то значит, что оно может быть ширины 1 и может быть ширины 1000. Поэтому и программу нужно писать так, что поле может быть как такой, так и такой ширины и при этом программа сработает правильно.
Прикреплённый файлы:
Снимок экрана 2020-03-19 в 00.00.21.png (37,6 KБ)
Офлайн
lapimax
Можете тогда объяснить, как тогда решить 20 задачу не прибегая к подпрограмме(как сделал я)?
Судя по названию раздела в заданиях, её нужно решить вложенным циклом без применения подпрограммы
шагнуть вправо
цикл выполнять
шагнуть вниз
если снизу_нет_стены то
шагнуть вверх
иначе
шагнуть вверх
выход из цикла
конец если
цикл пока справа_нет_стены выполнять
закрасить ячейку
шагнуть вправо
конец цикла
цикл пока слева_нет_стены выполнять
шагнуть влево
конец цикла
шагнуть вправо
шагнуть вниз
конец цикла
[guest@localhost pyrob]$ python3 task_20.py
INFO:pyrob:Starting task task_4_3
INFO:pyrob:Task task_4_3 finished: +
INFO:pyrob:Total: 1/1
[guest@localhost pyrob]$
lapimaxЕсть поле вокруг и его границы. Эти границы можно использовать как логические знаки. Но до границы часто нужно сходить и вернуться обратно, чтобы сделать логический вывод по ней.
В 20 задании выделенные клетки ни к чему не привязаны
Отредактировано py.user.next (Март 19, 2020 23:44:36)
Офлайн
Здравствуйте, подскажите
Задача №29: task_7_7
Решаю ее подсчтётом закрашенных клеток, клетки считаются, но счетчик не обнуляется, где ошибка?
def task_7_7():
filled = 0
while not wall_is_on_the_right():
if cell_is_filled():
filled += 1
if filled == 3:
break
else:
filled == 0
else:
filled == 0
move_right()
Отредактировано F.Dorohov (Март 26, 2020 17:00:02)
Офлайн
F.Dorohov
Здравствуйте, подскажите
Задача №29: task_7_7
количество_заполненных = 0
цикл пока справа_нет_стены выполнять
если клетка_заполнена то
количество_заполненных.увеличить на 1
иначе
количество_заполненных = 0
конец если
если количество_заполненных = 3 то
выход из цикла
конец если
шагнуть вправо
конец цикла
[guest@localhost pyrob]$ python3 task_29.py
INFO:pyrob:Starting task task_7_7
INFO:pyrob:Task task_7_7 finished: +
INFO:pyrob:Total: 1/1
[guest@localhost pyrob]$
Отредактировано py.user.next (Март 26, 2020 22:57:04)
Офлайн
py.user.nextТут применён возврат значения из функции. В этом курсе такие возможности не описываются, но в реале всё делается именно так. Если же по курсу брать, то регистр доступен во всех процедурах и из него можно брать значение (брать, наращивать и класть обратно). Но тут в курсе не указано, как брать значение регистра, хотя pyrob может его брать (если внутри пакета покопаться) через get_register_value(r). Короче, это всё частности; главное алгоритм составить, применив декомпозицию на подпрограммы, потому что регистр потом не пригодится, а вот навык декомпозиции (раскладывания на составные части) алгоритма потом всегда будет нужен.def walk_upstairs(): n = 0 while not wall_is_above(): move_up() if cell_is_filled(): n += 1 else: fill_cell() while not wall_is_beneath(): move_down() return n @task def task_8_18(): n = 0 while not wall_is_on_the_right(): if cell_is_filled(): n += 1 if wall_is_above(): if not cell_is_filled(): fill_cell() else: n += walk_upstairs() move_right() mov('ax', n)
@task(delay=0.01) def task_8_18(): y = 0 x = 0 for c in range(50): if wall_is_on_the_right() and not wall_is_beneath() and not wall_is_above() and not wall_is_on_the_left(): break elif wall_is_above() and not wall_is_on_the_right(): fill_cell() x += 1 move_right() elif not wall_is_above(): move_up() for c in range(15): if wall_is_above() and not cell_is_filled(): fill_cell() y += 1 elif wall_is_above() and cell_is_filled(): continue elif cell_is_filled(): move_up() elif not wall_is_above() and not cell_is_filled(): fill_cell() y += 1 else: while not wall_is_beneath(): move_down() move_right() print("x=", x) print("y=", y) total = x + y print("Кол-во закрашенных клеток:", total) mov("ax", total)
Офлайн
Условные действия на каждой итерации цикла
Задача №9: task_8_2
Закрасить клетки. Расстояние до стены не известно.
Решением этой задачи является клетки без верха,которые необходимо закрасить.Есть более простой вариант решения У меня получилось вот так:
from pyrob.api import * import time @task def task_8_2(): while not wall_is_on_the_right(): move_right() if not wall_is_above() and wall_is_beneath(): fill_cell() while not wall_is_on_the_left(): move_left() if not wall_is_above() and wall_is_beneath(): fill_cell() while not wall_is_on_the_right(): move_right() if not wall_is_above() and wall_is_beneath(): fill_cell() if __name__ == '__main__': run_tasks()
Офлайн