Can inner and outer loops interrupt and resume one after another? - java

I have an existing loop that draws the labels and textboxes in two horizontal lines (Line 1 as Label, Line 2 as textboxes). At that time, the loop was based on the definite requirement that there will not be more than 12 elements of each type. This was written using two loops (one loop representing a label, another as a text box):
Draw labels
for (int i = 2, i<hdrlabel.length; i++){
coldef.add(new ColDefType("",hdrLabel[i],"varchar",false,15,"HDR"+String.valueOf(i),1,i==2?"%-25s":"",6,"LABEL",true,""));
}
Draw Text Boxes
LinkedHashmap<String,String> row = dbVal.get(i)
for (int j = 1, i<hdrlabel.length-1; i++){
coldef.add(new ColDefType(j==1?row.get(hdrLabel[j]:"",row.get(hdrLabel[j+1],"decimal5",false,15,row.get(hdrLabel[0])+String.valueOf(j),i+2),j==1?"%-25s":"",6,"TXTFLD",true,""));
}
Now, as to take account of number of days, the number of elements (in hdrLabel.length-2) is now increased to a max of 31 for each component type. Due to spacing issues for mobile and tablet viewing, it was determined that it's best if we draw up to 12 elements per line. What I am looking for is that if the number of elements of each type is more than 12, it should be drawn like:
Line 1: Labels 1-12
Line 2: Text Box 1-12
Line 3: Labels 13-24
Line 4: Text Box 13-24
Line 5: Labels 25-31
Line 6: Text Box 25-31
If the number of elements is between 15 to 24, boxes and labels in lines 5 and 6 are not required to be drawn.
Is there any way to use only two loops where we pause one loop when either reaches the 12 / 24 element, run the other loop and then resume the former loop?
I could not find a much more leaner way to do this, as the closest I could get is to break it to several for loops, but it's definitely not efficient if given of the dynamic number of max elements:
Line 1 - (for i=2, i<14, i++) - break at 13
Line 2 - (for j=1, j<13,j++) - break at 12
Line 3 - (for i=14, i<26, i++) - break at 26
Line 4 - (for j=13, i<25, i++) - break at 25
Line 5 - (for i=26, i<hdrLabel.length, i++) - break at 31
Line 6 - (for j=25, i<hdrLabel.length-1, i++) - break at 31

Not sure if this is what you want since it used 3 loops, but at least it works (assuming you want loop 1 to always happen first)
int i_start = 2;
int j_start = 1;
int i_terminate = 32;
int j_terminate = 32;
int next_i, next_j;
while (true) {
next_i = Math.min(i_start + 12, i_terminate);
next_j = Math.min(j_start + 12, j_terminate);
for (int i = i_start; i < next_i; ++i) {
// do something
}
for (int j = j_start; j < next_j; ++j) {
// do something
}
i_start = next_i;
j_start = next_j;
if (i_start == i_terminate && j_start == j_terminate) {
break;
}
}

Related

How to construct a pyramid in Java

How do I construct a pyramid using a loop program, given a number of rows by a user's input? Such as
*
***
*****
*******
I've tried watching several videos and reading articles about the logic of this, but instructors were either not understandable or they skipped lines of reasoning.
I know every row increases by 2 stars, and I know that because every row has an odd number of stars I can define the number of stars in a row as 2n+1 where n is an integer. I noticed a 2 row triangle has a base of 3 stars, a 3 row triangle has a base of 5 stars, and so on. So for an nth row, the triangles base is n+(n-1), which is 2n-1. For example, r_5: base = 9 stars. The next thing I know my program needs to consider is spacing. I noticed, from the base, spacing increases by 2 every row until we have n-1 spaces on the first half and another n-1 spaces on the second half, in other words, spacing increases from the base until it is greater than or equal to 2b-2.
I think all that covers the gist a java program would need to know: the number of stars per row, the size of the base, and spacing.
But how do I translate all this in terms of a for while loop?
Method 1
Note that, if we denote current line number as "line" starting from 0, and total number of lines as "n",
Number of stars in each line = 2*line + 1
Number of leading (or trailing) spaces in each line = n - line - 1
We can simply generate the pyramid using this rule:
int n = 4;
for (int line = 0; line < n; line++) {
StringBuilder sb = new StringBuilder();
int starsToAppend = 2 * line + 1;
int spaceToAppend = n - line - 1;
while (spaceToAppend-- > 0) sb.append(" ");
while (starsToAppend-- > 0) sb.append("*");
System.out.println(sb.toString());
}
Method 2
You can also approach from the middle and expand. Note that there is a constant column of a star (*) in the middle, and on each side, only one star gets added in each line each time. And the rest are spaces.
int n = 4;
for(int line=0; line <n ; line++){
StringBuilder sb = new StringBuilder("*");
int spacesToAppendOnBothSides = n-line-1;
int starsToAppendOnBothSides = line;
for(int idx=0; idx<starsToAppendOnBothSides; idx++){
sb.insert(0, "*"); //appends to the beginning
sb.append("*"); //appends to the end
}
for(int idx=0; idx<spacesToAppendOnBothSides; idx++){
sb.insert(0, " ");
sb.append(" "); //NOTE: You may exclude this line to avoid adding trailing spaces
}
System.out.println(sb.toString());
}
Explanation:
On first iteration (line == 0) we take a single star,
*
and add zero extra stars (as our line# is zero) on both sides, which gives us (same string):
*
And then add n-line-1 (we substract 1 because we already added 1 character - the first star) = 3 spaces on each side of that star, which gives us:
...*...
On 2nd iteration (line == 1) if we apply same logic:
1.
*
***
^ This middle one is the first star
..***..
Pretty simple once you understand the logic.
There are multiple ways to do this, but these are among the simplest ones :)
Say you need to print a pyramid of n rows. You can see that row i (where i is between 1 and n) will start with n-i spaces and have (i-1)*2+1 asterisks:
for (int i = 1; i <= n; ++i) {
int spaces = n-i;
int stars = (i-1)*2+1;
for (int j = 1; j <= spaces; ++j) {
System.out.print(' ');
}
for (int j = 1; j <= stars; ++j) {
System.out.print('*');
}
System.out.println();
}
Here's my implementation -
public static String repeat(String str, int times) {
return new String(new char[times]).replace("\0", str);
}
public void createPyramid(int size) {
for (int i = 1; i <= size; i += 2) {
int numSpaces = (size - i) / 2;
System.out.println(repeat(" ", numSpaces) + repeat("*", i) + repeat(" ", numSpaces));
}
}
Call the method as - createPyramid(7); should give you the desired output. You can increase the size for bigger pyramid.
The variable i iterate for the size of the pyramid. And the number of stars on each row is increasing by 2 starting from 0. There i is incrementing by 2. The blank spaces will be equal to size - number of *'s but they have to be repeated before and after the *'s symmetrically, we divide it by 2. This will give the number of spaces before and after the *'s and in the middle we just need to print the *'s whose number is given by i.
So, we finally print them.
The repeat function creates a String formed from the str parameter repeated times times. eg - if we call repeat("abc", 3), it will return "abcabcabc".

How to avoid Array Out of Bound Exception in Java

I am trying to write code in Java (part of mapreduce job) to check a sentence for certain keywords, when any keyword found in the sentence, it should check the sentence up to 2 words before the keyword and/or up to 3 words after. if it finds a match it outputs something.
I am writing a code to iterate through 3 ArrayLists of Strings as follows:
1- iterate through Arraylist1<String) and check if ArrayList1.get(i)= ArrayList2.get(j). if equals, proceed to 2 (below), otherwise i++.
2- Iterate through ArraList3. Check up to 2 words before ArraList1[i] and up to 3 words after ArrayList1[i]. If in this range it finds a match within ArrayList3, it should output something.
Now the problem lies with implementing the conditions of 2 words before and 3 words after. Because it needs to consider a lot of conditions depending on the size of the sentence (i.e. size of ArrayList1).
Example: if you are at 1st or 2nd word of the sentence,you need to check 3 words after only And 1 word before and 3 words after (also depending on the size of the sentence).
for (int i = 0; i < tokensList.size(); i++) {
keywordsListLoop:
for (int j = 0; j < keywordsList.size(); j++) {
if (tokensList.get(i).startsWith(keywordsList.get(j)) == true)
for (int e = i - 2; e < i + 4; e++) {
boolean flag = false;
// I think the rules need to go here
for (int g = 0; g < posWordsList.size(); g++) {
// or perhaps here :s
if (tokensList.get(e).compareTo(posWordsList.get(g)) == 0) {
word.set(keywordsList.get(j));
context.write(word, one);
flag = true;
break; //breaks out of Inner loop (PosWords loop)
}
}
if (flag)
break; //breaks out of outter loop ( e loop)
break keywordsListLoop; //need to make sure this actually breaks out of keywords loop
}
}
//now check next token
The most important thing - structure your code, having 4 nested loops is insane. Try to write some function with some nice description of what they are doing and dont have more than 2 loops inside each other.
To your question, you have this if (tokensList.get(e), while e is set as int e = i - 2 and because i initially starts as int i = 0, then you can check the -2 or -1. Same goes for upper bound, you have e < i + 4 which is +4 more than is your list size.

Adding each column in a 2D array which become values of the last row

I'm trying to add all of the values for each column in a 2D array and these sums become values that overwrite the last row of the array
for example:
4 5 6 7 8
1 2 3 4 5
0 0 0 0 0 //this row will be replaced by the sum of each column
4 5 6 7 8
1 2 3 4 5
5 7 9 11 13
public static void fillTotals(int[][] scores)
{
int count = 0;
for (int r = 0; r < scores.length - 1; r++)
{
scores[r][0] += count;
scores[scores.length - 1][scores[0].length - 1] = count;
}
}
I thought I could keep the columns the same and add it down with the changing rows but it isn't rewriting the last row. Also I don't know how to change the values at the bottom
You need to iterate once over all rows and columns, actually iterate over all rows, for every column. If you assume that the number of columns is the same for every row, then you can use scores[0].length as a fixed value.
public static void fillTotals(int[][] scores) {
for (int c=0; c < scores[0].length; ++c) {
int sum = 0;
for (int r=0; r < scores.length - 1; ++r) {
sum += scores[r][c];
}
scores[scores.length - 1][c] = sum;
}
}
This assumes that the final row of the 2D array is not part of the sum and is available to be overwritten with the sum of all preceding values, for each column.
Well, the reason that nothing is being updated is that you never change count, so you just end up adding 0 to everything. I think what you want instead of:
scores[r][0] += count;
is:
count += scores[r][0];
That way count will contain the summation of every element in the first column.
To be clear, scores[r][0] += count; is the same as scores[r][0] = scores[r][0] + count;, whereas I think you probably want count = scores[r][0] + count;
That being said, Im still pretty sure this code isnt actually going to work (sorry), since you only ever actually sum values from the first column. However, for the sake of not just doing way may be a school assignment for you, Im just going to leave it there. If you're still stuck let me know, and I'll try to help!

Matrix Multiplication Java

I need help, I am trying to make use of Lattice Multiplication in java for use in a BigInt class I am having to write for a class.
Right now I have the code storing the digits needed for the adding part of the algorithm in a 2 dimensional array. From there though I am at a lose as to how to make a loop to go through the array and add the numbers in what would be a diagonal.
For instance here is the test numbers etc:
200
*311
= 62200
The array is holding:
6 0 0
2 0 0
2 0 0
6 is (2,2) in the array and the bottom right is (0,0)
I need to add in a diagonal, such as (1,0) + (0,1) = 0
The issue is how do I do this, since not only is it moving up and left in different ways, but it goes from 1 element to 2 elements to 3 elements, then back the other way, and of course this will get bigger the longer the number is.
This is the code that I have:
public int multiply(BigInt val){
int[] bigger;
int[] smaller;
int[] dStore;
int lengthMax = (val.getSize()+this.getSize()) - 1;
int first = 0;
int second = 0;
int[][] tempResult;
//Checks to see which is bigger and then adds that to bigger
if(val.getSize() >= this.getSize()){
bigger = val.getData();
smaller = this.getData();
dStore = new int[val.getSize()+this.getSize()];
}else{
bigger = this.getData();
smaller = val.getData();
dStore = new int[val.getSize()+this.getSize()];
}
tempResult = new int[smaller.length][bigger.length];
for(int i=0;i < smaller.length;i++){
for(int j = 0;j < bigger.length;j++){
tempResult[i][j] = smaller[i] * bigger[j];
}
}
** there is the return statement etc below
This might help as to explain lattice multi better: Lattice Multi Video
I would try a different approach. Look at the lattice in the video and imagine that you rotates the array a little bit to the left so that the diagonals becomes vertical. The array would then look like this:
2 3 5
8 3
2 4 0
Now, just summarize the columns and you would have the total.
You would of course have to split the numbers into arrays of digits first. The easiest way to do that (but not the most efficient) is to convert them into strings ...
Good luck!
To move diagonally, you'd increment both x and y:
// Loop though the diagonal of an array
x = 0;
y = 0;
while (x < ARR_X_SIZE && y < ARR_Y_SIZE) {
// Do something with arr[x][y]
x++;
y++;
}
This is the basic loop; you can change the x and y increments to determine the direction you need to go. The key to going through the whole array is the value of the coordinates going into the loop. Array:
1 2 3
4 5 6
7 8 9
If you set x = 1; y=0 at the beginning of the loop, you'll get 2 6. Set x = 0, y = 1 and you'll get 4 8.
I hope this helps you with your assignment. Good luck on the rest! That is definately an interesting algorithm to implement.

beginner's question: copying certain elements of an array

I am trying to copy certain elements of an array into another. For example, I want to copy index 0 of lines into index 0 of links, index 3 of lines into index 1 of links, and so on (every 3 element of lines basically basically).
What I have so far keeps getting me an ArrayIndexOutOfBound error. Thank you for your help!
String[] lines = inputString.split(System.getProperty("line.separator"));
String[] links = new String[lines.length];
int j = 0;
for (int i = 0; i < lines.length; i++) {
links[i] = lines[j+3];
j++;
System.out.println(links[i]);
}
It sounds like you need to be incrementing i by 3, rather than adding 3 to j (but then incrementing j by just 1). In fact, you don't need two variables at all:
for (int i = 0; i < lines.length; i += 3) {
links[i / 3] = lines[i];
}
You should also change your code to only create the array to be as large as you need:
String[] links = new String[lines.length / 3];
Just for the sake of interest, let's have a look at what your code was actually trying to do, in terms of assignments:
links[0] = lines[3];
links[1] = lines[4];
links[2] = lines[5];
// etc
As you can see, this is just offsetting the index, rather than multiplying it... and as soon as i was lines.length-3, you'd end up with
links[lines.length - 3] = lines[lines.length]; // Bang!
A few problems:
1.
You probably want this:
for (int i = 0; i < lines.length; i++) {
links[i] = lines[j+3];
To look like this:
for (int i = 0; i < links.length; i++) {
links[i] = lines[j * 3];
2.
Well, yes. You are going out of bounds. Let's say lines is 12 elements. links is the same size, so you're trying to read from element 15 / 36 (depending on my correction in #1)
The solution is to make links smaller:
String[] links = new String[(int)(lines.length / 3)];
Along with the correction in #1.
Jon Skeet has the right idea. What might be useful is to learn how to debug these things yourself. Say that lines.length is 5, meaning also that links.length is 5. What happens if you trace every iteration of the for loop?
i | j | j + 3
-----------------------------------------
0 0 3
1 1 4
2 2 5
It'll break on this 3rd iteration. You can see that you're not accessing every three elements at all, but every element, and you're storing it in an offset position, which causes your index out of bounds exception.

Categories

Resources