Ключевые наблюдения, лежащие в основе решения:
- когда мы совершаем переход от токенов к «концепциям», нам нужен диапазон вместо индекса.
- Нам нужно определить функцию длянайти «расстояние» между двумя понятиями, т.е. их соответствующий диапазон.(
dist
ниже) - другая функция для объединения понятий, т.е. их диапазонов.(
comb
ниже)
Теперь в нашей основной рекурсивной функции мы сначала выясним все вхождения обоих понятий.Тогда мы можем просто найти пары, расстояние которых меньше указанного.В этой реализации наша основная hits()
принимает «концепт»: это либо просто слово в базовом регистре, либо кортеж из 3 элементов, который имеет две концепции и int
, указывающий максимально возможное расстояние между ними.Выход этой функции представляет собой массив диапазонов, где каждый из этих диапазонов содержит обе концепции с максимальным расстоянием.Этот массив можно рассматривать как все вхождения концепции ввода.
Вот полный код.
#Find distance between two concept's ranges
#ex1: dist([2,9],[11,13]) = 2
#ex2: dist([2,9],[4,99]) = 0
def dist(r1,r2):
#check for overlap
if r2[0]<=r1[0]<=r2[1] or r1[0]<=r2[0]<=r1[1]:
return 0
return max(r1[0],r2[0]) - min(r1[1],r2[1])
#Combine two concept's ranges
#ex1: comb([1,3],[6,9]) = [1,9]
#ex2: comb([4,11],[1,7]) = [1,11]
def comb(r1,r2):
return [min(r1[0],r2[0]),max(r1[1],r2[1])]
def hits(concept):
if type(concept)==str:
return [(i,i) for i,w in enumerate(tokens) if w==concept]
c1,c2,R = concept
ans = []
for r1 in hits(c1):
for r2 in hits(c2):
if dist(r1,r2)<=R:
ans.append(comb(r1,r2))
return ans
Чтобы проверить это, случай 1: (это выводит [[0-9]])
tokens = "python group of words search implemented recursively How to proceed".split()
c1 = ("python","words",3)
c2 = ("recursively","proceed",4)
print(hits((c1,c2,3)))
случай 2: (выводит [[0-8]])
c1 = ("python","of",3)
c2 = ("search","recursively",4)
print(hits(((c1,c2,3),"to",3)))
случай 3: (выводит [[0, 3], [6, 8]])
tokens = "A B B X C C X Q A W".split()
c1 = ("A","X",4)
print(hits(c1))
Для производительности предварительно обработать базовый вариант рекурсии.