Value changes but is only used as parameter - java

I have to re write my implementation vor insert/selection-sort in Java from PHP. So, the algorithms work fine but as it's a pain in the rear to work with all the different types when writing a quick programm I'm using a Logger Class in order to save my multi-type values.
As I haven't worked with Java for a while, there might be a problem in the code that causes this weird bug.
I have to iterate over an Integer Array in order to generate and sort random Arrays of different lengths:
public static Log[][] eval(Integer[] sizes, Algorithm alg){
Log[][] logs = new Log[sizes.length][2];
for (int i = 0; i < sizes.length; i++) {
Log[] tmp = new Log[3];
Integer[] rand = randomArray(sizes[i]);
System.out.println("Before "+Arrays.toString(rand));
tmp[0] = new Log(sizes[i], rand);
tmp[1] = alg.insertionSort(rand);
tmp[2] = alg.selectionSort(rand);
System.out.println("After "+Arrays.toString(rand));
logs[i] = tmp;
}
return logs;
}
As you see, there are 2 debugs, which will give something like this:
Before [2, 1, 4, 5, 3]
After [1, 2, 3, 4, 5]
Before [1, 8, 9, 10, 5, 4, 2, 6, 7, 3]
After [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Before [11, 15, 20, 16, 18, 8, 4, 13, 2, 19, 12, 3, 10, 5, 17, 14, 1,
9, 6, 7]
After [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20]
This is strange, as I doesnt change the rand value. Even if I put an Int array called backup outside the loop and overwrite it and print out this in the last log, it's still a sorted array. I'm trying to fix this for over a hour and I can't find the bug. It must be within the algorithm methodes for index 1/2, because Before == After when skipping these lines. But I have no clue, what's wrong, as I'm only using the array as parameter and return an Object of Log.
Here's one algorithm-method:
public Log insertionSort(Integer[] sortieren) {
double startTime = System.nanoTime();
int temp;
for (int i = 1; i < sortieren.length; i++) {
temp = sortieren[i];
int j = i;
while (j > 0 && sortieren[j - 1] > temp) {
sortieren[j] = sortieren[j - 1];
j--;
}
sortieren[j] = temp;
}
double stopTime = System.nanoTime();
double time = stopTime - startTime;
Log log = new Log("Insertion-Sort", (time/1000000), sortieren);
return log;
}
And this is my Log Class:
public class Log {
public String name;
public double time;
public int size;
public Integer[] sorted;
public Integer[] randArray;
public Log(String name, double time, Integer[] sorted){
this.name = name;
this.time = time;
this.sorted = sorted;
}
public Log(int size, Integer[] random){
this.size = size;
this.randArray = random;
}
}
Later, I want to evalue this through this method:
public static void reportLogger(Log[][] log, boolean showArray){
for (int i = 0; i < log.length; i++) {
// Show Initial Array (0th Index) -> (size, array)
for (int j = 1; j <= 2 ; j++) {
Log tmp = log[i][j];
// 1st/2nd Index -> Insert/Selection -> name, time, sortedArray by using tmp.name ,etc..
System.out.println("---------------------");*/
}
}

The array is an input parameter, but it is also modified in the first sorting method alg.insertionSort(rand). At this point, the array became a sorted array - no longer a random one. At the point alg.selectionSort(rand), all it's trying to do is sorting on a sorted array rand. In order to compare the performance, you should make a copy of the array rand:
tmp[0] = new Log(sizes[i], rand);
Integer[] array_copy_1 = Array.copyof(rand, rand.size)
tmp[1] = alg.insertionSort(array_copy_1);
Integer[] array_copy_2 = Array.copyof(rand, rand.size)
tmp[2] = alg.selectionSort(array_copy_2);

Related

How can I create an array of only "odd" numbers between 1 and n - Java?

I ran into an issue I can't seem to solve, and all the searches I do are not completely relevant to the issue I am having, and trying to implement those things to solve my issue still doesn't work. I've spent an hour trying to find another question or post somewhere that would help but can't seem to find any specific to my issue (unless Google just doesn't want to work today).
I am trying to create a method that returns an array of all of the odd numbers between 1 and n, say in this example 1 to 255.
I tried the following (here is the method currently):
import java.util.Arrays;
public class BasicJava: {
public Integer[] arrayOfOdds() {
int n = 255;
Integer[] odds = new Integer[(n+1)/2];
for(int i = 1; i < n+1; i+=2) {
odds[i/2] = i;
}
return odds;
}
}
Main Method:
import java.util.Arrays;
public class BasicJavaTest {
public static void main(String[] args) {
BasicJava test = new BasicJava();
System.out.println(Arrays.toString(test.arrayOfOdds()));
}
}
I tried using an array to do the same thing before switching to using an ArrayList (I like other data structures more than I do arrays) and converting to an array and got the same output (I will just put part of the output array to not use too much space):
[0, 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0, 25, 0, 27, 0, 29, 0, 31, 0]
What do I need to resolve this issue?
If I just wanted to print all of the odds between 1 and N using the same for loop and if statement, I would get the correct output.
Thank you
You can do this is linear time complexity and without using an ArrayList.
Your final output will always have n/2 elements so your array size can be fixed at the same. In the next step you can simply populate the values in your array.
FYR code:
int[] arr = new int[((n+1)/2)];
for(int i = 0, e = 1; i < arr.length; e += 2, i++) {
arr[i] = e;
}
You can use IntStream like this.
static int[] arrayOfOdds() {
return IntStream.iterate(1, i -> i + 2)
.takeWhile(i -> i < 256)
.toArray();
}
public static void main(String[] args) {
System.out.println(Arrays.toString(arrayOfOdds()));
}
output:
[1, 3, 5, 7, 9, 11, 13, 15, ... , 251, 253, 255]
int N = 255;
Integer[] array = new Integer[(N+1)/2];
for (int j = 1; j < N+1; j+=2) {
array[j/2] = j;
}
System.out.println(Arrays.toString(array));
You don't need to add condition to check for each integer.
Here is a simple trick to create odds number:
Start with 1 and increase 2 for next element. ( 1,3,5...)
public static void main(String[] args) {
List<Integer> arr = getOddList(255);
System.out.print(arr);
}
private static List<Integer> getOddList(int n) {
List<Integer> nums = new ArrayList<>();
for (int i = 1; i < n; i = i + 2) {
nums.add(i);
}
return nums;
}
//Output [1, 3, 5, 7, 9, 11...

Finding the number of fails between 3 sets of array

This is a simple coding questions that is asking to sum the marks for each students. If the total marks reaches the pass mark then reach to the next student. If they did not reach the pass marks then it will return as failed.
class StudentMarks {
public int getCountFailures() {
int[] student1 = {3, 2, 6, 4, 3, 6, 6, 7, 3, 2};
int[] student2 = {8, 7, 8, 9, 10, 7, 6, 8, 9, 6};
int[] student3 = {2, 5, 3, 1, 4, 3, 3, 2, 5, 6};
int[][] allStudents = {student1, student2, student3};
int numberFails = 0;
int passMark = 50;
// YOUR CODE GOES HERE
return numberFails;
}
}
Test code
int numberFails = marks.getCountFailures();
System.out.println("Number of fails = " + numberFails);
How would I implement a way to sum the marks for each of the students and return the number of fails.
The expected outcome
Number of fails = 2
Seems as a homework question, so this is not a complete answer but would help you come up with one on your own.
// will return the count of the arrays - the sum of the elements
// of which are equal to or cross the threshold.
long count =
Arrays.stream(allStudents)
.peek(a -> System.out.println(Arrays.toString(a)))
.filter(a -> thresholdSum(a) )
.count();
System.out.print(count);
This is the helper method.
public static boolean thresholdSum(int[] a) {
int threshold = 50;
int sum =0;
for (int i : a) {
sum += i;
if (sum >= threshold) {
return true;
}
}
return false;
}

How can I pick out the odd numbers and even numbers from a given array and then store them in another array?

How can I pick out the odd numbers and even numbers from a given array and then store them in another array? The flow is: the odd numbers will go to the odd[] array while the even numbers will go to the even[] array??
Here's my code, I'm not sure if this is correct since it somewhat stores and prints a mix of zeros and even numbers, no presence of odd numbers.....
int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int[] odd = new int[10];
int[] even = new int[10];
for (int i = 0; i < num.length; i++) { // For odd numbers
if (num[i] % 2 != 0) {
num[i] = odd[i];
}
System.out.println(num[i] + " ");
}
for (int j = 0; j < num.length; j++) { // For even numbers
if (num[j] % 2 == 0) {
num[j] = even[j];
}
System.out.println(num[j] + " ");
}
You can do all that in one loop - that would be way faster. To know the correct position to put the number in, add extra counter for each array.
Your kind of approach
int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int[] odd = new int[10];
int[] even = new int[10];
int oddPos = 0;
int evenPos = 0;
for (int i = 0; i < num.length; i++) {
if (num[i] % 2 == 0) {
even[evenPos] = num[i];
evenPos++;
} else {
odd[oddPos] = num[i];
oddPos++;
}
}
However this would not be the best solution as you (in most cases) cannot determine the length of odd and even arrays beforehand. Then you should use either arraylists or count the values of each or something else.
More dynamic approach
As stated before - you need to determine the size of the arrays at first
int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int oddCount = 0, evenCount = 0;
int oddPos = 0, evenPos = 0;
//get the count of each type
for (int i = 0; i < num.length; i++) {
if (num[i] % 2 == 0)
oddCount++;
else
evenCount++;
}
//define arrays in correct sizes
int[] odd = new int[oddCount];
int[] even = new int[evenCount];
//put values in arrays
for (int i = 0; i < num.length; i++) {
if (num[i] % 2 == 0) {
even[evenPos] = num[i];
evenPos++;
} else {
odd[oddPos] = num[i];
oddPos++;
}
}
the approach for detecting odd and even numbers is correct, But I think the problem with the code you wrote is that the length of odd and even arrays, isn't determinant. so for this matter, I suggest using ArrayList<Integer>, let's say you get the array in a function input, and want arrays in the output (I'll mix the arrays in the output for better performance. but separating the functions for each list extracting is also ok depending on what you're going to do with them).
Solution
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static Integer[][] separateOddnEven(int[] input) {
Integer[][] output = new Integer[2][];
List<Integer> odds = new ArrayList<>();
List<Integer> evens = new ArrayList<>();
for (int i = 0; i < input.length; ++i) {
int temp = input[i];
if (temp % 2 == 0)
evens.add(temp);
else
odds.add(temp);
}
// alternative is to use these Arraylists directly
output[0] = new Integer[odds.size()];
output[1] = new Integer[evens.size()];
output[0] = odds.toArray(output[0]);
output[1] = evens.toArray(output[1]);
return output; // index 0 has odd numbers and index 1 has even numbers.
}
public static void main(String[] args) {
int[] input = {0, 21, 24, 22, 14, 15, 16, 18};
Integer[][] output = separateOddnEven(input);
System.out.println("odd numbers :");
System.out.println(Arrays.toString(output[0]));
System.out.println("even numbers :");
System.out.println(Arrays.toString(output[1]));
}
}
output :
odd numbers :
[21, 15]
even numbers :
[0, 24, 22, 14, 16, 18]
You can collect a 2d array with two rows: even and odd as follows:
int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
// a 2d array of two rows: even and odd
int[][] arr = new int[2][];
// process a 1d array and fill a 2d array
Arrays.stream(num).boxed()
// Map<Integer,List<Integer>>
.collect(Collectors.toMap(
// key: 0 - even, 1 - odd
n -> n % 2,
// value - a list of one
// element, i.e. number
n -> new ArrayList<>(List.of(n)),
// merge duplicates
(list1, list2) -> {
list1.addAll(list2);
return list1;
}))
// fill the rows of a 2d array: even and odd
.forEach((key, value) -> arr[key] = value.stream()
.mapToInt(Integer::intValue).toArray());
// output
System.out.println("Even: " + Arrays.toString(arr[0]));
// Even: [2, 4, 6, 8, 10, 12, 14, 16]
System.out.println("Odd: " + Arrays.toString(arr[1]));
// Odd: [1, 3, 5, 7, 9, 11, 13, 15]
in lambda (3 lines)
int[] nums = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
separate even and odd nums with partitioningBy:
Map<Boolean, List<Integer>> map = IntStream.of(nums)
.boxed().collect(partitioningBy(n -> (n & 1) == 0));
…and transform the resulting List<Integer> for even and odd to int[]:
int[] even = map.get(true).stream().mapToInt(i -> i).toArray();
int[] odd = map.get(false).stream().mapToInt(i -> i).toArray();
System.out.println("even numbers: " + Arrays.toString(even));
System.out.println("odd numbers: " + Arrays.toString(odd));
even numbers: [2, 4, 6, 8, 10, 12, 14, 16]
odd numbers: [1, 3, 5, 7, 9, 11, 13, 15]

arraycopy in Binary Search

I need help with my code here please. I wanted it display the arrays every time it is splitted while containing the key value until it arrives with the simplest array with key value in it then it display "Found!". My problem is, it worked for key = 2 only and not others keys. Please help me for that.
package Search;
import java.util.*;
public class BinarySearch{
/**Example is below of what I expected which is a result I obtained from key = 2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
[1, 2, 3, 4, 5, 6]
[1, 2]
Found!
**/
public static int binarySearch(int[] list, int key){
int low = 0;
int high = list.length;
while(high >= low){
int mid = (low+high)/2;
int[] temp = new int[high];
System.arraycopy(list, low, temp, 0, high);
System.out.println(Arrays.toString(temp));
int count = 0;
if(key < list[mid]){
high = mid - 1;
if(count<temp.length){
}
}
else if(key == list[mid]){
return mid;
}
else{
low = mid + 1;
}
}
return -1;
}
public static int User(){
Scanner scan = new Scanner(System.in);
System.out.println("Enter key: ");
String input = scan.nextLine();
int user = Integer.parseInt(input);
return user;
}
public static void main(String[] args){
int[] list = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
System.out.println("The array: "+Arrays.toString(list));
System.out.println("The key is found at "+BinarySearch.binarySearch(list, BinarySearch.User()));
}
}

Rotate array by arbitrary step size without creating second array

So for a step size of 1, I want the array:
{1, 2, 3, 4}
To become:
{4, 1, 2, 3}
And for a step of size 2 the result will be:
{3, 4, 1, 2}
This is the code I'm using now:
private static int[] shiftArray(int[] array, int stepSize) {
if (stepSize == 0)
return array;
int shiftStep = (stepSize > array.length ? stepSize % array.length : stepSize);
int[] array2 = new int[array.length];
boolean safe = false;
for (int i = 0; i < array.length; i++) {
if (safe) {
array2[i] = array[i - shiftStep];
}
else {
array2[i] = array[array.length - shiftStep + i];
safe = (i+1) - shiftStep >= 0;
}
}
return array2;
}
The code is working great, but is it possible to achieve this without creating a helper array (which is array2 in the code above)?
Thanks!
You can do it without creating as big an array:
// void return type as it shifts in-place
private static void shiftArray(int[] array, int stepSize) {
// TODO: Cope with negative step sizes etc
int[] tmp = new int[stepSize];
System.arraycopy(array, array.length - stepSize, tmp, 0, stepSize);
System.arraycopy(array, 0, array, stepSize, array.Length - stepSize);
System.arraycopy(tmp, 0, array, 0, stepSize);
}
So for a 100,000 array and a step size of 10, it creates a 10-element array, copies the last 10 elements into it, copies the first 999,990 elements to be later, then copies from the temporary array back to the start of the array.
Use not the i++, but i += shiftSize and several loops (amount of them would be equal to gcd of array.length and shifSize).
Then you'll need only one int as buffer and execution time will be almost the same.
You could do it with a couple of loops, but its not easy. Using recursion is simpler in this case.
public static void main(String... args) {
for (int i = 0; i < 12; i++) {
int[] ints = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
rotateLeft(ints, i);
System.out.println(Arrays.toString(ints));
}
}
public static void rotateLeft(int[] array, int num) {
rotateLeft(array, num, 0);
}
private static void rotateLeft(int[] array, int num, int index) {
if (index >= array.length) return;
int tmp = array[(index + num) % array.length];
rotateLeft(array, num, index + 1);
array[index] = tmp;
}
prints
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
[5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4]
[6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5]
[7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6]
[8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7]
[9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8]
[10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Yes it's possible, you'd only need to temporary store one element additional to the array.
Basically what you want to do is to:
store last element in tmp var
shift all elements to the right by one starting with the second to last element
sotre tmp var as first element
repeat from step 1 depending on your stepsize
This is not tested ...
public void rotateByStep(int[] array, int step) {
step = step % array.length;
if (step == 0) {
return;
}
int pos = step;
int tmp = array[0];
boolean inc = array.length % step == 0;
for (int i = 0; i < array.length; i++) {
int tmp2 = array[pos];
array[pos] = tmp;
tmp = tmp2;
pos = (pos + step) % array.length;
if (inc && pos < step) {
array[pos] = tmp;
pos++;
tmp = array[pos];
}
}
}
The idea I'm trying to implement is as follows:
If step isn't a factor of length, then incrementing an index (pos) by step modulo length starting from zero will visit every array element once after length iterations.
If step is a factor of length, then index (incremented as above) will get back to its starting point after length / step iterations. But if you then increment by one, you can process the cycle starting at 1, and then at 2, and so on. After length iterations, we'll have visited every array element once.
The rest is just rippling the element values as we cycle through the element indexes ... with some adjustment when we increment to the next cycle.
The other complete solutions have the advantage that they are much easier to understand, but this one requires no extra heap storage (i.e. no temporary array), and does the job in array.length loop iterations.
In n- 1 iterations
#include <stdio.h>
int main(int argc, char **argv) {
int k = 0, x = 0;
int a[] = {-5,-4,-1,0,1,2,30,43,52,68,700,800,9999};
int N = 0, R = 57; /*R = No of rotations*/
int temp = 0, temp2 = 0, start = 0, iter = 0;
x = 0;
temp2 = a[x];
N = sizeof(a) / sizeof(a[0]);
for ( k = 0; k < N - 1; k++) {
x = x + R;
while ( x >= N ) {
x = x - N;
}
temp = a[x];
a[x] = temp2;
temp2 = temp;
if ( x == start ) {
start = start + 1;
x = x + 1;
temp2 = a[x];
}
iter++;
}
a[start] = temp2;
for ( k = 0; k < N; k++) {
printf(" %d", a[k]);
}
printf("\n");
printf("Done in %d iteration\n", iter);
return 0;
}

Categories