Algorithm - Partition two numbers about a power-of-two - algorithm

Given two floating point numbers, p and q where 0 < p < q I am interested in writing a function partition(p,q) that finds the 'simplest' number r that is between p and q. For example:
partition(3.0, 4.1) = 4.0 (2^2)
partition(4.2, 7.0) = 6.0 (2^2 + 2^1)
partition(2.0, 4.0) = 3.0 (2^1 + 2^0)
partition(0.3, 0.6) = 0.5 (2^-1)
partition(1.0, 10.0) = 8.0 (2^3)
In the last instance I am interested in the largest number (so 8 as opposed to 4 or 2).

Let us assume assume that p and q are both normalized and positive, and p < q.
If p and q have differing exponents, it appears that the number you are looking for is the number obtained by zeroing the mantissa of q after the leading (and often implicit) 1. The corner cases are left as an exercise, especially the case where q's mantissa is already made of zeroes after the leading, possibly implicit, 1.
If p and q have the same exponent, then we have to look at their mantissas. These mantissas have some bits in common (starting from the most significant end). Let us call c1 c2 .. ck pk+1 ... pn the bits of p's mantissa, c1 c2 .. ck qk+1 ... qnthe bits of q's mantissa, where c1 .. ck are common bits and pk+1, qk+1 differ. Then pk+1 is zero and qk+1 is one (because of the hypotheses). The number with the same exponent and mantissa c1 .. ck 1 0 .. 0 is in the interval p .. q and is the number you are looking for (again, corner cases left as an exercise).

Write the numbers in binary (terminating if possible, so 1 is written as 1.0000..., not 0.1111...),
Scan from left to right, "keeping" all digits at which the two numbers are equal
At the first digit where the two numbers differ, p must be 0 and q must be 1 since p < q:
If q has any more 1 digits after this point, then put a 1 at this point and you're done.
If q has no more 1 digits after this point, then doing that would result in r == q, which is forbidden, so instead append a 0 digit. Follow that by a 1 digit unless doing so would result in r == p, in which case append another 0 and then a 1.
Basically, we truncate q down to the first place at which p and q differ, then jigger it a bit if necessary to avoid r == p or r == q. The result is certainly less than q and greater than p. It is "simplest" (has the least possible number of 1 digits) since any number between p and q must share their common initial sequence. We have added only one 1 digit to that sequence, which is necessary since the initial sequence alone is <= p, so no value in range (p,q) has fewer 1 digits. We've chosen the "largest" solution because we always place our extra 1 at the first (biggest) possible place.

It sounds like you just want to convert the binary representation of the largest integer strictly less than your largest argument to the corresponding sum of powers of two.

Related

How to solve SPOJ : SCALE using binary search?

http://www.spoj.com/problems/SCALE/
I am trying to do it using recursion but getting TLE.
The tags of the problem say BINARY SEARCH.
How can one do it using binary search ?
Thanx in advance.
First thing to notice here is that if you had two weights of each size instead of one, then the problem would be quite trivial, as we we would only need to represent X in its base 3 representation and take corresponding number of weights. For, example if X=21 then we could take two times P_3 and one time P_2, and put those into another scale.
Now let's try to make something similar using the fact that we can add to both scales (including the one where X is placed):
Assume that X <= P_1+P_2+...+P_n, that would mean that X <= P_n + (P_n-1)/2 (easy to understand why). Therefore, X + P_(n-1) + P_(n-2)+...+P_1 < 2*P_n.
(*) What that means is that if we add some of the weights from 1 to n-1 to same scale as X, then the number on that scale still does
not have 2 in its n-th rightmost digit (either 0 or 1).
From now on assume that digit means a digit of a number in its base-3 representation (but it can temporarily become larger than 2 :P ). Now lets denote the total weight of first scale (where X is placed) as A=X and the other scale is B=0 and our goal is to make them equal (both A and B will change as we will make our progress) .
Let's iterate through all digits of the A from smallest to largest (leftmost). If the current digit index is i and it:
Equals to 0 then just ignore and proceed further
Equals to 1 then we place weight P_i=3^(i-1) on scale B.
Equals to 2 then we add P_i=3^(i-1) to scale A. Note that it would result in the increase of the digit (i+1).
Equals to 3 (yes this case is possible, if both current and previous digit were 2) add 1 to digit at index i+1 and go further (no weights are added to any scale).
Due to (*) obviously the procedure will run correctly (as the last digit will be equal to 1 in A), as we will choose only one weight from the set and place them correctly, and obviously the numbers A and B will be equal after the procedure is complete.
Now second case X > P_1+P_2+...+P_n. Obviously we cannot balance even if we place all weights on the second scale.
This completes the proof and shows when it is possible and the way how to place the weights to both scales to equalise them.
EDIT:
C++ code which I successfully submitted on SPOJ just now https://ideone.com/tbB7Ve
The solution to this problem is quite trivial. The idea is the same as #Yerken's answer, but expressed in a bit different way:
Only the first weight has a mass not divisible by 3. So the first weight is the only one has effect on balancing mod 3 property of the 2 scales:
If X mod 3 == 0, the first weight must not be used
If X mod 3 == 1, the first weight must be on scale B (the currently empty one)
If X mod 3 == 2, the first weight must be on scale A
Subtract both scales by weight(B) --> solution doesn't change, and now weight(A) is divisible by 3 while weight(B) == 0
Set X' = weight(A)/3 and divide every weights Pi by 3 ==> Solution doesn't change, and now it's the same problem with N' = N-1 and X' = (X+1)/3
pseudo-code:
listA <- empty
listB <- empty
for i = 1 to N {
if (X == 0) break for loop; // done!
if (X mod 3 == 1) then push i to listB;
if (X mod 3 == 2) then push i to listA;
X = (X + 1)/3; // integer division
}
hasSolution <- (X == 0)
C++ code: http://ideone.com/LXLGmE

Computing the most accurate result for: the sum of a list of fixed point nubers

Lets say you'd have to add some 32-bit fixed point numbers stored in a huge array L and you'd like to get the most accurate result as possible. Furthermore, you're not allowed to use anything else than L and the 32-bit fixed point numbers (i.e. you're not allowed to convert them to 64-bit). What would be your approach to get the most accurate result for the sum of the numbers in L?
This would be my current approach noted in sudo code:
L = sort(L)
result = 0
lastMax = false -- indicates whether we've extracted the maximum from L last time
while (not empty(L)) and (result not equals +INF or -INF) do:
current = 0
if lastMax:
current = extractMin(L) -- gets and removes minimum from L
else:
current = extractMax(L) -- gets and removes maximum from L
result = safeAdd(result, current)
lastMax = not lastMax
safeAdd(a,b):
if a = +INF: return +INF
else if a = -INF: return -INF
else: return a + b
So I'm alternating between adding the minimum/maximum from the remaining list L in order to stay between the ranges of L. The way how safeAdd is implemented shows that once we've crossed the ranges of accuracy (i.e., the result of a+b has yielded +INF or -INF - just as it's done in C) we will not alter the result anymore.
Do you have any suggestions on how to improve the approach?
Sidenote: If we want to be very precise: We further assume that the + operation can yield +INF or -INF which can be represented as fixed point numbers in the programming language. But we assume that the values +INF, -INF do not occur in L. And we ignore the fact the fixed point standard may also have a representation for NaN.
If you know, that the result is in range, you don't need to care about overflow or underflow.
Here is an example with 4 bits only to keep it simple
7 0111
+1 0001
= 1000 <-- -8 overflow
-1 0001
= 0111
If you are not sure, if the result is in range, you need to count overflows and underflows.
For a = b + c
Overflow if b and c are positive and a is negative
Underflow if b and c are negative and a is positive

algorithm to find a number in which product of number of 4 & 7 is maximum in given range

I am stuck in a question in which lower bound L and Upper bound U is given.
Now suppose in the decimal representation of integer X digit 4 appears A times and digit 7 appears B times.
Problem is to find X which has maximum value of A*B for L<=X<=U.
Is there any efficient algorithm to solve it?
If I understood the problem correctly, the following should work:
Assume all numbers have the same number of digits (if e.g. L has less digits than U, we can just fill in the beginning with 0 s).
Let Z = U - L.
Now we go from the first (/highest/leftmost) digit to the last one. If we are looking at the i th digit, let L(i), U(i), Z(i) and X(i) be the corresponding digit.
for all leading Z(i) which are 0, we set X(i) = L(i) (we don't have a choice).
For the first not 0 Z(i) check: is there a 4 or a 7 in the interval [L(i), U(i)-1]? If yes let X(i) be that 4 or 7 otherwise let X(i) = U(i)-1.
Now fill up the rest of X with 4s and 7s such that you choose a 4 if you have assigned more 7s so far and vice versa.
Maybe an example can help in understanding this:
Given U = 5000 and L = 4900.
Now Z = 0100.
From the algorithm we set
X(1) = L(1) = 4 (we have no choice)
X(2) = U(2)-1 = 9 (the first non 0 digit in Z)
X(3) = 7 (we already had a 4)
X(4) = 4 (can be chosen arbitrarily)
Leading to X = 4974 with an objective of 2*1=2
It seems you have the algorithm thought out already.
Just break it down piece by piece and solve each part. I usually write something like you did there with comments and then break those down until they are at a reasonable bite size to write code for.
When you have it working, if needed, you can optimize it.

Number base conversion as a stream operation

Is there a way in constant working space to do arbitrary size and arbitrary base conversions. That is, to convert a sequence of n numbers in the range [1,m] to a sequence of ceiling(n*log(m)/log(p)) numbers in the range [1,p] using a 1-to-1 mapping that (preferably but not necessarily) preservers lexigraphical order and gives sequential results?
I'm particularly interested in solutions that are viable as a pipe function, e.i. are able to handle larger dataset than can be stored in RAM.
I have found a number of solutions that require "working space" proportional to the size of the input but none yet that can get away with constant "working space".
Does dropping the sequential constraint make any difference? That is: allow lexicographically sequential inputs to result in non lexicographically sequential outputs:
F(1,2,6,4,3,7,8) -> (5,6,3,2,1,3,5,2,4,3)
F(1,2,6,4,3,7,9) -> (5,6,3,2,1,3,5,2,4,5)
some thoughts:
might this work?
streamBasen -> convert(n, lcm(n,p)) -> convert(lcm(n,p), p) -> streamBasep
(where lcm is least common multiple)
I don't think it's possible in the general case. If m is a power of p (or vice-versa), or if they're both powers of a common base, you can do it, since each group of logm(p) is then independent. However, in the general case, suppose you're converting the number a1 a2 a3 ... an. The equivalent number in base p is
sum(ai * mi-1 for i in 1..n)
If we've processed the first i digits, then we have the ith partial sum. To compute the i+1'th partial sum, we need to add ai+1 * mi. In the general case, this number is going have non-zero digits in most places, so we'll need to modify all of the digits we've processed so far. In other words, we'll have to process all of the input digits before we'll know what the final output digits will be.
In the special case where m are both powers of a common base, or equivalently if logm(p) is a rational number, then mi will only have a few non-zero digits in base p near the front, so we can safely output most of the digits we've computed so far.
I think there is a way of doing radix conversion in a stream-oriented fashion in lexicographic order. However, what I've come up with isn't sufficient for actually doing it, and it has a couple of assumptions:
The length of the positional numbers are already known.
The numbers described are integers. I've not considered what happens with the maths and -ive indices.
We have a sequence of values a of length p, where each value is in the range [0,m-1]. We want a sequence of values b of length q in the range [0,n-1]. We can work out the kth digit of our output sequence b from a as follows:
bk = floor[ sum(ai * mi for i in 0 to p-1) / nk ] mod n
Lets rearrange that sum into two parts, splitting it at an arbitrary point z
bk = floor[ ( sum(ai * mi for i in z to p-1) + sum(ai * mi for i in 0 to z-1) ) / nk ] mod n
Suppose that we don't yet know the values of a between [0,z-1] and can't compute the second sum term. We're left with having to deal with ranges. But that still gives us information about bk.
The minimum value bk can be is:
bk >= floor[ sum(ai * mi for i in z to p-1) / nk ] mod n
and the maximum value bk can be is:
bk <= floor[ ( sum(ai * mi for i in z to p-1) + mz - 1 ) / nk ] mod n
We should be able to do a process like this:
Initialise z to be p. We will count down from p as we receive each character of a.
Initialise k to the index of the most significant value in b. If my brain is still working, ceil[ logn(mp) ].
Read a value of a. Decrement z.
Compute the min and max value for bk.
If the min and max are the same, output bk, and decrement k. Goto 4. (It may be possible that we already have enough values for several consecutive values of bk)
If z!=0 then we expect more values of a. Goto 3.
Hopefully, at this point we're done.
I've not considered how to efficiently compute the range values as yet, but I'm reasonably confident that computing the sum from the incoming characters of a can be done much more reasonably than storing all of a. Without doing the maths though, I won't make any hard claims about it though!
Yes, it is possible
For every I character(s) you read in, you will write out O character(s)
based on Ceiling(Length * log(In) / log(Out)).
Allocate enough space
Set x to 1
Loop over digits from end to beginning # Horner's method
Set a to x * digit
Set t to O - 1
Loop while a > 0 and t >= 0
Set a to a + out digit
Set out digit at position t to a mod to base
Set a to a / to base
Set x to x * from base
Return converted digit(s)
Thus, for base 16 to 2 (which is easy), using "192FE" we read '1' and convert it, then repeat on '9', then '2' and so on giving us '0001', '1001', '0010', '1111', and '1110'.
Note that for bases that are not common powers, such as base 17 to base 2 would mean reading 1 characters and writing 5.

Number of arrangements

Suppose we have n elements, a1, a2, ..., an, arranged in a circle. That is, a2 is between a1 and a3, a3 is between a2 and a4, an is between an-1 and a1, and so forth.
Each element can take the value of either 1 or 0. Two arrangements are different if there are corresponding ai's whose values differ. For instance, when n=3, (1, 0, 0) and (0, 1, 0) are different arrangements, even though they may be isomorphic under rotation or reflection.
Because there are n elements, each of which can take two values, the total number of arrangements is 2n.
Here is the question:
How many arrangements are possible, such that no two adjacent elements both have the value 1? If it helps, only consider cases where n>3.
I ask here for several reasons:
This arose while I was solving a programming problem
It sounds like the problem may benefit from Boolean logic/bit arithmetic
Maybe there is no closed solution.
Let's first ask the question "how many 0-1 sequences of length n are there with no two consecutive 1s?" Let the answer be A(n). We have A(0)=1 (the empty sequence), A(1) = 2 ("0" and "1"), and A(2)=3 ("00", "01" and "10" but not "11").
To make it easier to write a recurrence, we'll compute A(n) as the sum of two numbers:
B(n), the number of such sequences that end with a 0, and
C(n), the number of such sequences that end with a 1.
Then B(n) = A(n-1) (take any such sequence of length n-1, and append a 0)
and C(n) = B(n-1) (because if you have a 1 at position n, you must have a 0 at n-1.)
This gives A(n) = B(n) + C(n) = A(n-1) + B(n-1) = A(n-1) + A(n-2).
By now it should be familiar :-)
A(n) is simply the Fibonacci number Fn+2 where the Fibonacci sequence is defined by F0=0, F1=1, and Fn+2= Fn+1+Fn for n ≥ 0.
Now for your question. We'll count the number of arrangements with a1=0 and a1=1 separately. For the former, a2 … an can be any sequence at all (with no consecutive 1s), so the number is A(n-1)=Fn+1. For the latter, we must have a2=0, and then a3…an is any sequence with no consecutive 1s that ends with a 0, i.e. B(n-2)=A(n-3)=Fn-1.
So the answer is Fn+1 + Fn-1.
Actually, we can go even further than that answer. Note that if you call the answer as G(n)=Fn+1+Fn-1, then
G(n+1)=Fn+2+Fn, and
G(n+2)=Fn+3+Fn+1, so even G(n) satisfies the same recurrence as the Fibonacci sequence! [Actually, any linear combination of Fibonacci-like sequences will satisfy the same recurrence, so it's not all that surprising.] So another way to compute the answers would be using:
G(2)=3
G(3)=4
G(n)=G(n-1)+G(n-2) for n≥4.
And now you can also use the closed form Fn=(αn-βn)/(α-β) (where α and β are (1±√5)/2, the roots of x2-x-1=0), to get
G(n) = ((1+√5)/2)n + ((1-√5)/2)n.
[You can ignore the second term because it's very close to 0 for large n, in fact G(n) is the closest integer to ((1+√5)/2)n for all n≥2.]
I decided to hack up a small script to try it out:
#!/usr/bin/python
import sys
# thx google
bstr_pos = lambda n: n>0 and bstr_pos(n>>1)+str(n&1) or ""
def arrangements(n):
count = 0
for v in range(0, pow(2,n)-1):
bin = bstr_pos(v).rjust(n, '0')
if not ( bin.find("11")!=-1 or ( bin[0]=='1' and bin[-1]=='1' ) ):
count += 1
print bin
print "Total = " + str(count)
arrangements(int(sys.argv[1]))
Running this for 5, gave me a total of 11 possibilities with 00000,
00001,
00010,
00100,
00101,
01000,
01001,
01010,
10000,
10010,
10100.
P.S. - Excuse the not() in the above code.
Throwing my naive script into the mix. Plenty of opportunity for caching partial results, but it ran fast enough for small n that I didn't bother.
def arcCombinations(n, lastDigitMustBeZero):
"""Takes the length of the remaining arc of the circle, and computes
the number of legal combinations.
The last digit may be restricted to 0 (because the first digit is a 1)"""
if n == 1:
if lastDigitMustBeZero:
return 1 # only legal answer is 0
else:
return 2 # could be 1 or 0.
elif n == 2:
if lastDigitMustBeZero:
return 2 # could be 00 or 10
else:
return 3 # could be 10, 01 or 00
else:
# Could be a 1, in which case next item is a zero.
return (
arcCombinations(n-2, lastDigitMustBeZero) # If it starts 10
+ arcCombinations(n-1, lastDigitMustBeZero) # If it starts 0
)
def circleCombinations(n):
"""Computes the number of legal combinations for a given circle size."""
# Handle case where it starts with 0 or with 1.
total = (
arcCombinations(n-1,True) # Number of combinations where first digit is a 1.
+
arcCombinations(n-1,False) # Number of combinations where first digit is a 0.
)
return total
print circleCombinations(13)
This problem is very similar to Zeckendorf representations. I can't find an obvious way to apply Zeckendorf's Theorem, due to the circularity constraint, but the Fibonacci numbers are obviously very prevalent in this problem.

Resources