3D bin packing algorithm? - java

I wrote a 3D bin packing algorithm but I am still not sure if it is correct or not.
I did not follow any code or pseudo-code that's why I would like to know if it is an efficient algorithm for the 3D bin packing problem or not.
each container has a length, height and breadth
each item has a length , height and breadth.
This is the code I wrote to pack items one by one without exceeding the container's length, height or breadth:
private double x,y,z=0;
private double[] remainingLength;
private double[] remainingHeight;
private double[] remainingBreadth;
//----initialize the remaining dimensions' arrays
public void init(int n) {
remainingLength=new double[n];
remainingHeight=new double[n];
remainingBreadth=new double[n];
for (int i=0; i<n; i++) {
remainingLength[i]=length;
remainingHeight[i]=height;
remainingBreadth[i]=breadth;
}
}
public boolean put3D(ItemsUnit item, int p,int n) {
init(n);
if(x<length){
if(putL(item,p)) {
packedItems.add(item); // if item fits add it to the packedItems into the container
return true;
}
}
if(y<breadth) {
if(putB(item,p)){
packedItems.add(item); // if item fits add it to the packedItems into the container
return true;
}
}
if(z<height){
if(putH(item,p)){
packedItems.add(item); // if item fits add it to the packedItems into the container
return true;
}
}
return false;
}
public boolean putL(ItemsUnit item, int p) {
//remaining dimensions arrays already initialized in the optimization algorithm
double minRemL=remainingLength[0];
int i=0;
for (int j=0; j<remainingLength.length; j++){
if ((remainingLength[j]!=0)&&(minRemL>=remainingLength[j])&&(remainingLength[j]>=item.getLength())){
i=j; //choosing the item to which we should put the new packed item next to
minRemL=remainingLength[j]; //minimum length left
}else {
return false;
}
}
remainingLength[p]=remainingLength[i]-item.getLength();
remainingBreadth[p]-=item.getBreadth();
remainingHeight[p]-=item.getHeight();
remainingLength[i]=0;
x+=item.getLength(); //increment x
return true;
}
public boolean putB(ItemsUnit item, int p) {
//remaining dimensions arrays already initialized in the optimization algorithm
double minRemB=remainingBreadth[0];
int i=0;
for (int j=0; j<remainingBreadth.length; j++){
if ((remainingBreadth[j]!=0)&&(minRemB>=remainingBreadth[j])&&(remainingBreadth[j]>=item.getBreadth())){
i=j; //choosing the item to which we should put the new packed item next to
minRemB=remainingBreadth[j]; //minimum length left
}
else {
return false;
}
}
remainingBreadth[p]=remainingBreadth[i]-item.getBreadth();
remainingHeight[p]-=item.getHeight();
remainingLength[p]-=item.getLength();
remainingBreadth[i]=0;
y+=item.getBreadth(); //increment y
return true;
}
public boolean putH(ItemsUnit item, int p) {
//remaining dimensions arrays already initialized in the optimization algorithm
double minRemH=remainingHeight[0];
int i=0;
for (int j=0; j<remainingHeight.length; j++){
if ((remainingHeight[j]!=0)&&(minRemH>=remainingHeight[j])&&(remainingHeight[j]>=item.getHeight())){
i=j; //choosing the item to which we should put the new packed item next to
minRemH=remainingHeight[j]; //minimum length left
}
else {
return false;
}
}
remainingHeight[p]=remainingHeight[i]-item.getHeight();
remainingBreadth[p]-=item.getBreadth();
remainingLength[p]-=item.getLength();
remainingHeight[i]=0;
z+=item.getHeight(); //increment z
return true;
}
I tested the algorithm and it worked fine without exceeding the dimensions of the container but I am not fully certain if the code is correct.
Can anyone read the code and tell me if it has a problem somewhere or if it is correct?

Related

Minimum number steps to reach goal in chess - knight traversal with BFS

Code given below works for chess of size less than 13 efficiently, but after that it takes too much time and runs forever.
I want to reduce time to reach till end node.
Also this code finds minimum path from starti,startj to endi,endj where starti and startj takes value from 1 to n-1.
Here is the problem that I am trying to solve:
https://www.hackerrank.com/challenges/knightl-on-chessboard/problem
Program:
import java.util.LinkedList;<br>
import java.util.Scanner;
class Node {
int x,y,dist;
Node(int x, int y, int dist) {
this.x = x;
this.y = y;
this.dist = dist;
}
public String toString() {
return "x: "+ x +" y: "+y +" dist: "+dist;
}
}
class Solution {
public static boolean checkBound(int x, int y, int n) {
if(x >0 && y>0 && x<=n && y<=n)
return true;
return false;
}
public static void printAnswer(int answer[][], int n) {
for(int i=0; i<n-1; i++) {
for(int j=0; j<n-1; j++) {
System.out.print(answer[i][j]+" ");
}
System.out.println();
}
}
public static int findMinimumStep(int n, int[] start, int[] end, int a, int b) {
LinkedList<Node> queue = new LinkedList();
boolean visited[][] = new boolean[n+1][n+1];
queue.add(new Node(start[0],start[1],0));
int x,y;
int[] dx = new int[] {a, -a, a, -a, b, -b, b, -b};
int[] dy = new int[] {b, b, -b, -b, a, a, -a, -a};
while(!queue.isEmpty()) {
Node z = queue.removeFirst();
visited[z.x][z.y] = true;
if(z.x == end[0] && z.y == end[1])
return z.dist;
for(int i=0; i<8; i++)
{
x = z.x + dx[i];
y = z.y + dy[i];
if(checkBound(x,y,n) && !visited[x][y])
queue.add(new Node(x,y,z.dist+1));
}
}
return -1;
}
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int start[] = new int[] {1,1};
int goal[] = new int[] {n,n};
int answer[][] = new int[n-1][n-1];
for(int i=1; i<n; i++) {
for(int j=i; j<n; j++) {
int result = findMinimumStep(n, start, goal, i, j);
answer[i-1][j-1] = result;
answer[j-1][i-1] = result;
}
}
printAnswer(answer,n);
}
}
You set visited too late and the same cells are added multiple times to the queue, then you pop them from the queue without checking their visited state that makes things even worse. This leads to the fast growth of the queue.
You need to set visited right after you add the Node to the queue:
if(checkBound(x,y,n) && !visited[x][y]) {
queue.add(new Node(x,y,z.dist+1));
visited[x][y] = true;
}
Even if you optimize your code, you will not reduce the complexity of the algorithm.
I think you need to think about how to reduce the search space. Or search it in a clever order.
I would go for a A*-search
The most effective solution in your problem is Dijkstra's algorithm. Treat the squares as nodes and draw edges towards the other squares/nodes that the knight can visit. Then run the algorithm for this graph. It performs in logarithmic time so it scales pretty good for big problems.
A* search suggest by MrSmith, is a heuristic so I would not suggest it for this kind of problem.
Dijkstra is an important algorithm and implementing it will help you solve many similar problems in the future, for example you can also solve this problem problem with the same logic.

Yaroslavsky Dual-pivot Quicksort Java implementation

I'd like to ask you if you can show me how my code might look like so I might not get java.lang.StackOverflowError during the sort of 100000 ints (My implementation is good but only to 20000 numbers , bigger sizes of table to sort will produce that error). I've tryied to change the size of heap in InteliJ , but that way seems not to be working.Also I've spend like 2 hours trying to modyfy it and reading about it over the web , yet I can't overcome this problem. That's why I'm asking you guys , to show me where can I change my code in my implementation so I won't recive that error.
Here is the code:
import java.util.ArrayList;
import java.util.Random;
public class YaroslawskiSort {
Random gener;
public int temporary,genertype,NInts;
ArrayList<Integer> mylist;
public YaroslawskiSort(int type,int ilosc){
gener = new Random();
mylist= new ArrayList<>();
this.genertype=type;
this.NInts=ilosc;
}
void generate(){
if(genertype==0){
for(int i=0;i<NInts;i++){
mylist.add(gener.nextInt(100000));
}
}else {
for(int i=0;i<NInts;i++){
mylist.add(NInts-i);
}
}
}
void sortingI(int left,int right) {
for (int i=left+1;i<=right;i++)
{
int value = mylist.get(i);
int j =i-1;
while (j >= left && mylist.get(j)>value)
{
mylist.set(j+1,mylist.get(j));
j--;
}
mylist.set(j+1,value);
}
}
private void sorting( int left, int right) {
if((right-left)>=17) {
int[] index=new int[2];
index = partition(left, right);
if (left < index[0]) {
sorting(left, index[0]);
}
if(index[0]<index[1]){
sorting(index[0], index[1]);
}
if (index[1] < right) {
sorting(index[1], right);
}
}
if((right-left)<17 && (right-left)!=0){
sortingI(left,right); //INSERTION SORT!
}
}
private int[] partition( int left, int right) {
int pivot1 = mylist.get(left);
int pivot2 = mylist.get(right);
if(pivot1>pivot2){
mylist.set(left,pivot2);
mylist.set(right,pivot1);
temporary=pivot1;
pivot1=pivot2;
pivot2=temporary;
}
int L=left+1;
while(mylist.get(L)<pivot1 && L<right){
L++;
}
int K=L;
while( K<=right&& mylist.get(K)>=pivot1 && mylist.get(K)<=pivot2 ){
K++;
}
int G=right-1;
while(mylist.get(G)>pivot2 && G>left){
G--;
}
while (K <= G) {
if(mylist.get(K)<pivot1){
mylist.add(left+1,mylist.remove(K));
L++;
K++;
}
if(mylist.get(K)>=pivot1 && mylist.get(K)<=pivot2){
mylist.add(L,mylist.remove(K));
K++;
}
if(mylist.get(K)>pivot2){
mylist.add(right,mylist.remove(K));
G--;
}
}
mylist.set(left,mylist.get(L-1));
mylist.set(L-1,pivot1);
mylist.set(right,mylist.get(G+1));
mylist.set(G+1,pivot2);
int[] table=new int[2];
table[0]=L;
table[1]=G;
return table;
}
void printing(){
for(int k=0;k<NInts;k++){
System.out.print(" "+mylist.get(k));
}
}
public static void main(String[] args){
YaroslawskiSort instance = new YaroslawskiSort(1,100000);
instance.generate();
instance.sorting(0, instance.mylist.size() - 1);
instance.printing();
}
}
Thanks for helping :)
Your code is working good, to increase stack size open Edit configuration... of your project in intellij IDEA (top right corner) and in field VM options type -Xss16m. If you do so, you will not get StackOverflowError.
In my opinion you get StackOverflow cause you're recursively call sorting method and it in its turn call partition method where always a new int[2] is created and all of these arrays are on stack.
If you can rewrite partition method so it (for example) return int and call it for left and right bound separately, I think this will fix the problem.

DFS solving sudoku

I'm working on 16*16 sudoku problem with DFS algorithm. Java code looks like:
public class dfs {
public boolean dfs(int[][] puzzle,int i,int j){
if(i==15&&j>=16) return true;
if(j==16){
//System.out.println(String.valueOf(i));
return dfs(puzzle,i+1,0); //{j=0; i++;
}
if(puzzle[i][j]!=-1){
return dfs(puzzle,i,j+1); //next cell in the same row
}
else{
for(int num=1;num<=16;num++){
//System.out.println("trying"+i+","+j+","+num);
if(valid(puzzle,i,j,num)){
//System.out.println(String.valueOf(num));
puzzle[i][j]=num;
if(dfs(puzzle,i,j+1)){
return true;
}
}
//else return false;
}
}
return false;
}
public boolean valid(int[][] puzzle,int x,int y,int num){
for(int i=0;i<16;i++){
if(puzzle[i][y]==num) {
//System.out.println("a");
return false;
}
}
for(int j=0;j<16;j++){
if(puzzle[x][j]==num){
//System.out.println("b");
return false;
}
}
int c=(x/4)*4;
int r=(y/4)*4;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(puzzle[c+i][r+j]==num){
//System.out.println("c");
return false;
}
}
}
return true;
}
}
And the main method is:
public static void main(String[] args) {
sudoku sudokuPuzzleGenerator = new sudoku();
long start = System.currentTimeMillis();
int numOfSudokuMatrix = 1;
List<int[][]> sudoku = new ArrayList<int[][]>();
for (int count = 1; count <= numOfSudokuMatrix; count++) {
int[][] randomMatrix = sudokuPuzzleGenerator.generatePuzzleMatrix();
int hole = 81;
while (hole > 0) {
Random randomGenerator = new Random();
int x = randomGenerator.nextInt(16);
int y = randomGenerator.nextInt(16);
if (randomMatrix[x][y] != -1) {
randomMatrix[x][y] = -1;
hole--;
}
}
for(int i=0;i<16;i++){
for(int j=0;j<16;j++){
System.out.print(randomMatrix[i][j] + " ");
}
System.out.println();
}
sudoku.add(randomMatrix);
}
System.out.println();
long start2 = System.currentTimeMillis();
for (int[][] p:sudoku) {
dfs d=new dfs();
boolean b=d.dfs(p,0,0);
for (int rowNum = 0; rowNum < 16; rowNum++) {
for (int colNum = 0; colNum < 16; colNum++) {
System.out.print(p[rowNum][colNum] + " ");
}
System.out.println();
}
}
Long end2 = System.currentTimeMillis();
Long time2 = end2 - start2;
System.out.println("It took: " + time2 + " milliseconds.");
}
When I run the code, it often terminates before all blank spaces be filled, leaving many -1 in the puzzle. I'm not sure where the problem is. I will be really thankful for any help!
It doesn't matter, but this would probably be classified as a backtracking problem, not a search. Anyway, I think this is it, but it's hard to test without that generatePuzzleMatrix method. After you check every possible number at a given cell, if you don't find an answer (hit your base case), you need to set the cell back to -1.
for(int num=1;num<=16;num++){
if(valid(puzzle,i,j,num)){
puzzle[i][j]=num;
if(dfs(puzzle,i,j+1)){
return true;
}
}
}
puzzle[i][j] = -1;
Without setting this value back to -1, you are going to leave these values set as the highest valid value, even if you didn't find an answer. Future iterations of your recursive algorithm will skip that value because they assume it is correct. Thus, your loop will end without testing all possibilities and finding an answer. Hope this does it for ya.
Comment Response
Yes, I agree there is at least 1 solution. I believe the problem is that your loop is ending before you actually test all possibilities. Your recursive calls need to set the grid back once they have tested every possibility. At an arbitrary depth in the recursive stack, say you add a valid number to your grid. The number being valid at that stage does not imply it is in the right position. You could create a ripple effect. Though it is currently valid for that particular number, you have unintentionally elimanted the possibility of any solution based on the cells you have filled so far. Once you hit that scenario, you have a problem. Your grid will retain the most recently set value, and you will never try setting it to anything else (because you have a condition that ignores values != -1).

Moving elements in an array

I have an array of objects and i want to add elements in this array and simultaneously sort them in ascending order.Although I tried many compinations , I always take a java.lang.ArrayIndexOutOfBoundsException. Here is a part of my code :
public boolean insert(Person p)
{
for(int i=0;i<=size();i++)
{
if (c==0)
{
array[0] = p;
c++;
return true;
}
else
{
if (p.compareTo(array[i])==-1)
{
array[i]=p;
c++;
for(int j = size(); j>i; j--)
{
array[j]=array[j-1];
}
}
else if((p.compareTo(array[i])==1))
{
array[i+1]=p;
c++;
for (int j=(size()-1);j>= i+1; j--)
{
array[j+1]=array[j];
}
}
else
{
return false;
}
return true;
}
}
return false;
}
private int c;
private Person array[];
public SortedPersonList()
{
this.array = new Person[c];
}
public int size()
{
return c;
}
Remove the equal sign in for(int i=0;i<=size();i++). That is, change to
for(int i=0;i<size();i++)
Array indices go from 0 to size-1. So array[size()] is outside the array. Hence the error.
1) You are initializing your array to a size 0, and you never resize it. An array has a fixed size, so in order to populate it with items beyond its range, you should first create a larger array and copy the contents to it (This is how ArrayList works).
2) When you find the insertion point, you shouldn't override this position before keeping its value in a temp variable. (Also, I don't understand the third case in your code. Why do you insert if p is greater than array[i]? you should rethink your logic.)
3) you may want to use binary search to find the insertion point. It has a better performance than linear search.
Your code :
for(int i=0;i<=size();i++)
Write like
for(int i=0;i<size();i++) or for(int i=0;i<=size()-1;i++)

Complexity and Efficiency in Algorithm for: a[j]-a[i] i>=j

I'm looking to make this much quicker. I've contemplated using a tree, but I'm not sure if that would actually help much.
I feel like the problem is for most cases you don't need to calculate all the possible maximums only a hand full, but I'm not sure where to draw the line
Thanks so much for the input,
Jasper
public class SpecialMax {
//initialized to the lowest possible value of j;
public static int jdex = 0;
//initialized to the highest possible value of i;
public static int idex;
//will hold possible maximums
public static Stack<Integer> possibleMaxs = new Stack<Integer> ();
public static int calculate (int[] a){
if (isPositive(a)){
int size = a.length;
int counterJ;
counterJ = size-1;
//find and return an ordered version of a
int [] ordered = orderBySize (a);
while (counterJ>0){
/* The first time this function is called, the Jvalue will be
* the largest it can be, similarly, the Ivalue that is found
* is the smallest
*/
int jVal = ordered[counterJ];
int iVal = test (a, jVal);
possibleMaxs.push(jVal-iVal);
counterJ--;
}
int answer = possibleMaxs.pop();
while (!possibleMaxs.empty()){
if (answer<possibleMaxs.peek()){
answer = possibleMaxs.pop();
} else {
possibleMaxs.pop();
}
}
System.out.println("The maximum of a[j]-a[i] with j>=i is: ");
return answer;
} else {
System.out.println ("Invalid input, array must be positive");
return 0; //error
}
}
//Check to make sure the array contains positive numbers
public static boolean isPositive(int[] a){
boolean positive = true;
int size = a.length;
for (int i=0; i<size; i++){
if (a[i]<0){
positive = false;
break;
}
}
return positive;
}
public static int[] orderBySize (int[] a){
//orders the array into ascending order
int [] answer = a.clone();
Arrays.sort(answer);
return answer;
}
/*Test returns an Ival to match the input Jval it accounts for
* the fact that jdex<idex.
*/
public static int test (int[] a, int jVal){
int size = a.length;
//initialized to highest possible value
int tempMin = jVal;
//keeps a running tally
Stack<Integer> mIndices = new Stack<Integer> ();
//finds the index of the jVal being tested
for (int i=0; i<size; i++) {
if (jVal==a[i]){
//finds the highest index for instance
if (jdex<i){
jdex = i;
}
}
}
//look for the optimal minimal below jdex;
for (int i=0; i<jdex; i++){
if (a[i]<tempMin){
tempMin = a[i];
mIndices.push(i);
}
}
//returns the index of the last min
if (!mIndices.empty()){
idex = mIndices.pop();
}
return tempMin;
}
}
It can be done in linear time and linear memory. The idea is: find the minimum over each suffix of the array and maximum over each prefix, then find the point where the difference between the two is the highest. You'll also have to store the index on which the maximum/minimum for each prefix is reached if you need the indices, rather than just the difference value.
Pre-sorting a[] makes the procedure complicated and impairs performance. It is not necessary, so we leave a[] unsorted.
Then (EDITED, because I had read j>=i in the body of your code, rather than i>=j in the problem description/title, which I now assume is what is required (I didn't go over your coding details); The two varieties can easily be derived from each other anyway.)
// initialize result(indices)
int iFound = 0;
int jFound = 0;
// initialize a candidate that MAY replace jFound
int jAlternative = -1; // -1 signals: no candidate currently available
// process the (remaining) elements of the array - skip #0: we've already handled that one at the initialization
for (int i=1; i<size; i++)
{
// if we have an alternative, see if that combines with the current element to a higher "max".
if ((jAlternative != -1) && (a[jAlternative]-a[i] > a[jFound]-a[iFound]))
{
jFound = jAlternative;
iFound = i;
jAlternative = -1;
}
else if (a[i] < a[iFound]) // then we can set a[iFound] lower, thereby increasing "max"
{
iFound = i;
}
else if (a[i] > a[jFound])
{ // we cannot directly replace jFound, because of the condition iFound>=jFound,
// but when we later may find a lower a[i], then it can jump in:
// set it as a waiting candidate (replacing an existing one if the new one is more promising).
if ((jAlternative = -1) || (a[i] > a[jAlternative]))
{
jAlternative = i;
}
}
}
double result = a[jFound] - a[iFound];

Categories

Resources