Storing computations in arrays - second try - java

im new to Java and currently trying to learn how to best store numbers in arrays.
the specific problem im working on is trying to find a way to better implement the below methods by storing the computations in an array.
the code looks like this:
public static long myF(int N) {
long[] computedValues;
computedValues = new long[N+1];
computedValues[0] = 0;
computedValues[1] = 1;
for (int i = 2; i < computedValues.length ;i++){
computedValues[i] = computedValues[(i-1)]+computedValues[(i-2)];
System.out.println("array["+(i)+"] = "+computedValues[i]);
}
return computedValues[N-1];
}
public static void runMyF() {
for (int N = 0; N < 100; N++)
StdOut.println(N + " " + myF(N));
}
public static void main(String[] args) {
runMyF ();
}
Main in this code is supposed to call runMyF(), and then runMyF() is supposed to call myF().
My problem is that I cant get computedValues[0] = 0; computedValues[1] = 1; included in the output and the second problem is that ie get this error message when runMyF() calls myF():
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at algs11.MyFib.myF(MyFib.java:21)
at algs11.MyFib.runMyF(MyFib.java:30)
at algs11.MyFib.main(MyFib.java:37)
Any help please?
#Dukeling, your solution was a bit over my pay grade (sorry) - I think there are some bugs in my code and I need help to find them. Thank you.

You're incrementing the wrong variable.
for (int i = 2; i < computedValues.length; N++){
should be
for (int i = 2; i < computedValues.length; i++){
Note the N++ changed to i++.
Remember to initialize computedValues[0] and computedValues[1]. This should appear before the loop:
computedValues[0] = 0;
if (N > 0) // needed because when N = 0, the below will be out of bounds
computedValues[1] = 1;
It should probably be computedValues = new long[N+1];, otherwise the array is too small.
You need to return the correct value - change return computedValues[N]; to return 0;.
Additional efficiency:
I guess the point is to compare the efficiency of the two method. If not, you should declare computedValues outside of the function as an ArrayList and, in the function, add to it as required. This will cause you to only compute each value once for the entire run of the program.
static ArrayList<Long> computedValues = new ArrayList<Long>(Arrays.asList(0l,1l));
public static long myF(int N) {
for (int i = computedValues.size(); i <= N; i++){
computedValues.add(computedValues.get(i-1) + computedValues.get(i-2));
System.out.println("array[" + i + "] = " + computedValues.get(i));
}
return computedValues.get(N);
}

You forgot the initial numbers in the array:
long[] computedValues;
computedValues = new long[N];
computedValues[0] = 0;
computedValues[1] = 1;

You are initializing computedValues to a new long
computedValues = new long[N];
I think you wanted to do this :
computedValues[i] = F(N);
Also, in your loop you are not incementing i which makes it as infinite loop. Change it to
for (int i = 2; i < computedValues.length ;i++)

You can use a method that returns an arraylist:
ArrayList<Long>series=new ArrayList<Long>();
for(int i=0;i<100;i++)
{
if(i==0)series.add(new Long(0));
if(i==1)series.add(new Long(1));
if(i>1)series.add(new Long(series.get(i-1).longValue()+series.get(i-2).longValue()));
}
the list will have 0,1,1,2,3,5,8,....

Related

for loop math with array in java

I'm trying to practice using Arrays methods in java. I used the following code to make an Java array:
int numArr[] = new int[10];
for(int i = 0; i< numArr.length;++i)
{
numArr[(numArr.length)-i-1] = (i+1)*2;
System.out.println("numArr[i]" + numArr[i]);
}
My intention was to use this to make the list 20,18,...,4,2. Then, I wanted to use the Arrays sort method to see if it worked properly.
The odd result that I can't understand is that above code prints:
numArr[i] = 0;
numArr[i] = 0;
numArr[i] = 0;
numArr[i] = 0;
numArr[i] = 0;
numArr[i] = 10;
numArr[i] = 8;
numArr[i] = 6;
numArr[i] = 4;
numArr[i] = 2;
I understand the simple mistake with printing the i each time but I don't understand why the initial results are all the 0. I thought maybe it just failed and they were still just initialized to the 0 default. But then I realized that after later in the code after using Arrays.sort(), the list prints correctly for all of the indexes 2,4,...,18,20.
What mistake am I making on the pre-sorted array print?
Your mistake is in how you are indexing into the array in the loop. You are assigning to array element (numArr.length)-i-1 but printing array element i. Try printing array element (numArr.length)-i-1 inside the loop to see the value you just assigned.
Let's say i=0, or the first loop.
numArr[(numArr.length)-i-1] = (i+1)*2;
Run that through, you get
numArr[9] = 2;
Yet, you print numArr[0], which is not yet assigned.
You'll start seeing values once you reach the midpoint of the array
If you are still confused, write out your algorithm on paper
You are trying to print the results even before they are populated in the array.
Here you are populating from behind but trying to print from front(Which are not yet given any value)
Wait for the array to get populated and loop through the array to get the proper result
Doing this should solve your problem,
for(int i = 0; i< numArr.length;++i)
{
numArr[(numArr.length)-i-1] = (i+1)*2;
}
for(int i = numArr.length-1; i>-1;i--)
{
System.out.println(numArr[i]);
}
You are trying to print indexes which has their default value (0) in it. Instead, try printing the indexes which you've already assigned a value into
for(int i = 0; i< numArr.length;++i)
{
numArr[i] = (i+1)*2;
System.out.println("numArr[i]" + numArr[i]);
}
or
for(int i = 0; i< numArr.length;++i)
{
numArr[(numArr.length)-i-1] = (i+1)*2;
System.out.println("numArr[i]" + numArr[(numArr.length)-i-1]);
}
As #Vinay pointed out when printing you are using i as subscript for array elements that didn't get populated yet. If you want to print array while populated you have to use the same index
int numArr[] = new int[10];
for(int i = 0; i< numArr.length;++i)
{
numArr[(numArr.length)-i-1] = (i+1)*2;
System.out.println("numArr[(numArr.length)-i-1]);
}
The easiest way is populate the array and then print the result with another loop:
Test:
public class Test
{
public static void main ( String [ ] args )
{
int numArr[] = new int[10];
for(int i = 0; i< numArr.length;++i)
{
numArr[(numArr.length)-i-1] = (i+1)*2;
}
for(int i = 0; i < numArr.length; i++)
{
System.out.println("numArr["+i+"]" + numArr[i]);
}
}
}
Output:
numArr[0]20
numArr[1]18
numArr[2]16
numArr[3]14
numArr[4]12
numArr[5]10
numArr[6]8
numArr[7]6
numArr[8]4
numArr[9]2
int numArr[] = new int[10];
for(int i = numArr.length-1; i >= 0; i--)
{
numArr[i] = (i+1)*2;
System.out.println("numArr["+i+"]" + numArr[i]);
}
Output:
numArr[9]20
numArr[8]18
numArr[7]16
numArr[6]14
numArr[5]12
numArr[4]10
numArr[3]8
numArr[2]6
numArr[1]4
numArr[0]2
Is this what you wanted to look like?
[Vote up if helped]

Java : Simple array with custom range of values (int)?

i have the following code;
int minValForRange = myDataObj.getMinValue();
int maxValForRange = myDataObj.getMaxValue();
String[] arrOfRangesForSelection = new String[maxValForRange];
Logger.d(String.valueOf(minValForRange));
Logger.d(String.valueOf(maxValForRange));
for (int i = minValForRange; i <= maxValForRange; i++) {
arrOfRangesForSelection[i] = String.valueOf(i);
}
minValForRange & maxValForRange are dynamic variables (in this case are 1 and 300) so it this case code above is throwing exception:
length=300; index=300
How to have an array which is indexed from minValueRange please?
Many thanks for any advice.
How to have an array which is indexed from minValueRange please?
You can't, in Java. Your best bet is just to do the math as necessary (but I mention a couple of alternatives below, which really just encapsulate it), e.g.:
int minValForRange = myDataObj.getMinValue();
int maxValForRange = myDataObj.getMaxValue();
String[] arrOfRangesForSelection = new String[maxValForRange - minValForRange + 1];
// Enough room for the range (inclusive) -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Logger.d(String.valueOf(minValForRange));
Logger.d(String.valueOf(maxValForRange));
for (int i = minValForRange; i <= maxValForRange; i++) {
arrOfRangesForSelection[i - minValForRange] = String.valueOf(i);
// The math ------------^^^^^^^^^^^^^^^^^^
}
(Note that in the above I'm assuming maxValForRange should be included, because that's how you wrote your loop, which is why we have + 1 in the line allocating the array.)
If you didn't want maxValForRange to be included (in programming, we usually include the lower bound but not the upper bound), you wouldn't have the + 1 on the array allocation and would use < rather than <= in the loop:
int minValForRange = myDataObj.getMinValue();
int maxValForRange = myDataObj.getMaxValue();
String[] arrOfRangesForSelection = new String[maxValForRange - minValForRange];
// No + 1 here --------------------------------------------------------------^
Logger.d(String.valueOf(minValForRange));
Logger.d(String.valueOf(maxValForRange));
for (int i = minValForRange; i < maxValForRange; i++) {
// Just < here ----------------^
arrOfRangesForSelection[i - minValForRange] = String.valueOf(i);
}
If you want, you can trivially write a class that will provide get and set methods which do the necessary math so you don't have to repeat it all over the code, and wrap your array in that class.
You can also do an ArrayList subclass that does the necessary math.
Access to array element is zero-based, so when you try to access maxValForRange, you have to have maxValForRange+1 size;
just use i < maxVal instead of i <= maxVal.
for (int i = minValForRange; i < maxValForRange; i++)
arrOfRangesForSelection[i] = String.valueOf(i);

Floyd Warshall Algorithm for Shortest Path

I was looking through some old contest questions, and I found this one, it looked fun, http://dwite.ca/old/Problem5Jan2006.pdf , I tried using the floyd warshall algorithm to get the shortest path from any node to any other node, can you guys see what I did wrong? it does not give the desired output set out on the contest question page
import java.io.*;
import java.util.*;
public class DistanceBetween {
public static void main(String[] args) throws FileNotFoundException {
Scanner s = new Scanner(new File("DATA5.txt"));
int n = Integer.parseInt(s.nextLine());
int[][] dist = new int[60][60];
for(int y=0;y<60;++y)for(int x=0;x<60;++x)dist[y][x]=10000000;
Map<Character, Integer> map = new TreeMap<Character, Integer>();
for (int i = 0; i < n; ++i) {
String text[] = s.nextLine().split(" ");
int c = 0;
if (!map.containsKey(text[0].charAt(0))) {
map.put(text[0].charAt(0), c);
c++;
}
if (!map.containsKey(text[0].charAt(1))) {
map.put(text[0].charAt(1), c);
c++;
}
dist[map.get(text[0].charAt(0))][map.get(text[0].charAt(1))] = Integer.parseInt(text[1]);
}
for (int k = 0; k < map.size(); ++k) {
for (int i = 0; i < map.size(); ++i) {
for (int j = 0; j < map.size(); ++j) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
for (int i = 0; i < 5; ++i) {
String text = s.nextLine();
System.out.println(dist[map.get(text.charAt(0))][map.get(text.charAt(1))]);
}
}}
There are several problems in your code:
Overwritten mapping
Your int c is local variable of the for cycle which means the highest used mapping index doesn't survive to the next iteration, so the reading in next iteration overrides the previous one. So the distance matrix is not properly filled after data loading.
Solution: move the int c = 0; outside from the for loop.
Unidirectional roads
The roads are bidirectional in the instructions, but you register them only as unidirectional. As the consequence of that are higher on non-existent connections between towns.
Solution: add dist[map.get(text[0].charAt(1))][map.get(text[0].charAt(0))] = Integer.parseInt(text[1]); right after the similar one.
Besides these hard issues I have also couple hints for you. You do not have follow them but as if you want to improve your programming skills then you should think about them.
Messy code
Your code is hard to read, there are multiple restated information such as indicies, the solving process is in the single method etc. Such code is not only hard to read but also extremely hard to debug and fix. For your own good I recommend you to write it cleaner.
Algorithm efficiency
Floyd-Warshall's algorithm has a O(n^3) complexity. The size of problem (amount of towns) is A-M = 13. In this complexity it makes 13^3 = 2197 iterations. I know, it might not seem to be a lot, but consider the amount of tasks to solve in a given time limit.
I would recommend you to use Dijkstra's algorithm which has complexity O(|E| + |V|log|V|). In this task the worst case with some simplification is |E| = (|V|^2)/2, |V|=13. It means, that the final number of iterations is 5 (|V|^2 / 2 + |V|log|V|) = 5 (13^2 / 2 + 13 * log13) ~ 5 * 132 = 660. If I am not wrong and made any mistake, this is significantly less, especially when we consider the total amount of tasks.
Input reading
I might be wrong but I attended multiple programming contests and competitions and it never forced attendees to work with files. An input was always redirected from files to a standard input. I guess, that the main reason for this is a security, but the simplification is probably also highly beneficial.
Well that question I got, I am starting to do SPOJ now, and I gotta admit it is pretty difficult later on, but I came across the same kind of question http://www.spoj.com/problems/SHPATH/ , I also used Floyd Warshall
import java.util.*;
public class Floydwarshall {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String q = s.nextLine();
for(int t=0;t<Integer.parseInt(q);++t){
int n = Integer.parseInt(s.nextLine());
int[][] cost = new int[n][n];
for (int y = 0; y < n; ++y) {
for (int x = 0; x < n; ++x) {
cost[x][y] = 10000;
}
}
Map<String, Integer> map = new TreeMap<String, Integer>();
int c = 0;
for (int i = 0; i < n; ++i) {
String a = s.nextLine();
if (!map.containsKey(a)) {
map.put(a, c);
c++;
}
int f = Integer.parseInt(s.nextLine());
for (int j = 0; j < f; ++j) {
String text[] = s.nextLine().split(" ");
cost[map.get(a)][Integer.parseInt(text[0]) - 1] =
cost[Integer.parseInt(text[0]) - 1][map.get(a)] = Integer.parseInt(text[1]);
}
}
for (int k = 0; k < map.size(); ++k) {
for (int i = 0; i < map.size(); ++i) {
for (int j = 0; j < map.size(); ++j) {
cost[i][j] = Math.min(cost[i][j], cost[i][k] + cost[k][j]);
}
}
}
int num = Integer.parseInt(s.nextLine());
for (int i = 0; i < num; ++i) {
String text[] = s.nextLine().split(" ");
System.out.println(cost[map.get(text[0])][map.get(text[1])]);
}
}
}}
now it runs alright for the sample input, but when I hand it in, it gives me this
NZEC (non-zero exit code) - this message means that the program exited returning a value different from 0 to the shell. For languages such as C, this probably means you forgot to add "return 0" at the end of the program. For interpreted languages (including JAVA) NZEC will usually mean that your program either crashed or raised an uncaught exception.
Problem is I cannot kind where it crashes or raises an uncaught exception since it
works with the sample input

How to increment the size of an array within a loop

I have this bubblesort code that i'm performing a runtime analysis on recording the time it takes to sort the array. I was wondering if there is any way i could increment the size of the array using a loop? Because at the moment i am incrementing it 100 at a time manually and i need to reach an array size of 5000.
public class BubbleSortworking{
public static void main (String[] args) {
Random rand = new Random();
int myArray[] = new int[100]; //How to increment this using a loop
int count, count2;
count2 = 2; //amount of times to run the loop
//repeats the bubble sort, while also producing new arrays each time
for (count = 0; count < count2; count++){
for (int i = 0; i < myArray.length; i++){
myArray[i] = rand.nextInt(100) + 1; //produce numbers between 1 - ?
//System.out.print(myArray[i] + ", "); //displays unsorted array
}
bubble(myArray);
// uncomment below 2 lines to prove each new sorted array cycle is unique
//for (int i = 0; i < myArray.length; i++)
// System.out.print(myArray[i] + ", ");
}
}
public static void bubble(int myArray[]){
int temp;
long start = System.nanoTime();
//System.out.println("start " + start);
//for (count = 0; count < count2; count++){
for (int i=0; i < myArray.length - 1; i++) {
for(int j=myArray.length - 1; j > i; j--) {
if (myArray[j] < myArray[j-1]){
temp = myArray[j];
myArray[j] = myArray[j-1];
myArray[j-1] = temp;
}
}
}
long end = System.nanoTime();
System.out.println(end - start);
//System.out.println("elapsed time " + (end - start));
}
}
No you can't change the size of an array once created. You either have to allocate it bigger than you think you'll need or accept the overhead of having to reallocate it needs to grow in size. When it does you'll have to allocate a new one and copy the data from the old to the new.
You either need to use an ArrayList, which will do this for you but with extra overheads.
Or, you can allocate the array as size 5000 before you start, and record up to how many elements you have used so far in a variable (rather than relying on array.length)
Or, you can resize the array by making a new array which is bigger and copying all the elements to it (System.arrayCopy(..)), as well as putting the new ones in.
The answer by rizon is correct, you cannot change the size of an array. BTW, nowhere are you re-creating the array, nor do I see where you are processing 5000 elements. If you are concerned about processing time, you would not want to recreate/resize an array, as that would be very inefficient. You would want a different solution.
This may help you
int[] intA = new int[100];
int sizeToIncrement = 100;
for(int i=0;i<5000;i++) {
if(i== intA.length ) {
intA = Arrays.copyOf(intA, intA.length + sizeToIncrement);
}
intA[i] = i;
}

Efficient methods for Incrementing and Decrementing in the same Loop

Suppose some situations exist where you would like to increment and decrement values in the same for loop. In this set of situations, there are some cases where you can "cheat" this by taking advantage of the nature of the situation -- for example, reversing a string.
Because of the nature of building strings, we don't really have to manipulate the iterate or add an additional counter:
public static void stringReversal(){
String str = "Banana";
String forwardStr = new String();
String backwardStr = new String();
for(int i = str.length()-1; i >= 0; i--){
forwardStr = str.charAt(i)+forwardStr;
backwardStr = backwardStr+str.charAt(i);
}
System.out.println("Forward String: "+forwardStr);
System.out.println("Backward String: "+backwardStr);
}
However, suppose a different case exists where we just want to print a decremented value, from the initial value to 0, and an incremented value, from 0 to the initial value.
public static void incrementAndDecrement(){
int counter = 0;
for(int i = 10; i >= 0; i--){
System.out.println(i);
System.out.println(counter);
counter++;
}
}
This works well enough, but having to create a second counter to increment seems messy. Are there any mathematical tricks or tricks involving the for loop that could be used that would make counter redundant?
Well it looks like you just want:
for(int i = 10; i >= 0; i--){
System.out.println(i);
System.out.println(10 - i);
}
Is that the case? Personally I'd normally write this as an increasing loop, as I find it easier to think about that:
for (int i = 0; i <= 10; i++) {
System.out.println(10 - i);
System.out.println(i);
}
Note that your string example is really inefficient, by the way - far more so than introducing an extra variable. Given that you know the lengths involved to start with, you can just start with two char[] of the right size, and populate the right index each time. Then create a string from each afterwards. Again, I'd do this with an increasing loop:
char[] forwardChars = new char[str.length()];
char[] reverseChars = new char[str.length()];
for (int i = 0; i < str.length(); i++) {
forwardChars[i] = str.charAt(i);
reverseChars[reverseChars.length - i - 1] = str.charAt(i);
}
String forwardString = new String(forwardChars);
String reverseString = new String(reverseChars);
(Of course forwardString will just be equal to str in this case anyway...)
You can have multiple variables and incrementers in a for loop.
for(int i = 10, j = 0; i >= 0; i--, j++) {
System.out.println(i);
System.out.println(j);
}

Categories