Reputation: 11
I was practicing with function and I encountered this problem. I would be grateful if someone gave me pointers on how to solve it.
Python function given below in a monotonically increasing function in N. Find the N value that makes G(N) as close 124599 as possible. You may use trial and error or you may use a for loop
def G(N):
a, b = 7, 9
while N > 2:
N = N - 1
a = b
b = int(0.83*a + 0.83*b)
return b
I have tried to use for in range loop but the numbers I get are too small compare to the given number.
Upvotes: 0
Views: 96
Reputation:
The key point here is that the function is monotonically increasing. That means that in between two points, the function can only go up.
So if G(A) < target
and G(B) > target
then, and only then, the answer we seek will be between A
and B
, and it will be there only once.
Knowing this, all we need to do is evaluate G()
at the midpoint between A
and B
, and compare that result to the target to narrow down the range until we stop making progress. aka: a binary search.
Here's a rather verbose (for clarity) way to do that:
def monotonic_closest(Func, target, integral):
# First, find points below and above the target
bottom = -1
while G(bottom) > target:
bottom *= 2
top = 1
while G(top) < target:
top *= 2
# Now narrow down the range until we stall.
while True:
# Get a halfway point
if integral:
mid = (top + bottom) // 2
else:
mid = (top + bottom) / 2
if G(mid) > target:
# We are stalling, stop
if top == mid:
return mid
# narrow the range
top = mid
else:
# We are stalling, stop
if bottom == mid:
return mid
# narrow the range
bottom = mid
result = monotonic_closest(G, 124599, integral=True)
Depending on the shape of the function, there are other methods that can converge faster, but the simply binary search has the advantage of being consistent, no matter what the function is.
Upvotes: 1
Reputation: 3591
One of the first things that comes to mind when dealing with this sort of problem is a binary search. At the moment, there is no upper limit to the search space, so the first step would be to find one. Going by powers of ten, that would be:
guess = 1
target = 124599
while G(guess) < target:
guess = 10*guess
From there, you can set your upper limit to guess
and do a binary search:
lower = 0
upper = guess
while True:
difference = upper - lower
if difference < 2:
break
midpoint = lower + difference//2
if G(midpoint) > target:
upper = midpoint
if G(midpoint) < target:
lower = midpoint
However, you can also use math to solve it. Just before the line b = int(0.83*a + 0.83*b)
, a
has been set to b
. So this is just b = int(0.83*b + 0.83*b)
, which is equivalent to b = int(1.66*b)
. If it weren't for the int
part, this would be just be multiplying b
by 1.66
over and over again, so we would get b*1.66^k
. If we take the initial value of 9
, we get 9*1.66^k = 12599
, or 1.66^k = 1399.888888888889
. Next, we can take the log of both sides. This gets us k log(1.66) = log( 1399.888888888889)
, or k = log(1399.888888888889)/log(1.66) = 14.29
.
With the first method, I got 21. The second number is off because G(N)
doesn't get started until N
is greater than 2
, and it grows slower than 1.66x at the beginning because of the rounding of int
. If you were to start later in the series, such as at 10, you'd get
G(10) = 473
G(k) = 124599
G(k)/G(10) = 263.4
log(263.4)/log(1.66) = 10.997
Rounding to the nearest integer, this would tell you that the number you're looking for is 11 greater than 10, or 21.
Upvotes: 0