Increment through int[] as an int - java

So during a homework assignment I made a method that would increment through an integer array as if it were an integer. So what I mean by that is that the index of the int[] would represent the digits in a number.
for example:
int[] digits;
digits = new int[4]
this would be a 4 digit number. index 0 being the 1000's place, index 1 being the 100's place, index 2 being the 10's place and index 3 being the 1's place.
So the method I made increments through that array like this:
0000, 0001, 0002, 0003, 0004, --> 0010, 00011, ----> 9999.
public void increment(){
if(digits[3] <= 8){
digits[3]++;
}
else{
digits[3] = 0;
if(digits[2] <= 8){
digits[2]++;
}
else{
digits[2] = 0;;
if(digits[1] <= 8){
digits[1]++;
}
else{
digits[1] = 0;
if(digits[0] <= 8){
digits[0]++;
}
else{
digits[0] = 0;
}
}
}
}
}
My question is how would I go about making a method that does the same thing but the method requires an index to be passed in.
for example:
public void increment(int index){
//increments through index number of digits.
}
So something like this:
increment(7);
would yield this: 0000000, 0000001, 0000002, 0000003, --> 0000009, 0000010, 0000011, -----> 9999999.
This is personally for my own satisfaction so any help would be great =)

Aside: int [] = digits; is a syntax error; remove the =.
The increment routine needs access to the array of digits, and in Java arrays 'know' their bounds so you don't need a separate parameter or variable for the length. Given that, the classic hacker method (from the age of the dinosaurs when hacker meant good) is:
void increment (int[] digits){
for( int i = digits.length; --i>=0 && ++digits[i]==10; ) digits[i]=0;
}
# alter the 10 to change radix, or make it variable if desired
This mimics the procedure you learned in elementary school (or at least I did): start at the rightmost digit, add one, if it doesn't overflow you're done, if it does overflow change it to zero and move one place to the left except stop when you are already at the left end and can't move further.

Here's my implementation:
Live demo
Example for reference:
[0,0]
[0,1]
[0,2]
[0,3]
[0,4]
[0,5]
[0,6]
[0,7]
[0,8]
[0,9]
[1,0]
[1,1]
[1,2]
[1,3]
[1,4]
[1,5]
[1,6]
...
First create a 2D array where each row represent a number with n digits. We can get the 2D array height by doing 10^n because we have n digits and 10 possibilities for each digit (0-9)
We can notice a pattern in the numbers generated which is the rightmost column switches digit every one iteration, the second rightmost digit switches digit every 10 iterations, the third one switches digit each 100 iteration etc... so the kth rightmost index switches iteration every 10^k iterations. This is noted by the variable level. Also some iterations on the digits can be omitted because we know that some digits will not increase until a specific row (example the leftmost digit will not increase for row 1 if n > 1). You can get the width of digits to loop on by doing log10(row) which will give you the number of digits in the integer row minus one. This is called width in the code.
Then all we need to do is check if now it's time to switch row%level == 0 then we increment the value from above level by one, otherwise we just copy the same value from row above.
public static void numbers(int n) {
int nums[][] = new int[(int)Math.pow(10, n)][n];
for(int row=1; row < nums.length; row++) {
int width = (int) Math.log10(row);
for(int col = nums[row].length-1; col >= nums[row].length-1-width; col--) {
int level = (int) Math.pow(10, n - col - 1);
if(row % level == 0) {
nums[row][col] = (nums[row-level][col]+1) % 10;
} else {
nums[row][col] = nums[row-1][col];
}
}
System.out.println(Arrays.toString(nums[row]));
}
}

I think the following is quiet simple and readable:
public class Test{
public static void main(String[] args){
increment(7);
}
static void increment (int index){
index = Math.abs(index) ;
int[] digits = new int [index];
Arrays.fill(digits, 0); //initialize array with 0
for( int i = index-1; i>=0 ; i--) {//loop over all digits
for(int digit = 0; digit <=9 ; digit++) {//increment each
digits[i] = digit;
System.out.println(Arrays.toString(digits));
}
}
}
}

Related

Reduce time complexity of game program

Adam wants to watch a football game from the top of the building that is arranged in a straight line.
Adam can watch the football match from the top of ith building if
there exists a maximum of K[i] buildings in front of Adam with a
height less than or equal to the height of ith building.
If there is any building in front of Adam with a height more than
the height of ith position building then he cannot see the match
from this ith building.
Count the positions of buildings where Adam can see the match from the top of the buildings.
Example:
Both arrays have the same length.
B (Buildings) = [2,1,3] represents the height of buildings
K = [1,2,1]
Answer:
1
Explanation:
For B[0] = 2 we have K[0] = 1. The number of buildings in front of it that have a height smaller than or equal to 2 is 0. This is <= K[0] So Adam can see the match.
For B[1] = 1, we have K[1] = 2. The number of buildings in front of it that have a height smaller than or equal to 1 is 0. But B[0] = 2 so Adam cannot see the match.
For B[2] = 3, we have K[2] = 1. The number of buildings in front of it that have a height smaller than or equal to 3 is 2. But this value is >= K[2] i.e 1 so Adam cannot see the match
The total positions where Adam can see the match is 1.
Constraints:
Array size is 1 to 10^5
Each element in Arrays is 1 to 10^5
This is the code I tried with the time complexity of O(n^2):
public static int process(int[] buildings, int[] K) {
int n = buildings.length;
int answer = 0;
for(int i=0; i<n; i++) {
int count = 0;
boolean valid = true;
for(int j=i-1; j>=0; j--) {
if(buildings[j] <= buildings[i]) count++;
if (buildings[j] > buildings[i]) {
valid = false;
break;
}
}
if(valid && count <= K[i]) answer++;
}
return answer;
}
This program works for arrays of small size but fails for large arrays as the time complexity of my program is O(n^2).
What is the better approach to solve this and how can we reduce the time complexity?
you have 2 conditions which we look on one by one but we'll start from the second:
The second condition can be interpreted as if ith building is the highest building from any other building in front of it. this can be achieved by checking the max hight to the ith position and update it as you go.
if the second condition is true that's means you have i-1 buildings in front of the ith building that are equal or smaller than it (i instead of i-1 if you start to count from 0 like in array). so the first condition would be true only if k[i] is bigger than (i-1) you just need to compare between them.
here is the code in java:
import java.util.*;
class HelloWorld {
public static void main(String[] args) {
List<Integer> buildings = Arrays.asList(2, 1, 3);
List<Integer> K = Arrays.asList(1, 2, 1);
System.out.println(process(K, buildings));
}
public static Integer process(List<Integer> K, List<Integer> buildings){
Integer maxHightBuilding = buildings.get(0);
Integer sum = 0;
for(Integer i = 0; i < buildings.size(); i++){
if(buildings.get(i) >= maxHightBuilding ){
maxHightBuilding = buildings.get(i);
if(i <= K.get(i)){
sum++;
}
}
}
return sum;
}
}
I think if you retain the biggest value in front of the actual index, you can just check with the value and when your index passes the biggest value you can update it.
So find the biggest value from the end of the array.
HF!

What is this method doing? (Arrays and random numbers)

My textbook gave me this code to help count the amount of times a certain number shows up in an array of integers. I tried to apply the code my textbook gave me to my assignment but it doesn't seem to be working. Basically, I have to generate 30 random integers in an array, with the upper bound being 15 and lower bond being -5.
I want to find out how many times a number in the array is equal to 0, 1, 2... all the way until 10. The first code is the one my textbook gave me. They also used a random number generator but instead of finding how many elements is equal to 0, 1, etc, they want to find how many times each number appears. (The scores array is simply the random number generator, and their upper bound is 100). The second code is mine.
int[] counts = new int [100];
for (int i = 0; i < scores.length; i++) {
int index = scores[i];
counts[index]++;
}
//This is my code
public static void main(String[] args) {
int []a = arrayHist ();
printArray (a);
}
public static int randomInt (int low, int high) {
int range = (high - low) +1;
return (int) (Math.random() * range) + low;
}
public static int[] randomIntArray (int x) {
int[] random = new int[x];
for (int i = 0; i< x; i++) {
random [i] = randomInt (-5, 15);
}
return random;
}
public static int[] arrayHist () {
int[] counts = new int [30];
int[] hist = randomIntArray (30);
for (int i = 0; i < 10 && i >= 0; i++) {
int index = hist[i];
counts[index]++;
}
return hist;
}
public static void printArray (int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.println (a[i]);
}
}
I'm supposed to be getting only 11 elements, but instead I get 30 random numbers again. Why is that?
I'll put some comments in your code, and see if you can spot where it goes wrong:
//take a histogram of the array. We're only going to count values between 0 and 10
//so 25th to 75 centiles, ignoring values that are lower than 0 or higher than 10
public static int[] arrayHist () {
//need to make an array of 11 numbers for the counts
int[] counts = new int [30];
//get an array of 30 random numbers
int[] hist = randomIntArray (30);
//loop over the whole array of 30 numbers
for (int i = 0; i < 10 && i >= 0; i++) {
//retrieve the random number into a variable temporarily
int index = hist[i];
//if the value is too low or too high, skip it
//else, store it in the counts array - the value from the random array
//serves as the index position in the counts array
counts[index]++;
}
//return the counts array
return hist;
}
What I've done with my comments is equivalent to designing the algorithm using the language you think in (English) and then you can translate it into the language you're learning (java). Very few developers think in the programming language they write. As a student I recommend you should ALWAYS write comments to explain your algorithm to yourself before you write code underneath the comments. You get points for writing comments (usually) so if you write them first then a) it helps you write the code and b) you don't have the tedious job of writing comments after you get the code working
Please please, for your own good/learning, try working out what is wrong from the above before looking at the spoilers(answers) below. Roll the mouse over the box to display the spoilers
//loop over the whole array of 30 numbers - YOU ONLY LOOP 10
for (int i = 0; i < 10 && i >= 0; i++) {
//if the value is too low or too high, skip it - YOU DIDN'T DO THIS CHECK
...
}
//return the counts array - YOU RETURNED THE WRONG ARRAY
return hist;
Edits in response to comments:
Checking a range
You'll have to check two limits, and hence it will need to be of one of the following forms:
if(x < 0 || x > 10) then don't do the count
if(!(x >= 0 && x <= 10)) then don't do the count
if(x >= 0 && x <= 10) then do the count
if(!(x < 0 || x > 10)) then do the count
Tests that use NOT - the exclamation mark ! - are typically a bit harder to read and understand, so try to avoid them is possible. Tests that are "positive minded" - i.e. they return a positive result rather than a negative that needs to be negated - are easier to read and understand.
A helpful tip for loops and methods, in terms of error checking, is to test for bad values that meet certain conditions, and if a bad value is encountered, then skip processing the rest of the loop (using the continue) keyword, or skip the rest of the method (by returning from it)
Doing this means that your if body (the bit between { and } ) doesnt get massive. Compare:
for(...){
if(test for bad values)
continue;
//50 lines long loop body
}
Is neater than doing:
for(...){
if(test for goodvalues){
//50 lines long loop body
}
}
If you use the bottom pattern, you can end up after several IFs in a real indented mess, with { and } all over the place and your code is way over to the right hand side of the screen:
for(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
}
//code
}
//code
}
//code
}
//code
}
//code
}
//code
}
Keeping indent levels to a minimum helps make your code more readable
Hence, I recommend in your case, that rather than test for the value being inside the range 0 to 10 and doing something with it, you adopt the form "if value is OUTSIDE" the range 0 to 10, skip doing the rest of the loop
Your arrayHist() method just returns the array with the random numbers. It should be more like this:
public static int[] arrayHist() {
// generate array with random numbers
int[] hist = randomIntArray(30);
// initialize the array for counting
int[] counts = new int[11];
// step through the random numbers array and increase corresponding counter if the number's values is between 0 and 10
for (int j = 0; j < hist.length; j++) {
int number = hist[j];
if (number > -1 && number < 11) {
counts[number]++;
}
}
return counts;
}

product of the numbers in list in java

My task here is to find the minimal positive integer number say 'A' so that the product of digits of 'A' is exactly equal to N.
example: lets say my N = 32
so my A would be 48 coz the divisors of 32 would be 1,2,4,8,16,32 and the minimum numbers that would make 32 is 4 and 8. so output is 48.
what i did is first read N, then found the divisors and stored them in a list. and used
if(l.get(i)*l.get(i+1)==N) {
sysout.print(l.get(i));
sysout.print(l.get(i+1));
but im not able to make the numbers as minimum. and also i need to print as -1 if no match is found.
for that i did:
if (l.get(i)*l.get(i+1)!=N) {
System.out.print(-1);
break;
}
but it is printing -1 initially only and breaking off. now im stuck here. please find my code below:
my code:
int N=1;
Scanner in = new Scanner(System.in);
List<Integer> l = new ArrayList<Integer>();
System.out.println("Enter N: ");
if (N>=0 && N<=Math.pow(10, 9)) {
N = in.nextInt();
}
for (int i=1; i<=N;i++) {
if (N%i==0) {
l.add(i);
}
}
System.out.println(l);
for (int i=0; i<l.size()-1;i++) {
if (l.get(i)*l.get(i+1)==N) {
System.out.print(l.get(i));
System.out.print(l.get(i+1));
}
}
in.close();
kindly help. thanks.
You're on the right track with finding the divisors on N. I'm not going to code it for you(you'll learn more by doing) but here's what you do: The divisors will be sorted already so loop the arraylist adding first to last and finding the min.
So for 1,2,4,8,16,32: Find 1+32, 2+16, 4+8; And then fin the max among these.
This is to get you started:
int first = 0;
int last = l.size()-1;
while(first<last){
//Find min using Math.min;
++first;
--last;
}
Happy Coding!
Could not resist. Below is a quick way to do what you want. Tested it here
(https://ideone.com/E0f4X9):
public class Test {
static ArrayList<Integer> nums = new ArrayList<>();
public static void main(String[] args){
int N =32;
findDivisors(N);
int first = 0, a = 0, b = 0;
int last = nums.size()-1;
int results = Integer.MAX_VALUE;
while(first < last){
int sum = nums.get(first) + nums.get(last);
results = Math.min(sum,results);
a = nums.get(first);
b = nums.get(last);
first++;
last--;
}
System.out.println(a+" "+b);
}
private static void findDivisors(int n){
for(int i=1; i<=n; i++){
if(n%i == 0){
nums.add(i);
}
}
}
}
Obviously if N<10 then A=N.
Otherwise A has to consist of more than one digit. Every digit of A is a divisor of N. The more significant digits of A always have to be less or equal than the lesser significant digits. Otherwise the order of digits could be changed to produce a smaller number.
For example A could not be 523 because the digits could be rearranged into 235 which is a smaller number. In this example we have 2 < 3 < 5.
Observation #1: when looking at A the smallest digits are at the front, the digits get higher towards the end.
Observation #2, A can never contain two digits a and b if the product of a and b is also a digit. For example, there can never be a 2 and a 3, there would have to be a 6 instead. There could never be three 2s, it would have to be an 8 instead.
This suggests that when building A we should start with the highest possible divisors of N (because a 9 is always better than two 3s, and so on). Then we should put that digit at the end of A.
So, while N > 10, find the highest divisor x of N that is a single digit (2<=x<=9). Add this value x to the end of A. Divide N by x and proceed with the loop.
Example:
N=126, A=?
Highest possible divisor x that is less or equal to 9 is 9. So 9 is going to be the last digit of A.
Divide N by 9 and repeat the process. N=126/9=14.
Now N=14, A=?9
Highest possible divisor x that is less or equal to 9 is 7. We have found the second to last digit of A.
Divide N by 7 and repeat the process. N=14/7=2.
Now N=2, A=?79
N<10. So 2 is the first digit of A.
The solution is A=279

Length and location of longest contiguous sequence of equal values where just before and just after are smaller

I have a problem that asks:
Write a program that converts its input arguments into an array of
integers, and then finds the length and location of the longest
contiguous sequence of equal values where the values of the elements
just before and just after this sequence are smaller.
For example, if
the command line arguments are “1 2 2 2 2 5 5 5 3” your program should
output the numbers 5 3 (the first number is a zero-based offset, and
the second number is the length of the subsequence). If a contiguous
subsequence appears at the beginning or end of the array, treat this
as a special case;e.g.,for input “5 5 5 5 3 8 8 8 1”your output should
be 0 4 (and not 5 3). If there are multiple subsequences that satisfy
the above condition, then output the first one.
Updated code:
public class LongestPlateau {
public static void main(String[] args) {
// TODO - Your solution
int N= args.length;
int [] array = new int [N];
int new_length=0;
int location=0;
int max=0;
int current_length=0;
//assign digits into array
for (int i=0; i < N; i++){
int number = Integer.parseInt(args[i]);
array [i] = number;
}
int compare=array[0];
for (int l=0; l<N; l++){
if (array[l] < compare){
current_length=0;
compare = array[l];
}
else if (array[l] == compare){
current_length+=1;
compare = array[l];
}
else if (array[l] > compare){
compare=array[l];
l++;
}
compare= array[l];
for (int b=0; b<N; b++){
if (current_length > max){
max = current_length;
location = array[l];
new_length=max-1;
}
else if (current_length==1){
new_length=max;
}
}
}
System.out.println(location);
System.out.println(new_length);
}
}
Issue is that for the input of "1 2 3 4" I continously get an Array Index out of bounds error.
Before you start writing code, try and think how a human would have solved it.
e.g.
For every item in the input, compare it to the previous, if it's larger, start a new sequence length check (write 0 in your notebook under - "current sequence length)), if it's the same, increase it by 1, if it's less, mark that sequence length as complete. if it's larger than your largest sequence length so far (started with 0) then this is now your largest sequence, if not, ignore that sequence length and move on to the next character. (or something like this)
write these instructions to yourself as a human, and try to follow them, and fix them as you find edge cases. Once you have a working human language algorithm, writing the code will be almost self driven.
You really need to post the specific issue you are seeing, how your actual results differ from your expected results, and what solutions you have attempted.
In any case, as for the general "how to proceed" question, I find that it often helps to work out these types of problems on paper first. Write down your sequence and step through it, observe what information you need to keep track of and what logic you need to apply to produce the desired results. Once you are able to do this, it will be far more straightforward to translate your clearly thought out algorithm into concrete code.
It appears you are at least somewhat on the right track parsing and storing your integer array, but you are a bit misguided with your [t+?] lookaheads. If you write this out and step through it by hand, you may be surprised at what you come up with.
Here is a full program description with test cases:
Given an array of integers int A[], find the length and location of the longest contiguous sequence of equal values for which the values of the elements just before and just after this sequence are smaller.
You should just print these two numbers (first is the length and second is the starting index of the plateau).
To complete the definition, we can consider there are imaginary index positions at A[-1] and A[A.length] where A[-1] < A[0] and A[A.length] < A[A.length-1]. Therefore, the plateau can start/end at both ends of array A. This condition guarantees the existence of a plateau. A plateau can be of length 1.
Example 1:
java LongestPlateau 1 2 2 2 2 1
With this command line arguments, program should print:
4
1
Example 2:
java LongestPlateau 1 2 2 2 2 3
With this command line arguments, program should print:
1
5
Example 2:
java LongestPlateau 3 2 2 2 1 2 1 1 1 2 2 0 1 1 1 1 0
With this command line arguments, program should print:
4
12
Example 2:
java LongestPlateau 3 2 2 2 2 2 2 1 2 1 1 1 2 2 0 1 1 1 1
With these command-line arguments, the program should print:
4
15
Here is my solution:
public class LongestPlateau {
private static int[] parseInputArray(String[] args) {
int[] value = new int[args.length+1];
for(int i = 0 ; i < args.length; i++){
if (i == args.length-1) value[i] = 0; // this imaginary last value of the array ensures that if the plateau is the last value of the array, then it outputs the correct answer
value[i] = Integer.parseInt(args[i]);
}
return value;
}
public static void printLargestPlateau(int[] values) {
int biggestStartIndex = -1;
int biggestLength = 0;
int currentIndex = 1;
int currentPlateauStartIndex = 1;
int currentLength = 1;
boolean plateauStarted = false;
while (currentIndex < values.length) {
if(isStartOfPlateau(currentIndex, values)){
currentLength = 1;
plateauStarted = true;
currentPlateauStartIndex = currentIndex;
} else if (isEndOfPlateau(currentIndex, values)) {
if(plateauStarted && currentLength > biggestLength){
biggestLength = currentLength;
biggestStartIndex = currentPlateauStartIndex;
}
plateauStarted = false;
currentLength = 1;
} else {
currentLength++;
}
currentIndex++;
}
System.out.println(biggestLength +"\n"+biggestStartIndex);
}
private static boolean isStartOfPlateau(int index, int[] values){
if(index <= 0){
return false;
}
return values[index-1] < values[index];
}
private static boolean isEndOfPlateau(int index, int[] values){
if(index <= 0){
return false;
}
return values[index - 1] > values[index];
}
public static void main(String[] args) {
int[] values = parseInputArray(args);
printLargestPlateau(values);
}
}

abundant sums, logic

I have been working on the problem below but I get the wrong answer. What is wrong with my logic?
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
Here is my code:
public class EulerProblem23 {
public static void main(String[] args) {
//First, I create an array containing all the numbers ranging from 1 to 28123.
int[] tall = new int[28123];
int x = 0;
for (int j = 1;j<=28123;j++){
tall[x] = j;
x++;
}
//Then, give all the numbers that can be written as the sum of two abundant numbers
//the value 0.
int forrige = 0;
for (int i = 1;i<=28123;i++){
if (isAbundant(i)){
if (2 * i <= 28123){
tall[i - 1] = 0;
}
if (forrige + i <= 28123){
tall[i - 1] = 0;
}
}
}
//All that's left should be summing all the numbers in the array.
long sum = 0;
for (int y = 0;y<28123;y++){
sum += tall[y];
}
System.out.println(sum);
}
public static boolean isAbundant(int n){
int sumAvDivisorer = 0;
for (int i = 1;i<n;i++){
if (n % i == 0){
sumAvDivisorer += i;
}
}
if (sumAvDivisorer > n){
return true;
}
else {
return false;
}
}
}
Is there something wrong with my logic here? Wouldn't all of the integers that can be defined as the sum of two abundant numbers become 0?
I would do it like this:
Make an array of all abundant numbers.
Add all pairs together. You can do this with nested for loops.
For every pair that adds to a number less than or equal to 28123, add the sum of that pair to the total sum.
This code makes no sense:
//Then, give all the numbers that can be written as the sum of two abundant numbers
//the value 0.
int forrige = 0;
for (int i = 1;i<=28123;i++){
if (isAbundant(i)){
if (2 * i <= 28123){
tall[i - 1] = 0;
}
if (forrige + i <= 28123){
tall[i - 1] = 0;
}
}
}
Supposedly, what you want to know if, for each i in the loop, if there are two numbers j and k which are both abundant and such that j + k = i.
Your code has no relation with it. Also, the second if has little meaning, as forrige is always 0.
What I would do.
1) An array of booleans [0, 28123]. True if the number is abundant (previous step). (*)
2) Another array [0, 28123]. True if the number in the position is the add of two abundant numbers. Loop i from 1 to 28123, for each i, loop z from 1 to i/2 (either j <= i/2 or k <= i / 2). For each z, check in the previous array for z and i-z, if both are true set the value to true.
3) Loop the previous array and add all the indexes that are true in the array.
Alternatively, is the condition of "abundant" is sparse enough, you could replace 1) with a list of the numbers which are abundant, and a hashset of them. So, instead of running j from 1 to i/2, you loop this list until you get to i/2 (use the hashset to find quickly if i-j is abundant or not).
Anyway, the idea in this problem is precalculating the values that you will be using again and again, instead of repeating the isAbundant calls to the same values time after time.

Categories

Resources