Cut and Stack the Array - java

I have an array of int as input. The array will always be a length of 2^n. I want to cut the array in half and stack it. Repeat cutting and stacking until there is only one stack. For example:
int[] array = {1,2,3,4,5,6,7,8}
if we cut the array in half we and stack them it would be:
{1,2,| 3,4}
{5,6,| 7,8}
cut it and stack again:
{1,|2}
{5,|6}
{3,|4}
{7,|8}
again:
{1}
{5}
{3}
{7}
{2}
{6}
{4}
{8}
the desired output would be an array of int from the top to the end of the stack
int[] output = {1,5,3,7,2,6,4,8}
I have tried to construct the output array by looping the input array in a particular way. Note that when I reach the array I just start from the head again. I start at the array[i] where i = 0. I get the first number this way. then I increment i by n where n is the log(array.legnth) (base 2). This is how I get the second number. For the third number, we increment i by (n + n/2). For the fourth number, we increment i by n again. I am wondering is there a pattern? Or what would be your approach to solve this problem? I am looking for a solution in java or python.
Edit/Update:
I tried a new approach using queue. I basically keep cutting array in half and push both half of array into queue until arrays in queue all have length of 2 (or the stack is at height n). but my result is not correct. I think it has to do with the order I add the half arrays back into the queue.
import java.util.*;
public class StackArray{
public static void main(String[] args){
int[] array = {1,2,3,4,5,6,7,8};
int[] answer = stackArray(array);
for(int n : answer){
System.out.println(n);
}
}
public static int[] stackArray(int[] array){
int height = (int) (Math.log(array.length)/Math.log(2)) + 1;
Queue<int[]> queue = new LinkedList<int[]>();
ArrayList<Integer> list = new ArrayList<>();
queue.add(array);
while(queue.size() < height){
int currentLength = queue.size();
int i = 0;
while(i < currentLength){
int[] temp = queue.poll();
int[] array1 = new int[temp.length/2];
int[] array2 = new int[temp.length/2];
System.arraycopy(temp, 0, array1, 0, array1.length);
System.arraycopy(temp, array1.length, array2, 0, array2.length);
queue.add(array1); //I think the problem is here
queue.add(array2);
i++;
}
}
int y = 0;
while(y < 2){
for(int i = 0; i < queue.size(); i++){
int[] curr = queue.poll();
list.add(curr[y]);
queue.add(curr);
}
y++;
}
int[] ret = new int[list.size()];
for(int i = 0; i < list.size(); i++){
ret[i] =list.get(i);
}
return ret;
}
}
result:
1
3
5
7
2
4
6
8
how would I fix this?
update: I solved it and posted my own answer. but I am still curious as of how would other people solve this. Please stil feel free to answer.

I think the pattern becomes clear if you use 0-based indices
and express numbers in binary. e.g
0 1 2 3 4 5 6 7
000 001 010 011 100 101 110 111
0 1 2 3
000 001 010 011
100 101 110 111
4 5 6 7
0 = 000 001 = 1
4 = 100 101 = 5
2 = 010 011 = 3
6 = 110 111 = 7
0 = 000
4 = 100
2 = 010
6 = 110
1 = 001
5 = 101
3 = 011
7 = 111
see the pattern in the left-most bits? the sequence is just
the numbers 0,1,2 .. with the bit order reversed.

I solved it using two artillery queues and a main queue:
import java.util.*;
public class StackArray{
public static void main(String[] args){
int[] array = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int[] answer = stackArray(array);
for(int n : answer){
System.out.println(n);
}
}
public static int[] stackArray(int[] array){
int height = (int) (Math.log(array.length)/Math.log(2)) + 1;
Queue<int[]> queue = new LinkedList<int[]>();
ArrayList<Integer> list = new ArrayList<>();
Queue<int[]> queue1 = new LinkedList<int[]>();
Queue<int[]> queue2 = new LinkedList<int[]>();
queue.add(array);
while(queue.size() < height){
int currentLength = queue.size();
int i = 0;
while(!queue.isEmpty()){
int[] temp = queue.poll();
int[] array1 = new int[temp.length/2];
int[] array2 = new int[temp.length/2];
System.arraycopy(temp, 0, array1, 0, array1.length);
System.arraycopy(temp, array1.length, array2, 0, array2.length);
queue1.add(array1); //I think the problem is here
queue2.add(array2);
i++;
}
while(!queue1.isEmpty()){
int[] temp1 = queue1.poll();
queue.add(temp1);
}
while(!queue2.isEmpty()){
int[] temp2 = queue2.poll();
queue.add(temp2);
}
}
int y = 0;
while(y < 2){
for(int i = 0; i < queue.size(); i++){
int[] curr = queue.poll();
list.add(curr[y]);
queue.add(curr);
}
y++;
}
int[] ret = new int[list.size()];
for(int i = 0; i < list.size(); i++){
ret[i] =list.get(i);
}
return ret;
}
}
output;
1
5
3
7
2
6
4
8
also test on when n = 4:
1
9
5
13
3
11
7
15
2
10
6
14
4
12
8
16

Related

Maximum difference between final and initial sum

I am new to programming and having trouble solving one task. I have several input example. First line contains two numbers m (number of digits on paper, 1<m<1000) and h (limit on the number of operations, 1<h<1000). I have the opportunity, no more than h times, to take any number from a piece of paper (means m), then paint over one of the old digits, and write a new arbitrary digit in its place. By what maximum value can I be able to increase the sum of all the numbers on the piece of paper?
First example:
Input:
5 2 //m and h
1 3 1 4 5 //m = 5, so I can add 5 arbitrary numbers and h=2, so I can change 2 numbers
Output:
16 // cause I changed 1 and 1 to 9 and 9, so the difference 8 and 8 and the sum is 16
Second example:
Input:
3 1
99 5 85
Output:
10 //85 to 95, so the difference is 10
Third example:
Input:
1 10
9999
Output:
0 // nothing to be change
What I have for now:
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number: ");
int m = sc.nextInt();
int h = sc.nextInt();
System.out.println("Entered: " + m);
System.out.println("Entered: " + h);
int[] numbers = new int[m];
for(int i = 0; i < m; ++i) {
numbers[i] = sc.nextInt();
}
Arrays.sort(numbers);
//here is my logic: I am changing 1 to 9
for (int i = 0; i < h; i++) {
if (numbers[i] < 10) {
numbers[i] = 9;
}
else if (numbers[i] > 9 and numbers[i] < 100) {
numbers[i] = 99;
}
}
sc.close();
My logic can work for the first example, but for the second example it won't work. Can you assist me if I am using right logic or is there any easier way to solve this? Thanks in advance.
I quickly came up with below solution
public static void calculateMax(int m,int h, int[] arr){
int sum = 0;
ArrayList<Integer> al = new ArrayList<>();
for(int i=0;i<arr.length;i++){
String stringNum = Integer.toString(arr[i]);
int num = Integer.parseInt(stringNum.substring(0, 1));
if(num!=9){
al.add(Integer.parseInt(("9"+stringNum.substring(1)))-arr[i]);
continue;
}
al.add(0);
}
Collections.sort(al);
int j = al.size()-1;
for(int i=0;i<h && j>0;i++){
sum+=al.get(j--);
}
System.out.println(sum);
}
Here what I am doing is basically, calculating for each number what we can get as maximum by removing one digit and replacing by 9. And I am storing them in a list. Then we can sort that list and get 'h' largest numbers from stored list, and essentially getting the sum of them and printing it.
Break each input number into its digits times the appropriate power of 10. Sort these by powers of 10 descending, digits ascending. Apply your operation in this order.
E.g., 876, 12, 42 -> 800, 70, 6, 10, 2, 40, 2 -> 800, 10, 40, 70, 2, 2, 6.

an int array from Command Line Arguments

I'm trying to convert command line arguments in an int array, but it appears a "0" in the end of the array. How can I fix it?
import java.util.Arrays;
public static void main(String[] args){
int[] game = new int[9];
for (int i = 0; i <= 8; i++)
game[i] = Integer.parseInt(args[i]);
System.out.println(Arrays.toString(game));
}
Example run:
$ java edu.kit.informatik.TicTacToe 5 6 4 1 2 3 7 8 9
[5, 6, 4, 1, 2, 3, 7, 8, 9, 0]
I have tested your code, there aren't '0' at the end of the list. I recommend you that use args.length for handling variety arguments count.
public static void main(String[] args) {
int[] game = new int[args.length];
for (int i = 0; i < args.length; i++)
game[i] = Integer.parseInt(args[i]);
System.out.println(Arrays.toString(game));
}
When you create a new int[] array in Java, its initial contents are all zeros. If you then fill it up with fewer numbers than it is long, you'll see the zeros that have not been overwritten at the end.
// creating an array of size 10
int[] array = new int[10];
// only filling up the first 8 elements
for (int i = 1; i <= 8; i++) {
array[i-1] = i;
}
// printing the full array
for (int i = 0; i < array.length; i++) {
System.out.print(i + " ");
}
System.out.println();
This will output:
1 2 3 4 5 6 7 8 0 0
The last two zeros are just the elements that have not been set to anything else.

How this recursive code works.I'm trying to understand the concept but couln't get throuh it

import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int ar[] = new int[n];
for (int i = 0; i < n; i++) {
ar[i] = sc.nextInt();
}
int a = sc.nextInt();
HelloWorld h = new HelloWorld();
h.find(ar, a);
}
public void find(int ar[], int a) {
System.out.println(a);
for (int i = 0; i < ar.length; i++) {
if (ar[i] == a) {
//System.out.println(a+" "+i);
a = a + 1;
find(ar, a);
}
}
}
}
Input:
2
1
2
1
Output:
1
2
3
3
Can anyone explains me how that recursive code generate the following output?
When you input
2
1
2
1
n = the first number = 2
ar = next n(2) numbers = [1,2]
a = fourth
number = 1
then the find method is called as:
h.find(ar = [1,2], a = 1);
For the output:
Inside find method
a = 1 is printed. As passed from the main method.
ar = [1,2] is iterated.
Since a[0] = 1 = a, a is incremented to 2. find(ar = [1,2], a = 2) is called.
a = 2 is printed.
ar = [1,2] is iterated.
This time a[0] = 1 != a = 2.
Next element, a[1] = 2 = a, a is incremented to 3. find(ar = [1,2], a = 3) is called.
a = 3 is printed..
ar = [1,2] is iterated.
No element in ar is equal to a = 3.
a[1] = 2 = a. a was turned from 1 to 2 in prev iteration. Again a = 2+1=3. find(ar = [1,2], a = 3) is called.
a = 3 is printed..
ar = [1,2] is iterated.
No element in ar is equal to a = 3.
Final Output:
1
2
3
3
Point to note:
If you change value of primitive type variables (like int a) inside a recursive call, the change will not affect value of a for the parent function.
it appears that you start with
looping an through an integer 'array of size n' to find a value 'a'
if it exists you are then recusing to find 'a+1'
main.find [1,2], 1
console >> 1
first recursive [1,2], 2. -------- match for 1
consoles >> 2
second recursive [1,2] 3. -------- match for 2
consoles >> 3
exit second recursive (no match for 3)
third recursive [1,2], 2. -------- match for 2
consoles >> 3
exit third recursive (no match for 3)
loop ends
Don't get confused about the recursive code - AFAIK it could be done without recursive code.
It looks like it sorts the content of the variable ar in a weard kind and removes duplicates.
But if the value does not exist in ar, it simply prints out a for each element of ar.
And if a exists in ar, it prints the next higher value,
and if that exists in ar, it prints the next higher value,
but if currernt value of a does not exist in ar, just print it for the remaining loop iterations.
a at start = 0
result = 0 0 0 0
a at start = 1
result = 1 2 3 3
a at start = 2
result = 2 3 3 3
a at start = -infinite ... 0, 3, 4, ... +infite
result = a a a a
if ar = 1 2 4 5 (order of elements does not matter)
a = 0, result = 0 0 0 0
a = 1, result = 1 2 3 3
a = 2, result = 2 3 3 3
a = 3, result = 3 3 3 3
a = 4, result = 4 5 6 6
a = 5, result = 5 6 6 6
a = 6, result = 6 6 6 6
PS: The recusivity is not really needed, too few parameters change, only a.
The content of find without recursivity
public void find(int ar[], int a) {
for (int i = 0; i < ar.length; i++) {
System.out.println(a);
if (doesArrayContain(ar, a)) {
//System.out.println(a+" "+i)
a = a + 1;
}
}
}
private boolean doesArrayContain(int ar[], int a) {
for (int idx = 0; idx < ar.length; idx++) {
if (ar[idx] == a) {
return true;
}
}
return false;
}

Doubling a Matrix

I've created a two dimensional matrix and populated it with random numbers. I've then printed it out. I need help creating a second matrix that is twice the size of the first, and is populated with the numbers from the first one (which are now 2x2). For example:
Starting Matrix:
3 4
2 1
Doubled Matrix:
3 3 4 4
3 3 4 4
2 2 1 1
2 2 1 1
import java.util.Scanner;
import java.util.Random;
public class MatrixDoubler {
public static void main(String[] arg) {
Scanner keyboard = new Scanner(System.in);
Random rand = new Random();
System.out.println("Enter the size of the matrix");
int size = keyboard.nextInt();
int A[][] = new int[size][size];
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
A[row][col] = rand.nextInt(10);
}
}
System.out.println("Matrix A:");
printMatrix(A);
int[][] B = doubleMatrix(A);
System.out.println("Matrix B:");
printMatrix(B);
}
private static int[][] doubleMatrix(int[][] A) {
int rows = A.length;
assert(rows > 0);
int cols = A[0].length;
assert(cols > 0);
int B[][] = new int[rows * 2][cols * 2];
for (int row = 0; row < rows * 2; ++row) {
for (int col = 0; col < cols * 2; ++col) {
B[row][col] = A[row / 2][col / 2];
}
}
return B;
}
private static void printMatrix(int[][] M) {
for(int i = 0; i < M.length; i++) {
for(int j = 0; j < M.length; j++) {
System.out.print(M[i][j] + " ");
}
System.out.println();
}
}
}
I'm no sure if that is what you are looking for but try this:
for (int i = 0; i < newMatrix.length; i++) {
for (int j = 0; j < newMatrix.length; j++) {
newMatrix[i][j] = matrix[i/size][j/size];
}
}
Note: This code is surely not the best solution but a fast an easy one. It only works if both dimensions are the same size and it won't work if newMatrix is not exactly two times matrix. If it's always just to "double" a matrix it should work fine.
Output:
If you choose size 2 than it will output:
Enter the size of the matrix
2
The Matrix is
3 5
5 2
The newMatrix is
3 3 5 5
3 3 5 5
5 5 2 2
5 5 2 2
and for size 3 it would be for example
Enter the size of the matrix
3
The Matrix is
4 4 3
5 9 4
7 4 1
The newMatrix is
4 4 4 4 3 3
4 4 4 4 3 3
5 5 9 9 4 4
5 5 9 9 4 4
7 7 4 4 1 1
7 7 4 4 1 1
It's not clear what you are asking but I hope this helps (:
In Java 8 you can handle this pretty easily using maps and collectors. Here is a full example:
public class DoubleMatrix {
public static void main(String[] args) {
List<List<Integer>> startingMatrix = Arrays.asList(
Arrays.asList(3, 4),
Arrays.asList(2, 1)
);
List<List<Integer>> doubleMatrix
= startingMatrix.stream()
.map(innerList -> { //For each list
List<Integer> doubled = innerList.stream()
.map(element -> Arrays.asList(element, element)) //Return a list doubling each element
.flatMap(l -> l.stream()) //Flatten out/join all doubled lists
.collect(Collectors.toList());
return Arrays.asList(doubled, doubled); //Double the list
})
.flatMap(l -> l.stream())
.collect(Collectors.toList()); //Collect into a final list
System.out.println(doubleMatrix);
}
}
This avoids needing to know the size of the list beforehand, and is also tolerant of there being a difference between the width and height of your matrix - simply doubling every element in both directions.

UVA#523 Minimum Transport Cost

UVA link: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=464
I'm lost as to what I'm doing now. I don't know why I'm producing incorrect values. I printed out the array after I looked for shortest path. And it produces this:
[0, 3, 8, 8, 4]
[3, 0, 5, 11, 7]
[8, 5, 0, 9, 12]
[8, 11, 9, 0, 4]
[4, 7, 12, 4, 0]
The sample input is:
1
0 3 22 -1 4
3 0 5 -1 -1
22 5 0 9 20
-1 -1 9 0 4
4 -1 20 4 0
5 17 8 3 1
1 3
3 5
2 4
With the sample input, I produce the output:
From 1 to 3 :
Path: 1-->2-->3
Total cost :8
From 3 to 5 :
Path: 3-->2-->5
Total cost :12
From 2 to 4 :
Path: 2-->5-->4
Total cost :11
If I look at my array, it seems to be correct. But the correct answer is:
From 1 to 3 :
Path: 1-->5-->4-->3
Total cost : 21
From 3 to 5 :
Path: 3-->4-->5
Total cost : 16
From 2 to 4 :
Path: 2-->1-->5-->4
Total cost : 17
I think I missed adding the tax, but I don't know where to add it. I tried adding tax[j] to the path[i][j] while doing the shortest path, and then subtracting the tax[x-1] and tax[y-1] (x-1 is my source, y-1 is my destination). It doesn't work, and messes up my path array (it gives value to loops; I don't really need that). I really don't know where to put the tax.
Here is my code for reference:
import java.util.*;
public class Main{
public static final int INF = 9999999;
public static int[][] path;
public static int[][] next;
public static int[] tax;
public static void main(String[] adsf){
Scanner pp = new Scanner(System.in);
int testCases = pp.nextInt();
boolean first = true;
pp.nextLine();
pp.nextLine();
while(testCases-- >0){
String[] s1 = pp.nextLine().split(" ");
int size = s1.length;
path = new int[size][size];
next = new int[size][size];
for(int i = 0; i < path.length; i++)
Arrays.fill(path[i],INF);
tax = new int[size];
for(int j = 0; j < path[0].length; j++){
path[0][j] = Integer.parseInt(s1[j]);
if(path[0][j]==-1)
path[0][j]=INF;
}
for(int i = 1; i < path.length;i++){
s1 = pp.nextLine().split(" ");
for(int j = 0; j < path[0].length; j++){
path[i][j] = Integer.parseInt(s1[j]);
if(path[i][j]==-1)
path[i][j]=INF;
}
}
for(int k=0; k<tax.length;k++){
tax[k] = pp.nextInt();
} pp.nextLine();
apsp();
int x,y;
//for(int i = 0; i < size; i++)
//System.out.println(Arrays.toString(path[i]));
while(pp.hasNextInt()){
if(!first)
System.out.println();
x=pp.nextInt();
y=pp.nextInt();
int cost = path[x-1][y-1];
System.out.println("From "+x+" to "+y+" :");
System.out.print("Path: ");
ArrayList<Integer> print = getpath(x-1,y-1);
for(int l = 0; l < print.size(); l++){
System.out.print(print.get(l)+1);
if(l!=print.size()-1) System.out.print("-->");
else System.out.println();
}
System.out.println("Total cost :"+cost);
first = false;
}
}
}
public static void apsp(){
for(int k=0;k<path.length;k++){
for(int i=0;i<path.length;i++){
for(int j=0;j<path.length;j++){
if (path[i][k] + path[k][j] + tax[j] < path[i][j] + tax[j]) {
path[i][j] = path[i][k]+path[k][j];
next[i][j] = k;
} else{
path[i][j] = path[i][j];
}
}
}
}
}
public static ArrayList<Integer> getpath (int i, int j) {
ArrayList<Integer> pat = getMidPath(i,j);
pat.add(0,i);
pat.add(j);
return pat;
}
public static ArrayList<Integer> getMidPath(int i, int j){
if(next[i][j]==0)
return new ArrayList<Integer>();
ArrayList<Integer> pat = new ArrayList<Integer>();
pat.addAll(getMidPath(i,next[i][j]));
pat.add(next[i][j]);
pat.addAll(getMidPath(next[i][j],j));
return pat;
}
}
The tax is applied:
whenever any cargo passing through one city, except for the source and the destination cities.
So you if you have a path:
a -> b -> c -> d
Then you should include the cost of the path (a,b) + tax(b) + (b,c) + tax(c) + (c,d).
For implementing that into your algorithm, you should be able to add the city taxes to the path lengths like this:
If you know you're starting at a and ending at d, then any directed path to a city x, where x isn't a or b, should be treated as the cost of x + the tax at city x.
You will need to revert the path cost values back to the original ones for the next path you want to calculate the value of and re-add the tax values in for the new starting point and destination.

Categories