What I have done here is taken the contents of the table below and stored them in a list called tableElems
0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35
List<WebElement> tableElems = chrome.findElements(By.tagName("td"));
From this table I want to print in a pattern starting at the 4th element (#3 in the table) and I want to print 3 elements, then skip the next 6, print the next 3 and then skip the next 6, etc. etc.
So my expected output would be 3 4 5 12 13 14 21 22 23 30 31 32
My initial attempt ended with
for (int i = 3; i<tableElems.size(); i++) {
if(i % 3 == 0) { System.out.println(tableElems.get(i).getText()); }
else if(i % 4 == 0) { System.out.println(tableElems.get(i).getText()); }
else if(i % 5 == 0) { System.out.println(tableElems.get(i).getText()); }
}
Obviously this is wrong, because my % 3 will print the 9th element, % 4 will print the 16th element, etc.
I am having trouble wrapping my head around this, so any advice to point me in the right direction is appreciated!
try this:
for (int i = 3; i<tableElems.size(); i++) {
if (((i / 3) % 3) == 1) { System.out.println(tableElems.get(i).getText()); }
}
Think about this as dividing into groups of nine, and further dividing each group of 9 into groups of 3. on the second group of 3 (i.e. 3-5, 12-14) it will display.
int offset = 4;
int width = 3;
advice:
for each row in table check offset + width is under the row width, and then start from offset + 0, offset + 1 upto offset + width
and continue this loop for all the row of table
You mentioned that tableElems is a list, so I assume it's akin to a single-dimension array, rather than what appears to be a multi-dimensional table like you've laid out(I assume for visual purposes).
You're right by starting the for loop at i = 3. The easiest way, IMO, to do this is to just bump the loop ahead several spaces in the array after you've printed three elements. Here's my solution using C# and an array; you should be able to convert it to Java pretty easily.
int counter = 0;
for (int i = 3; i < array.Length; i++)
{
if (counter < 3)
{
Console.WriteLine(array[i]);
counter++;
}
else
{
i += 5; // we are incrementing by one on the next pass, so this can be 5
counter = 0;
}
}
If you want to stick to %, then this should work
int rowSize = 9;
for (int i = 0; i < tableElems.size(); i++) {
int column = i % rowSize;
if (column >=3 && column <= 5) {
System.out.println(tableElems.get(i).getText());
}
}
Update: Java code
for (int i = 3; i<tableElems.size(); i += 9) {
System.out.println(tableElems.get(i).getText());
System.out.println(tableElems.get(i+1).getText());
System.out.println(tableElems.get(i+2).getText());
System.out.println(tableElems.get(i+3).getText());
}
If you are creating a larger pattern:
int starting = 3;
int nextStartDistance = 9;
int waveCount = 3;
for (int i = starting; i<tableElems.size(); i += nextStartDistance) {
for (int b = 0; b <= waveCount; b ++) {
System.out.println(tableElems.get(i).getText());
}
}
This code is written in JavaScript, but the algorithm considered:
var list =[
0,1,2,3,4,5,6,7,8,
9,10,11,12,13,14,15,16,17,
18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35];
for (var index = 3; index <= list.length; index +=9 ) {
var a = list[index];
var b = list[index+1];
var c = list[index+2];
var d = list[index+3];
console.log(a,b,c,d);
}
Result will be what you expected:
// 3 4 5 6
// 12 13 14 15
// 21 22 23 24
// 30 31 32 33
// user:~$
for (int i = 3; i < tableElems.size(); i += 9) {
for (int j = i; j < i + 3 && j < tableElems.size(); j++) {
System.out.println(tableElems.get(j).getText());
}
}
i think this would be very close to your code:
for (int i = 3; i < tableElems.size(); i++) {
if (i % 3 == 0) {
System.out.println(tableElems.get(i).getText());
} else if ((i % 3) == 1) {
System.out.println(tableElems.get(i).getText());
} else if ((i % 3) == 2) {
System.out.println(tableElems.get(i).getText());
i = i + 6;
}
}
i just adapted your modulo and skip 6 elements every time i hit the last one to print out
furthermore its quite effective because all unneeded elements are just skipped instead of iterated and checked
Assuming you only care about the values out of your table and the html structure is standard html tags as shown on your questions, then you can use css selector to select appropriate values.
chrome.findElements(By.cssSelector("td:nth-child(4),td:nth-child(5), td:nth-child(6)"))
Please note that css nth-child selector is 1 based.
Related
i'm just started to learn java yesterday. But, now i met difficulty to show the arithmetic progression like the display below:
1 2 2 2 3 3 3 3 3 4 4 4 4 4 4 4
From that example, i know that every odd numbers, the numbers increment. I've tried to make it, but the display just keep showing like this:
2 4 4 4 6 6 6 6 6 8 8 8 8 8 8 8 10 10 10 10 10 10 10 10 10
Here's my code:
for (int i = 0; i <= 10; i++) {
if (i % 2 == 0) {
for(int j = 1; j<i; j++){
System.out.print(i + " ");
}
}
}
And then, i want to take the last value of it. For example, if i have row = 3, it must be value = 2.
because :
row = 1 2 3 4 5 6 7 8 9 10
value = 1 2 2 2 3 3 3 3 3 4
Would you tell me, what line is exactly must be fix? Thank you
It's not about a line that is wrong, it's your approach that's a bit off. You could fix it in multiple ways. Easiest (but not most efficient) way is this:
for (int i = 0; i <= 10; i++) {
if (i % 2 == 0) {
for(int j = 1; j<i; j++){
System.out.print((i/2) + " ");
}
}
}
As you can see, only the output was changed and now it works. However, iterating over 11 numbers (0-10) when you only really care about 4-5 is not necessarily the best way to go here.
It also doesn't make your code easy to understand.
Here's an alternative.
int amount = 1;
for (int i = 1; i <= 5; i++) {
for (int j = 0; j < amount; j++) {
System.out.print(i + " ");
}
amount = amount + 2;
}
Here you can see that the outer for has been changed to only take the numbers we actually care about, which means we can remove the if completely.
We just have to somehow decide how many times we want to execute the print call, which is done with the amount variable.
Try this.
for (int i = 1, r = 1; i <= 4; ++i, r += 2)
System.out.print((i + " ").repeat(r));
You can calculate value from row with this method.
static int value(int row) {
return (int)Math.ceil(Math.sqrt(row));
}
So you can also do like this.
for (int row = 1; row <= 16; ++row)
System.out.print(value(row) + " ");
result:
1 2 2 2 3 3 3 3 3 4 4 4 4 4 4 4
Hey it's a representation of a sequence that grows by 2 every step.
i.e the first element is 1 which shows up one time.
the second element is 3 which shows up 3 times (2 2 2)
and so on and on..
so the code you need is:
int a = 1;
for(int i=1; i<=10;i++){
int j=1;
while(j<=a){
System.out.print(i);
j++;
}
a+=2;
}
printing the value in a wanted row:
Scanner in = new Scanner(System.in);
int rowU = in.nextInt(); // User inputs row
int row = 1; // a variable to keep track of the rows
int repeats = 1; // the number of times a value shoud appear
for(int value=1;value<=10;value++){
int j=1;
while(j<=repeats){
if(row==rowU) // if we got to the wanted row
System.out.println(value); // print the wanted value
j++;
row++;
}
repeats+=2;
}
There is a better, more efficient way to get the value of a wanted row:
int wanted_value = Math.ceil(Math.sqrt(wanted_row));
Thanks to #saka for bringing this one up!
Hope I helped :)
i % 2 == 0 means that the following code is only going to be executed, if i is even.
You could try removing the if, and change the second for to something like
int j = 0; j < 2 * i - 1; j++.
This code snippet will do the work
int n=4;
int printTimes=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<printTimes;j++)
System.out.print(i+" ");
printTimes+=2;
}
System.out.println();
Here is the example code.
int start = 1;
int end = 5;
int time = 1;
for (int i = start,j = time; i < end; i++,j+=2) {
for (int k = 0; k < j; k++) {
System.out.print(i+" ");
}
}
there is such a question. I have a method that reads the bytes from a file into an array, and the method that searches for the longest byte sequence in this array.
private int element;
private int lastElement;
private int length;
private byte[] readByteFromFile(File name) throws IOException {
return Files.readAllBytes(name.toPath());
}
private void searchByte(byte[] byteMass) {
for (int i = 0; i < byteMass.length; i++) {
int count = 0;
for (int j = i + 1; j < byteMass.length; j++) {
if (byteMass[i + count] == byteMass[j]) {
if (count >= length) {
length = count + 1;
element = i;
lastElement = j - count;
}
count++;
} else {
count = 0;
}
}
}
}
Suppose that my file contains such a sequence of numbers:
444478126354444
In the case of processing, my method will deduce that the first occurrence was at 0, and the second at 11 and length of sequence = 4
But if I have such a sequence
133333444478126354444
Then my method will deduce that the first occurrence was at 1, and the second at 2, and the length of the sequence 4
How it can be fixed, that the method to continue to work correctly?
It is not tested. Don't have IDE infront of me.
The changes from the original code are. The second loop iterates one element less. If the next element is not equel to the previous then the loop exits.
private void searchByte(byte[] byteMass) {
int maxLength = 0
int element;
for (int i = 0; i < byteMass.length; i++) {
int count = 0;
for (int j = i + 1; j < byteMass.length-1; j++) {
if (byteMass[i] == byteMass[j]) {
if (count > length) {
maxLength = count;
element = i;
}
count++;
} else {
break;
}
}
}
If you haven't already I think it's very important to trace out the logic of your code!!! It's really important that you attempt to do this before asking for help. If you rely on others to work out your own logic, you won't make much progress as a programmer.
That being said, let's dive in and follow your code when it runs with the problem input (this isn't actual code, we're just looking at the values as the program runs)
byteMass = 133333444478126354444
(byteMass.length = 21)
length = 0
0 (i) < 21 (byteMass.length): true
count = 0
1 (j) < 21: true
1 (byteMass[0 (i + count)]) == 3 (byteMass[1 (j)]): false
count = 0
2 (j) < 21: true
1 (byteMass[0 (i + count)]) == 3 (byteMass[2 (j)]): false
count = 0
3 (j) < 21: true
1 == 3: false
it continues on like this, but something interesting happens when j = 12
12 (j) < 21: true
1 (byteMass[0 (i + count)]) == 1 (byteMass[12 (j)]): true
0 (count) >= 0 (length): true
length = 1 (count + 1)
element = 0 (i)
lastElement = 12 (j - count)
count = 1
This, to me at least, looks like unexpected behavior! We want to count repeated numbers, but this 1 is 11 digits away from the previous 1! We can fix this by editing the inner for loop like this
for (int j = i + 1; j < byteMass.length && byteMass[i] == byteMass[j]; j++) {
This way, the inner loop breaks as soon as byteMass[i] == byteMass[j] evaluates to false. now let's restart our process with the new inner for loop
byteMass = 133333444478126354444
(byteMass.length = 21)
length = 0
0 (i) < 21 (byteMass.length): true
count = 0
1 (j) < 21 && 1 (byteMass[0 (i)]) == 3 (byteMass[1 (j)]): false
1 (i) < 21: true
count = 0
2 (j) < 21 && 3 (byteMass[1 (i)]) == 3 (byteMass[2 (j)]): true
0 (count) >= 0 (length): true
length = 1 (0 (count) + 1)
element = 1 (i)
lastElement = 2 (2 (j) - 0 (count))
count = 1 (0 (count) + 1)
3 (j) < 21 && 3 (byteMass[2 (1 (i) + 1 (count))]) == 3 (byteMass[3 (j)]): true
1 (count) >= 1 (length): true
length = 2 (1 (count) + 1)
element = 1 (i)
lastElement = 2 (3 (j) - 1 (count))
This seems like unexpected behavior to me, but I won't fix it because I don't know how: I have no idea what element and lastElement represent. The code continues on like this until j = 6:
6 (j) < 21 && 3 (byteMass[5 (1 (i) + 4 (count))]) == 4 (bteMass[3 (j)]): false
2 (i) < 21: true
count = 0
3 (j) < 21: true
3 (byteMass[2 (2 (i) + 0 (count))]) == 3 (byteMass[3 (j)]): true
length = 1 (0 (count) + 1)
element = 2 (i)
lastElement = 3 (3 (j) - 1 (count))
count = 1 (0 (count) + 1)
This once again continues in the same fashion until j = 6. At this point hopefully you can see why your program isn't working as expected. But I still haven't answered the question of how to fix it. I don't really understand your thought process on how to solve this problem but I'll share with you my own
First of all we need to break the problem into smaller chunks!
You can do that any way you want to but here's my way: Our goal is to find the longest repeated pattern. Well in order to do that we need to figure out
when a number repeats itself and how many times it repeats itself
if that specific number repeated itself that specific amount of times anywhere else in the sequence. If it does, we'll need to save the amount of times it repeats itself
Then we'll repeat the process but only save the data if the number of repeats is larger than the saved data
It's actually a kind of complex problem and will probably be easier to solve with helper functions to be honest. I hope this helps!
This is the same person who had trouble with the last array problem just one or two days ago.
We've a new assignment which asks us to find and replace duplicates in an array of randomly generated numbers. I wrote a code and sent it to my teacher for feedback; she responded with this solution:
So, take the first random num and store into the first slot (this can be done before the loop). Then, start a loop that creates the second random num and tests backwards to see if there are duplicates from the ones already stored. So, a backwards loops that tests for duplicates and counts down to 0 from the current location and replaces duplicates. Once that test passes, then you'll go to the next element, create a new random number, and then test the ones before it for duplicates.
I've done this here, and it's reduced the number of randomly generated numbers, but I still run into the stray duplicate:
import java.lang.Object;
import java.util.Random;
public class Prog433a {
public static void main(String[]args) {
Random randslct = new Random();
int[] list = new int[20];
int counter = 0;
int index = 0;
int min2 = 0;
System.out.println("\nAfter");
for (int k = 0; k < list.length - 1; k++) {
list [k] = randslct.nextInt(30) + 1;
for (int z = list.length - 1; z >= 0; z--) {
if (list[k] == list[z] && z!=k) {
while (list[k] == list[z]) {
list [k] = randslct.nextInt(30) + 1;
}
}
}
}
int min = list[0];
while (counter < list.length - 1) {
for (int x = 0; x < list.length - 1; x++) { // scroll through the indexes.
if (list[x] < min) {
min = list[x];
index = x; // keep the index of the biggest number.
}
}
System.out.println(list[index]);
min = 100 * (list[index]);
list[index] = 100 * (list[index]); // change the value in the original array so it won't find the same max again
counter++;
}
}
}
System Output:
After
2
5
6
10
11
12
13
15
16
17
19
22
22
24
25
27
28
29
29
After
1
2
2
4
5
7
8
9
10
13
15
16
21
24
25
26
28
29
30
After
1
2
3
5
6
7
11
12
13
14
15
16
18
21
22
25
26
27
29
After
2
3
3
4
6
10
12
14
15
16
17
20
22
23
24
25
26
27
30
After
7
8
11
12
13
14
15
16
17
17
18
19
20
21
23
24
27
29
30
I posted my output towards the bottom.
Because this is an introductory coding class, I'd prefer if the solution did not involve Sets or any of the like. But alas, beggars cannot be choosers.
Is there something I have forgotten to add?
Your problem is that when you detect a duplicate you generate a new number, but you never go back and check that the the newly generated number is not a duplicate of the numbers you already checked. When you run into a duplicate you'll need to reset the checking loop through some mechanism.
I fixed up the code to work around the problem, but it's not the prettiest solution. I also did some minor optimisation as you were looping through unnecessary indices.
import java.util.Random;
public class Prog433a {
public static void main(String[] args) {
Random randslct = new Random();
int[] list = new int[20];
int counter = 0;
int index = 0;
int min2 = 0;
System.out.println("\nAfter");
for(int k = 0; k < list.length - 1; k++) {
list[k] = randslct.nextInt(30) + 1;
boolean unique = true;
for(int z = k - 1; z >= 0; z--) {
if(list[k] == list[z]) {
if(list[k] == list[z]) {
unique = false;
break;
}
}
}
if(!unique) {
// Repeat last index
--k;
}
}
int min = list[0];
while(counter < list.length - 1) {
for(int x = 0; x < list.length - 1; x++) { // scroll through the indexes.
if(list[x] < min) {
min = list[x];
index = x; // keep the index of the biggest number.
}
}
System.out.println(list[index]);
min = 100 * (list[index]);
list[index] = 100 * (list[index]); // change the value in the original array so it won't find the same max again
counter++;
}
}
}
Your mistake is when you try to add a new number. You just check, if it isn't the same as the one before, but not if it is the same as twice before. You can do this as follow:
boolean isDuplicate(int index, int[] list){
for(int i=index-1; i>=0;i--){
if(int[i]==int[index])
return false
}
return true;
}
instead of your inner of the for-loop you can now write:
do{
list[k] = randslct.nextInt(30) + 1;
}while(isDuplicate(k, list));
Also you should change your output, e.g. give the already written output a negative value and ignore negative values. If you want to change the numbers up to e.g. 200 your code now won't work.
Lets take this by example. Consider that the current list that has been generated is:
list = [5, 7, 9, 3, 8, 9]
where 9 is the current number.
Now in the for-loop, you iterate from list[6] to list[0]. Here, in comparision, you come to 2nd index (list[2]) where the condition
list[k] == list[z] && z != k
turns out to be true and a new random number is generated. Lets assume that here the new random number that you generated is '8'. The loop terminates successfully and your array now has a duplicate.
As the title suggests, I have code for a Fibonacci series and my goal is to replace multiples of numbers (3, 5, 7 and combinations of them) in the series with a word. I was suggested to use a flag in my if loop to check for the printed phrase, and if the phrase is printed, to skip that number. Essentially, what I want the output to look like is:
1 1 2 skip 8 13 skip 34 55
(this is replacing multiple of three only, for now).
Instead, what I am getting is:
1 1 2 3 skip5 8 13 21 skip34 55
Here is my code as of now:
int febCount = 50;
long[] feb = new long[febCount];
feb[0] = 1;
feb[1] = 1;
for (int i = 2; i < febCount; i++) {
feb[i] = feb[i - 1] + feb[i - 2];
}
for (int i = 0; i < febCount; i++) {
System.out.print(feb[i] + ((i % 10 == 9) ? "\n" : " "));
if (feb[i] % 3 == 0)
System.out.print("skip");
}
Any and all help is appreciated!
Let's walk through the code you have provided and attempt to understand why it's not working.
//The first thing we do is setup the loop to iterate through the fib numbers.
//This looks good.
for (int i = 0; i < febCount; i++) {
//Here we print out the fibonacci number we are on, unconditionally.
//This means that every fibonacci number will be printed no matter what number it is
//we don't want that.
System.out.print(feb[i] + ((i % 10 == 9) ? "\n" : " "));
//After we print the number, we check to see if it is a multiple of three.
//maybe we should be waiting to print until then?
if (feb[i] % 3 == 0)
System.out.print("skip");
}
Now that we have walked through the code, we can propose a new solution.
Let's try updating the loop so that it wait's to print the fibonacci number until AFTER we've checked to see if it meets our conditions.
for (int i = 0; i < febCount; i++) {
if (feb[i] % 3 == 0 || feb[i] % 5 == 0 || feb[i] % 7 == 0) { //check if multiple of 3 5 or 7
System.out.println(" Skip ");
} else { //if it's not a multiple, then print the number
System.out.println(" " + feb[i]);
}
}
is there any way to align these values in my sparse matrix?
0 0 0 0 8 2
0 0 0 19 11 0
0 11 0 13 0 0
0 18 0 0 7 0
0 0 0 0 4 0
0 0 3 0 0 0
at the moment i have this:
if (matrix[i][j] < 20)
System.out.print(matrix[i][j] + " ");
else
System.out.print(" " + 0 + " ");
the problem i'm having is if the value is between 1 and 9 then no space is left before the value and therefore messes up my alignment. i could insert another if statement, but was wondering if theres an easier/cleaner way of doing this?
any help would be appreciated, thanks
I was solving the similar task while working on la4j (Linear Algebra for Java). The la4j uses overriden toString() method for this needs. So, I decided to use slow (since the console output is using primary in debug mode and la4j has fast and effective streams for release versions) but safe algorithm. Here is the code (the precision is number of digits after delimiter):
#Override
public String toString() {
final int precision = 3;
int formats[] = new int[columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
long value = (long) unsafe_get(i, j);
int size = Long.toString(value).length() + precision + 2;
formats[j] = size > formats[j] ? size : formats[j];
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
sb.append(String.format("%" + Integer.toString(formats[j])
+ "." + precision + "f", unsafe_get(i, j)));
}
sb.append("\n");
}
return sb.toString();
}
So, there are two steps in algorithm:
Calculate formats array as number of charachers that needs to
print i colomn aligned
Print matrix