Creating a Histogram from an Array using parallel Arraylists - java

I writing a program learning arraylists. Essentially what it does is pulls from an array of Strings (each a word) and find the duplicates using to parallel arraylists. There are two arraylists one for the words and one for the number of times each word appears. The word in 0th spot of the words list corresponds to the number in the 0th spot of counts list and so on. I am successfully finding duplicate words and counting their occurrences but for words that occur only once I am getting a count of 2 and I can't seem to find out why. Here is the code
String[] wordList = fileContents.split("\\s");
ArrayList<String> words = new ArrayList<String>();
ArrayList<Integer> counts = new ArrayList<Integer>();
words.add(wordList[0]);
counts.add(0);
for (int i = 0; i < wordList.length; i++) {
String tempWord = wordList[i];
boolean foundEqual = false;
int count = 0;
for(int q = 0;q < words.size();q++) {
if (tempWord.equals(words.get(q))) {
foundEqual = true;
counts.add(q, counts.get(q) + 1);
}
}
if(!foundEqual){
words.add(tempWord);
counts.add(1);
}
}
for (int i = 0; i < words.size(); i++) {
System.out.println(words.get(i) + ":" + counts.get(i));
}
Here are the words
this is a test
this is also a test
this is the last test
And here it the output, as you can see the last three items should be 1 but are 2.
this:3
is:3
a:2
test:3
also:2
the:2
last:2
Any help would be really appreciated!

When looking at the structure of counts and words in a debugger just before the print statement, it becomes clear that there is something amiss.
words: counts
0 = this 0 = 3
1 = is 1 = 3
2 = a 2 = 2
3 = test 3 = 3
4 = also 4 = 2
5 = the 5 = 2
6 = last 6 = 2
7 = 1
8 = 0
9 = 1
10 = 1
11 = 1
12 = 1
13 = 1
14 = 1
The problem is the add statement in the ArrayList. From the Javadocs:
Inserts the specified element at the specified position in this list.
Shifts the element currently at that position (if any) and any
subsequent elements to the right (adds one to their indices).
And so, each time you are doing that counts.add(q, counts.get(q) + 1) you are inserting another element into the list. You should instead use set.
Setting a breakpoint on the for and running this through a debugger (eclipse debugging tutorial) I can look at the arrays as each one of them grows:
words: counts
0 = this 0 = 0
This is from the first bit of:
words.add(wordList[0]);
counts.add(0);
When it hits the for loop again:
words: counts
0 = this 0 = 1
1 = 0
What happened there is that the counts.add(0,1) put a 1 at the 0th location and then shifted everything else in the array down.
After several iterations of the not finding, we are back to this again.
words: counts
0 = this 0 = 1
1 = is 1 = 0
2 = a 2 = 1
3 = test 3 = 1
4 = 1
And then matching the 'this' again:
words: counts
0 = this 0 = 2
1 = is 1 = 1
2 = a 2 = 0
3 = test 3 = 1
4 = 1
5 = 1
And you should be able to see how this structure is growing incorrectly.

Aside: your main loop should start at i = 1, since i = 0 is covered before the loop starts.
The bug is that you're counting the first occurence on each subsequent trip through. Change q = 0 to q = i + 1 to avoid that.
You'll also have to check your end conditions because of that.

Related

Error in taking input from the BufferedReader

I was asked a question regarding to find the common divisors between two numbers. I was able to figure out the logical approach using " Sieve of Eratosthenes " and I was dry running my code. But my code was giving an unexpected output in the sense that it was able to figure out the no. of common divisors between two numbers. For the 1st input but for the rest it is somehow continuing with the previous value of "inner loop j" at which it was stopped for the 1st test case ; for other test cases.
Logical approach --> if a prime no. is a factor of given two nos. then we'll check that for every multiple of the prime no.(using array of primes[] and converting the value of multiple of primes[]=0 ) whether some of them are multiples of both the numbers or not and if yes then we'll increase the value by 1.
My question is - am using BufferedReader in the wrong way or there is some error in the code itself
Question Link-> https://www.geeksforgeeks.org/common-divisors-of-two-numbers/
Input Format
The first line of the input contains a single integer
T
denoting the number of test cases.
The description of
T
test cases follows.
The first line of each test case contains two integers
A
and
B
.
Output Format
For each test case, output the number of common divisors between the given pair on a seperate line.
Constraints
1
≤
T
≤
10
^2
1
≤
A
,
B
≤
10
^9
Example
Input
3
100000 100000
12 24
747794 238336
Expected Output
36
6
2
try{
long primes[]=new long[1000005];
for(int i=2;i<=100000;i++){
primes[i]=1;
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
for(int k=0;k<t;k++){
String s = br.readLine();
String s2[] = s.split(" ");
long a = Long.parseLong(s2[0]);
long b = Long.parseLong(s2[1]);
long min = Math.min(a,b);
long max= Math.max(a,b);
System.out.println("Value of max = "+max);
System.out.println("Value of min = "+min);
long count=1;
for(int i=2;i*i<=min;i++){
if(primes[i]==1){
System.out.println("Value of i = "+i);
if(max%i==0 && min%i==0){
count++;
}
for(int j=i;j*i<=min;j++){
if(primes[i*j]==1){
primes[i*j]=0;
System.out.println("Value of j = "+j);
if((max%(i*j)==0) && (min%(i*j)==0)){
count++;
}
}
}
}
}
System.out.println(count);
}
}catch(Exception e){
return;
}
My output for different values of input -
Value of max = 24
Value of min = 12
Value of i = 2
Value of j = 2
Value of j = 3
Value of j = 4
Value of j = 5
Value of j = 6 <------
Value of i = 3
Value of j = 3
6
Value of max = 40
Value of min = 20
Value of i = 2
Value of j = 7 <------
Value of j = 8
Value of j = 9
Value of j = 10
Value of i = 3
Value of j = 5
3
Value of max = 100
Value of min = 20
Value of i = 2
Value of i = 3
2
How can I figure out the mistake? I am new in using BufferedReader?
Your algorithm is wrong. BufferedReader is working fine.
Take a simple example, say a=131, b=262, your program will return 1 as an answer but the correct answer would be 2 (1 & 131). Why is this happening?
Simply because your program misses to check for all those primes which are > sqrt(min) and are factors of both numbers.
To rectify this you need to check for the divisibility with those primes in a linear manner at the end as below but this will be inefficient.
for (int i=2; i<=min; i++)
if (primes[i] == 1 && (max%(i)==0) && (min%(i)==0))
++count;
Also, for the correct working of above, you need to mark the i-th number as composite by primes[i]=0 during each i-th iteration.
Also, initialization of primes array should be done during each test case as in the previous testcase, the primes array would have been modified.
primes[] = new long[1000005];
for(int i=2; i<=100000; i++)
primes[i] = 1;
For an efficient approach, please refer to the GFG article you shared.

Having problems understanding following simple algorithm

public class Test1
{
public static void main (String[]args)
{
int number = 0;
for (int i = 0; i < 5; i++)
{
if (number != 0)
{
number = i * number;
}
else
{
number = i;
}
}
System.out.println (number);
}
}
I'm not quite sure how this algorithm works. My thought process is:
We set number to 0 by default.
In the for loop we are just saying, continue counting i till it's no longer smaller than 5.
We say that if number isn't 0, we update number by multiplying it with i. So in our case, i is 0,1,2,3 and 4.
Else we are saying the number is i and i is what we were counting.
Lastly, we print number.
Am I missing something? Am I wrong somewhere?
If I run this code why do I get 24 as output? I cannot understand how this simple program works.
public class Test
{
public static void main (String[]args)
{
int number = 0;
for (int i = 0; i < 5; i++)
{
if (number != 0)
{
number = i * number;//For i=2, 3, 4
}
else
{
number = i;//This is executed twice - for i=0 and i=1
}
}
System.out.println (number);
}
}
Let's understand this program.
Execution begins from the main() method.
A variable named number is defined and initialized to 0.
A loop control variable named i is defined. Its initial value is 0 and it is increased by 1 at the end of every iteration till it reaches 5. Note that i is never modified inside the loop body.
For i = 0, the condition number != 0 is false, the else block is executed. number = i. The value of number remains 0.
For i = 1, the condition number != 0 is false, the else block is executed. number = i. The value of number changes to 1.
For i = 2, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 2.
For i = 3, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 6.
For i = 4, the condition number != 0 is true, the if block is executed. number = i * number. The value of number changes to 24.
Since i = 5, the loop breaks. The value of number is printed.
This is how we end up getting 24 as the output.
Executing the algorithm step by step will help understanding it.
Let's start with the first line. As you said, this line just sets number to 0.
int number = 0; | number: 0
I included the value of the variable on the right side after the bar.
Second step is to start with the loop. Before the loop starts, the counter variable i is set to zero.
int i = 0; | number: 0, i: 0
As a second step we have to check if the loop criterion is fulfilled, so that the body of the loop will be executed.
The criterion of the loop is i < 5 and since the current value of i is 0 and 0 < 5, the body of the loop is executed:
if (number != 0) {
number = i * number;
} else {
number = i;
}
Since it is an if statement, we have to see if the if-condition is fulfilled. number is currently 0, so number != 0 is not true. This means we go to the else branch with is:
number = i; | i = 0 -> number = 0
Since i is zero, number continues to be zero after this statement was executed.
This is the end of the first execution of the loop. Last thing the loop does before restarting is incrementing the counter:
i++; | number = 0, i = 1
Now i < 5 is still true, so the loop body runs again.
We still have number = 0 therefore number != 0 is still false.
Note that i was updated to 1, but number was not until now. Now:
number = i; | i = 1 -> number = 1
Now the loop increments the counter and starts anew:
i++; | i = 2
Still i < 5, so the body of the loop is executed again.
For the first time number != 0 is true, because number = 1.
So now we execute:
number = i * number; | i = 2 -> number = 2
number used to be 1, i is to, so i * number = 2
Again the loop body ends, the counter is incremented and the loop restarts, since 3 < 5:
i++; | i = 3
Here again number != 0, so we execute
number = i * number;
which yields number = 6 since 2 * 3 = 6.
The same process continues one more time with i = 4.
Now number = 4 * 6 = 24.
We increment the counter
i++; | i = 5, number = 24
Now i < 5 is no longer true, the loop exits and
System.out.println(number);
prints the current value of number, 24 to the screen.
Your thought process was good, but it wasn't exact or detailed enough because the meshing/merging of the sequence of the multiplication (of number) with the sequence of incrementing i is important.
Work it out on paper with a table, one column per variable, one line per instruction executed:
i number
null 0 int number = 0; // i has not been initialized yet.
0 0 int i = 0;
0 0 number = i; // it took the else branch
1 0 i++
1 1 number = i;
2 1 i++
2 2 number = i * number
3 2 i++
3 6 number = i * number
4 6 i++
4 24 number = i * number
5 24 i++
5 24 falls out of loop since i < 5 is now false

Using Java for loops to make a times table

I'm trying to make a Java program that creates multiplication tables using nested for loops by asking the user for upper bounds and display the following result such as this (first image attached). Desired format
However, my code is causing it the program to only print out the multiple of the two inputs and looping that the same amount of times as the multiple. For example in here (second image attached), if it put in the input as 3 and 5, it is displaying 15 to me 15 times. My displayed format
This is what my code looks like (last image attached):
My code
Thank you all so much in advance. Please help me out!!! I've been stuck on this for a while.
Try this:
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int firstFactor = 0;
int secondFactor = 0;
System.out.print("Enter the first factor: ");
firstFactor = s.nextInt();
System.out.print("Enter the second factor: ");
secondFactor = s.nextInt();
for(int i=1; i<=firstFactor; i++) {
for(int j=1; j<=secondFactor; j++) {
System.out.println(i + " * " + j + " = " + i*j);
}
System.out.println();
}
}
Output:
Enter the first factor: 3
Enter the second factor: 5
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
Modifications:
Change firstFactor*secondFactor to i*j. Since firstFactor was 3 and secondFactor was 5. Hence you were getting 15 as an output each time.
I would strongly suggest not using an image for your code. You can just add it as part of your question using the provided edit tools (or Ctrl+k).
Anyway, from a quick look your code looks fine with one bug. You just need to do this:
System.out.println(i*j)
Where you had:
System.out.println(firstFactor*secondFactor)
Those are set to input values and do not change during the loop.
Change your first and second factor to i and j.
for(int i=1;i<=3;i++) {
for(int j=1; j<=5; j++) {
System.out.print("i: "+i+" j: "+j);
System.out.println(" Value: "+i*j);
}
}

How to create an array of integers that equal a certain value?

Hello i am having a tough time trying to write a function that can create an array that holds integers, that equal my simple math problem.
my problem is not adding integers into the array but finding the correct integers that could add up to a math problem.
for example i have a simple math problem like: 10 + 10 = ? we know it equals 20
so i want my array to hold up to ten integers, that when added all together equal 20.
this is what i have been trying in code but not getting the results i want.
while (totalCount != answer
&& count < setCount) {
randomNumber = rand.nextInt((int) answer / 2) + 1;
if(count < setCount) {
sumOfBalloons.add(randomNumber);
totalCount += randomNumber;
count++;
}
if(totalCount > answer) {
count = 0;
totalCount = 0;
sumOfBalloons.clear();
}
}
i am trying to find random numbers that add up to the math problems answer so i can draw them on balloons. problem is i can never get ten numbers to equal the answer in my while loop.
does anyone know some way of doing something like this?
need array to hold 3 - 10 integers that equals my math problems answer.
** update on code thanks to the advice i received i managed to fix my while loop now it looks like this
had to post like this cause my rep is very low. sorry.
while (totalCount != answer) {
randomNumber = rand.nextInt((int) answer / 2) + 1;
if(totalCount + randomNumber > answer) {
randomNumber = rand.nextInt((int) answer - totalCount) + 1;
}
if(count + 1 == setCount) {
randomNumber = answer - totalCount;
}
if(count < setCount) {
sumOfBalloons.add(randomNumber);
totalCount += randomNumber;
count++;
}
if(totalCount > answer
|| totalCount == answer
&& count < setCount
|| totalCount != answer
&& count == setCount) {
count = 0;
totalCount = 0;
sumOfBalloons.clear();
}
}
this is what i got in my console from this code
Total count = 10
Total totalCount = 20
sumOfBalloons 0 = 2
sumOfBalloons 1 = 3
sumOfBalloons 2 = 3
sumOfBalloons 3 = 2
sumOfBalloons 4 = 1
sumOfBalloons 5 = 4
sumOfBalloons 6 = 2
sumOfBalloons 7 = 1
sumOfBalloons 8 = 1
sumOfBalloons 9 = 1
I think there are a few options here re: generating random numbers that sum to 20.
Here's one possible solution:
Create an array of length 4, for example.
Generate random number between 1 and 6 for each of the first 3 indices of your array.
At this point you'll have an array of the form: { 4, 5, 2, _ } (where our 4th element hasn't been chosen yet).
Sum our first 3 elements: 4 + 5 + 2 = 11. Determine 4th element by calculating 20 - current_total (11) = 9.
Set myArray[3] = 9;
A few things to note:
You may need to modify the range of possible random numbers ( 1-6 ) I've given. Consider what happens if the array we generate turns out to be { 2, 1, 2, _ }...then there's no digit that will ensure the elements sum to 20.
Another option is to use an arrayList instead of an array. The benefit to this is that you can keep adding elements to your arrayList until you either hit 20 (then you're done) or go over (in which case you delete the most recent element and begin adding again). You also won't need (or be able) to know the length of your arrayList in advance.

Java for loop algorithm

how do I make a loop that checks 1, 4 times and then moves to 2, and checks it 4 times, and moves to 3, and checks it 4 times.
For example:
//Btw, isNextFree is a boolean that returns true or false if the next line is free.
while(linenumber.isNextFree()){
int linenumber=1;
username = line(linenumber,usernamefile);
linenumber+=1;
}
So, what that loop does is it checks linenumber of usernamefile.txt and stores that value in a hashmap, I need to check use that string value in line one which is stored in that hashmap to make a 4 strings on what is on linenumber 1 on username file concatenate with 1 same passwordstring on passwordfile.txt.
By the way, I'm using scanner, so the line and linenumber.isNextFree doesn't exist, it is like scanner's .isNext basically.
I don't understand the second part of the question, for the first:
for(int i=1; i<4; i++)
{
for(int j=1; j<5; j++)
{
//Do somethings for check
//Example
System.out.println("It's "+ i + " = " j ");
}
System.out.println(""); //only a new line like \n
}
With this code, it do somethings with 1, 4 times
after do something with 2, 4 times
and after do somethings with 3, 4 times
the output is:
It's 1 = 1
It's 1 = 2
It's 1 = 3
It's 1 = 4
It's 2 = 1
It's 2 = 2
It's 2 = 3
It's 2 = 4
It's 3 = 1
It's 3 = 2
It's 3 = 3
It's 3 = 4
I hope this helps.

Categories

Resources