I'm trying to solve a practice problem and all is well except for the last 2 inputs my solution is too slow. Just one loop is slowing it down I think.
Herd Sums
Execution Time Limit: 2 seconds
Problem Statement
The cows if farmer John's herd are numbered and banded with consecutive integers from 1 to N (1 ≤ N ≤ 10,000,000). When the cows come to the barn for milking, they always come in sequential order from 1 to N.
Farmer John, who majored in mathematics in college and loves numbers, often looks for patterns. He has noticed that when he has exactly 15 cows in his herd, there are precisely four ways that the numbers on any set of one or more consecutive cows can add up to 15 (the same as the total number of cows). They are: 15, 7 + 8, 4 + 5 + 6, and 1 + 2 + 3 + 4 + 5.
When the number of cows in the herd is 10, the number of ways he can sum consecutive cows and get 10 drops to two: namely 1 + 2 + 3 + 4 and 10.
Write a program that will compute the number of ways farmer John can sum the numbers on consecutive cows to equal N.
Input
The input consists of several test cases, each on a separate line. Each test case consists of a single integer N. The program should terminate when it encounters -1. This should not be processed.
Output
For each test case, output the number of ways Farmer John can sum the numbers on consecutive cows to equal N. Print the output for each test case in a separate line.
Sample Input
15 10 -1
Sample Output
4 2
Full Solution
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Main { static Map<Integer,Integer> cache = new HashMap<>(); static { cache.put(0, 0); } public static void main(String[] args) { long start = System.nanoTime(); String[] in = getInput(); int inRead = 0; while (inRead < in.length) { int numCows = Integer.parseInt(in[inRead++]); System.out.println(getNumSums(numCows)); } long end = System.nanoTime(); long elapsed = (end - start)/1000000000; System.out.println("Elapsed:" + elapsed); } private static int getNumSums(int numCows) { int count = 0; for (int i = 1; i <= numCows; i++) { int sum = sumTo(i); if (sum >= numCows) { int j = 1; while (sum > numCows) { sum -= j++; } if (sum == numCows) ++count; } } return count; } private static int sumTo(int end) { if (cache.get(end) == null) { int prev = cache.get(end - 1); cache.put(end, prev + end); } return cache.get(end); } private static String[] getInput() { List<String> ret = new ArrayList<>(); String line; try (BufferedReader br = new BufferedReader(new FileReader("g_input.txt"))){ while(!(line = br.readLine()).equals("-1")) { ret.add(line); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ret.toArray(new String[ret.size()]); } }
Input
1 2 3 4 5 10 15 99 200 578 690 30007 45000 143929 9909909 10000000 -1
Output
1 1 2 1 2 2 4 6 3 3 8 4 15 4 24 8
Problem
private static int getNumSums(int numCows) { int count = 0; for (int i = 1; i <= numCows; i++) { int sum = sumTo(i); if (sum >= numCows) { int j = 1; while (sum > numCows) { //this is slow sum -= j++; } if (sum == numCows) ++count; } } return count; }
This part seems to be the slow one. I've make the sumTo()
dynamic but I can't think of a way to make this part dynamic.
It works alright until it reaches numCows = 9909909
, when it reaches that part it just becomes really slow.