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

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

29.10.2024, 05:55. Показов 1105. Ответов 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
38162 / 21097 / 4306
Регистрация: 12.02.2012
Сообщений: 34,685
Записей в блоге: 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
6136 / 2830 / 1039
Регистрация: 01.06.2021
Сообщений: 10,331
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
14437 / 7479 / 1579
Регистрация: 06.09.2009
Сообщений: 27,113
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
14437 / 7479 / 1579
Регистрация: 06.09.2009
Сообщений: 27,113
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
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru