Java/Replacing elements in a simple array with a while loop - java

I have two Arrays (not ArrayLists):
A: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 0, 0, 0, 0, 0];
B: [50, 100, 150, 200, 250];
I need to create a while loop that inserts the values from array B to array A.
For example, If position/index K = 5, then the result should be:
A: [0, 5, 10, 15, 20, 25, 50, 100, 150, 200, 250, 30, 35, 40, 45];
Such that the contents of B[] get inserted in-place into A[], at index K. This pushes existing contents to the right, and deletes any content that is pushed outside the bounds of the array.
Then I need to use a do while loop to print out the new A values.
I need to do all that using 2 loops: 1 while loop for replacing and a do While loop for printing. Even if that is not necessary, those are the conditions given to me.
In the context of my question, all that is mentioned in the assignment is:
Nest all the elements of Array B in the Array A according to the element with an index K.
Sorry if I am being unclear, I began learning programming 5 days ago and I am not that familiar as to what details I should mention, maybe the code that I have wrote up until now can help to bring some more context (The first while loop is where I try to do what I am asking in this thread):
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Rainers {
public static void main(String[] args) {
int A[] = new int[15];
int B[] = new int[5];
for (int i = 10; i < A.length; i++) {
A[i] = 0;
}
int K;
Scanner sc = new Scanner(System.in);
System.out.println("Name Lastname ID1 ID2");
System.out.print("K=");
if (sc.hasNextInt())
K = sc.nextInt();
else {
System.out.println("input-output error");
sc.close();
return;
}
sc.close();
if (K >= 0 && K <= 9) {
for (int k = 0; k <= 9; ++k) {
A[k] = k * K;
}
for (int k = 0; k <= 4; ++k) {
B[k] = 10 * (k + 1) * K;
}
}
else if (K < 0 || K > 9) {
K = 5;
Random diapazons = new Random();
for (int c = 0; c < 10; ++c) {
A[c] = diapazons.nextInt(50);
}
for (int c = 0; c < 5; ++c) {
B[c] = diapazons.nextInt(100 - 50 + 1) + 50;
}
}
sc.close();
System.out.println("A: " + Arrays.toString(A));
System.out.println("B: " + Arrays.toString(B));
int count = K;
while (count > K && count <= A.length) {
int x = 0;
x++;
A[K] = B[x];
count++;
}
System.out.println("A: " + Arrays.toString(A));
}
}
Thank you in advance for your time, I really appreciate it.

I'm also a noobie in stack overflow .
First of all I suggest you to use ArrayList as they are more flexible once learnt.
It's not a clean or optimised code but,
Try to add the following algorithm into your code .
I am a noobie trying to be active and learn and participate in stack overflow. This code might have blunder bugs in it. But I hope I helped explain the approach of the alogirthm.
void mergep(ArrayList<Integer> a[], ArrayList<Integer> b[], ArrayList<Integer> c)
{
int acursor = c;
int bcursor = 0;
while(acursor<= b.length())
{
int shiftcursor = b.length()-1;
while(shiftcursor>acursor)
{
a[shiftcursor+1] = a[shiftcursor];
shiftcursor--;//This shifts all the existing entries to the right
}
a[acursor] = b[bcursor];
bcursor++;
acursor++;
}
}

Your code
int count = K;
while (count > K && count <= A.length) {
int x = 0;
x++;
A[K] = B[x];
count++;
}
has a few problems:
It does nothing because you set count = K and then give the condition count > K.
The condition count <= A.length will cause a AIOOBE because the last element is at A.length - 1.
You want to start accessing B from the beginning, but you increment its value before the first access to it.
Since you are iterating over B as well, you will need a stop condition in the loop to not attempt to access indexes greater than it has.
You are putting values of B into A, but at the same time you are losing the ones in A because they are overridden. You need to store the value at the right place before you overwrite it.
Once you fix these mistakes you will solve your problem. You can edit your question with your attempt at solving these.

The elements in A have to be moved before the elements from B can be inserted. Begin by shifting all values from the back of the array to avoid losing any elements. The shift of the elements should look as follows when moving the elements one step to the right:
1. [5, 10, 15]
2. [5, 10, 15] 15
3. [5, 10, 10] 15
4. [5, 5, 10] 15
5. [2, 5, 10] 15
The element 15 will be dropped from the array, but 5 and 10 will still be kept in the array. 5's old location can then be assigned a new value, e.g. 2.
Iterate from the last index of the array and move the elements so that B's elements can fit. But instead of one step as above, move the elements the length of B. Stop iterating when index K is reached, since no more elements will be inserted or moved. The below java code moves the elements of array A and assigns the values from B. The first if statement avoids indexing out of bounds. The second if statement checks if the elements from B should be inserted into A.
int idxA = A.length - 1;
int idxB = B.length - 1;
while(idxA >= K){
if (idxA + B.length < A.length)
A[idxA + B.length] = A[idxA];
if (idxA < B.length + K){
A[idxA] = B[idxB];
idxB--;
}
idxA--;
}
If you are unsure about how the code works, use pen and paper to write the current state of each array at each step in the code.

I modified the code as per output.
// while (count > K && count <= A.length) {
// int x = 0;
// x++;
// A[K] = B[x];
// count++;
//
// }
Change to new code
System.arraycopy(A, K, A, K + B.length, B.length);
System.arraycopy(B, 0, A, K, B.length);

Related

How can I create a java program to find the amount of consecutive numbers in an array?

I'm trying to make a Java program to find the number of consecutive numbers in an array. For example, if an array has the values, 1,8,10,4,2,3 there are 4 numbers that are consecutive (1,2,3,4). I've created this program, but I'm getting an error on lines 28 and 31 for ArrayIndexOutOfBoundsException, how do I fix the error? (I'm not even sure if the program I made will work if the errors are fixed). Note: I know there are many solutions online for this but I'm a beginner programmer, and I'm trying to do this a more simple way.
import java.util.Arrays;
class Main {
public static void main(String[] args) {
consec();
}
static void consec()
{
int[] nums = {16, 4, 5, 200, 6, 7, 70, 8};
int counter=0;
Arrays.sort(nums);
for (int i=0; i < nums.length; i++)
if (i != nums.length - 1)
System.out.print(nums[i] + ", ");
else
System.out.print(nums[i]);
for (int i=0; i < nums.length; i++)
for (int j=i; j < nums.length - i; j++)
if (nums[j + 1] - 1 == nums[j])
counter++;
else if (nums[j+1]==counter)
System.out.print("Consective amount is" + counter);
}
}
The issue for the exception lies within the access of nums[j + 1].
Note that j can be as large as nums.length - 1 due to the for loop.
Thus j + 1 can be nums.length which is an OutOfBounds array index.
Secondly I don't think your code solves the task - for example you only print a result if the number of consecutive numbers you've counted appears within the array. However I don't see how these things should correlate.
You can solve the problem like this:
for (int i = 1; i < nums.length; i++) {
if (nums[i-1] == nums[i] - 1) {
counter+= 2;
int j = i + 1;
while (j < nums.length && nums[j] - 1 == nums[j-1]) {
j++;
counter++;
}
i = j;
}
}
System.out.print("Consective amount is" + counter);
Note that the index i starts at 1, thus we can be assured that nums[i-1] exists.
If nums has only one element we should not run into any issues as the condition i < nums.length would not be fulfilled. We count two consequitves for every start of a sequence and one addition element for every following consequtive (while loop).
When the sequence ends we try finding a new sequence behind it by moving the index i to the end of the last sequence (j = i).
The above code will sum multiple distinct sequences of consequtive numbers. For example the array [17,2,20,18,4,3] has five consequitve numbers (2,3,4 and 17,18)
The algorithm has a time colpexity within O(n) as we either increase i or j by at least on and skip i to j after each sequence.
I would recommend re-thinking your approach to scanning over the array. Ideally you should only require one for-loop for this problem.
I personally created a HashSet of Numbers, which cannot hold duplicates. From there, you can iterate from 1 to nums.length-1, and check if nums[i] - 1 == nums[i-1] (ie: if they're consecutive). If they are equal, you can add both numbers to the HashSet.
Finally, you actually have the set of consecutive numbers, but for this question, you can simply return the size of the set.
I strongly recommend you attempt this problem and follow my explanation. If you simply require the code, this is the method that I came up with.
public static int countConsecutive(int[] nums) {
Set<Integer> consecutive = new HashSet<>();
if (nums.length <= 1)
return 0;
Arrays.sort(nums);
for (int i = 1; i < nums.length; i++) {
if (nums[i] != nums[i - 1] + 1)
continue;
consecutive.add(nums[i]);
consecutive.add(nums[i - 1]);
}
return consecutive.size();
}
Here is another approach where sorting is not necessary. It uses a BitSet. And as in your example, is presumes positive numbers (BitSet doesn't permit setting negative positions).
int[] values = {4, 3, 10, 11, 6, 1, 4, 8, 7};
set the corresponding bit positions based on the values.
BitSet bits = new BitSet();
for (int i : values) {
bits.set(i);
}
Initialize some values for output, starting bit position, and the set length.
BitSet out = new BitSet();
int start = 0;
int len = bits.length();
Now iterate over the bit set finding the range of bits which occupy adjacent positions. Those will represent the consecutive sequences generated when populating the original BitSet. Only sequences of two or more are displayed.
while (start < len) {
start = bits.nextSetBit(start);
int end = bits.nextClearBit(start+1);
if (start != end-1) {
// populate the subset for output.
out.set(start,end);
System.out.println(out);
}
out.clear();
start = end;
}
prints
{3, 4}
{6, 7, 8}
{10, 11}
If you just want the largest count, independent of the actual values, it's even simpler. Just use this in place of the above after initializing the bit set.
int len = bits.length();
int total = 0;
while (start < len) {
start = bits.nextSetBit(start);
int end = bits.nextClearBit(start + 1);
if (end - start > 1) {
total += end - start;
}
start = end;
}
System.out.println(total);

Is there a more efficient form of sorting this array than bubblesort given the problem criteria?

I was practicing some more problems on HackerRank and I ran into this one called "New Year Chaos". Basically the premise is to sort the array and count the switches made. The catch is no number is allowed to make more than 2 switches. BubbleSort passes the first few tests, but times out on the rest. Is there a more efficient array sorting algo that still takes into account the number of switches? I tried mergeSort and quickSort but it's hard to track the switches when dividing the array like that.
Problem prompt:
It's New Year's Day and everyone's in line for the Wonderland rollercoaster ride! There are a number of people queued up, and each person wears a sticker indicating their initial position in the queue. Initial positions increment by from at the front of the line to at the back.
Any person in the queue can bribe the person directly in front of them to swap positions. If two people swap positions, they still wear the same sticker denoting their original places in line. One person can bribe at most two others. For example, if n = 8 and Person 5 bribes Person 4, the queue will look like this: {1, 2, 3, 5, 4, 6, 7, 8}.
Fascinated by this chaotic queue, you decide you must know the minimum number of bribes that took place to get the queue into its current state!
public class LineBribing {
static int[] replace(int[] q, int i, int n) {
int temp = q[i];
q[i] = q[n];
q[n] = temp;
return q;
}
static void minimumBribes(int[] q) {
int count = 0;
for (int i = 0; i < q.length - 1; i++) {
if (q[i] > i + 3 || q[i] < i - 1) {
System.out.println("Too chaotic");
return;
}
if (q[i] > q[i + 1]) {
count++;
replace(q, i, i + 1);
i = 0;
}
}
System.out.println(count);
}
public static void main(String[] args) {
int[] test = {1, 2, 5, 3, 4, 7, 8, 6};
int[] test2 = {1, 2, 5, 3, 7, 8, 6, 4};
minimumBribes(test);
minimumBribes(test2);
}
}
Given the input in the main method, the output should be 4 for test 1 (switches: 5, 3 at index = 3 | 5, 4 at index = 4 | 8, 6 at index = q.length - 1 | 7, 6 at index = q.length - 2) and "Too Chaotic" for test 2 (Because 5 is > 2 switches away from its initial position)
I think this problem don't need to sort the array. You only need count the number of person who overtake a person. Note that:
a person can bribe at most 2 different persons
a person can bribe who is in the front of him
So, you should judge that anyone bribe more than 2 persons first. Then count the number of overtake person.
My Java code like this:
int ans = 0;
for (int i = q.length - 1; i >= 0; i--) {
if (q[i] - (i + 1) > 2) {
System.out.println("Too chaotic");
return;
}
for (int j = Math.max(0, q[i] - 2); j < i; j++) {
if (q[j] > q[i]) {
ans++;
}
}
}
System.out.println(ans);
This is my java 7 code for this problem.
public static void minimumBribes(List<Integer> q) {
int count = 0;
for(int i = q.size()-1; i >= 0; i--){
if(q.get(i) != (i+1)){
if((i+1) == q.get(i-1) && (i - 1) >= 0){
Collections.swap(q, i-1, i);
count++;
}else if((i+1) == q.get(i-2) && (i-2) >= 0){
Collections.swap(q, i-2, i-1);
Collections.swap(q, i-1, i);
count+=2;
}else{
System.out.println("Too chaotic");
return;
}
}
}
System.out.println(count);
}

Is this the correct implementation of an insertion sort?

Hello I have done an insertion sort in Java but I do not know whether I have implemented this correctly. Can anybody collaborate ?
I think insertion sort needs to include a while loop within a for loop
hence I implemented this but I do not know whether it is correct.
// ------------------------------------------------------------
import java.lang.Math; // headers MUST be above the first class
import java.util.Arrays;
// one class needs to have a main() method
public class Insertionsort {
// arguments are passed using the text field below this editor
public static void main(String[] args) {
// --------------------------------------------- insertion sort
int mainInsersionSortArray[] = {64, 25, 12, 22, 11, 10, 9, 8, 7, 6, 5, 4, 3};
int insertionSortTemporaryValue = 0;
System.out.println("Array before insertion sort");
for (int z = 0; z < mainInsersionSortArray.length; z++) {
System.out.println(mainInsersionSortArray[z]);
}
int x1;
for (int k0 = 1; k0 < mainInsersionSortArray.length; k0++) {
x1 = k0;
while (x1 != 0) {
if (mainInsersionSortArray[x1] < mainInsersionSortArray[x1 - 1]) {
insertionSortTemporaryValue = mainInsersionSortArray[x1];
mainInsersionSortArray[x1] = mainInsersionSortArray[x1 - 1];
mainInsersionSortArray[x1 - 1] = insertionSortTemporaryValue;
}
x1 = x1 - 1;
}
}
System.out.println("\n" + "Array after insertion sort");
for (int z1 = 0; z1 < mainInsersionSortArray.length; z1++) { // integerArray.lenght - looping through the whole array starting from i[0]
System.out.println(mainInsersionSortArray[z1]);
}
}
}
Insertion sort implemented in java.
Assume that after a number of steps of the algorithm, the part A[0:k[ (i.e. k excluded) of the array is sorted. In the next step, we consider the element A[k], search its insertion place and shift all elements after this location. This is better done in a single pass by keeping a copy of A[k], shifting the larger elements and putting the copied element at the right place. To avoid buffer overflow, the search should stop at index 0.
The inner loop reads
int Save= A[k];
for ( ; k >= 0 && A[k-1] > Save; k--) // Loop until you can insert
{
A[k]= A[k-1]; // Shift
}
A[k]= Save;
A slightly better variant avoids unnecessary copies if A[k] is already at the right place:
if (A[k] <= A[k-1])
{
int Save= A[k];
A[k]= A[k-1]; // Shift
for (k--; k >= 0 && A[k-1] > Save; k--) // Loop until you can insert
{
A[k]= A[k-1]; // Shift
}
A[k]= Save;
}
Beware that it can only be used provided k > 0.
Now the outer loop just grows the sorted part A[0..j[ with
for (j= 1; j < n; j++)
{
k= j;
"Inner loop"
}

Divide an Array in equal size, such that value of given function is minimum

I've came across the following problem statement.
You have a list of natural numbers of size N and you must distribute the values in two lists A and B of size N/2, so that the squared sum of A elements is the nearest possible to the multiplication of the B elements.
Example:
Consider the list 7 11 1 9 10 3 5 13 9 12.
The optimized distribution is:
List A: 5 9 9 12 13
List B: 1 3 7 10 11
which leads to the difference abs( (5+9+9+12+13)^2 - (1*3*7*10*11) ) = 6
Your program should therefore output 6, which is the minimum difference that can be achieved.
What I've tried:
I've tried Greedy approach in order to solve this problem. I took two variables sum and mul. Now I started taking elements from the given set one by one and tried adding it in both the variables and calculated current
square of sum and multiplication. Now finalize the element in one of the two sets, such that the combination gives minimum possible value.
But this approach is not working in the given example itselt. I can't figure out what approach could be used here.
I'm not asking for exact code for the solution. Any possible approach and the reason why it is working, would be fine.
EDIT:
Source: CodinGame, Community puzzle
Try out this:
import java.util.Arrays;
public class Test {
public static void main(String [] args){
int [] arr = {7, 11, 1, 9, 10, 3, 5, 13, 9, 12};
int [][] res = combinations(5, arr);
int N = Arrays.stream(arr).reduce(1, (a, b) -> a * b);
int min = Integer.MAX_VALUE;
int [] opt = new int [5];
for (int [] i : res){
int k = (int) Math.abs( Math.pow(Arrays.stream(i).sum(), 2) - N/(Arrays.stream(i).reduce(1, (a, b) -> a * b)));
if(k < min){
min = k;
opt = i;
}
}
Arrays.sort(opt);
System.out.println("minimum difference is "+ min + " with the subset containing this elements " + Arrays.toString(opt));
}
// returns all k-sized subsets of a n-sized set
public static int[][] combinations(int k, int[] set) {
int c = (int) binomial(set.length, k);
int[][] res = new int[c][Math.max(0, k)];
int[] ind = k < 0 ? null : new int[k];
for (int i = 0; i < k; ++i) {
ind[i] = i;
}
for (int i = 0; i < c; ++i) {
for (int j = 0; j < k; ++j) {
res[i][j] = set[ind[j]];
}
int x = ind.length - 1;
boolean loop;
do {
loop = false;
ind[x] = ind[x] + 1;
if (ind[x] > set.length - (k - x)) {
--x;
loop = x >= 0;
} else {
for (int x1 = x + 1; x1 < ind.length; ++x1) {
ind[x1] = ind[x1 - 1] + 1;
}
}
} while (loop);
}
return res;
}
// returns n choose k;
// there are n choose k combinations without repetition and without observance of the sequence
//
private static long binomial(int n, int k) {
if (k < 0 || k > n) return 0;
if (k > n - k) {
k = n - k;
}
long c = 1;
for (int i = 1; i < k+1; ++i) {
c = c * (n - (k - i));
c = c / i;
}
return c;
}
}
Code taken from this stackoverflow answer, also take a look at this wikipedia article about Combinations.
I am not sure if there is any exact solution in polynomial time. But you could try a simulated annealing based approach.
My approach would be:
Initialize listA and listB to a random state
With probability p run greedy step, otherwise run a random step
Keep track of the state and corresponding error (with a HashMap)
Greedy step: Find one element you can move between the list that optimizes the error.
Random Step: Pick a random element from either of these two sets and calculate the error. If the error is better, keep it. Otherwise with probability of q keep it.
At either of these two steps make sure that the new state is not already explored (or at least discourage it).
Set p to a small value (<0.1) and q could depend on the error difference.

Iterating over a sorted array and storing the count of distinct integers

Can somebody PLEASE answer my specific question, I cannot use material not covered in class yet and must do it this way.
I'm trying to iterate over a sorted array and if the previous number == the current number it stores the count in possiton n of a new array; when the previous number != the current number, it then moves to n+1 on the new array and starts counting again.
I'm debugging it now but having trouble working out what it isn't work. Any help is much appreciated.
// Get the count of instances.
int[] countOfNumbers = new int[50]; // Array to store count
int sizeOfArray = 0; // Last position of array filled
int instanceCounter = 1; // Counts number of instances
int previousNumber = 0; // Number stored at [k-1]
for (int k=1; k < finalArrayOfNumbers.length; k++) {
previousNumber = finalArrayOfNumbers[k-0];
if (previousNumber == finalArrayOfNumbers[k]) {
instanceCounter++;
countOfNumbers[sizeOfArray] = instanceCounter;
}
instanceCounter = 1;
sizeOfArray++;
countOfNumbers[sizeOfArray] = instanceCounter;
Don't worry about mapping or anything, I just need to know how If I have an array of:
[20, 20, 40, 40, 50]
I can get back
[2, 2, 1]
There's lots of neat tools in the Java API so you can avoid doing a lot of this yourself:
List<Integer> list = Arrays.asList(20, 20, 40, 40, 50);
Map<Integer, Integer> freq = new LinkedHashMap<>();
for (int i: list) {
freq.put(i, Collections.frequency(list, i));
}
System.out.println(freq.values());
That'll print [2, 2, 1] like you wanted.
Alternatively if you'd like a list of only the distinct values in the list, you can use an implementation of Set.
But since you're restricted because this is a class assignment, you could do something like this instead:
int[] a = { 20, 20, 40, 40, 50 };
int[] freq = new int[a.length];
// count frequencies
for (int i = 1, j = 0, count = 1; i <= a.length; i++, count++) {
if (i == a.length || a[i] != a[i - 1]) {
freq[j++] = count;
count = 0;
}
}
// print
for (int i = 0; i < freq.length && freq[i] != 0; i++) {
System.out.println(freq[i]);
}
And the output is still the same.
I put comments in the two places you were off, here's your fixed code.
for (int k = 1; k < finalArrayOfNumbers.length; k++) {
previousNumber = finalArrayOfNumbers[k - 1]; // changed 0 to 1
if (previousNumber == finalArrayOfNumbers[k]) {
instanceCounter++;
countOfNumbers[sizeOfArray] = instanceCounter;
} else { // put this last bit in an else block
instanceCounter = 1;
sizeOfArray++;
countOfNumbers[sizeOfArray] = instanceCounter;
}
}
I'm debugging it now but having trouble working out what it isn't work. Any help is much appreciated.
Here's a clue for you:
previousNumber = finalArrayOfNumbers[k-0];
if (previousNumber == finalArrayOfNumbers[k]) {
Clue: 'k - 0' has the same value as 'k' in the above.
Clue 2: If your intention is that previousNumber contains the number you are currently counting, then it needs to be initialized outside of the loop, and updates when the current number changes.
Clue 3: You should not increment sizeOfArray on every loop iteration ...
Based on your Question, I'd say that your thinking about / understanding of the code that you have written is woolly. And this is why you are having difficulty debugging it.
In order to debug a piece of code effectively, you first need a mental model of how it ought to work. Then you use the debugger to watch what is happening at key points to confirm that the program is behaving as you expect it to.
(If you come into the debugging process without a mental model, all you see is statements executing, variables changing, etcetera ... with nothing to tell you if the right thing is happening. It is like watching the flashing lights on a computer in an old movie ... not enlightening.)
I would opt for a hashmap where the key is the number and its value the count. This way you have a unique number and count. Your solution runs into a problem where you don't really know at index i, what count that number belongs to, unless your list has no duplicates and is in order with no gaps, like 1, 2, 3, 4, 5 as opposed to the case of 1, 1, 1, 1, 5, 5, 5, 5
HashMap<Integer, Integer> occurances = new HashMap>Integer, Integer>();
int[] someSortedArray = new int[10];
//fill up a sorted array
for(int index = 0; index < someSortedArray.length; index++)
{
someSortedArray[index] = index+1;
}
int current = someSortedArray[0];
int count = 1;
for(int index = 1; index < someSortedArray.length; index++)
{
if(someSortedArray[index] != current)
{
occurances.put(current, count);
current = someSortedArray[index];
count = 1;
}else
{
count++;
}
}
System.out.println(occurances);
I think this should do it (haven't compiled).
You where not increasing sizeOfArray anywhere in your for loop.
// Get the count of instances.
int[] countOfNumbers = new int[50]; // Array to store count
int sizeOfArray = 0; // Last position of array filled
int instanceCounter = 1; // Counts number of instances
int previousNumber = finalArrayOfNumbers[0]; // Number stored at [k-1]
for (int k=1; k < finalArrayOfNumbers.length; k++) {
if (previousNumber == finalArrayOfNumbers[k]) {
instanceCounter++;
}
else
{
countOfNumbers[sizeOfArray] = instanceCounter;
instanceCounter = 1;
sizeOfArray++;
previousNumber = finalArrayOfNumbers[k]
}
}
countOfNumbers[sizeOfArray] = instanceCounter;

Categories

Resources