Java - Repeat Function for Specific Numbers - java

I am exceptionally new to programming, but I am working on improving my skills as a programmer. Recently, I gave myself the challenge to determine what multiples of a given number are made up of distinct digits. I have gotten most of it to work, but I still need to make the code apply for every number that is a multiple of the input one. The code I have working so far is as follows:
Integer numberA = 432143;
Integer numberB = numberA;
Integer[] digitArray = new Integer[numberA.toString().length()];
int index;
for (index = 0; index < digitArray.length; index++) {
digitArray[index] = (numberA % 10);
numberA /= 10;
}
int repeats = 0;
for (int i = 0; i < digitArray.length; i++) {
for (int j = 0; j < digitArray.length; j++) {
if ((i != j) && (digitArray[i]==digitArray[j])) repeats = repeats + 1;
}
}
if (repeats == 0) {
System.out.println(numberB);
}
This will determine if the number is made up of distinct digits, and, if it is, print it out. I have spent quite a bit of time trying to make the rest of the code work, and this is what I've come up with:
Integer number = 1953824;
Integer numberA = number;
Integer numberB = numberA;
for (Integer numberC = number; numberC.toString().length() < 11;
numberC = numberC + number) {
Integer[] digitArray = new Integer[numberA.toString().length()];
int index;
for (index = 0; index < digitArray.length; index++) {
digitArray[index] = (numberA % 10);
numberA /= 10;
}
int repeats = 0;
for (int i = 0; i < digitArray.length; i++) {
for (int j = 0; j < digitArray.length; j++) {
if ((i != j) && (digitArray[i]==digitArray[j])) repeats = repeats + 1;
}
}
if (repeats == 0) {
System.out.println(numberB);
}
}
I can't figure out why, but his just prints whatever the number is a bunch of times if it is made up of distinct digits, and leaves it blank if it is not. If anyone could tell me why this is occurring, or even tell me what I need to do to fix it, that would be superb. Remember, I am very new to programming, so please give a short explanation for any terms you use that are at all out of the ordinary. I am eager to learn, but I currently know very little. Thank you for your time, and I greatly appreciate any and all help you can give me.

You assign the value of numberA to numberB (which is the value of number) right before the for loop. After that, numberB is never modified or assigned to a new value, so for every pass through the for loop, you're simply printing the value of numberB, which is always 1953824 in this case.
There are several corrections that can be made to achieve the result you desire, while cleaning up the code a little. The first thing is to change the print statement to print the correct number:
System.out.println(numberC);
Since numberC is the variable that is being updated by the for loop, that's what you'll want to conditionally print out if there are no repeat digits. Since we've replaced numberB with numberC, that means numberB is not longer needed, you can delete the declaration for it.
Now, the next issue is when you're defining the digital array - you should use the length of numberC, not numberA. Also, inside the for loop, you should assign numberA the value of numberC, or else eventually nothing but 0s will be stored in your digitArray. Overall, here's what it should look like.
Integer number = 1953824;
Integer numberA = number;
for (Integer numberC = number; numberC.toString().length() < 11;
numberC = numberC + number) {
Integer[] digitArray = new Integer[numberC.toString().length()];
numberA = numberC;
int index;
for (index = 0; index < digitArray.length; index++) {
digitArray[index] = (numberA % 10);
numberA /= 10;
}
int repeats = 0;
for (int i = 0; i < digitArray.length; i++) {
for (int j = 0; j < digitArray.length; j++) {
if ((i != j) && (digitArray[i] == digitArray[j]))
repeats = repeats + 1;
}
}
if (repeats == 0) {
System.out.println(numberC);
}
}
This should produce the desired result. It seems to work on my machine :)
If you want, you can take Jeffrey's suggestion and change the Integer to the primitive int to avoid the overhead of boxing. However, you still need to use the Integer class to use the toString() method, but you can accomplish that using Integer.valueOf():
Integer.valueOf(numberC).toString()

So if I understand correctly you are trying to find out if certain multiple exists within your number. Instead of constantly dividing by 10 instead use the modulus symbol. You can even embed it in conditional statements.
For example:
if(numberOne % 2 == 0)
Then we know that numberOne divided by 2 has a remainder of zero and is thus a multiple of 2

Related

Java Variable expected inside a for loop

I'm pretty new here and new to Java in general. I'm trying to solve a projecteuler question and I thought I had a solution but got stick with this error that I cannot fix. Just to give you an idea of what I was going for(in case it wasn't clear) this is the question:
"What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"
I don't want a solution but rather any help with getting rid of the "Java Variable expected inside a for loop." error would be appreciated.
public class Main {
public static void main(String[] args) {
int remainder = 0;
int remainders[] = new int[20];
int j = 1;
int remaindersMax = 0;
while (true) {
for (int i = 1; i <= 20; i++) {
j % i = remainders[i];
for (int k = 0; k < remainders.length; k++) {
if (remaindersMax < remainders[i]) {
remaindersMax = remainders[i];
}
}
}
if (remaindersMax == 0) {
break;
}
System.out.println(j);
}
}
}
j % i = remainders[i];
is invalid syntax. The left hand side (LHS) of a variable assignment can only contain a variable, not an expression. The right hand side (RHS) can contain arbitrarily complex expressions. You want to assign the array remainders at index i the value of the modulo operation. Swap LHS and RHS to make your program compile:
remainders[i] = j % i;

Algorithm output to length starts new line

I am trying to format the output from what I have written to display a list of primes (Eratosthenes) to a certain number results per line. Do they need to placed into an Array to accomplish this? I have not come across a way to implement their division besides .split("");, which would render a single line for each and the Oracle site's System.out.format(); argument index to specify length. Yet, these require the characters to be known. I am printing it with the following, which of course creates an infinite line.
for (int count = 2; count <= limit; count++) {
if (!match[count]) {
System.out.print(count + ", ");
}
}
Is there a way to simply call System.out.print("\n"); with an if(...>[10] condition when System.out.print() has run for instance 10 times? Perhaps I am overlooking something, relatively new to Java. Thanks in advance for any advice or input.
By using a tracker variable, you can keep track of how many items have been displayed already so you know when to insert a new line. In this case, I chose 10 items. The exact limit is flexible to your needs.
...
int num = 0;
//loop
for(int count = 2; count <= limit; count++)
{
if(!match[count])
{
if (num == 10) { System.out.print("\n"); num = 0; }//alternatively, System.out.println();
System.out.print(count + ",");
num++;
}
}
...
You can just simply create some int value e.g.
int i = 1;
...and increment it's value everytime Sysout is running.
Something like this:
int i = 1;
for (int count = 2; count <= limit; count++) {
if (!match[count]) {
if (i%10 == 0)
System.out.print(count+ "\n");
else
System.out.print(count + ", ");
i++;
}
}
Try this:
int idx=1;
int itemsOnEachLine=10;
for(int count = 2; count <= limit; count++)
{
if(!match[count])
{
System.out.print(count+(idx%itemsOnEachLine==0?"\n":","));
idx++;
}
}
you go increasing a counter (idx) along with every write, every 10 increments (idx modulus 10 == 0), you will be printing a new line character, else, a "," character.

in Java, design linear algorithm that finds contiguous subsequence with highest sum

this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.

Adding all odd numbers in an array not working correctly

I will be creating an array that accepts 10 integers from the user, finds the second largest value, and finally adds all odd numbers. If I use 10-1 as input, it will do everything correctly; the problem arises when the first number entered is an odd number it will ignore it in the summation and I have no idea as to why. Any ideas?
for (int j = 0; j < 10; j++) {
arra[j] = keyboard.nextInt();
if (arra[j] > maxValue) {
secondLargest = maxValue;
maxValue = arra[j];
} else if (arra[j] > secondLargest) {
secondLargest = arra[j];
}
}
System.out.println("The second largest number is: " + secondLargest);
for (int i = 0; i < arra.length; i++) {
if (i % 2 == 0) {
numberOdds++;
}
}
int[] odds = new int[numberOdds];
for (int i = 1; i < arra.length; i++) {
if (arra[i] % 2 == 1) {
odds[count] = arra[i];
count++;
}
}
for (int i = 0; i < odds.length; i++) {
sum = sum + odds[i];
}
System.out.println("The sum of all odd numbers is: " + sum);
[This appears to be homework, so exact code will not be given.]
For good form, consider getting the input array separately -- then call a method to get each computational result you want.
For "second largest" method, you do not appear to be initializing the two values. Make sure you handle the (odd) case in which all values in the array are the same. Perhaps you want to set the max and the second-to-max to the first array value and then loop on the 2nd through the end?
To add all the odd numbers create a method that sets the initial sum to zero and then add a number only if it is odd (n % 2 != 0)

Finding the longest down sequence in a Java array

Given this array
int [] myArray = {5,-11,2,3,14,5,-14,2};
I must be able to return 3 because the longest down sequence is 14,5,-14.
What's the fastest way to do this?
PS: Down sequence is a series of non-increasing numbers.
another implementation in python:
def longest_down_sequence(seq):
max = 0
current_count = 0
last = None
for x in seq:
if x <= last: current_count += 1
else: current_count = 1
if current_count > max: max = current_count
last = x
return max
Just make one pass through the list of numbers. Pseudocode:
bestIndex = 0
bestLength = 0
curIndex = 0
curLength = 1
for index = 1..length-1
if a[index] is less than or equal to a[index-1]
curLength++
else
//restart at this index since it's a new possible starting point
curLength = 1
curIndex = index
if curLength is better than bestLength
bestIndex = curIndex
bestLength = curLength
next
Note: You can ditch any line containing bestIndex or curIndex if you don't care about knowing where that subsequence occurs, as seen in Gary's implementation.
In java:
int [] myArray = {5,-11,2,3,14,5,-14,2};
int downSequence = 1;
int longestDownSequence = 1;
for(int i = 1; i < myArray.length; i++) {
if(myArray[i] <= myArray[i-1]) downSequence++;
else {
if(downSequence > longestDownSequence)
longestDownSequence = downSequence;
downSequence = 1;
}
}
if(downSequence > longestDownSequence)
longestDownSequence = downSequence;
System.out.println(longestDownSequence);
Since you're asking for fastest or better performance, only check for the longest down sequence just before you reset the counter. Never on each iteration. However, you have to check again after the loop in case the longest sequence is at the end of the array.
Another solution in Java:
static int[] longestDownSequenceList(int[] array) {
if (array.length <= 1) {
return array;
}
int maxSize = 1;
int maxEnd = 0;
int curSize = 1;
for (int i = 1; i < array.length; i++) {
if (array[i] < array[i-1]) {
curSize++;
if (curSize > maxSize) {
maxSize = curSize;
maxEnd = i;
}
}
else {
curSize = 1;
}
}
return Arrays.copyOfRange(array, maxEnd-maxSize+1, maxEnd+1);
}
As Bill above said, this is essentially longest increasing subsequence. See the wikipedia entry for the optimal solution. This is quoted from there with small changes to work for the nondecreasing case
L = 0
for i = 1, 2, ... n:
binary search for the largest positive j ≤ L such that X[M[j]] >= X[i] (or set j = 0 if no such value exists)
P[i] = M[j]
if j == L or X[i] >= X[M[j+1]]:
M[j+1] = i
L = max(L, j+1)
See counterexample to other proposed solution in my comment above.
The fastest way might depend on the environment: computer and problemsize.
For a very large List (or array) it might be useful to parallelize the job, which could be implemented:
Split and split and split the List to simple elements.
Glue together elements which are down sequences (or non increasing) to chunks, and glue together chunks, if possible.
Search for the longest chunk.

Categories

Resources