I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Thursday Code Puzzler: Investment Predictor

11.22.2012
| 4094 views |
  • submit to reddit

 Thursday is code puzzler day here at DZone. The idea is simple: solve the coding problem as efficiently as you can, in any language or framework that you find suitable.

Note: Even though there really is nothing stopping you from finding a solution to this on the internet, try to keep honest, and come up with your own answer.  It's all about the participation!

Do you have code puzzlers that you'd like to share with the DZone community?  If so, please submit here. 

Investment Predictor

With an initial investment of 1,000, and a daily increase of 1%, how long would it take for the initial amount to double?

Catch up on all our previous puzzlers here.

Comments

Vijay Nathani replied on Thu, 2012/11/22 - 4:46am

 Groovy code that prints 70 as answer

double INTEREST_PER_DAY = 1
println Math.round(Math.log(2) / Math.log(1 + INTEREST_PER_DAY/100))

Mihai Dinca - P... replied on Thu, 2012/11/22 - 7:01am in response to: Vijay Nathani

 You should use Math.ceil instead of Math.round

Mark Howard replied on Thu, 2012/11/22 - 8:26am

I did it like so, in Java with a recursive static method:

public static void investmentPrediction(double balance, double percentage, int target, int weeks){
		if(balance<target){
			weeks++;
			balance = balance+(balance*(percentage/100));
			investmentPrediction(balance, percentage, target, weeks);
		}
		else{
			System.out.println("It will take "+weeks+" weeks to reach 2000");
		}
		
	}

Daniel Seidler replied on Thu, 2012/11/22 - 8:51am

Kotlin

val s   = 1000.0
val e   = s * 2
val inc = 1.0

//Log
ceil(log(e/s) / log(1 + (inc / 100)))

//Recursive
fun interest(start: Double, i: Int = 0): Int {
    if(start >= e) return i
    else return interest(start + start * inc / 100, i + 1)
}

// Iterative
fun interest(var start: Double, var days: Int = 0) : Int{
    while (start < e) {
        days++
        start += start * inc/100
    }
    return days
}

Iterativ is the fastest Solution:

recursive: 70 days - runtime 90425 ns
log: 70.0 days - runtime 492878 ns
iterative: 70 days - runtime 28715 ns

Verny Bonilla replied on Thu, 2012/11/22 - 10:10am

In Oracle / PL-SQL

DECLARE
  vInt   NUMBER    := .01;  
  vMonto NUMBER    := 1000;
  vResul NUMBER    := vMonto;
  vDias  NUMBER(3) := 1;
BEGIN
  LOOP
    vResul := vResul + (vResul * vInt);
  EXIT WHEN vResul > (vMonto * 2);      
    vDias  := vDias + 1;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE(vDias || ' Días');
END;

Vijay Nathani replied on Thu, 2012/11/22 - 10:27am

 Iterative will always be faster than recursive.

Log is slow in Java because multiple mathematical need to be performed. Accelerated Math libraries are available in C++ for Intel and AMD processor that ask the processor to compute log to the base 2 in a single instruction. Unfortunately Java 7 does not use this optimization. So Log is slower than iterative calculation.

If later versions of Java optimize calculation of log by asking microprocessor to perform the same, then log may be faster than iterative. Obviously this optimization is not a high priority for Oracle.

Vijay Nathani replied on Thu, 2012/11/22 - 2:45pm in response to: Vijay Nathani

On C# in Visual Studio 2010 with .NET 4, log is faster than iterative
using System;

namespace LearnCS
{
    internal class Compute
    {
        private const double RateOfInterest = 1.0, TimesAmount = 2.0;

        private static void Run(string message, Func<long> task)
        {
            var start = DateTime.Now;
            for (int i=1; i< 10000; ++i)
                task(); //delay
            var returnValue = task();
            var timeTaken = (DateTime.Now.Ticks - start.Ticks); // 1 nano second = 100 ticks
            Console.WriteLine("{0} returned {1} and took {2} ticks", message, returnValue, timeTaken);
        }

        private long LogCompute()
        {
            return (long) Math.Ceiling(Math.Log(TimesAmount, 1 + RateOfInterest/100));
        }

        private long ItrativeCompute()
        {
            long days = 0;
            for (var start = 1.0; start < TimesAmount; days++)
                start += start*RateOfInterest/100;
            return days;
        }

        public void Main1()
        {
            //Warm-up
            LogCompute();
            ItrativeCompute();
            Run("Start of Test", () => 0 );
            //Actual run
            Run("Log", LogCompute);
            Run("Iterative", ItrativeCompute);
        }
    }
}
/*
 * The ouput of the code was
        Start of Test returned 0 and took 19531 ticks
        Log returned 70 and took 9765 ticks
        Iterative returned 70 and took 78125 ticks
 *  So apparently, log is faster in C# than in Java because C# uses processor to compute the log function, 
 *  while Java apparently does not use this optimization. This also seems logical because Java is popular 
 *  on server, where the need to use log function is minimal. C# is very popular for desktop applications, 
 *  where log function is probably needed.
*/

Boyko Bantchev replied on Wed, 2012/11/28 - 10:11am

In J:

>.1.01^.2


Apperson Johnson replied on Wed, 2012/11/28 - 11:00am

http://www.google.com/#hl=en&q=(ln+2)%2F(ln+1.01)

Mike Lynch replied on Wed, 2012/11/28 - 12:01pm in response to: Daniel Seidler

Is anyone else suprised that a one liner is slower then a function!  Great info! 

Rohit Rai replied on Wed, 2012/11/28 - 2:47pm

Scala

import scala.math._

val p = 1000
val target = 2000
val r = 0.01

println ceil(log(target/p)/log(1.0 + r))

Boyko Bantchev replied on Wed, 2012/11/28 - 4:01pm in response to: Mike Lynch

The problem statement says nothing about program speed — it says 'solve the coding problem as efficiently as you can'.  Picking a proper language for the problem, and then making 10 keystrokes (including the carriage return) to obtain the solution seems like an efficient problem solving to me.  Especially when compared to writing several tens of li[n]es in some other language :)

Manoj Balu replied on Thu, 2012/11/29 - 12:45am

 runtime 20140 nanoseconds

// objective C / objective c++

double principal = 1000;
double target = 2 * principal;
CGFloat rate = 0.01;

NSLog(@"Amount doubles in %.0f", ceil(log(target/ principal)/log(1.0 + rate))); 

ebenezer raj replied on Fri, 2012/11/30 - 10:27am

Using q

{ceiling(log y%x)%log 1+z%1e2}[1000;2000;1]

prints 70

Andrius S. replied on Thu, 2012/12/06 - 8:23am

I just devide 70 by percentage and get in how many time it would double. Say, with 1%, 70/1=70 would double in 70 days.

Ed Griebel replied on Wed, 2012/12/12 - 10:11am

Here are two basic Clojure (Java-based Lisp variant) versions. The first is easier to understand but could lead to a stack overflow for large values of to because it doesn't use the recur primitive that simulates tail recursion.

(defn calc_v1
  ([amt to]
    (if (>= amt to)
      0
      (inc (calc_v1 (* amt 1.01) to))
    )
  )
)

The recur in this version will recursively call calc but not add each individual frame to the call stack.

(defn calc_v2
  ([amt to] (calc_v2 amt to 0))
    ([amt to i]
      (if(>= amt to)
        i
      (recur (* amt 1.01) to (inc i))
    )
  )
)

To run either one, call like this: (calc 1000 2000)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.