Optimizations for Solitaire SPOJ - algorithm

Problem Code: SOLIT
Problem Link: http://www.spoj.com/problems/SOLIT/
I tried solving the SPOJ problem Solitaire. However, I ended up with a TLE (Time Limit Exceeded). My current solution is taking around 2 seconds to execute. I have no idea how to optimize my solution further in order to reduce the time. So, I would be grateful for any help in this regard.
Link to my solution: https://ideone.com/eySI91
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
class Solitaire {
enum Direction {
TOP, RIGHT, DOWN, LEFT;
};
static class Piece {
int row, col;
public Piece(int row, int col) {
this.row = row;
this.col = col;
}
#Override
public boolean equals(Object o)
{
if (!(o instanceof Piece))
return false;
Piece p = (Piece)o;
return (row==p.row && col==p.col);
}
#Override
public int hashCode()
{
return (row*10 + col)%11;
}
}
static class State {
HashSet<Piece> pieces;
public State() {
pieces = new HashSet<>(11);
}
public State(State s) {
pieces = new HashSet<>(11);
for (Piece p: s.pieces)
pieces.add(new Piece(p.row, p.col));
}
#Override
public boolean equals(Object o) {
if (!(o instanceof State))
return false;
State s = (State) o;
if (pieces.size()!=s.pieces.size())
return false;
for (Piece p: pieces)
{
if (!s.pieces.contains(p))
return false;
}
return true;
}
#Override
public int hashCode() {
final int MOD = 1000000007;
long code = 0;
for (Piece p: pieces) {
code = (code + p.hashCode())%MOD;
}
return (int) code;
}
#Override
public String toString()
{
String res = "";
for (Piece p: pieces)
res = res + " (" + p.row + ", " + p.col + ")";
return res;
}
public int getCloseness(State s)
{
int medianRow=0, medianCol=0, sMedianRow=0, sMedianCol=0;
for (Piece p: pieces)
{
medianRow+=p.row;
medianCol+=p.col;
}
medianRow/=4;
medianCol/=4;
for (Piece p: s.pieces)
{
sMedianRow+=p.row;
sMedianCol+=p.col;
}
sMedianRow/=4;
sMedianCol/=4;
int closeness = ((sMedianCol-medianCol)*(sMedianCol-medianCol)) + ((sMedianRow-medianRow)*(sMedianRow-medianRow));
return closeness;
}
}
static State makeMove(State curr, Piece piece, Direction dir, HashSet<State> visited) {
if (dir == Direction.TOP) {
if (piece.row==1)
return null;
if (curr.pieces.contains(new Piece(piece.row-1, piece.col)))
{
if (piece.row==2 || curr.pieces.contains(new Piece(piece.row-2, piece.col)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row-2, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row-1, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else if (dir == Direction.RIGHT) {
if (piece.col==8)
return null;
if (curr.pieces.contains(new Piece(piece.row, piece.col+1)))
{
if (piece.col==7 || curr.pieces.contains(new Piece(piece.row, piece.col+2)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col+2));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col+1));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else if (dir == Direction.DOWN) {
if (piece.row==8)
return null;
if (curr.pieces.contains(new Piece(piece.row+1, piece.col)))
{
if (piece.row==7 || curr.pieces.contains(new Piece(piece.row+2, piece.col)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row+2, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row+1, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else // dir == Direction.LEFT
{
if (piece.col==1)
return null;
if (curr.pieces.contains(new Piece(piece.row, piece.col-1)))
{
if(piece.col==2 || curr.pieces.contains(new Piece(piece.row, piece.col-2)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col-2));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col-1));
if (visited.contains(newState))
return null;
else
return newState;
}
}
}
static boolean isReachableInEightMoves(State src, State target) {
Queue<State> q = new LinkedList<>();
HashSet<State> visited = new HashSet<>();
int closeness = src.getCloseness(target);
q.add(src);
int moves = 0;
while (!q.isEmpty() && moves <= 8) {
int levelNodes = q.size();
for (int i = 0; i < levelNodes; i++) {
State curr = q.remove();
if (curr.equals(target))
return true;
if (moves==8)
continue;
visited.add(curr);
for (Piece p: curr.pieces)
{
State newState = makeMove(curr, p, Direction.TOP, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
newState = makeMove(curr, p, Direction.RIGHT, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
newState = makeMove(curr, p, Direction.DOWN, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
newState = makeMove(curr, p, Direction.LEFT, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
}
}
moves++;
}
return false;
}
public static void main(String[] args) throws IOException {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(FileDescriptor.out), "ASCII"));
CustomScanner sc = new CustomScanner();
int t = sc.nextInt();
long start = System.currentTimeMillis();
while (t-- > 0) {
State src = new State(), target = new State();
for (int i = 0; i < 4; i++) {
src.pieces.add(new Piece(sc.nextInt(), sc.nextInt()));
}
for (int i = 0; i < 4; i++) {
target.pieces.add(new Piece(sc.nextInt(), sc.nextInt()));
}
if (isReachableInEightMoves(src, target))
out.write("YES");
else
out.write("NO");
out.newLine();
}
long end = System.currentTimeMillis();
out.write("Time to execute = " + Double.toString((end-start)/1000d));
out.flush();
}
static class CustomScanner {
BufferedReader br;
StringTokenizer st;
public CustomScanner() {
br = new BufferedReader(new InputStreamReader(System.in));
}
private String next() {
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public String nextLine() {
String str = "";
try {
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
}
Some notes regarding the implementation:-
I am just doing a simple bfs traversal where each node is a state of
the board.
I have defined a function called getCloseness() which measures the closeness of two different states. It is basically the square of the distance between the centroids of the two states. A centroid of a state is the sum of all row values of each piece divided by 4 and the same for columns.
After calculating each state, I am checking if the closeness of this new state is lesser than or equal to the current closeness.
If it is not closer, then I will simply discard the new discovered state.
If it is closer, then I will update the closeness value and insert this new state into the Queue for future processing.
This process terminates when either the queue becomes empty or a state is discovered which is same as the target state.
The above approach takes approximately 1-3 seconds for cases where a minimum of 7 moves are required. I would be grateful if you can tell me how I can further optimize this solution.
The expected time according to the problem is 0.896s.

Related

Adding Object[] method to main()

I am trying to pass this method through my main() function but The loadMap already has the bufferreader so I am trying to use that rather than creating my own new buffer reader. How can I do this?
public static void main(String args[]) {
//throw exceptions here if args is empty
filename = args[0];
System.out.println(MapIO.loadMap(filename)[0]);
System.out.println(MapIO.loadMap(filename)[1]);
if (args.length < 1) {
System.err.println("Usage:\n" +"java CrawlGui mapname");
System.exit(1);
}
List<String> names=new LinkedList<String>();
try (BufferedReader reader = new BufferedReader(new FileReader(new
File(filename)))) {
String line;
while ((line = reader.readLine()) != null)
names.add(line);
System.out.println(names);
} catch (IOException e) {
e.printStackTrace();
}
MapIO.loadMap(filename);
launch(args);
}
/** Read information from a file created with saveMap
* #param filename Filename to read from
* #return null if unsucessful. If successful, an array of two Objects.
[0] being the Player object (if found) and
[1] being the start room.
* #detail. Do not add the player to the room they appear in, the caller
will be responsible for placing the player in the start room.
*/
public static Object[] loadMap(String filename) {
Player player = null;
try {
BufferedReader bf = new BufferedReader(
new FileReader(filename));
String line = bf.readLine();
int idcap = Integer.parseInt(line);
Room[] rooms = new Room[idcap];
for (int i = 0; i < idcap; ++i) {
line = bf.readLine();
if (line == null) {
return null;
}
rooms[i] = new Room(line);
}
for (int i = 0; i < idcap; ++i) { // for each room set up exits
line = bf.readLine();
int exitcount=Integer.parseInt(line);
for (int j=0; j < exitcount; ++j) {
line = bf.readLine();
if (line == null) {
return null;
}
int pos = line.indexOf(' ');
if (pos < 0) {
return null;
}
int target = Integer.parseInt(line.substring(0,pos));
String exname = line.substring(pos+1);
try {
rooms[i].addExit(exname, rooms[target]);
} catch (ExitExistsException e) {
return null;
} catch (NullRoomException e) {
return null;
}
}
}
for (int i = 0;i<idcap;++i) {
line = bf.readLine();
int itemcount = Integer.parseInt(line);
for (int j = 0; j < itemcount; ++j) {
line = bf.readLine();
if (line == null) {
return null;
}
Thing t = decodeThing(line, rooms[0]);
if (t == null) {
return null;
}
if (t instanceof Player) { // we don't add
player = (Player)t; // players to rooms
} else {
rooms[i].enter(t);
}
}
}
Object[] res = new Object[2];
res[0] = player;
res[1] = rooms[0];
return res;
} catch (IOException ex) {
return null;
} catch (IndexOutOfBoundsException ex) {
return null;
} catch (NumberFormatException nfe) {
return null;
}
}
You shouldn't do anything in main() other than call launch(). Move all the other startup code to your start() method. You can get the content of the args array using getParameters().getRaw():
#Override
public void start(Stage primaryStage) {
//throw exceptions here if args is empty
filename = getParameters().getRaw().get(0);
System.out.println(MapIO.loadMap(filename)[0]);
System.out.println(MapIO.loadMap(filename)[1]);
if (args.length < 1) {
System.err.println("Usage:\n" +"java CrawlGui mapname");
System.exit(1);
}
List<String> names=new LinkedList<String>();
try (BufferedReader reader = new BufferedReader(new FileReader(new
File(filename)))) {
String line;
while ((line = reader.readLine()) != null)
names.add(line);
System.out.println(names);
} catch (IOException e) {
e.printStackTrace();
}
Object[] whateverThisThingIs = MapIO.loadMap(filename);
// Now you have access to everything you need, at the point where you need it.
// existing start() code goes here...
}
public static void main(String args[]) {
launch(args);
}

Shape segmentation using Depth-First-Search

How to solve this in Depth-First-Search:
6x6 squares, cut along the edges of the lattice into two parts.
The shape of the two parts is required to be exactly the same.
Try to calculate: There are a total of how many different segmentation methods.
Note: Rotational symmetry belongs to the same segmentation method.
For example:
Sorry, it looks like I'm just looking for an answer without thinking. Actually, I think a lot. The original title didn't require a Depth-First-Search, and I think it needs to be used to solve this problem, but I don't have a clear idea. I think that meet the requirements is between grid is continuous, but I don't know how to express this kind of situation.
I think the idea to use dfs is good. You could start the search on a clear (no walls) maze.
Start the search on an arbitrary cell.
For each cell explored : mark the symmetric one as "wall".
A pseudo code to find one segmentation could be:
boolean dfs(cell) {
if cell is not empty or was explores or null - return false
symCell = get Symetric Cell of cell
if symCell is not empty or was explores or null - return false
else mark symCell as wall
mark cell as explored
//loop over neighbors
for(Cell c : getNeighbors of cell){
if ( dfs(c) ) return true
}
return false
}
The process can be repeated over and over again to find more segmentations.
I did not come up yet with any good idea about a stop criteria: how do you know that all possible segmentations were found.
Here is a simple java swing demonstration of finding one segmentation:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SwingMaze extends JFrame {
private JPanel mazePanel;
private Cell[][] cells;
private int mazeRows = 6, mazeCols = 6; //default size
public SwingMaze() { this(null); }
public SwingMaze(Cell[][] cells) {
this.cells = (cells == null) ?
getCells(mazeRows,mazeCols) : cells;
mazeRows = this.cells.length; mazeCols = this.cells[0].length;
setTitle("Grid");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buildUi();
pack();
setVisible(true);
}
void buildUi() {
mazePanel = new JPanel();
mazePanel.setLayout(new GridLayout(cells.length, cells[0].length));
add(mazePanel, BorderLayout.CENTER);
for (Cell[] cellsRow : cells) {
for (Cell cell : cellsRow) {
cell.addMouseListener(cellMouseListener(cell));
mazePanel.add(cell);
}
}
add(new JLabel("Click any cell to set it origin and start search"),
BorderLayout.SOUTH);
}
private MouseListener cellMouseListener(Cell cell) {
return new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {solve(cell);}
};
}
private List<Cell> getNeighbors(Cell cell){
List<Cell> neighbors = new ArrayList<>();
for(int row = (cell.getPosition().x -1) ;
row <= (cell.getPosition().x +1) ; row++) {
if(! validPosition (row,0)) { continue;}
for(int col = (cell.getPosition().y -1) ;
col <= (cell.getPosition().y +1) ; col++) {
if(! validPosition (row,col)) { continue;}
if((row == cell.getPosition().x) &&
(col == cell.getPosition().y) ) { continue;}
if((row != cell.getPosition().x) &&
(col != cell.getPosition().y) ) { continue;}
neighbors.add(cells[row][col]);
}
}
Collections.shuffle(neighbors);
return neighbors;
}
private boolean validPosition(int row, int col) {
return (row >= 0) && (row < mazeRows)
&& (col >= 0) && (col < mazeCols);
}
private Cell getSymetricCell(Cell cell) {
if(! validPosition(cell.getPosition().x,
cell.getPosition().y)) { return null; }
int row = mazeRows - cell.getPosition().x -1;
int col = mazeCols - cell.getPosition().y -1;
return cells[row][col];
}
private Cell[][] getCells(int rows, int cols) {
Cell[][] cells = new Cell[rows][cols];
for(int row=0; row <cells.length; row++) {
for(int col=0; col<cells[row].length; col++) {
cells[row][col] = new Cell();
cells[row][col].setPosition(row, col);
}
}
return cells;
}
boolean solve(Cell cell) {
reset();
return dfs(cell);
}
boolean dfs(Cell cell) {
if(cell == null){ return false; }
//if cell is wall, or was explored
if( !cell. isToBeExplored()) { return false; }
Cell symCell = getSymetricCell(cell);
if((symCell == null) || ! symCell.isToBeExplored()) { return false; }
symCell.setState(State.WALL);
cell.setState(State.WAS_EXPLORED);
//loop over neighbors
for(Cell c : getNeighbors(cell)){
if (dfs(c)) { return true; }
}
return false;
}
private void reset() {
for(Cell[] cellRow : cells) {
for(Cell cell : cellRow) {
cell.setState(State.EMPTY);
}
}
}
public static void main(String[] args) {
new SwingMaze();
}
}
class Cell extends JLabel {
Point position;
State state;
private static int cellH =65, cellW = 65;
Cell() {
super();
position = new Point(0,0);
state = State.EMPTY;
setBorder(BorderFactory.createLineBorder(Color.RED));
setPreferredSize(new Dimension(cellH , cellW));
setOpaque(true);
}
boolean isToBeExplored() { return state == State.EMPTY; }
Point getPosition() {return position;}
void setPosition(Point position) {this.position = position;}
void setPosition(int x, int y) { position = new Point(x, y); }
void setState(State state) {
this.state = state;
setBackground(state.getColor());
}
State getState() { return state; }
#Override
public String toString() {
return "Cell " + position.getX() + "-" + position.getY()+ " " + state ;
}
}
enum State {
EMPTY (Color.WHITE), WALL (Color.BLUE), EXPLORED(Color.YELLOW),
WAS_EXPLORED(Color.PINK);
private Color color;
State(Color color) { this.color = color; }
Color getColor() { return color; }
}
Clicking will set it as origin and start search. Click the same cell again to see different segmentation.
I saw a way to solve this problem, which is to search from the line dividing the grid, the code is as follows:
public class Maze {
int point[][] = new int[10][10]; // The intersection between the line and the line
int dir[][] = {{-1,0},{1,0},{0,-1},{0,1}}; // get Neighbors
static int N = 6; // default size
static int count = 0;
public void dfs(int x, int y) {
if (x == 0 || y == 0 || x == N || y == N) {
count++;
return;
}
for(int i = 0; i < 4; i++) {
int n = x + dir[i][0];
int m = y + dir[i][1];
if (n < 0 || n > N || m < 0 || m > N) { continue; }
if (point[n][m] == 0) {
point[n][m] = 1;
point[N-n][N-m] = 1;
dfs(n, m);
point[n][m] = 0;
point[N-n][N-m] = 0;
}
}
}
public static void main(String[] args) {
Maze test = new Maze();
test.point[N/2][N/2] = 1; // Search from the center point
test.dfs(N/2, N/2);
System.out.println(count/4); // There are four types of rotational symmetry
} }

heap data structure via pointers

Suggest an efficient way to find last position in heap satisfying the following conditions:
1) via pointers not via array
2) where we can insert or delete node
I could find it in O(n) time complexity but suggest a way which is of O(logn) or O(1) time complexity.
I'm assuming here that you mean a binary heap.
If you know how many nodes are in the heap, you can find the last node in O(log n) time by converting the count to binary, and then following the path of bits from high to low. That is, take the left node if the bit is 0, and the right node if the bit is 1.
For example, if there are three nodes in the heap, the binary representation of the count is 11. The root is always the first node, leaving you with 1. Then you take the right branch to get the last node.
Say there are 5 nodes in the heap:
1
2 3
4 5
In binary, that's 101. So you take the root. The next digit is 0 so you take the left branch. The next digit is 1, so you take the right branch, leaving you at node 5.
If you want the next available slot, you add 1 to the count and do the same thing. So 6 would be 110. You take the root, then the right branch, and the left child of 3 is where you'd add the new node.
You can do the same kind of thing with any d-ary heap, except that instead of converting to binary you convert to base d. So if your heap nodes each have up to three children, you'd convert the count to base 3, and use essentially the same logic as above.
An alternative is to maintain a reference to the last node in the heap, updating it every time you modify the heap. Or, if you want to know where the next node would be placed, you maintain a reference to the first node that doesn't have two children. That's O(1), but requires bookkeeping on every insertion or deletion.
I am answering my own question, There is no need to keep track of next pointer while inserting in heap (heap via pointers), even there is no need to keep track of parent, i am attaching running java code for heap, all possible method are included in it, getMin() = O(1), insert() = O(logn), extractMin = O(logn), decreasePriorityOfHead = O(logn), I have implemented it for generic code so it would be helpful to understand generic concept also.
class MinHeap<E extends Comparable<E>> {
private DoublyNode<E> root;
private int size = 0;
public DoublyNode<E> getRoot() {
return root;
}
public void setRoot(DoublyNode<E> root) {
this.root = root;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public MinHeap() {
}
public MinHeap(E data) {
this.root = new DoublyNode<E>(data);
this.size++;
}
private class NodeLevel<E extends Comparable<E>> {
private int level;
private DoublyNode<E> node;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public DoublyNode<E> getNode() {
return node;
}
public void setNode(DoublyNode<E> node) {
this.node = node;
}
public NodeLevel(DoublyNode<E> node, int level) {
this.node = node;
this.level = level;
}
}
public void insert(E data) {
if (this.size == 0) {
this.root = new DoublyNode<E>(data);
this.size++;
return;
}
DoublyNode<E> tempRoot = this.root;
Integer insertingElementPosition = this.size + 1;
char[] insertingElementArray = Integer.toBinaryString(
insertingElementPosition).toCharArray();
DoublyNode<E> newNode = new DoublyNode<E>(data);
int i;
for (i = 1; i < insertingElementArray.length - 1; i++) {
if (newNode.getData().compareTo(tempRoot.getData()) < 0) {
this.swap(newNode, tempRoot);
}
char c = insertingElementArray[i];
if (c == '0') {
tempRoot = tempRoot.getLeft();
} else {
tempRoot = tempRoot.getRight();
}
}
// newNode.setParent(tempRoot);
if (newNode.getData().compareTo(tempRoot.getData()) < 0) {
this.swap(newNode, tempRoot);
}
if (insertingElementArray[i] == '0') {
tempRoot.setLeft(newNode);
} else {
tempRoot.setRight(newNode);
}
this.size++;
}
public void swap(DoublyNode<E> node1, DoublyNode<E> node2) {
E temp = node1.getData();
node1.setData(node2.getData());
node2.setData(temp);
}
public E getMin() {
if (this.size == 0) {
return null;
}
return this.root.getData();
}
public void heapifyDownWord(DoublyNode<E> temp) {
if (temp == null) {
return;
}
DoublyNode<E> smallerChild = this.getSmallerChild(temp);
if (smallerChild == null) {
return;
}
if (smallerChild.getData().compareTo(temp.getData()) < 0) {
this.swap(temp, smallerChild);
this.heapifyDownWord(smallerChild);
}
}
public DoublyNode<E> getSmallerChild(DoublyNode<E> temp) {
if (temp.getLeft() != null && temp.getRight() != null) {
return (temp.getLeft().getData()
.compareTo(temp.getRight().getData()) < 0) ? temp.getLeft()
: temp.getRight();
} else if (temp.getLeft() != null) {
return temp.getLeft();
} else {
return temp.getRight();
}
}
public E extractMin() {
if (this.root == null) {
return null;
}
E temp = this.root.getData();
if (this.root.getLeft() == null && this.root.getRight() == null) {
this.root = null;
this.size--;
return temp;
}
DoublyNode<E> parentOfLastData = this.getParentOfLastData();
if (parentOfLastData.getRight() != null) {
this.root.setData(parentOfLastData.getRight().getData());
parentOfLastData.setRight(null);
} else {
this.root.setData(parentOfLastData.getLeft().getData());
parentOfLastData.setLeft(null);
}
this.heapifyDownWord(this.root);
return temp;
}
public DoublyNode<E> getParentOfLastData() {
if (this.size == 0) {
return null;
}
DoublyNode<E> tempRoot = this.root;
Integer insertingElementPosition = this.size;
char[] insertingElementArray = Integer.toBinaryString(
insertingElementPosition).toCharArray();
int i;
for (i = 1; i < insertingElementArray.length - 1; i++) {
char c = insertingElementArray[i];
if (c == '0') {
tempRoot = tempRoot.getLeft();
} else {
tempRoot = tempRoot.getRight();
}
}
return tempRoot;
}
public DoublyNode<E> getParentOfLastEmptyPosition() {
if (this.size == 0) {
return null;
}
DoublyNode<E> tempRoot = this.root;
Integer insertingElementPosition = this.size + 1;
char[] insertingElementArray = Integer.toBinaryString(
insertingElementPosition).toCharArray();
System.out.println(insertingElementArray.toString());
int i;
for (i = 1; i < insertingElementArray.length - 1; i++) {
char c = insertingElementArray[i];
if (c == '0') {
tempRoot = tempRoot.getLeft();
} else {
tempRoot = tempRoot.getRight();
}
}
return tempRoot;
}
public void print() {
if (this.root == null) {
System.out.println("Heap via pointer is empty!");
return;
}
System.out.println("\n Heap via pointer is:- ");
Queue<NodeLevel<E>> dataQueue = new Queue<NodeLevel<E>>();
Queue<Space> spaceQueue = new Queue<Space>();
dataQueue.enQueue(new NodeLevel<E>(this.root, 1));
int heightOfTree = this.getHeightOfHeap();
Double powerHeghtBST = Math.pow(heightOfTree, 2);
spaceQueue.enQueue(new Space(powerHeghtBST.intValue(), false));
while (!dataQueue.isEmpty()) {
Space space = spaceQueue.deQueue();
NodeLevel<E> nodeLevel = dataQueue.deQueue();
while (space.isNullSpace()) {
space.printNullSpace();
spaceQueue.enQueue(space);
space = spaceQueue.deQueue();
}
space.printFrontSpace();
System.out.print(nodeLevel.getNode().getData().printingData());
space.printBackSpace();
if (nodeLevel.getNode().getLeft() != null) {
dataQueue.enQueue(new NodeLevel<E>(nodeLevel.getNode()
.getLeft(), nodeLevel.getLevel() + 1));
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, false));
} else {
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, true));
}
if (nodeLevel.getNode().getRight() != null) {
dataQueue.enQueue(new NodeLevel<E>(nodeLevel.getNode()
.getRight(), nodeLevel.getLevel() + 1));
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, false));
} else {
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, true));
}
if (!dataQueue.isEmpty()
&& nodeLevel.getLevel() + 1 == dataQueue.getFrontData()
.getLevel()) {
System.out.println("\n");
}
}
}
public int getHeightOfHeap() {
if (this.size == 0) {
return 0;
}
Double height = Math.log(this.size) / Math.log(2) + 1;
return height.intValue();
}
public void changePriorityOfHeapTop(E data) {
if (this.root == null) {
return;
}
this.root.setData(data);
this.heapifyDownWord(this.root);
}
}
interface Comparable<T> extends java.lang.Comparable<T> {
/**
* this methos returns a string of that data which to be shown during
* printing tree
*
* #return
*/
public String printingData();
}
public class PracticeMainClass {
public static void main(String[] args) {
MinHeap<Student> minHeap1 = new MinHeap<Student>();
minHeap1.insert(new Student(50, "a"));
minHeap1.insert(new Student(20, "a"));
minHeap1.insert(new Student(60, "a"));
minHeap1.insert(new Student(30, "a"));
minHeap1.insert(new Student(40, "a"));
minHeap1.insert(new Student(70, "a"));
minHeap1.insert(new Student(10, "a"));
minHeap1.insert(new Student(55, "a"));
minHeap1.insert(new Student(35, "a"));
minHeap1.insert(new Student(45, "a"));
minHeap1.print();
minHeap1.getMin();
minHeap1.print();
System.out
.println("\nminimum is:- " + minHeap1.getMin().printingData());
minHeap1.print();
System.out.println("\nminimum is:- "
+ minHeap1.extractMin().printingData());
minHeap1.print();
minHeap1.changePriorityOfHeapTop(new Student(75, "a"));
minHeap1.print();
}
}
class DoublyNode<E extends Comparable<E>> {
private E data;
private DoublyNode<E> left;
private DoublyNode<E> right;
// private DoublyNode<E> parent;
public DoublyNode() {
}
public DoublyNode(E data) {
this.data = data;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public DoublyNode<E> getLeft() {
return left;
}
public void setLeft(DoublyNode<E> left) {
this.left = left;
}
public DoublyNode<E> getRight() {
return right;
}
public void setRight(DoublyNode<E> right) {
this.right = right;
}
// public DoublyNode<E> getParent() {
// return parent;
// }
// public void setParent(DoublyNode<E> parent) {
// this.parent = parent;
// }
}
class Space {
private boolean isNullSpace = false;
private String frontSpace;
private String backSpace;
private String nullSpace;
private int spaceSize;
public boolean isNullSpace() {
return isNullSpace;
}
public void setNullSpace(boolean isNullSpace) {
this.isNullSpace = isNullSpace;
}
public int getSpaceSize() {
return spaceSize;
}
public void setSpaceSize(int spaceSize) {
this.spaceSize = spaceSize;
}
public Space(int spaceSize, boolean isNullSpace) {
this.isNullSpace = isNullSpace;
this.spaceSize = spaceSize;
if (spaceSize == 0) {
this.frontSpace = "";
this.backSpace = "";
this.nullSpace = " ";
} else if (spaceSize == 1) {
this.frontSpace = " ";
this.backSpace = "";
this.nullSpace = " ";
} else if (spaceSize == 2) {
this.frontSpace = " ";
this.backSpace = "";
this.nullSpace = " ";
} else {
this.frontSpace = String.format("%" + (spaceSize) + "s", " ");
this.backSpace = String.format("%" + (spaceSize - 2) + "s", " ");
this.nullSpace = String.format("%" + 2 * (spaceSize) + "s", " ");
}
}
public void printFrontSpace() {
System.out.print(this.frontSpace);
}
public void printBackSpace() {
System.out.print(this.backSpace);
}
public void printNullSpace() {
System.out.print(this.nullSpace);
}
}
class Queue<E> {
private Node<E> front;
private Node<E> rear;
private int queueSize = 0;
public Queue() {
}
public Queue(E data) {
this.front = new Node(data);
this.rear = this.front;
}
public void enQueue(E data) {
if (this.rear == null) {
this.rear = new Node(data);
this.front = this.rear;
} else {
Node newNode = new Node(data);
this.rear.setNext(newNode);
this.rear = newNode;
}
this.queueSize++;
}
public E deQueue() {
E returnValue;
if (this.front == null) {
return null;
} else if (this.front == this.rear) {
returnValue = this.front.getData();
this.front = null;
this.rear = null;
} else {
returnValue = this.front.getData();
this.front = this.front.getNext();
}
this.queueSize--;
return returnValue;
}
public void print() {
Node temp = this.front;
System.out.print("\n Queue is:- ");
if (temp == null) {
System.out.println(" Empty! ");
}
while (temp != null) {
System.out.print(temp.getData() + ",");
temp = temp.getNext();
}
}
public int getQueueSize() {
return queueSize;
}
public E getFrontData() {
if (this.front == null) {
System.out.println("queue is empty!");
return null;
}
return this.front.getData();
}
public E getRearData() {
if (this.rear == null) {
System.out.println("queue is empty!");
return null;
}
return this.rear.getData();
}
public boolean isEmpty() {
return this.front == null;
}
}
class Node<E> {
private E data;
private Node next;
public Node(E data) {
this.data = data;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
class Student implements Comparable<Student> {
private int id;
private String name;
#Override
public int compareTo(Student student) {
if (this.id == student.id) {
return 0;
} else if (this.id < student.id) {
return -1;
} else {
return 1;
}
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String printingData() {
// String printingData = "{ id: "+this.id+" name: "+this.name+" }";
String printingData = String.valueOf(this.id);
return printingData;
}
}
Output of this code is:-
Heap via pointer is:-
10
30 20
35 40 70 60
55 50 45
Heap via pointer is:-
10
30 20
35 40 70 60
55 50 45
minimum is:- 10
Heap via pointer is:-
10
30 20
35 40 70 60
55 50 45
minimum is:- 10
Heap via pointer is:-
20
30 45
35 40 70 60
55 50
Heap via pointer is:-
30
35 45
50 40 70 60
55 75

Null pointer Exception while reversing a Queue using stack

I was practicing on how to implement queue using arrays. I have easily implemented how to enqueue and dequeue the elements in queue. But I have encountered an exception while implementing reverse of queue using stacks
public class QueueImpl {
private int capacity;
int queueArr[];
int front = 0;
int rear = -1;
int currentSize = 0;
QueueImpl(int queueSize){
this.capacity=queueSize;
queueArr=new int[this.capacity];
}
public void enqueue(int data){
if(isQueueFull()){
System.out.println("Overflow");
return;
}
else{
rear=rear+1;
if(rear==capacity-1)
{
rear=0;
}
queueArr[rear]=data;
currentSize++;
System.out.println("Element " + data+ " is pushed to Queue !");
}
}
public int dequeue(){
if(isQueueEmpty()){
System.out.println("UnderFlow");
}
else{
front=front+1;
if(front == capacity-1){
System.out.println("Pop operation done ! removed: "+queueArr[front-1]);
front = 0;
} else {
System.out.println("Pop operation done ! removed: "+queueArr[front-1]);
}
currentSize--;
}
return queueArr[front-1];
}
private boolean isQueueEmpty() {
boolean status=false;
if(currentSize==0){
status=true;
}
return status;
}
private boolean isQueueFull() {
boolean status=false;
if(currentSize==capacity){
status=true;
}
return status;
}
public static void main(String arg[]) {
QueueImpl queueImpl=new QueueImpl(5);
queueImpl.enqueue(5);
queueImpl.enqueue(2);
queueImpl.enqueue(9);
queueImpl.enqueue(1);
// queueImpl.dequeue();
queueImpl.printQueue(queueImpl);
queueImpl.reverse(queueImpl);
}
private void printQueue(QueueImpl queueImpl) {
System.out.println(queueImpl.toString());
}
#Override
public String toString() {
return "Queue [front=" + front + ", rear=" + rear + ", size=" + currentSize
+ ", queue=" + Arrays.toString(queueArr) + "]";
}
private QueueImpl reverse(QueueImpl queueImpl) throws ArrayIndexOutOfBoundsException {
int i=0;
Stack<Integer> stack=new Stack<Integer>();
while(!queueImpl.isQueueEmpty()){
stack.push(queueImpl.dequeue());
}
while(!stack.isEmpty()){
stack.get(i);
i++;
}
while(!stack.isEmpty()){
queueImpl.enqueue(stack.pop());
}
return queueImpl;
}
}
The error log is -
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at com.tcs.QueueUsingAraay.QueueImpl.dequeue(QueueImpl.java:51)
at com.tcs.QueueUsingAraay.QueueImpl.reverse(QueueImpl.java:93)
at com.tcs.QueueUsingAraay.QueueImpl.main(QueueImpl.java:78)
There was a problem in your dequeue method:
1. you were making front=0 and were trying to access front-1 which was -1
as a result the exception was thrown.
Removed stack.get as it was not required.
Corrected working code.
public class QueueImpl {
private int capacity;
int queueArr[];
int front = 0;
int rear = -1;
int currentSize = 0;
QueueImpl(int queueSize) {
this.capacity = queueSize;
queueArr = new int[this.capacity];
}
public void enqueue(int data) {
if (isQueueFull()) {
System.out.println("Overflow");
return;
} else {
rear = rear + 1;
if (rear == capacity - 1) {
rear = 0;
}
queueArr[rear] = data;
currentSize++;
System.out.println("Element " + data + " is pushed to Queue !");
}
}
public int dequeue() {
int element=-1;
if (isQueueEmpty()) {
System.out.println("UnderFlow");
} else {
element = queueArr[front];
front=front+1;
if (front == capacity - 1) {
System.out.println("Pop operation done ! removed: "
+ queueArr[front - 1]);
front = 0;
} else {
System.out.println("Pop operation done ! removed: "
+ queueArr[front - 1]);
}
currentSize--;
}
return element;
}
private boolean isQueueEmpty() {
boolean status = false;
if (currentSize == 0) {
status = true;
}
return status;
}
private boolean isQueueFull() {
boolean status = false;
if (currentSize == capacity) {
status = true;
}
return status;
}
public static void main(String arg[]) {
QueueImpl queueImpl = new QueueImpl(5);
queueImpl.enqueue(5);
queueImpl.enqueue(2);
queueImpl.enqueue(9);
queueImpl.enqueue(1);
queueImpl.printQueue(queueImpl);
queueImpl.reverse(queueImpl);
queueImpl.printQueue(queueImpl);
}
private void printQueue(QueueImpl queueImpl) {
System.out.println(queueImpl.toString());
}
#Override
public String toString() {
return "Queue [front=" + front + ", rear=" + rear + ", size="
+ currentSize + ", queue=" + Arrays.toString(queueArr) + "]";
}
private QueueImpl reverse(QueueImpl queueImpl)
throws ArrayIndexOutOfBoundsException {
Stack<Integer> stack = new Stack<Integer>();
while (!queueImpl.isQueueEmpty()) {
stack.push(queueImpl.dequeue());
}
while (!stack.isEmpty()) {
queueImpl.enqueue(stack.pop());
}
return queueImpl;
}
}

How to build a binary tree from a given interface

I need to build a simple binary tree, which includes Person elements.
Persons must be sorted by height(from low to high). If there are two people with same height, but different sex, men should be first. Usually we use left and right nodes of the element. How can I build tree otherways?
Here is how persons are created:
Person john = new Person() {
#Override
public boolean isMale() {
return true;
}
#Override
public int getID() {
return 1;
}
#Override
public int getHeight() {
return 175;
}
};
This is an interface:
public interface Person {
public int getID();
public boolean isMale();
public int getHeight();
}
Full code with test class
Node.java
public class Node {
double key = 0;
Node parent = null, left = null, right = null;
IDancer dancer = null;
public Node(IDancer d) {
this.dancer = d;
String key = d.getHeight() + (d.isMale() ? "0." : "1.") + d.getID();
this.key = Double.parseDouble(key);
System.out.println("new node: " + this.key);
}
public void copy(double key, IDancer d) {
this.dancer = d;
this.key = key;
}
public boolean hasRight() {
if (this.right != null) return true;
else return false;
}
public boolean hasLeft() {
if (this.left != null) return true;
else return false;
}
public boolean hasParent() {
if (this.parent != null) return true;
else return false;
}
public boolean isMale() {
if (this.dancer.isMale())
return true;
else return false;
}
}
Dancers.java
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.List;
public class Dancers implements IDancers {
public Tree tree = new Tree();
#Override
public SimpleEntry<IDancer, IDancer> findPartnerFor(IDancer d) throws IllegalArgumentException {
if (!(d instanceof IDancer) ||
(d.getHeight() <= 0) ||
(d.getID() <= 0)) throw new IllegalArgumentException();
IDancer partner = null;
tree.insert(d);
try {partner = (d.isMale()) ? tree.female(d) : tree.male(d);
} catch (NullPointerException n) {return null;}
if (partner != null) {
tree.remove(d);
tree.remove(partner);
System.err.println("Partner: "
+ d.getID()
+ (d.isMale() ? "M " : "F ")
+ " For: "
+ partner.getID()
+ (partner.isMale() ? "M " : "F "));
return new SimpleEntry<IDancer, IDancer>(d, partner);
} return null;
}
#Override
public List<IDancer> returnWaitingList() {
try {return tree.inorder(tree.root, new ArrayList<IDancer>());
} catch(NullPointerException n) {return new ArrayList<IDancer>();}
}
}
Tree.java
import java.util.ArrayList;
public class Tree {
public Node root = null;
public IDancer male(IDancer female) {
Node current = search(genKey(female));
Node tmp = succsessor(current);
while (!tmp.isMale()) {
tmp = succsessor(tmp);
} return tmp.isMale() ? tmp.dancer : null;
}
public IDancer female(IDancer male) {
Node current = search(genKey(male));
Node tmp = predecessor(current);
while (tmp.isMale()) {
tmp = predecessor(tmp);
} return tmp.isMale() ? null : tmp.dancer;
}
public Node minimum() {return minimum(this.root);}
private Node minimum(Node node) {
if (node.hasLeft())
return minimum(node.left);
else return node;
}
public Node maximum() {return maximum(this.root);}
public Node maximum(Node node) {
if (node.hasRight())
return maximum(node.right);
else return node;
}
public double genKey(IDancer d) {
return Double.parseDouble(d.getHeight() + (d.isMale() ? "0." : "1.") + d.getID());
}
private Node search(double key, Node current) {
if (current.key == key) return current;
if (current.key > key
&& current.hasLeft())
return search(key, current.left);
if (current.key < key
&& current.hasRight())
return search(key, current.right);
return null;
}
public Node search(double key) {return search(key, this.root);}
public void insert(IDancer d) {
Node dancer = new Node(d);
Node y = null;
if (root == null) {
this.root = dancer;
return;
}
Node x = this.root;
while (x != null) {
y = x;
if (dancer.key < x.key) x = x.left;
else x = x.right;
} dancer.parent = y;
if (y == null) this.root = dancer;
else {
if (dancer.key < y.key) y.left = dancer;
else y.right = dancer;
}
}
public ArrayList<IDancer> inorder(Node node, ArrayList<IDancer> output) {
if (node.hasLeft())
inorder(node.left, output);
output.add(node.dancer);
if (node.hasRight())
inorder(node.right, output);
return output;
}
public void remove(IDancer d) {
Node z = search(genKey(d)); //toRemove
Node y = null; //replacer
Node x = null;
if (!z.hasLeft() || !z.hasRight())
y = z;
else y = succsessor(z);
if (y.hasLeft())
x = y.left;
else x = y.right;
if (x != null)
x.parent = y.parent;
if (!y.hasParent())
this.root = x;
else if (y == y.parent.left)
y.parent.left = x;
else y.parent.right = x;
if (y != z)
z.dancer = y.dancer;
y = null;
}
private Node succsessor(Node n) {
if (n.hasRight())
return minimum(n.right);
Node tmp = n.hasParent() ? n.parent : null;
while (tmp != null && n == tmp.right) {
n = tmp;
tmp = tmp.parent;
} return tmp;
}
private Node predecessor(Node n) {
if (n.hasLeft())
return maximum(n.left);
Node tmp = n.hasParent() ? n.parent : null;
while (tmp != null && n == tmp.left) {
n = tmp;
tmp = tmp.parent;
} return tmp;
}
}

Resources