[OT] Reciprocal function?

Terry Reedy tjreedy at udel.edu
Fri Nov 22 13:06:04 EST 2002


"Anton Vredegoor" <anton at vredegoor.doge.nl> wrote in message
news:aril5k$e07$1 at news.hccnet.nl...
> def rowinc(x,base):
>     i,j = 0,1
>     while i <= x:
>         j = j * base
>         i = i + j
>     return j

Odd and misleading name.  Somewhat odd function.  For x < 0 (which
your problem specification may exclude), rowinc==1.  Otherwise, it
return the largest power of base, base**n, such that sum(k=1..n-1;
base**k)  <= x.  For x>=0, this is at least base**1.

When base=2 and hence base-1==1, this is the largest power of 2 in
x+2.  Which is to say, n is the index of the high order 1-bit in the
binary expression of x+2.  This could be done more simply with shifts,
but this does not generalize very well to other bases.

> def concat(a,b,base):
>     f = rowinc(b,base)
>     return f*(a+1)+b

This multiply-add (which characterization is the key to your problem)
has nothing obvious to do with concat-enation.  You implicitly assume
below that a and b are counts (non-negative ints).  It would be less
confusing if you did not add 1 to a, so a is the actual multiplier
rather than 1 less, and instead required input to be positive rather
than just non-negative.

> And, for the moment, lets assume "base" is fixed to the value 2.
>
> Then concat(9,5,2) will return 45.
> But concat(3,13,2) will also return 45.
>
> In fact if the number that concat returns is known, and the "base"
> argument is also known, the function below can be used to calculate
> how many other tuples (a,b) will have the same result:
>
> def seqlen(x,base):
>     i,j,k = 0,1,0
>     while i <= x:
>         j = j * base
>         i = i + j
>         k = k + 1
>     return k

This version of rowinc returns n instead of base**n.

> So seqlen(45,2) returns 5. The number of possible tuples (a,b) that
> make concat(a,b,2) return 45 is seqlen(45,2)-1 which is 4.

Only because you exclude concat(-1,45,2) = 45.

> For (a,b) in [(0, 29), (3, 13), (9, 5), (21, 1)], concat(a,b,2)
> returns 45 and there are no other tuples (a,b) that return 45 for
> concat(a,b,2).

Only with the unstated condition.

>
> Now I need a function that looks a bit like this:
>
> def splitat(i,a,base):
> """
> returns the i'th tuple (x,y) out of the set of possible
> tuples that make concat(x,y,base) return a
> """
>     return x,y
>
> Any pointers appreciated.

Overloading a as both a param of concat and its result is poor.  I
will call the result cc instead.  Defining i'th tuple depends on the
ordering.   Sorting on b instead of a makes problem slightly easier.
In any case, the 'inverse' of multiply-add is divmod(), possibly
adjusted.  Because of the rowinc condition linking b, base, and power
of base, there is (definitely for base 2 and perhaps for others - not
sure) one possible value of a,b for each possible value of rowinc,
each of which is a positive power of base.  So generate the list of
tuples by looping thru powers of base.  Example for cc=45 and base=2
to generate pairs (a+1,b) (I'll let you do subtraction of 1 from a+1):

divmod(45,2) = (22,1) #OK since rowinc(1,2)=2
divmod(45,4) = (10,5) # OK since rowinc(5,2) = 4
divmode(45,8) = (5,5) # not OK
# adjust a down and b up to maintain product-sum of 45
  adjust to 4,13(=5+8) # OK since rowinc(13,2)=8
divmod(45,16) = (2,13) # not OK
  adjust to 1,29(=13+16) #OK since rowinc(29,2)=16
divmod(45,32) = (1,13) # not OK
  adjust to 0.45 #stop because a+1<1 not allowed
return list of 4 tuples

With other bases, you might have to adjust more than once.  If doing a
lot of calculations with one base, it would be worthwhile to calculate
a vector of rowinc results.

Terry J. Reedy





More information about the Python-list mailing list