Я написал этот ответ, как я понял, поэтому, пожалуйста, несите меня.
Как уже упоминалось, это намного проще, чтобы выяснить, где персонаж в b[p][q]
приходит из числа первоначальных x
символов, чем для создания b[p]
для больших p
. Для этого мы будем использовать петлю, чтобы найти, откуда пришел ток b[p][q]
, тем самым уменьшив p
до тех пор, пока он не станет между 1
и x
и q
до тех пор, пока не будет 1
.
Давайте посмотрим на пример для x=3
, чтобы увидеть, если мы можем получить формулу:
p N(p) b[p]
- ---- ----
1 1 a
2 1 b
3 1 c
4 3 a b c
5 5 b c abc
6 9 c abc bcabc
7 17 abc bcabc cabcbcabc
8 31 bcabc cabcbcabc abcbcabccabcbcabc
9 57 cabcbcabc abcbcabccabcbcabc bcabccabcbcabcabcbcabccabcbcabc
Последовательность ясна: N(p) = N(p-1) + N(p-2) + N(p-3)
, где N(p)
является количество символов в р-й элемент b
.Учитывая p
и x
, вы можете просто перечислить все N
для диапазона [1, p]
. Это позволит вам выяснить, из какого из предшествующих элементов был b
b[p][q]
.
Для иллюстрации, скажем x=3
, p=9
и q=45
.
- Диаграмма выше дает
N(6)=9
, N(7)=17
и N(8)=31
. С 45>9+17
вы знаете, что b[9][45]
исходит от b[8][45-(9+17)] = b[8][19]
.
- Продолжение итеративно/рекурсивно,
19>9+5
, поэтому b[8][19] = b[7][19-(9+5)] = b[7][5]
.
- сейчас
5>N(4)
но 5<N(4)+N(5)
, поэтому b[7][5] = b[5][5-3] = b[5][2]
.
b[5][2] = b[3][2-1] = b[3][1]
- С
3 <= x
, у нас есть условие завершения, и b[9][45]
является c
от b[3]
.
Что-то, как это может быть очень легко вычислить либо рекурсивно или итеративно с учетом запуска p
, q
, x
и b
до x
. Мой метод требует p
элементов массива для вычисления N(p)
для всей последовательности. Это может быть выделено в массиве или в стеке, если они работают рекурсивно.
Вот эталонная реализация в ванильным Python (без внешних импорта, хотя NumPy, вероятно, поможет упорядочить это):
def so38509640(b, p, q):
"""
p, q are integers. b is a char sequence of length x.
list, string, or tuple are all valid choices for b.
"""
x = len(b)
# Trivial case
if p <= x:
if q != 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
return p, b[p - 1]
# Construct list of counts
N = [1] * p
for i in range(x, p):
N[i] = sum(N[i - x:i])
print('N =', N)
# Error check
if q > N[-1]:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
print('b[{}][{}]'.format(p, q), end='')
# Reduce p, q until it is p < x
while p > x:
# Find which previous element character q comes from
offset = 0
for i in range(p - x - 1, p):
if i == p - 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
if offset + N[i] >= q:
q -= offset
p = i + 1
print(' = b[{}][{}]'.format(p, q), end='')
break
offset += N[i]
print()
return p, b[p - 1]
Вызов so38509640('abc', 9, 45)
производит
N = [1, 1, 1, 3, 5, 9, 17, 31, 57]
b[9][45] = b[8][19] = b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
Аналогично, для примера в вопрос, so38509640('abc', 7, 5)
выдает ожидаемый результат:
N = [1, 1, 1, 3, 5, 9, 17]
b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
Извините, я не мог придумать лучшего имени функции :) Это достаточно простой код, который должен работать одинаково хорошо в Py2 и 3, несмотря на различия в функции/классе range
.
Мне было бы очень любопытно узнать, нет ли итеративного решения этой проблемы. Возможно, есть способ сделать это с помощью модульной арифметики или чего-то еще ...
Итак, для x = 3, b = a, b, c, a b c, b c abc, c abc bcabc, abc bcabc cabcbcabc и т. Д.? (Пространства для ясности, только отдельные элементы массива) –
Что написал @Mad Physicist правильно. Теперь, если есть запрос, где p = 7, q = 5, мой ответ должен быть c или третьим символом. –
Подсказка: длина элементов - это последовательность Фибоначчи более высокого порядка. Сначала вам нужно найти, какая часть (pi) равна q, т. Е. Если q
lorro