Friday, August 9, 2019

summation - Determining the row of an element at position _i_ in a triangle generated from this sequence




I'm working on Project Euler problem 18 where we're given a triangle that looks like this:



enter image description here



I can solve the problem (using a shortest-path-like algorithm), but as is often the case with problems like these, I stumbled onto another problem while solving the first.



The problem arose while I was trying to find a simple way to generate a graph from the triangle.



If this were a binary tree (which it is not) I would be able to determine the left and right children for each parent node with the equations left_child = 2*i+1 and right_child = 2*i+2 – but I haven't been able to come up with a closed-form solution for the triangle in this problem.




So what I would like to know, for a start, is if there is a closed-form equation to find the corresponding level for a given index in this triangle; hopefully, from there I can derive the left and right child equations. If no closed-form equation exists, how could I prove it?



I can already see that the levels would follow the pattern



[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6...]


Is there even a way to represent this sequence as a summation or some other formula?




Thank you.






EDIT:



# Code for messing around with this problem
triangle = \
"0 \n" \
"1 2 \n" \

"3 4 5 \n" \
"6 7 8 9 \n" \
"10 11 12 13 \n" \
"14 15 16 17 18 \n" \
"19 20 21 22 23 24"


from collections import namedtuple, defaultdict

Children = namedtuple('Children', ['left', 'right'])

children = defaultdict(lambda: None)

triangle = [s.split() for s in triangle.split("\n")]
print(triangle)
print('number of elements: ', sum([len(ls) for ls in triangle]))

index = 0
for level in range(len(triangle)):
lvl = triangle[level]
for element in range(1, len(lvl)):

children[index] = Children(lvl[element - 1], lvl[element])
index += 1

print('0 -->', children[0])

print('3 -->', children[3])
print('4 -->', children[4])
print('5 -->', children[5])

print('23 -->', children[23])

print('24 -->', children[24])

Answer



Call the first row (with 1 element) row 0 and the first element on each row element 0. (as in Pascal's triangle)



For row y, there are y rows on top it, and for element x, there are x elements to the left of it.



So to find the index of the element x on row y, where 0xy,



i(y,x)=y(y+1)2+x




where the element 0 on row 0 has index i(0,0)=0.



For the purpose of finding the children of a particular element, it is easier if you also know the element's row y (the level in your for loop). Then the index of the left child is just y+1 later:



L(i,y)=i+y+1,R(i,y)=L(i,y)+1



Otherwise, the row y of an element at index i can be determined by some flooring:



0xx<y+1y(y+1)2ii<y(y+1)2+y+1y2+y2i00<y2+3y+22i1+14(2i)2yy>3+94(22i)21+1+8i2yy>1+1+8i21
y=1+1+8i2L(i)=i+1+1+8i2+1=i+1+1+8i2



But I don't see this easier than keeping a y level counter somewhere.


No comments:

Post a Comment

analysis - Injection, making bijection

I have injection f:AB and I want to get bijection. Can I just resting codomain to f(A)? I know that every function i...