Определите последовательности как:
a1 <= a2 <= a3 ...
b1 <= b2 <= b3 ...
Позвольте a1b1
означать op(a1,b1)
для краткости.
Исходя из ваших допустимых предположений (очень важно), вы знаете следующее:
max(a1, b1) <= a1b1 <= a1b2 <= a1b3 ...
<=
max(a2, b1) <= a2b1 <= a2b2 <= a2b3 ...
<=
max(a3, b1) <= a3b1 <= a3b2 <= a3b3 ...
. .
. .
. .
Вам нужно будет сделать что-то вроде:
Generate a1b1
.Вы знаете, что если вы продолжите увеличивать переменные b
, вы получите только более высокие значения.Теперь возникает вопрос: есть ли меньшее значение путем увеличения переменных a
?Ваша нижняя граница равна min(a1, b1)
, поэтому вам придется увеличивать значения a
до min(ax,b1) >= a1b1
.Как только вы достигнете этой точки, вы можете найти наименьшее значение из anb1
, где 1 <= n <= x
и получить его безопасно.
У вас будет несколько горизонтальных цепочек, которые вам придется отслеживать.Каждый раз, когда у вас есть значение, которое превышает min(ax,b1)
, вам придется увеличивать x
(добавляя больше цепочек), пока min(ax,b1)
не станет больше, чем оно, прежде чем безопасно его испустить.
Просто отправная точка ... У меня нет времени кодировать это в данный момент.
РЕДАКТИРОВАТЬ: О хе, это именно то, что вы уже имели.Ну, без дополнительной информации, это все, что вы можете сделать, так как я уверен, что математически, это то, что необходимо.
EDIT2: Что касается вашего «приемлемого» решения: вы можете просто дать a1bn
в порядке возрастания n
, возвращая min(a1,b1)
как N
= P.Вам нужно быть более конкретным.Вы говорите так, как будто у вас есть эвристика того, что вы обычно хотите видеть, общий способ, которым вы хотите пройти через обе итерации, но не говоря нам, что это такое, я не знаю, как можно добиться большего.
ОБНОВЛЕНИЕ: Уинстон хорош, но делает предположение, что автор не упомянул: что op(a,c)
> op(b,c)
, если b>a
.Тем не менее, мы знаем, что op(a,b)>=a
и op(a,b)>=b
.
Вот мое решение, которое принимает это второе предположение, но не то, которое взял Уинстон.Пропишет ему структуру кода, хотя:
def increasing(fn, left, right):
left_items = [next(left)]
right_items = [next(right)]
#columns are (column value, right index)
columns = [(fn(left_items[0],right_items[0]),0)]
while True:
#find the current smallest value
min_col_index = min(xrange(len(columns)), key=lambda i:columns[i][0])
#generate columns until it's impossible to get a smaller value
while right_items[0] <= columns[min_col_index][0] and \
left_items[-1] <= columns[min_col_index][0]:
next_left = next(left)
left_items.append(next_left)
columns.append((fn(next_left, right_items[0]),0))
if columns[-1][0] < columns[min_col_index][0]:
min_col_index = len(columns)-1
#yield the smallest value
yield columns[min_col_index][0]
#move down that column
val, right_index = columns[min_col_index]
#make sure that right value is generated:
while right_index+1 >= len(right_items):
right_items.append(next(right))
columns[min_col_index] = (fn(left_items[min_col_index],right_items[right_index+1]),
right_index+1)
#repeat
Для (патологического) ввода, демонстрирующего разницу, рассмотрим:
def pathological_one():
cur = 0
while True:
yield cur
cur += 100
def pathological_two():
cur = 0
while True:
yield cur
cur += 100
lookup = [
[1, 666, 500],
[666, 666, 666],
[666, 666, 666],
[666, 666, 666]]
def pathological_op(a, b):
if a >= 300 or b >= 400: return 1005
return lookup[b/100][a/100]
r = increasing(pathological_op, pathological_one(), pathological_two())
for x in range(15):
print next(r)
Ответ Уинстона дает:
>>>
1
666
666
666
666
500
666
666
666
666
666
666
1005
1005
1005
Пока мой дает:
>>>
1
500
666
666
666
666
666
666
666
666
666
666
1005
1005
1005