Java cut the sticks - java

I am very new to Java and I was trying to solve this problem on Hackerrank:
Here's the task:
https://www.hackerrank.com/challenges/cut-the-sticks
You are given N sticks, where the length of each stick is a positive
integer. A cut operation is performed on the sticks such that all of
them are reduced by the length of the smallest stick.
Suppose we have six sticks of the following lengths:
5 4 4 2 2 8
Then, in one cut operation we make a cut of length 2 from each of the six
sticks. For the next cut operation four sticks are left (of non-zero length), > whose lengths are the following:
3 2 2 6
The above step is repeated until no sticks are left.
Given the length of N sticks, print the number of sticks that are left before > each subsequent cut operations.
Note: For each cut operation, you have to recalcuate the length of smallest
sticks (excluding zero-length sticks).
Here is my attempt at it, but it doesnt seem to be working. The output gets stuck in while loop (4 gets printed out infinitely)
import java.io.*;
import java.util.*;
public class Solution {
private static int findMin (int[] A)
{
int min = A[0];
for (int i =0; i<A.length; i++)
{
if (A[i] < min)
{
min = A[i];
}
}
return min;
}
private static int countNonZeros (int[] A)
{
int zeros = 0;
for (int i =0; i<A.length; i++)
{
if (A[i] == 0)
{
zeros++;
}
}
int nonZeros = A.length - zeros;
return nonZeros;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] A = new int[n];
for (int i=0; i<n; i++)
{
A[i] = scanner.nextInt();
}
int nums = countNonZeros(A);
while (nums > 0)
{
int mins = findMin(A);
for (int j = 0; j<A.length; j++)
{
A[j]=A[j]-mins;
}
nums = countNonZeros(A);
System.out.println(nums);
}
}
}
Any help is appreciated
(PS I know I can just look the solution up somewhere, but I want to know why my code isn't working)

The problem that you have is that your findMin is not excluding zero-length elements, so once you have a zero that will be the min, and as a result an iteration of the while loop will be the same as the previous iteration, having subtracted 0 from each of the elements of A.

Related

HackerRank Coding Problem : Ways to sum to N using Natural Numbers up to K with repetitions allowed

I have coded recursive solutions for this problem
int NumberOfways(int total, int K, int start, int[] memo){
if (total < 0) return 0;
if (total == 0) return 1;
if (memo[total] != -1 ) return memo[total];
memo[total]=0;
for(int i=start;i<=K;i++){
memo[total] += R2NumberOfways(total-i,K,i,memo);
}
return memo[total];
}
public static void main(String[] args)
{
int N = 8;
int K = 5;
int[] memo = new int[N+1];
for(int i=0; i<N+1;i++)
memo[i] = -1;
System.out.println(NumberOfways(N,K,1,memo));
}
Answer for N=8, K=5 is 120, which is completely wrong. It should be 18.
But, following piece of code with global counter works and I am having difficult time understanding the difference. I am sure answer lies with the difference in recursion tree. But I am having difficulty visualizing the difference.
void NumberOfwaysWithGlobalCounter(int total, int K, int start){
if (total < 0) return;
if (total == 0) counter++;
for(int i=start;i<=K;i++){
NumberOfwaysWithGlobalCounter(total-i,K,i);
}
return;
}
public static void main(String[] args)
{
int N = 8;
int K = 5;
counter=0;
NumberOfwaysWithGlobalCounter(N,K,1);
System.out.println(counter);
}
Please help!!
Make a table where one axis represents the sum (n), and the other axis represents the max digit among all solutions (so integers from 1 to k). The cells hold the count of all solutions that sum to n and have a max digit matching their column.
Then, to go from n-1 to n, set the (n, i) cell equal to the sum of the counts all solutions in the n-1 row with max_digits <= i. This represents taking these solutions and appending an i.

finding longest sequence of consecutive numbers

Problem H (Longest Natural Successors):
Two consecutive integers are natural successors if the second is the successor of the first in the sequence of natural numbers (1 and 2 are natural successors). Write a program that reads a number N followed by N integers, and then prints the length of the longest sequence of consecutive natural successors.
Example:
Input 7 2 3 5 6 7 9 10 Output 3 this is my code so far and i have no idea why it does not work
import java.util.Scanner;
public class Conse {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int[] array = new int[x];
for (int i = 0; i < array.length; i++) {
array[i] = scan.nextInt();
}
System.out.println(array(array));
}
public static int array(int[] array) {
int count = 0, temp = 0;
for (int i = 0; i < array.length; i++) {
count = 0;
for (int j = i, k = i + 1; j < array.length - 1; j++, k++) {
if (Math.abs(array[j] - array[k]) == 1) {
count++;
} else {
if (temp <= count) {
temp = count;
}
break;
}
}
}
return temp + 1;
}
}
Why two loops? What about
public static int array(final int[] array) {
int lastNo = -100;
int maxConsecutiveNumbers = 0;
int currentConsecutiveNumbers = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == lastNo + 1) {
currentConsecutiveNumbers++;
maxConsecutiveNumbers = Math.max(maxConsecutiveNumbers,
currentConsecutiveNumbers);
} else {
currentConsecutiveNumbers = 1;
}
lastNo = array[i];
}
return Math.max(maxConsecutiveNumbers, currentConsecutiveNumbers);
}
This seems to work:
public static int longestConsecutive(int[] array) {
int longest = 0;
// For each possible start
for (int i = 0; i < array.length; i++) {
// Count consecutive.
for (int j = i + 1; j < array.length; j++) {
// This one consecutive to last?
if (Math.abs(array[j] - array[j - 1]) == 1) {
// Is it longer?
if (j - i > longest) {
// Yup! Remember it.
longest = j - i;
}
} else {
// Start again.
break;
}
}
}
return longest + 1;
}
public void test() {
int[] a = new int[]{7, 2, 3, 5, 6, 7, 9, 10};
System.out.println("Longest: " + Arrays.toString(a) + "=" + longestConsecutive(a));
}
prints
Longest: [7, 2, 3, 5, 6, 7, 9, 10]=3
Since your question has "Problem H" associated with it, I'm assuming you are just learning. Simpler is always better, so it usually pays to break it down into "what has to be done" before starting on a particular road by writing code that approaches the problem with "how can this be done."
In this case, you may be over-complicating things with arrays. A number is a natural successor if it is one greater than the previous number. If this is true, increment the count of the current sequence. If not, we're starting a new sequence. If the current sequence length is greater than the maximum sequence length we've seen, set the max sequence length to the current sequence length. No arrays needed - you only need to compare two numbers (current and last numbers read).
For example:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int maxSequenceLen = 0; // longest sequence ever
int curSequenceLen = 0; // when starting new sequence, reset to 1 (count the reset #)
int last = 0;
for(int i = 0; i < N; i++) {
int cur = scan.nextInt();
if ((last+1) == cur){
++curSequenceLen;
}
else{
curSequenceLen = 1;
}
if (curSequenceLen > maxSequenceLen){
maxSequenceLen = curSequenceLen;
}
last = cur;
}
System.out.println(maxSequenceLen);
Caveat: I'm answering this on a computer that does not have my Java development environment on it, so the code is untested.
I'm not sure I understand this question correctly. The answer's written here assumes that the the natural successors occur contiguously. But if this is not the same then the solution here might not give the correct answer.
Suppose instead of [7 2 3 5 6 7 9 10] the input was [7 2 6 3 7 5 6 9 10] then the answer becomes 2 while the natural successor [5 6 7] is present in the array.
If the input is not sorted we'll have to use a different approach. Like using HashSet
Load the entire array into a HashSet which removes duplicates.
Pick the first value from the HashSet and assigned it to start and end and remove it from the set.
Now decrements start and check if it is present in the HashSet and continue till a particular value for start is not present int the HashSetwhile removing the value being searched from the set.
Do the same for end except that you will have to increase the value of end for each iteration.
We now have to continuous range from start to end present in the set and whose range is current_Max = end - start + 1
In each iteration we keep track of this current_Max to arrive at the longest natural successor for the entire array.
And since HashSet supports Add, Remove, Update in O(1) time. This algorithm will run in O(n) time, where n is the length of the input array.
The code for this approach in C# can be found here

Adding integers of array upto some number (java)

I have a java question.
I have two int[] arrays: cdn and cmn.
cdn is {1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
cmn is {8,8,16}
I need a program that adds the consecutive integers of cdn[] upto cmn[init] and returns the number of integers used in the addition. Then it continues adding from the next integer of cdn[] upto cmn[init+1] and return the number of integers. For the arrays above this is done 3 times: the first time the return value is 7, the second time it is 7, and the third time it is 16. The number of integers can be collected in and int[] which is {7,7,16}. The code I have is:
int numofints = 0;
int init = 0;
int plus = 0;
while(init < m2){
for(int j = 0; j < cdn.length; j++){
plus += cdn[j];
numofints++;
if(plus == cmn[init]){
init++;
}
}
}
System.out.print(numofints);
in which m2 is the size of cmn, which is 3 in this case. Note that my program starts to loop from the beginning of cdn over and over again, because j = 0. I want it to start where it ended the previous time!
I hope you have a solution for me.
Bjorn
just pull j out of the outer loop, and use a while, instead of for, for the inner loop
and you also need to put plus = 0 into the loop
public class T {
public static void main(String[] args) {
int[] cdn = {1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int[] cmn = {8,8,16};
int numofints = 0;
int init = 0;
int m2 = 3;
int j = 0;
while(init < m2){
int plus = 0;
while(j < cdn.length){
plus += cdn[j];
j++;
numofints++;
if(plus == cmn[init]){
init++;
System.out.println(j);
break;
}
}
if (j == cdn.length) break;
}
}
}
Shoudln't if(plus == cmn[init]){ be if(plus >= cmn[init])? If you change cdn at all and "plus" happens to go over "cmn[init]", your code is going to break.

Where does this program get its numbers from, and why is this caused by increasing 1 array size? (Java)

This program simply is supposed to eliminate duplicates from an array. However, the second for loop in the eliminate method was throwing an out of bounds exception. I was looking and couldnt see how that could be, so I figured I would increase the array size by 1 so that I would get it to work with the only downside being an extra 0 tacked onto the end.
To my surprise, when I increased tracker[]'s size from 10 to 11, the program prints out every number from 0 to 9 even if I dont imput most of those numbers. Where do those numbers come from, and why am I having this problem?
import java.util.*;
class nodupes
{
public static void main(String[] args)
{
int[] dataset = new int[10];
//getting the numbers
for (int i = 0; i <= 9 ; i++)
{
Scanner input = new Scanner(System.in);
System.out.println("Enter a one digit number");
dataset[i] = input.nextInt();
}
int[] answer = (eliminateduplicates(dataset));
System.out.println(Arrays.toString(answer));
}
public static int[] eliminateduplicates(int[] numbers)
{
boolean[] tracker = new boolean[11];
int arraysize = 1;
for(int k = 0; k <= 9; k++)
{
if(tracker[numbers[k]] == false)
{
arraysize++;
tracker[numbers[k]] = true;
}
}
int[] singles = new int[arraysize];
for(int l = 0; l <= arraysize; l++)
{
if(tracker[l] == true)
{
singles[l] = l;
}
}
return singles;
}
}
The exception was occuring at this part
if(tracker[l] == true)
but only when trackers size was 10. At 11 it just prints [0,1,2,3,4,5,6,7,8,9]
EDIT: The arraysize = 1 was a hold over from debugging, originally it was at 0
EDIT: Fixed it up, but now there is a 0 at the end, even though the array should be getting completely filled.
public static int[] eliminateduplicates(int[] numbers)
{
boolean[] tracker = new boolean[10];
int arraysize = 0;
for(int k = 0; k < numbers.length; k++)
{
if(tracker[numbers[k]] == false)
{
arraysize++;
tracker[numbers[k]] = true;
}
}
int[] singles = new int[arraysize];
int counter = 0;
for(int l = 0; l < arraysize; l++)
{
if(tracker[l] == true)
{
singles[counter] = l;
counter++;
}
}
return singles;
}
Since arrays start at 0, your arraysize will be one larger than the number of unique numbers, so your final loop goes through one too many times. In other words "l" (letter l -- try using a different variable name) will get to 11 if you have 10 unique numbers and tracker only has item 0-10, thus an out of bounds exception. Try changing the declaration to
int arraysize = 0;
Once again defeated by <=
for(int l = 0; l <= arraysize; l++)
An array size of 10 means 0-9, this loop will go 0-10
For where the numbers are coming from,
singles[l] = l;
is assigning the count values into singles fields, so singles[1] is assigned 1, etc.
Edit like 20 because I should really be asleep. Realizing I probably just did your homework for you so I removed the code.
arraySize should start at 0, because you start with no numbers and begin to add to this size as you find duplicates. Assuming there was only 1 number repeated ten times, you would've created an array of size 2 to store 1 number. int arraysize = 0;
Your first for loop should loop through numbers, so it makes sense to use the length of numbers in the loop constraint. for( int i = 0; i < numbers.length; i ++)
For the second for loop: you need to traverse the entire tracker array, so might as well use the length for that (tracker.length). Fewer magic numbers is always a good thing. You also need another variables to keep track of your place in the singles array. If numbers was an array of 10 9s, then only tracker[9] would be true, but this should be placed in singles[0]. Again, bad job from me of explaining but it's hard without diagrams.
Derp derp, I feel like being nice/going to bed, so voila, the code I used (it worked the one time I tried to test it):
public static int[] eliminateduplicates(int[] numbers)
{
boolean[] tracker = new boolean[10];
int arraysize = 0;
for(int k = 0; k < numbers.length; k++)
{
if(tracker[numbers[k]] == false)
{
arraysize++;
tracker[numbers[k]] = true;
}
}
int[] singles = new int[arraysize];
for(int l = 0, count = 0; l < tracker.length; l++)
{
if(tracker[l] == true)
{
singles[count++] = l;
}
}
return singles;
}
I feel you are doing too much of processing for getting a no duplicate, if you dont have the restriction of not using Collections then you can try this
public class NoDupes {
public static void main(String[] args) {
Integer[] dataset = new Integer[10];
for (int i = 0; i < 10; i++) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a one digit number");
dataset[i] = input.nextInt();
}
Integer[] arr = eliminateduplicates(dataset);
for (Integer integer : arr) {
System.out.println(integer);
}
}
public static Integer[] eliminateduplicates(Integer[] numbers) {
return new HashSet<Integer>(Arrays.asList(numbers)).toArray(new Integer[]{});
}
}
To answer your question your final loop is going one index more than the size.
The range of valid indexes in an array in Java is [0, SIZE), ie. from 0 up to arraysize-1.
The reason you're getting the exception is because in your loop you're iterating from 0 to arraysize inclusively, 1 index too far:
for(int l = 0; l <= arraysize; l++)
Therefore when you get to if(tracker[l] == true) in the last iteration, l will equal arraysize and tracker[l] will be outside the bounds of the array. You can easily fix this by changing <= to < in your for loop condition.
The reason that the problem goes away when the size of your array is changed from 10 to 11 has to do with arraysize being incremented up to 10 in the for loop above the one causing the problems. This time, singles[10] is a valid element in the array since the range of indexes in your array is now [0, 11).
EDIT: Actually arraysize has the potential to be incremented to 11, I thought it was initialised to 0 in which case it would only get to 10. Either way the above is still valid; the last index you try and access in your array must be 1 less than the length of your array in order to avoid the exception you're getting, since arrays are zero-based. So yeah, long story short, <= should be <.

java- "-1" position

I have this question:
The method accepts an integer array as its input and returns a new array which is a
permutation of the input array. The method fix34 rearranges the input array such
that every 3 is immediately followed by a 4 (e.g. if there is a 3 at position i, there will
be a 4 at position i+1). The method keeps the original positions of the 3s but may
move any other number, moving the minimal amount of numbers.
Assumptions regarding the input:
The array contains the same number of 3's and 4's (for every 3 there is a 4)
There are no two consecutive 3s in the array
The matching 4 for a 3 at some position i is at position j where j > i
ok, so this is what I wrote:
public class Fix34 {
public static void main(String[] args){
int [] args1 ={3,1,2,3,5,4,4};
int[] args11=fix34(args1);
for (int i = 0; i<=args11.length-1;i++ ){
System.out.print(args11[i]+" ");}}
public static int pos (int[] arr){
int i= arr.length-1;
while (arr[i]!=4){
i=-1;
}
return i;
}
public static int[] fix34(int[] nums){
for(int i = 0; i<=nums.length-1; i++){
if (nums[i] == 3){
nums[pos(nums)]=nums[i+1];
nums[i+1]=4;
}
}
return nums;
}
}
when I insert arrays such {3,2,1,4} it works, but with the array as written in the code, it gives me the error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at Fix34.pos(Fix34.java:15)
at Fix34.fix34(Fix34.java:25)
at Fix34.main(Fix34.java:6)
how come the arrays gets to -1 position?!
Thanks
you are setting it to -1 here:
i=-1;
Your issue in in this piece of code
public static int pos (int[] arr){
int i= arr.length-1;
while (arr[i]!=4){
i=-1;
}
return i;
}
If the last element in the array is 4 the while loop is never entered so arrays like 3, 1, 2, 4 are fine. Otherwise the loop is entered and i is set to -1. I think that you mean to decrement. In that case replace
i=-1
with
i--
or
i=i-1
and as mentioned in another answer make sure i doesn't go below 0.
I think you ment
i-= 1;
instead of that:
i=-1;
Whoa there that is a little overblown for this problem. Nested loops are they key hereā€¦come take a look
public int[] fix34(int[] nums) {
for(int a = 0; a < nums.length; a++){ //we see 4's first
for(int b = 0; b < nums.length - 1; b++){ //then the nested loop finds a 3
//length - 1 to stay in bounds, although not needed here...
if(nums[a] == 4 && nums[b] == 3){
//swap
int tmp = nums[b + 1];
nums[b + 1] = nums[a];
nums[a] = tmp;
}
}
}
return nums;
}

Categories