Reputation: 13
I've been puzzling over how to get a certain function working in Python. The function itself is like this:
(Phi_m)x((n2)) = (Phi_m)(x(m*n + r)) = m*x[n1] + r*(x([n1] + 1) - x[n1])
Note: n here is just to specify some multiple. It is not a list element, but it becomes a list element when x is applied. In the below example For example, we might have that n is larger than any element on the list. E.g. a list has 9 elements, the largest is 3, and m=1 - here n=9 =/= element of the list.
where n2 and n1 are two different values of an input string, and where n1 is derived by 'decomposing' n2. We consider x[0] = 0
, r
is always at zero or positive and less than m
, and all values of n
(either of them) are positive integers. In general functional takes in a string of numbers and outputs another string. What normally happens is we fix an m
, say m = 2
. Now we decompose n2
. Say n2 = 5
. Then F(x(5)) = F(x(2*2+1)) 2x[2] + 1(x[3] - x[2])
. So if our full input sequence was 0, 1, 1, 2, 3, 3
we'd have 2*1+0=2
. So our fifth output term is 2
.
I initially thought to do something like:
x = [0,1,1,2,3,3,3,3]
def F(n,j,r,x):
return j * x[n] + r(x[n + 1] - x[n])
for n in range(len(x) - 1):
print n
but this clearly fails for my purposes.
The thing is, for Python to do this it has to know how to decompose each number. So it knows 2
is fixed, and knows 2*3
is too much and so chooses 2*2
. Then it has to know this is too little and add remainder 1
. Only once it's done this can it actually grab n = 5
. That is, it can run the function. It seems clear that once it knows how to do this it can just run through every n
in our range, but I'm really not sure how to program the meat of this function.
Upvotes: 1
Views: 4220
Reputation: 24304
here is how I would decompose a number in the form of n2 = m * n1 + r
:
>>> def decompose(number):
... # returns a generator of tuples (m, n1, r)
... for m in range(1, number+1):
... yield m, number // m, number % m
...
>>> for m, n1, r in decompose(5):
... print "5 = %s * %s + %s" % (m, n1, r)
...
5 = 1 * 5 + 0
5 = 2 * 2 + 1
5 = 3 * 1 + 2
5 = 4 * 1 + 1
5 = 5 * 1 + 0
or with a fixed m
, this is the same as a regular divmod
:
>>> def decompose(number):
... return number // m, number % m
...
>>> m = 2
>>> n1, r = decompose(5)
>>> print "5 = %s * %s + %s" % (m, n1, r)
5 = 2 * 2 + 1
>>> m = 4
>>> n1, r = decompose(5)
>>> print "5 = %s * %s + %s" % (m, n1, r)
5 = 4 * 1 + 1
or more simply using lambda
:
>>> decompose = lambda number: divmod(number, m)
>>>
>>> m = 2
>>> decompose(5)
(2, 1)
>>> m = 4
>>> decompose(5)
(1, 1)
and now, for a full exanple:
>>> decompose = lambda number: divmod(number, m)
>>>
>>> class Phi_m(list):
... def __init__(self, items):
... list.__init__(self)
... # you need to know at least m numbers.
... assert len(items) >= m, 'Not enough data'
... list.extend(self, items)
... # this is a sparse list
... # http://stackoverflow.com/questions/1857780/sparse-assignment-list-in-python
... def __setitem__(self, index, value):
... missing = index - len(self) + 1
... if missing > 0:
... self.extend([None] * missing)
... list.__setitem__(self, index, value)
... def __getitem__(self, index):
... try:
... value = list.__getitem__(self, index)
... if value is not None:
... # the item is in the list, yeah!
... return value
... # the item is in the list because it was resized
... # but it is None, so go on and calculate it.
... except IndexError:
... # the item is not in the list, calculate it.
... pass
... print 'calculating Fm[%s]' % index
... A, B = decompose(index)
... value1 = self.__getitem__(A)
... value2 = self.__getitem__(A + 1)
... print 'Fm[A=%s] = %s, Fm[A+1=%s] = %s' % (A, value1, A+1, value2)
... print 'back to calculating Fm[%s]' % index
... # m * x[n1] + r * (x[n1 + 1] - x[n1]) = (m - r) * x[n1] + r * x[n1 + 1]
... # A = n1 ; B = r ; value1 = x[n1] ; value2 = x[n+1]
... value = (m - B) * value1 + B * value2
... self.__setitem__(index, value)
... return value
...
>>> x = Phi_m([0, 1, 1])
>>>
>>> x[5]
calculating Fm[5]
calculating Fm[3]
Fm[A=1] = 1, Fm[A+1=2] = 1
back to calculating Fm[3]
Fm[A=2] = 1, Fm[A+1=3] = 2
back to calculating Fm[5]
3
>>>
>>>
Upvotes: 1