Форум программистов, компьютерный форум, киберфорум
Python: Решение задач
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 28.08.2024
Сообщений: 4

В НИИ метеорологии решили изучить процесс образования водоемов на различных рельефах местности во время дождя

29.10.2024, 05:55. Показов 1150. Ответов 19

Студворк — интернет-сервис помощи студентам
Задача: код выдает ошибку вычислений, помогите, пжл, исправить! в упор не вижу ((((

В НИИ метеорологии решили изучить процесс образования водоемов на различных рельефах местности во время дождя. Ввиду сложности реальной задачи была создана двумерная модель, в которой местность имеет только два измерения — высоту и длину. В этой модели рельеф местности можно представить как N-звенную ломаную c вершинами (x0, y0), ..., (xN, yN), где x0 < x1 < ... < xN и yi ≠ yj, для любых i ≠ j. Слева в точке x0 и справа в точке xN рельеф ограничен вертикальными горами огромной высоты.
Если бы рельеф был горизонтальным, то после дождя вся местность покрылась бы слоем воды глубины H. Но поскольку рельеф — это ломаная, то вода стекает и скапливается в углублениях, образуя водоемы.
Требуется найти максимальную глубину в образовавшихся после дождя водоемах.

Формат ввода

В первой строке расположены натуральное число N (1 ≤ N ≤ 100) и H — действительное число, заданное с тремя цифрами после десятичной точки (0 ≤ H ≤ 109). В последующих N + 1 строках — по два целых числа xi, yi (-10000 ≤ xi, yi ≤ 10000).
Числа в строках разделены пробелами.
Формат вывода

Выведите единственное число — искомую глубину с точностью 10-4.

Пример
Ввод
7 7.000
-5 10
-3 4
-1 6
1 –4
4 17
5 3
9 5
12 15

Вывод 15.8446


Python
1
2
3
4
5
6
7
8
9
10
11
12
13
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
def min(a, b):
    return b if a > b else a
 
def max(a, b):
    return a if a > b else b
 
def solve(BV, p, q):
    global uh, hmax, deltaX, deltaY, dh
 
    vsleva = 0
    vsprava = 0
    maxk = -float('inf')
    gde = -1
 
    for i in range(p, q):
        if y[i] > maxk:
            maxk = y[i]
            gde = i
 
    # Слева
    for i in range(p, gde + 1):
        deltaX = abs(x[i] - x[i - 1])
        deltaY = abs(y[i] - y[i - 1])
        vsleva += (deltaX * deltaY / 2)
        if maxk >= max(y[i], y[i - 1]):
            vsleva += (maxk - max(y[i], y[i - 1])) * deltaX
        else:
            vsleva += (maxk - max(y[i], y[i - 1])) * deltaX + ((maxk - max(y[i], y[i - 1])) ** 2 * deltaX * deltaY / 2)
 
    # Справа
    for i in range(gde + 1, q + 1):
        deltaX = abs(x[i] - x[i - 1])
        deltaY = abs(y[i] - y[i - 1])
        vsprava += (deltaX * deltaY / 2)
        if maxk >= max(y[i], y[i - 1]):
            vsprava += (maxk - max(y[i], y[i - 1])) * deltaX
        else:
            vsprava += (maxk - max(y[i], y[i - 1])) * deltaX + ((maxk - max(y[i], y[i - 1])) ** 2 * deltaX * deltaY / 2)
 
    uh = 10000
    if vsprava >= (x[q] - x[gde]) * h:
        for i in range(gde + 1, q + 1):
            dh[i] = maxk
        for j in range(gde, q + 1):
            if y[j] < uh:
                uh = y[j]
        hmax = maxk - uh
 
    uh = 10000
    if vsleva >= (x[gde] - x[p]) * h:
        for i in range(p, gde + 1):
            dh[i] = maxk
        for j in range(p - 1, gde + 1):
            if y[j] < uh:
                uh = y[j]
        hm = maxk - uh
        if hm > hmax:
            hmax = hm
 
# Основная программа
hmax = -1
n = 0
h = 0
 
# Чтение входных данных
n, h = map(str, input().split())
n = int(n)
h = float(h)
x = [0] * (n + 1)
y = [0] * (n + 1)
for i in range(n + 1):
    x[i], y[i] = map(int, input().split())
 
BigV = h * (x[n] - x[0])
dh = [0] * (n + 1)
 
solve(BigV, 1, n)
 
if hmax == -1:
    om = 0
    for i in range(1, n + 1):
        deltaX = abs(x[i] - x[i - 1])
        deltaY = abs(y[i] - y[i - 1])
        if deltaY / deltaX > om:
            om = deltaY / deltaX
            hmax = deltaY
 
# Запись результата
print(f"{hmax:.4f}\n")
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
29.10.2024, 05:55
Ответы с готовыми решениями:

Три друга А, Н, Ш решили провести каникулы в трех различных городах
Помогите пожалуйста срочно Три друга А, Н, Ш решили провести каникулы в трех различных городах – Ялте, Одессе, Киеве. Определите, в...

Реализовать эффект дождя из одиночных различных типов заливки произвольного цвета
Помогите пожалуйста реализовать эффект дождя из одиночных различных типов заливки произвольного цвета. Капли по одной в столбце падают.

Написать программу, моделирующую процесс распространения инфекционного заболевания на местности размером клеток (зад
Написать программу, моделирующую процесс распространения инфекционного заболевания на местности размером клеток (задается с...

19
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38183 / 21118 / 4307
Регистрация: 12.02.2012
Сообщений: 34,728
Записей в блоге: 14
29.10.2024, 12:15
Цитата Сообщение от luciaa_ Посмотреть сообщение
код выдает ошибку вычислений
- код нормально работает, выдаёт 21.000
0
Эксперт PythonЭксперт Java
19530 / 11067 / 2931
Регистрация: 21.10.2017
Сообщений: 23,294
29.10.2024, 12:20
Цитата Сообщение от luciaa_ Посмотреть сообщение
n, h = map(str, input().split())
Зачем строку преобразовывать в строку? Чтоб строковее стала?
n, h = input().split()

Цитата Сообщение от luciaa_ Посмотреть сообщение
def min(a, b):
Зачем определять функции min и max, если они повторяют стандартные, как именем, так и реализацией?
2
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6224 / 2925 / 1046
Регистрация: 01.06.2021
Сообщений: 10,832
29.10.2024, 12:32
Цитата Сообщение от iSmokeJC Посмотреть сообщение
Зачем строку преодразовывать в строку? Чтоб строковее стала?
Мне кажется, что это код ИИ. На это намекают зашкварные комментарии в коде.
1
Эксперт PythonЭксперт Java
19530 / 11067 / 2931
Регистрация: 21.10.2017
Сообщений: 23,294
29.10.2024, 12:36
Royal_X, да походу. Но ржачно то, что если это проделки ИИ, то значит эту дичь кто-то где-то когда-то таки писал и выложил )))
0
29.10.2024, 13:46

Не по теме:

Цитата Сообщение от iSmokeJC Посмотреть сообщение
то значит эту дичь кто-то где-то когда-то таки писал и выложил
Генеративный ИИ не занимается копипастой. Имею в виду, вы не найдете то, что он написал, нигде в инете. При каждом новом запросе будет уникальный ответ, даже если не менять промт, ибо там меняется сид рандома.
Однако, если вернуться к нашему случаю, то можно сказать, что "в инете очень много похожих дичевых кодов", раз ИИ выдал такой ответ. Но не всегда качество ИИ определяют данные, которые были использованы для обучения модели. В эпоху информационной сингулярности очень важно фильтровать правду от неправды, хорошие вещи от мусора. Не факт, что та инфа, которой больше в инете, является правдой, а та, которой меньше, ложью. Поэтому качественный ИИ должен уметь правильно выставлять приоритет источников инфы.

0
30.10.2024, 08:14

Не по теме:

Цитата Сообщение от iSmokeJC Посмотреть сообщение
если это проделки ИИ, то значит эту дичь кто-то где-то когда-то таки писал и выложил
- и с каким основанием мы называем это искусственным интеллектом? Интеллект - способность к обучению. Обучение базируется на запоминании. Запоминать GPT умеет. И не более того...

0
30.10.2024, 09:04

Не по теме:

Цитата Сообщение от Catstail Посмотреть сообщение
и с каким основанием мы называем это искусственным интеллектом? Интеллект - способность к обучению. Обучение базируется на запоминании. Запоминать GPT умеет. И не более того...
Так ведь, потому что суррогат, потому и искусственный, т.е. подобный оригиналу, но таки не оригинал, т.е. не природный, а созданный рукотворно. И кстати, не способность к обучению, а способность к поиску решения (там не только обучение, целый комплекс характеристик, в том числе и воображение, например), т.е. к познанию/пониманию задачи и соответственно, выдачи её решения, при этом оригинал может выйти за пределы предыдущего опыта при его отсутствии, а вот искусственная поделка - вряд ли, хотя и пытаются обозначить, что это возможно. Хотя грани, конечно, размыты, в большинстве ситуаций...

0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
30.10.2024, 09:56
Цитата Сообщение от luciaa_ Посмотреть сообщение
Задача: код выдает ошибку вычислений, помогите, пжл, исправить! в упор не вижу ((((
Давайте разберем сначала алгоритм. Опишите своими словами, как вы вычисляете
3
Эксперт PythonЭксперт Java
19530 / 11067 / 2931
Регистрация: 21.10.2017
Сообщений: 23,294
30.10.2024, 09:58
0
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
30.10.2024, 19:54
Так решил кто-то хоть? У меня аналитическое решение для примера:
(-238+√292390) / 18 ≈ 16.818388151152987738,
что расходится с 15.8446 больше чем на "точность".. Выходит условие не правильно понял?

PS вылетать может из-за –4 во входных данных, откуда она там взялась?
0
1956 / 874 / 352
Регистрация: 05.09.2021
Сообщений: 1,387
30.10.2024, 21:29
Цитата Сообщение от Aael Посмотреть сообщение
Так решил кто-то хоть?
Я пока пасс. Кроме предположения что эта развернутая на плоскость модель является системой сообщающихся сосудов, в которую налили 119 единиц жидкости ( (max_x - min_x) * h ), дальше дело не пошло.
Еще нарисовал эту "пилу" в matplotlib, но как это проинтегрировать не знаю.

Если я правильно понял условия, то площадь под красной линией должна равняться объему (119 для данного примера), и тогда разница между ординатой этой линии и min_y будет ответом. Но это не точно =)
1
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
30.10.2024, 21:45
anton78spb, ну вроде все так, прост я сколько не считаю сижу другой ответ получается.. вот двоичный поиск, например
Кликните здесь для просмотра всего текста
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
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
# file = open('input.txt', encoding='utf-8')
# input = lambda: file.readline().rstrip()
 
n, H = input().split()
n, H = int(n), float(H)
p = [(*map(float, input().split()), ) for _ in range(n + 1)]
w = p[-1][0] - p[0][0]   # lake width
b = min(y for x, y in p) # lake bottom
t = max(y for x, y in p) # lake top
s = []
 
from itertools import pairwise
for (x1, y1), (x2, y2) in pairwise(p):
    if y1 > y2: y1, y2 = y2, y1
    s.append((y1 - b, y2 - b, x2 - x1, y2 - y1))
 
def g(y1, y2, dx, dy, h):
    # area of segment (trapezoid or rectangle or empty)
    return \
        0 if h < y1 else \
        (h - y2 + dy / 2) * dx if y2 < h else \
        (h - y1) * (h - y1) * dx / dy / 2
 
def f(h): 
    # total area of lake
    return sum(g(*si, h) for si in s)
 
# binary search
hl, hr = 0, t - b + H
while 1e-10 < abs(hl - hr):
    h = (hl + hr) / 2
    if f(h) < H * w: hl = h
    else: hr = h
 
print(h := (hl + hr) / 2)
 
# print(f(h), f(h)/w)             # 119 7
# print(f(15.8446), f(15.8446)/w) # 104 6 - WTF???
0
Вирусоборец
 Аватар для thyrex
14450 / 7489 / 1582
Регистрация: 06.09.2009
Сообщений: 27,133
30.10.2024, 23:44
anton78spb, красная линия будет проходить там, где Вы ее нарисовали, только в левой части. А в правой части она будет проходить по вершине самой высокой "горы". В правой части глубина получается меньше, и вода начнет переливаться в левую часть.

Добавлено через 46 минут
Или я тоже что-то не так понимаю. Потому что при этом в правой части получает 80 из 119.

Добавлено через 25 минут
Если исходить из равномерности заполнения обеих частей, тогда они должны иметь равную площадь. И красная линия в обеих частях все равно может не совпасть.
1
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
31.10.2024, 00:11
Цитата Сообщение от thyrex Посмотреть сообщение
Потому что при этом в правой части получает 80 из 119.
почему? пока дождь будет сверху литься в левую чашку попадет 9/17 объема (т.к. x из -5..4), а в правую - 8/17 (x из 4..12). Т.е. 119 = 63+56. В левой чашке высота 15.8446, а в правой 10.9369, все как по условию

Вы пока про дождь не напомнили, тоже считал как anton78spb площадь под прямой.. Теперь, кстати, совсем не ясно как задачу решать..

2
1956 / 874 / 352
Регистрация: 05.09.2021
Сообщений: 1,387
31.10.2024, 00:19
thyrex, Я думал о том, каким образом "оно" заполняется. Сначала тоже предположил, что весь объем должен делиться пропорционально ширинам "тазиков". Но потом решил сделать допущение что это система сообщающихся сосудов, и уровень воды будет одинаковым. Т.к. если "пилить" все это на отдельные "тазики", то надо так же учитывать, что объем какого-то может оказаться достаточно маленьким, и из него начнет переливаться в соседние.
0
Вирусоборец
 Аватар для thyrex
14450 / 7489 / 1582
Регистрация: 06.09.2009
Сообщений: 27,133
31.10.2024, 07:20
Сообщающиеся сосуды друг с другом соединены, а тут такого нет.

Aael, 80 получается при заполнении доверху правого водоема. Я ведь изначально писал про возможность перелива через край. Но когда посчитал полную площадь справа понял, что при таких данных это невозможно.
0
0 / 0 / 0
Регистрация: 28.08.2024
Сообщений: 4
02.11.2024, 13:00  [ТС]
Это не ИИ, а эээ... "ремастеринг" с древнего паскаля )) комментарии автора решения сохранены! )
Код не идеальный, да, но тут ошибка в вычислениях.
Задача стара как паскаль начала нулевых.
Двоичный поиск здесь и сообщающиеся сосуды.
Сначала считаем площадь труеугольников, потом, когда (если) они заполнятся, слияние с трапеции, потом слияние трапеций и т.д. Площадь треугольников посчитали, но как потом считать перливание в трапеции?.. Я не очень понимаю, простите, поэтому пишу (((
Один из вариантов здесь https://svgimnazia1.grodno.by/... resh55.htm, но у меня не получилось полностью "переварить его" ((((( Буду благодарна, если поможете через функции решить.

Добавлено через 2 минуты
ИИ подключала, чушь пишет, даже "перевести" нормально не может.
0
964 / 485 / 241
Регистрация: 02.06.2016
Сообщений: 760
03.11.2024, 05:16
Лучший ответ Сообщение было отмечено luciaa_ как решение

Решение

luciaa_, вот нашел у себя, как вам такой chatgpt? Не знаю поможет или нет, реализация не совсем "олимпиадная" =). Алгоритм, кстати, похож на тот, что скинули, но вместо переливаний туда-сюда строится дерево из "чашек", т.е. мы заранее знаем какие вложены в какие и заливаем жидкость в корень, распределяя объем по веткам рекурсивно. Можно сразу вычислять объемы и отсекать лишние чаши. Перелива нет, вместо него весь объем заливается порциями по пороговым значениям (это минимальный среди всех чаш объем для заполнения до следующей точки ломаной), полные чаши "выкидываются" из рассмотрения.

всякие классы
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
class Math:
    eps = 1e-7
 
    @staticmethod
    def eq(x: float, y: float):
        return abs(x - y) < Math.eps
    
    @staticmethod
    def le(x: float, y: float):
        return x - Math.eps < y
    
class Point:
    def __init__(p, x: float, y: float):
        p.x, p.y = x, y
 
    def __repr__(p):
        return f'({p.x}, {p.y})'
 
class Line:
    def __init__(l, a: Point, b: Point):
        l.a, l.b = a, b
 
    def by_y(l, y: float):
        dx, dy = l.a.x - l.b.x, l.a.y - l.b.y
        return Point(l.a.x + (y - l.a.y) * dx / dy, y)
    
    def __repr__(p):
        return f'L[{p.a} - {p.b}]'
    
class Trapezoid:
    def __init__(t, left: Line, right: Line):
        t.left, t.right = left, right
    
    def area(t, bottom_y: float, top_y: float):
        '''Площадь по двум основаниям'''
        dy = top_y - bottom_y
        s0 = t.right.by_y(bottom_y).x - t.left.by_y(bottom_y).x
        s1 = t.right.by_y(top_y).x - t.left.by_y(top_y).x
        return max(0, (s0 + s1) * dy / 2)
    
    def height(t, bottom_y: float, area: float):
        '''Высота по основанию и площади'''
        # можно вывести закрытую формулу
        # но прямые left и right могут быть параллельными
        hl, hr = 0, 1
        while t.area(bottom_y, bottom_y + hr) < area: hr *= 2
        while not Math.eq(hl, hr):
            h = (hl + hr) / 2
            if t.area(bottom_y, bottom_y + h) < area: hl = h
            else: hr = h
        return (hl + hr) / 2
 
class Lake:
    @property
    def is_overflown(lake) -> bool:
        raise NotImplemented
    
    @property
    def width(lake) -> float: 
        raise NotImplemented
    
    @property
    def wall_left(lake) -> Line:
        raise NotImplemented
    
    @property
    def wall_right(lake) -> Line:
        raise NotImplemented
    
    @property
    def empty_left_wall(lake) -> list[Point]:
        raise NotImplemented
    
    @property
    def empty_right_wall(lake) -> list[Point]:
        raise NotImplemented
    
    @property
    def threshold(lake) -> float:
        '''Объем, после наливания которого меняется динамика'''
        raise NotImplemented
    
    def pour(lake, volume):
        '''Налить сверху объем меньший порогового значения'''
        raise NotImplemented
    
    def pour_from_left(lake, volume): 
        '''Перелить из чаши слева объем меньший порогового значения'''
        raise NotImplemented
 
    def pour_from_right(lake, volume):
        '''Перелить из чаши справа объем меньший порогового значения'''
        raise NotImplemented
    
    def pour_big_volume(lake, volume):
        while not (Math.le(volume, 0) or Math.le(th := lake.threshold, 0)):
            dv = min(volume, th)
            lake.pour(dv)
            volume -= dv
        return volume
 
    def find_max_deep(lake) -> float:
        '''Максимальная глубина жидкости среди всех чашек'''
        raise NotImplemented
    
    def find_bottom(lake) -> Point:
        '''Самая нижняя точка'''
        raise NotImplemented
    
    def find_volume(lake) -> float:
        '''Общий объем влитой жидкости'''
        raise NotImplemented
    
    @staticmethod
    def build(points: list[Point]) -> 'Lake':
        # несложно заменить на линейный алгоритм со стеком
 
        # ищем локальный максимум по Y,
        # т.к. все Y различны, то он либо единственный либо его нет
        local_max = None
        for i in range(1, len(points) - 1):
            if points[i-1].y < points[i].y > points[i+1].y and \
                not (local_max and points[local_max].y > points[i].y):
                local_max = i
 
        # если локальный максимум существует, то создаем пару чашек
        return (LakePair(
                    Lake.build(points[:local_max + 1]), 
                    Lake.build(points[local_max:])) 
                if local_max else LakeCup(points))
 
class LakeCup(Lake):
    '''Модель выпуклого вниз озера.'''
 
    def __init__(cup, points: list[Point]):
        cup.points = points
        cup.bottom_idx = 0      # любая точка с наименьшим y
        cup.wall_left_idx = 0   # левая точка с наименьшим y
        cup.wall_right_idx = 0  # правая точка с наименьшим y
        for i, pi in enumerate(points): # просто поиск минимумов в массиве
            if pi.y < points[cup.bottom_idx].y: cup.bottom_idx = i
            if not (Math.le(points[cup.wall_left_idx].y, pi.y)): cup.wall_left_idx = i
            if Math.le(pi.y, points[cup.wall_right_idx].y): cup.wall_right_idx = i
 
        cup.water = cup.bottom.y
        cup.volume = 0
 
    @property
    def width(cup): 
        return cup.points[-1].x - cup.points[0].x
    
    @property
    def bottom(cup): 
        return cup.points[cup.bottom_idx]
    
    @property
    def is_overflown(cup):
        top = min(cup.points[0].y, cup.points[-1].y)
        return Math.le(top, cup.water)
 
    @property
    def wall_left(cup):
        return Line(
            cup.points[cup.wall_left_idx - 1], 
            cup.points[cup.wall_left_idx])
    
    @property
    def wall_right(cup):
        return Line(
            cup.points[cup.wall_right_idx], 
            cup.points[cup.wall_right_idx + 1])
    
    @property
    def threshold(cup):
        yl = cup.points[cup.wall_left_idx - 1].y
        yr = cup.points[cup.wall_right_idx + 1].y
        t = Trapezoid(cup.wall_left, cup.wall_right)
        return t.area(cup.water, min(yl, yr))
    
    def pour(cup, volume):
        t = Trapezoid(cup.wall_left, cup.wall_right)
        cup.water += t.height(cup.water, volume)
        cup.wall_left_idx -= Math.le(cup.wall_left.a.y, cup.water)
        cup.wall_left_idx = max(1, cup.wall_left_idx)
        cup.wall_right_idx += Math.le(cup.wall_right.b.y, cup.water)
        cup.wall_right_idx = min(len(cup.points) - 2, cup.wall_right_idx)
        cup.volume += volume
 
    def pour_from_left(cup, volume):
        cup.pour(volume)
        cup.volume += volume
 
    def pour_from_right(cup, volume):
        cup.pour(volume)
        cup.volume += volume
 
    @property
    def empty_left_wall(cup):
        return cup.points[:cup.wall_left_idx] + \
            [cup.wall_left.by_y(cup.water)]
    
    @property
    def empty_right_wall(cup):
        return [cup.wall_right.by_y(cup.water)] + \
            cup.points[cup.wall_right_idx + 1:]
    
    def find_max_deep(cup):
        return cup.water - cup.bottom.y
    
    def find_bottom(cup):
        return cup.bottom
    
    def find_volume(cup):
        return cup.volume
 
class LakePair(Lake):
    '''Модель озера из двух смежных чаш. 
    Жидкость сначала наливается в обе пропорционально
    ширине чаш, затем одна из пустых или идет перелив 
    из меньшей в большую (методами pour_from_left/right). 
    После того как уровень воды в обоих сравняется создаётся
    вспомогательная "надчаша", и заполняется она'''
 
    def __init__(pair, left: Lake, right: Lake):
        pair.left, pair.right = left, right
        pair.overcup: LakeCup = None
 
    @property
    def is_overflown(pair):
        return pair.overcup and pair.overcup.is_overflown
    
    @property
    def width(pair): 
        return pair.left.width + pair.right.width
    
    @property
    def wall_left(pair):
        return pair.overcup and pair.overcup.wall_left \
            or pair.left.wall_left
    
    @property
    def wall_right(pair):
        return pair.overcup and pair.overcup.wall_right \
            or pair.right.wall_right
    
    @property
    def ratio(pair):
        wl, wr = pair.left.width, pair.right.width
        return wl / (wl + wr), wr / (wl + wr)
    
    @property
    def threshold(pair):
        if pair.overcup: return pair.overcup.threshold
        if pair.left.is_overflown: return pair.right.threshold
        if pair.right.is_overflown: return pair.left.threshold
        tl, tr = pair.left.threshold, pair.right.threshold
        ql, qr = pair.ratio
        return min(tl / ql, tr / qr)
    
    def pour(pair, volume):
        if pair.overcup: return pair.overcup.pour(volume)
        if pair.left.is_overflown: pair.right.pour(volume)
        elif pair.right.is_overflown: pair.left.pour(volume)
        else:
            ql, qr = pair.ratio
            pair.left.pour(ql * volume)
            pair.right.pour(qr * volume)
        pair.update_overcup()
 
    def pour_from_left(pair, volume):
        if pair.overcup: return pair.overcup.pour_from_left(volume)
        if pair.left.is_overflown: pair.right.pour_from_left(volume)
        else: pair.left.pour_from_left(volume)
        pair.update_overcup()
 
    def pour_from_right(pair, volume):
        if pair.overcup: return pair.overcup.pour_from_right(volume)
        if pair.right.is_overflown: pair.left.pour_from_right(volume)
        else: pair.right.pour_from_right(volume)
        pair.update_overcup()
 
    def update_overcup(pair):
        if not pair.left.is_overflown: return
        if not pair.right.is_overflown: return
        pair.overcup = LakeCup(
            pair.empty_left_wall + 
            pair.empty_right_wall
        )
 
    @property
    def empty_left_wall(pair):
        cup = pair.overcup or pair.left
        return cup.empty_left_wall
    
    @property
    def empty_right_wall(pair):
        cup = pair.overcup or pair.right
        return cup.empty_right_wall
    
    def find_max_deep(pair):
        h1 = max(pair.left.find_max_deep(), pair.right.find_max_deep())
        h2 = pair.overcup.find_max_deep() if pair.overcup else 0
        return h1 + h2
    
    def find_bottom(pair):
        return min(
            pair.left.find_bottom(),
            pair.right.find_bottom(),
            key = lambda p: p.y)
    
    def find_volume(pair):
        v1 = pair.left.find_volume()
        v2 = pair.right.find_volume()
        v3 = pair.overcup.find_volume() if pair.overcup else 0
        return v1 + v2 + v3
анимашка на pygame
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
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
import pygame as pg
import random as rnd
 
class Model:
    def __init__(m, points: list[tuple[float, float]]):
        lx, ux = min(x for x,y in points), max(x for x,y in points)
        ly, uy = min(y for x,y in points), max(y for x,y in points)
        uy += max(1, (uy - ly)) * 0.2
        m.points = ((points[0][0], uy), *points, (points[-1][0], uy))
        m.points = [Point(x, y) for x, y in m.points]
        m.bounds = pg.Rect(lx, ly, ux - lx, uy - ly)
        m.lake = Lake.build(m.points)
 
    @staticmethod
    def random():
        k = rnd.randrange(5, 20)
        x = rnd.sample(range(100), k)
        y = rnd.sample(range(100), k)
        x.sort()
        return Model([*zip(x, y)])
 
class PGWnd:
    def __init__(wnd, size = (550, 400), margin = 30, fps = 60, style=pg.RESIZABLE):
        if pg.init()[1]: raise Exception
        wnd.model: Model = None
        wnd.clock = pg.time.Clock()
        wnd.screen = pg.display.set_mode(size, style)
        wnd.font = pg.font.SysFont(pg.font.get_default_font(), 20)
        wnd.margin = margin
        wnd.fps = fps
 
    def to_screen(wnd, p: Point):
        x, y = p.x, p.y
        rx = (wnd.screen.get_width() - 2 * wnd.margin) / wnd.model.bounds.width
        ry = (wnd.screen.get_height() - 2 * wnd.margin) / wnd.model.bounds.height
        x = wnd.margin + (x - wnd.model.bounds.left) * rx
        y = wnd.screen.get_height() - wnd.margin - (y - wnd.model.bounds.top) * ry
        return x, y
 
    def run(wnd):
        while not pg.event.get(pg.QUIT):
            wnd.screen.fill(0x1f1f1f)
            wnd.draw_model()
            pg.display.update()
            wnd.update_model()
            wnd.clock.tick(wnd.fps)
            
    def update_model(wnd):
        full_rect_volume_per_second = 20
        w, h = wnd.model.bounds.size
        dv = h * w / full_rect_volume_per_second / wnd.fps
        left = wnd.model.lake.pour_big_volume(dv)
        if left > 0: wnd.model = Model.random()
 
    def draw_poly(wnd, points: list[Point], color=0, line_color=0, width=1, closed=True):
        points = [*map(wnd.to_screen, points)]
        if closed: pg.draw.polygon(wnd.screen, color, points)
        if width: pg.draw.lines(wnd.screen, line_color, closed, points, width) 
 
    def draw_model(wnd):
        if not wnd.model: return
        wnd.draw_lake(wnd.model.lake)
        wnd.draw_deeps(wnd.model.lake)
        wnd.draw_poly(wnd.model.points, line_color=0xffffff, closed=False, width=3)
        wnd.draw_statictics()
 
    def draw_lake(wnd, lake: Lake):
        match lake:
            case LakeCup(): wnd.draw_cup(lake)
            case LakePair(): wnd.draw_pair(lake)
            
    def draw_pair(wnd, pair: LakePair):
        wnd.draw_lake(pair.left)
        wnd.draw_lake(pair.right)
        if not pair.overcup: return
        wnd.draw_cup(pair.overcup)
 
    def draw_cup(wnd, cup: LakeCup):
        if not cup.water: return
        points = [
            cup.wall_left.by_y(cup.water),
            *cup.points[cup.wall_left_idx : cup.wall_right_idx + 1],
            cup.wall_right.by_y(cup.water)]
        wnd.draw_poly(points, 0x1177AE, width=0, closed=True)
 
    def draw_deeps(wnd, lake: Lake):
        if isinstance(lake, LakePair):
            if lake.overcup: 
                wnd.draw_deep(lake.overcup.water, lake)
            else:
                wnd.draw_deeps(lake.left)
                wnd.draw_deeps(lake.right)
        elif isinstance(lake, LakeCup):
            wnd.draw_deep(lake.water, lake)
 
    def draw_deep(wnd, water: float, lake: Lake):
        deep = lake.find_max_deep()
        bottom = lake.find_bottom() 
        b = wnd.to_screen(bottom)
        t = wnd.to_screen(Point(bottom.x, water))
        pg.draw.line(wnd.screen, 0xffffff, b, t)
 
        text = wnd.font.render(f'{deep:.2f}', True, 0xffffffff)
        text_rect = text.get_rect()
        text_rect.midbottom = t
        wnd.screen.blit(text, text_rect)
 
    def draw_statictics(wnd):
        volume = wnd.model.lake.find_volume()
        max_deep = wnd.model.lake.find_max_deep()
        text1 = wnd.font.render(f'volume: {volume:13.4f}', True, 0xFFED00ff)
        text2 = wnd.font.render(f'max_deep: {max_deep:9.4f}', True, 0xFFED00ff)
        rc1, rc2 = text1.get_rect(), text2.get_rect()
        w, h, m = *wnd.screen.get_size(), wnd.margin
        rc2.bottomleft = m, h - m
        rc1.bottomleft = rc2.topleft
        wnd.screen.blit(text1, rc1)
        wnd.screen.blit(text2, rc2)
 
wnd = PGWnd()
wnd.model = Model([(-5, 10), (-3, 4), (-1, 6), (1, -4), (4, 17), (5, 3), (9, 5), (12, 15)])
wnd.model = Model.random()
wnd.run()
решение задачи
Python
1
2
3
4
5
6
7
h, line = 7.00, [(-5, 10), (-3, 4), (-1, 6), (1, -4), (4, 17), (5, 3), (9, 5), (12, 15)]
 
big_y = max(y for x, y in line) + 1e7
line = (line[0][0], big_y), *line, (line[-1][0], big_y)
lake = Lake.build([Point(x, y) for x, y in line])
lake.pour_big_volume(lake.width * h)
print(lake.find_max_deep()) # 15.844619423151016

3
0 / 0 / 0
Регистрация: 28.08.2024
Сообщений: 4
03.11.2024, 17:55  [ТС]
Aael, спасибо!! ясность уже ближе.
Не всегда заходит, когда склон из двух звеньев "крышей"
Буду разбираться
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
03.11.2024, 17:55
Помогаю со студенческими работами здесь

Время образования строки
Добрый Всем день. Из базы выбираются данные:товар и кол-во.Нужно в следующем третьем столбце вывести время образования строки. Зараннее...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru