Задание №6 — Анализ алгоритмов для исполнителя
Исполнитель Черепаха действует на плоскости с декартовой системой координат. В начальный момент Черепаха находится в начале координат, её голова направлена вдоль положительного направления оси ординат, хвост опущен. При опущенном хвосте Черепаха оставляет на поле след в виде линии. В каждый конкретный момент известно положение исполнителя и направление его движения. У исполнителя существует две команды: Вперед n (где n — целое число), вызывающая передвижение Черепахи на n единиц в том направлении, куда указывает её голова, и Налево m (где m — целое число), вызывающая изменение направления движения на m градусов против часовой стрелки.
Запись Повтори k [Команда1 Команда2 ... КомандаS] означает, что последовательность из S команд повторится k раз.
Черепахе был дан для исполнения следующий алгоритм:
Направо 90 Вперёд 4 Направо 90 Вперёд 48 Направо 90 Вперёд 4 Направо 30 Повтори 8 [Вперёд 6 Направо 120 Вперёд 6 Направо 240].
Определите, сколько точек с целочисленными координатами будут находиться внутри области, ограниченной линией, заданной данным алгоритмом. Точки на линии учитывать не следует.
Правильный ответ
285
Пояснение
Решение:
Команды Направо 90 Вперёд 4 Направо 90 Вперёд 48 Направо 90 Вперёд 4 дают три стороны прямоугольника: . Это прямоугольник , четвёртая сторона которого — отрезок оси .
Дальше Направо 30, и цикл Вперёд 6 Направо 120 Вперёд 6 Направо 240 восемь раз рисует «зубцы» — равносторонние треугольники со стороной 6, направленные влево от оси ; их вершины удалены от оси на . Восемь зубцов покрывают отрезок от до , линия замыкается.
Считаем по вертикальным столбцам:
- — внутренность прямоугольника, по 47 точек (): ;
- — отрезок оси проходит внутри фигуры, но «впадины» лежат на линии: ;
- внутри одного зубца: при — 5 точек, при — 3, при — 3, при — 1, при — 1; итого 13, а на восемь зубцов — 104.
. Проверим программой (фигура невыпуклая — считаем методом луча и отбрасываем точки на ломаной):
from math import sin, cos, radians, hypot
P = [(0.0, 0.0)]
x = y = 0.0
a = 90.0
def F(n):
global x, y
x = round(x + n * cos(radians(a)), 9) # round убирает шум float
y = round(y + n * sin(radians(a)), 9)
P.append((x, y))
def R(m):
global a
a -= m
R(90); F(4); R(90); F(48); R(90); F(4); R(30)
for i in range(8):
F(6); R(120); F(6); R(240)
def on_line(px, py): # точка лежит на самой ломаной?
for i in range(len(P) - 1):
x1, y1 = P[i]; x2, y2 = P[i + 1]
L = hypot(x2 - x1, y2 - y1)
d = ((x2 - x1) * (py - y1) - (y2 - y1) * (px - x1)) / L
if abs(d) < 1e-6 and min(x1, x2) - 1e-6 <= px <= max(x1, x2) + 1e-6 \
and min(y1, y2) - 1e-6 <= py <= max(y1, y2) + 1e-6:
return True
return False
def inside(px, py): # луч вправо: чётность числа пересечений
c = False
for i in range(len(P) - 1):
x1, y1 = P[i]; x2, y2 = P[i + 1]
if (y1 > py) != (y2 > py):
if x1 + (py - y1) * (x2 - x1) / (y2 - y1) > px:
c = not c
return c
xs = [p[0] for p in P]; ys = [p[1] for p in P]
print(sum(inside(px, py) and not on_line(px, py)
for px in range(int(min(xs)) - 1, int(max(xs)) + 2)
for py in range(int(min(ys)) - 1, int(max(ys)) + 2)))
Ответ: 285