Efficient loop code? Also, a query about the "for each" loop - java

The following code compiles and does what I require. It iterates through an int-based multidimensional array (called nums), and searches for all occurances of the value 1. This program's output is shown below. There are three things to note:
Regarding the "outer for" loop statement, I have used Java's comma operator to declare two additional variables.
Also regarding this "outer for", I've used another comma operator in the "iteration section", to reset one of these additional variables.
Regarding the "inner for", I've used another comma operator in the "iteration section" to increment this additional variable.
int[][] nums = {{1,1,2},{3,4},{5},{6,7,8},{9,1,1}};
for (int i=0, elsSearched=0, foundCount=0; i < nums.length; i++, elsSearched=0) {
for (int j=0; j < nums[i].length; j++, elsSearched++) {
if (nums[i][j] == 1) {
foundCount++;
}
}
System.out.println("Searched " + elsSearched +
" elements, and found \'number one\' a total of " + foundCount + " times..");
}
Program output:
Could this code be written more effeciently/elegantly?
My other query is about Java's "for each" loop. I tried rewritting the code above using the "for each" loop with the comma operator, but the code wouldn't compile. I quickly came to the obvious conclusion, but would the "for each" loop be better if the comma operator could be used with it, or would that just introduce "distracting clutter"?

Edit: Be aware that foundCount is the total number of elements found up until now, as it is never reset to zero. Was this intended?
Don't you agree that this code is easier to read and more concise? (Note: efficiency is the same as your code)
int[][] nums = {{1,1,2},{3,4},{5},{6,7,8},{9,1,1}};
int foundCount = 0;
for(int[] inner : nums){
for(int i : inner){
if (i == 1){
foundCount++;
}
}
System.out.println("Searched " + inner.length +
" elements, and found \'number one\' a total of " + foundCount + " times..");
}
Output:
Searched 3 elements, and found 'number one' a total of 2 times..
Searched 2 elements, and found 'number one' a total of 2 times..
Searched 1 elements, and found 'number one' a total of 2 times..
Searched 3 elements, and found 'number one' a total of 2 times..
Searched 3 elements, and found 'number one' a total of 4 times..

First, you probably shouldn't optimize something until you've proven it's a significant contributor to your program runtime. That being said, why not try this instead...
int foundCount = 0;
int totalCount = 0;
for (final int[] i : nums) { // foreach int[] in nums
for (final int v : i) { // foreach value v in the int[] from nums
switch (v) { // switch on a constant int...
case 1: // The value we seek.
++foundCount; // Add to the foundCount, and fall through!
default:
++totalCount;
}
}
}
System.out.println("Searched a total of " + totalCount +
" elements and found '#1' a total of " + foundCount);

If you have performance issues you can try to use binary search (if your array is always sorted) on the sub arrays.
int valueToSearch = 1;
for(int[] inner : nums){
int foundIndex = Arrays.binarySearch(inner, valueToSearch);
if (foundIndex >= 0){
foundCount ++;
}
}
So you will get a performance of O(n * log(n) ) instead of O(n^2).
I guess you have to do some benchmarks. But the most important thing is to know how your input looks like. Than you can find the best algorithm for it.

Related

How to substract a list of numbers from another list of numbers until 0 in java

I have 2 lists of numbers. I need to subtract the second list from the first in a way that shows the balance until the first list equals 0.
For example
List A = [10,9]
List B - [1,2,3,4,5,4]
I need to show
10-1=9
9-2=7
7-3=4
4-4=0
9-5=4
4-4=0
I tried
for (int a : List A){
do {
for (int b : List B){
a = -b
}
} while (a >= 0)
}
I don't think the logic is sound enough and could use a few pointers.
You can make your logic more simpler with early breaks if a becomes 0 before subtracting from all elements in B. Also, it looks like you wish to subtract them in a circular manner until a becomes 0.
Snippet:
for(int a : A){
int ptr = 0;
while(a > 0){
System.out.println(a + " - " + B.get(ptr) + " = " + (a - B.get(ptr)));
a -= B.get(ptr);
ptr = (ptr + 1) % B.size();
}
}
Online Demo
Note: Not every element subtraction leads to the beautiful 0, but that is how your array is kept in the first place.
Also, there is no other optimized way looking at your current requirements since you will have to loop through each one and show the subtraction steps.

How to print a number pattern

So I got this task to do :
(Display patterns) Write a method to display a pattern as follows:
The method header is:
public static void displayPattern(int n)
Basically , I understood "HOW" to do the excerice, and even coded it on my own and got 99% of the code right.
I know that I need to do 2 loops, one that prints the whitespaces and each time declines by 1 and the other that prints the number after the whitespace and inclines by 1.
Here is my method:
public static void printPattern(int n) {
int m =1;
int k=1;
while (m-1-1 <=n) {
int numberOfWhiteSpaces = n -1;
for (int i = numberOfWhiteSpaces; i >= 0; i--) {
System.out.print(" ");
}
for (k=m; k>0; k--) {
System.out.print( k + "");
}
System.out.println();
m++;
n--;
}
}
Let's say i call
printPattern(3);
My only problem that the output is like this :
1
21
321
No white spaces between the numbers, and yes, I tried to change this:
System.out.print( k + "");
to this:
System.out.print( k + " ");
The result? :
I have been on this problem for 2 hours straight, couldn't get it right.
Might use some help, thanks guys.
This happens because you did not count the number of spaces correctly: your code assumes that you need one space in the prefix portion of the string for each number that you print. However, when you switch to k + " ", prefix would require two spaces, not one, per number printed (assuming single-digit numbers). Therefore, when you switch to k + " " in the second loop, you need to also switch to System.out.print(" "); (two space) in the first loop.
This will fix the problem for single-digit numbers. Generalizing to multi-digit numbers would require more work: you would need to count the number of digits on the last line, then count the number of digits on the current line, and print the required number of prefix spaces to compensate for the difference.

array index not incrementing (need to do casting in square brackets)

I have some doubts as to why the value of index is not incrementing here.
The reason why I have declared my array like that is because I need to store n natural numbers where (1 ≤ n ≤ 1012), so numbers are large which is why I have taken an array of type long, but then I get an error that I cannot put any long value in the group, which is why I cast it to int. Is there any way to declare an array for this type of condition, as I want a large number of indexes, and I can not put a long number in the [ ].
hope you guys understand my problem
CODE:
import java.util.Scanner;
class Error{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long array[] = new long[(int) n];
long index = 0;
for (int j = 1; j <= n; j++) {
if (j % 2 != 0) {//odd
array[(int) index++] = j;
System.out.print(" " + array[(int) --index]);
System.out.print(index);// index value -> always 0 why??
System.out.print(j);
}
}
System.out.println();
}
}
OUTPUT:
Unix-Box ~/Desktop$ javac Error.java
Unix-Box ~/Desktop$ java Error
10
101 303 505 707 909
Unix-Box ~/Desktop$
the middle value is of index and it is always 0
what i shout it to be like
10
101 313 525 737 949
Unix-Box ~/Desktop$
According to
https://www.quora.com/What-is-the-maximum-size-of-the-array-in-Java,
the max size of an array is 2147483647 theoretically, but in practice we would want to use 2147483600 to be safe. Declaring the array as type long will mean that long values can be stored inside. Maybe you can use a two dimensional array to store a long n amount of values. Something like--
public static void main(String[] args)
{
System.out.println("enter the size of the array:");
Scanner in = new Scanner(System.in);
long n = Long.parseLong(in.nextLine());
int secondIndex = 2147483600;
int firstIndex = ((int)(n/secondIndex))+1;
if(secondIndex > n)
{secondIndex = (int)n;
}
else{int leftover = (int)(n%secondIndex);
secondIndex = secondIndex - leftover;}
long[][] array = new long[firstIndex][secondIndex];
//loop through array
outerloop:
for(int i =0;i <firstIndex; i++)
{
for(int z = 0; z<secondIndex; z++)
{
System.out.println("do work with number here: " + array[i][z]);
if(z==(secondIndex-1))
{
z=0;
continue outerloop;
}
}
}
}
You might get a java.lang.OutOfMemoryError:, which can be resolved by reading this article https://plumbr.eu/outofmemoryerror/java-heap-space.
As others have indicated,
array[(int) index++] = j; // You use index and then increment it
System.out.print(" " + array[(int) --index]); // You decrement the index here
That's why index will always be 0 when you print it.
Personally, I don't like mixing brackets with increment operators for the precise reason you're seeing here - it tends to be confusing and it lends itself to subtle (and not-so-subtle) bugs and off-by-one errors. In fact, I really don't like mixing them with any other syntax (with the exception of for loops) as it can quickly become very unclear. For example, if you had done something like
index++;
array[(int)index] = j;
index--;
System.out.print(" " + array[(int)index]);
the problem would've been obvious immediately.
In general, it's a bad idea to sacrifice clarity for brevity.
Also, just to review how the operators in question are working:
index++ - use the value and then increment it
index-- - use the value and then decrement it
++index - increment the value and then use it
--index - decrement the value and then use it.
Here's a C# code sample I put together (Java's behavior will be identical) to illustrate this:
int i = 0;
Trace.TraceInformation((i++).ToString()); // Prints 0
Trace.TraceInformation(i.ToString()); // Prints 1
Trace.TraceInformation((--i).ToString()); // Prints 0
Trace.TraceInformation((i--).ToString()); // Prints 0
Trace.TraceInformation(i.ToString()); // Prints -1
I'd encourage you to trace/step through this to convince yourself that that's the case and to understand exactly why the value is what it is at every point.
Either way, this syntax can be very confusing if overused.

primitive list's don't seem to match even when values/order are the same? Is it possible?

I have a list of ints[] that I list one at a time. I found an intresting pattern that the results seem to reverse so to test it I reversed the list that came into my method and then displayed them, and found they matched. I want to programmatically find them but when I print the list itself as a string the results don't match even if the items/order match.
Here's the method(it simply gets data in, reverses the order and prints both..nothing fancy):
private static void show (int [] arr) {
//before we print results lets reverse the list and study if there's something we can do to make this go faster
int[] ReversedList = new int[arr.length];
for (int x = arr.length-1, y=0; x>=0;x--, y++) {
ReversedList[y] = arr[x];
}
for (int x = 0; x < arr.length; x++) {
//System.out.print (" " + (arr [x] + low[x]));
System.out.print (" " + (arr[x]));
}
System.out.println (" " + arr.toString());
for (int x = 0; x < ReversedList.length; x++) {
//System.out.print (" " + (arr [x] + low[x]));
System.out.print (" " + (ReversedList[x]));
}
System.out.println (" " + ReversedList.toString() + " ***");
//System.out.println("*****************");
}
but the strings don't match. Here's a snippet of the output( * means it been reversed):
0 0 0 20 [I#199a0c7c
20 0 0 0 [I#50a9ae05 ***
....
20 0 0 0 [I#1e9af0b1
0 0 0 20 [I#4e300429 ***
They all are like this and I'm unsure why they don't match when they are the same(at least look the same). I have a arraylist called results that has all the int[] and I tried to do a results.indexof(reversed) but no luck(I get '-1' for everything). How can I find matches?
You are looking at the addresses for the int arrays you have. The data is the same, but the data is stored in multiple locations because you are using multiple instances.
To compare arrays, use Arrays.equals(int[], int[]). Alternatively, you can view the information in the arrays in a better format with Arrays.toString(int[]).
Those are all object addresses. They refer to different integer arrays, so they wouldn't match up.
Use the java.util.Arrays.toString(int[]) method instead to visually see the contents of an array:
import java.util.Arrays;
// ... code
System.out.println (" " + Arrays.toString(arr));
What is getting printed is the HASHCODE. It is like both are separate objects and are stored separately on the heap memory. HashCode is nothing but unique number allocated to each object by the JVM. I hope this is what you are looking for.

Help with understanding java 'for' loops

I have to write a java program where the solution will include the printing of the arrow tip figure depending on the number of rows. Below are example of how the result should look. However, I cannot do this until I understand for loops. I know I have to work with the rows and columns and possibly nested loops. I just dont know how to connect the row with the columns using for loops. Please help me in understanding these loops. Thanks!
Example #1 (odd number of rows)
>
>>>
>>>>>
>>>>>>>
>>>>>
>>>
>
Example #2 (even number of rows)
>
>>>
>>>>>
>>>>>>>
>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>
>>>
>
a for loop will loop through a collection of data, such as an array. The classic for loop looks like this:
for(counter=0;counter <= iterations;counter++){ }
the first param is a counter variable. the second param expresses how long the loop should last, and the 3rd param expresses how much the counter should be incremented by after each pass.
if we want to loop from 1 - 10, we do the following:
for(counter=1;counter<=10;counter++){ System.out.println(counter); }
if we want to loop from 10 - 1, we do the following:
for(counter=10;counter>=1;counter--){ System.out.println(counter); }
if we want to loop through a 2 dimensional collection, like...
1 2 3
4 5 6
7 8 9
int[][] grid = new int[][] {{1,2,3},{4,5,6},{7,8,9}};
we need 2 loops. The outer loop will run through all the rows, and the inner loop will run through all the columns.
you are going to need 2 loops, one to iterate through the rows, one to iterate through the columns.
for(i=0;i<grid.length;i++){
//this will loop through all rows...
for(j=0;j<grid[i].length;j++){
//will go through all the columns in the first row, then all the cols in the 2nd row,etc
System.out.println('row ' + i + '-' + 'column' + j + ':' + grid[i][j]);
}
}
In the outer loop, we set a counter to 0 for the first parameter. for the second, to calculate how many times we will loop, we use the length of the array, which will be 3, and for the third param, we increment by one. we can use the counter, i, to reference where we are inside the loop.
We then determine the length of the specific row by using grid[i].length. This will calculate the length of each row as they are being looped through.
Please feel free to ask any questions you may have regarding for loops!
EDIT: understanding the question.....
You are going to have to do several things with your code. Here we will store the number of lines in a variable, speak up if you need to pass in this value to a method.
int lines = 10; //the number of lines
String carat = ">";
for(i=1;i<=lines;i++){
System.out.println(carat + "\n"); // last part for a newline
carat = carat + ">>";
}
The above will print out carats going all the way up. We print out the carat variable then we make the carat variable 2 carats longer.
.... the next thing to do is to implement something that will decide when to decrease the carats, or we can go up half of them and down the other half.
Edit 3:
Class Test {
public static void main(String[] args) {
int lines = 7;
int half = lines/2;
boolean even = false;
String carat = ">";
int i;
if(lines%2==0){even = true;} //if it is an even number, remainder will be 0
for(i=1;i<=lines;i++){
System.out.println(carat + "\n");
if(i==half && even){System.out.println(carat+"\n");} // print the line again if this is the middle number and the number of lines is even
if(((i>=half && even) || (i>=half+1)) && i!=lines){ // in english : if the number is even and equal to or over halfway, or if it is one more than halfway (for odd lined output), and this is not the last time through the loop, then lop 2 characters off the end of the string
carat = carat.substring(0,carat.length()-2);
}else{
carat = carat + ">>"; //otherwise, going up
}
}
}
}
Explanation and commentary along shortly. Apologies if this is over complicated (i'm pretty sure this is not even close to the best way to solve this problem).
Thinking about the problem, we have a hump that appears halfway for even numbers, and halfway rounded up for the odd numbers.
At the hump, if it is even, we have to repeat the string.
We have to then start taking off "<<" each time, since we are going down.
Please ask if you have questions.
I had the same question for a homework assignment and eventually came to a correct answer using a lot of nested if loops through a single for loop.
There is a lot of commenting throughout the code that you can follow along to explain the logic.
class ArrowTip {
public void printFigure(int n) { //The user will be asked to pass an integer that will determine the length of the ArrowTip
int half = n/2; //This integer will determine when the loop will "decrement" or "increment" the carats to String str to create the ArrowTip
String str = ">"; //The String to be printed that will ultimately create the ArrowTip
int endInd; //This integer will be used to create the new String str by creating an Ending Index(endInd) that will be subtracted by 2, deleting the 2 carats we will being adding in the top half of the ArrowTip
for(int i = 1; i <= n; i++) { //Print this length (rows)
System.out.print(str + "\n"); //The first carat to be printed, then any following carats.
if (n%2==0) { //If n is even, then these loops will continue to loop as long as i is less than n.
if(i <= half) { //This is for the top half of the ArrowTip. It will continue to add carats to the first carat
str = str + ">>"; //It will continue to add two carats to the string until i is greater than n.
}
endInd = str.length()-2; //To keep track of the End Index to create the substring that we want to create. Ultimately will determine how long the bottom of the ArrowTip to decrement and whether the next if statement will be called.
if((endInd >= 0) && (i >= half)){ //Now, decrement the str while j is greater than half
str = str.substring(0, endInd); //A new string will be created once i is greater than half. this method creates the bottom half of the ArrowTip
}
}
else { //If integer n is odd, this else statement will be called.
if(i < half+1) { //Since half is a double and the integer type takes the assumption of the one value, ignoring the decimal values, we need to make sure that the ArrowTip will stick to the figure we want by adding one. 3.5 -> 3 and we want 4 -> 3+1 = 4
str = str + ">>"; //So long as we are still in the top half of the ArrowTip, we will continue to add two carats to the String str that will later be printed.
}
endInd = str.length()-2; //Serves the same purpose as the above if-loop when n is even.
if((endInd >= 0) && (i > half)) { //This will create the bottom half of the ArrowTip by decrementing the carats.
str = str.substring(0, endInd); //This will be the new string that will be printed for the bottom half of the ArrowTip, which is being decremented by two carats each time.
}
}
}
}
}
Again, this was for a homework assignment. Happy coding.
Here is a simple answer for you hope it helps! Cheers Logan.
public class Loop {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
int count = i;
int j = 0;
while (j != count) {
System.out.print(">");
j++;
}
System.out.println();
}
for (int i = 10; i > 0; i--) {
int count = i;
int j = 0;
while (j != count) {
System.out.print(">");
j++;
}
System.out.println();
}
}
}
For making a 'for' loop:
public class Int {
public static void main(String[] args) {
for (Long num = 1000000L; num >= 9; num++) {
System.out.print("Number: " + num + " ");
}
}
}
Output:
Number: 1008304 Number: 1008305 Number: 1008306 Number: 1008307 ...

Categories

Resources