What is the most efficient way to represent edge weights for Dijkstra's algorithm - algorithm

I'm making a little game where I'm going to have a character on a grid that moves around. I was going to use Dijkstra's algorithm for the pathing as they move around. Only problem being is I want to make thin walls(instead of just removing nodes) like so: http://i.gyazo.com/85d110c17cf027d3ad0219fa26938305.png
I was thinking the best way to do it was just edit the edge weights between 2 squares to be so high that it would never be crossed. Anyway, onto the question:
What is the most efficient way to assign edge weights to each connection in the grid?
I've thought about using an adjacency matrix, but for a 15x6 grid, that's a 90x90 matrix which seems... excessive. Any help would be nice, thanks (:

You only need to store edges between the rectilinear squares and a square can have at most 4 neighbors, once for each direction. Store the edge accessed by node as up to 4 entries of the enumeration {up, down, left, right}. That's is less than 90 x 4.

Some pointers that can help you decide what you should do:
It seems your graph is unweighted, so you could use a BFS, which is
both simpler to implement and more efficient than Dijkstra's algorithm in this case.
90x90 matrix is hardly an issue for a modern machine (unless you are going to use the pathfinding algorithm in a very tight loop)
If you are using double as weights, a lot of languages got
infinity value that you could use. In java that's
Double.POSITIVE_INFINITY. Beauty about infinity - as much as you add to it, it stays infinity (and does not overflow like integers).
You can always use adjacency lists, which can be thought of as a sparsed implementation of a matrix - where most edges have some constant predefined weight (infinity for example, for non existing edge).
Note that using adjacency matrix rather than adjacency lists for very sparsed graph (like yours) makes the time complexity of BFS O(V^2) instead of O(V+E) (which is actually O(V) in your case), and O(V^2) for Dijkstra's algorithm instead of O(E + VlogV) (which is O(VlogV) for your graph)

I agree with rocky's answer - just store the weights for the four directions for each square in an array (each array element will be a struct/tuple which contains the four weights). To look up an edge between two arbitrary squares, you first check if they are adjacent, and if so use the appropriate weight from the array. Not sure why anyone mentioned adjacency lists or matrix, which are redundant here.

Try code below to create you game.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
object[,] input = {
{
new object[] { 0, -1, -1, 1, 6}, //index, left, up, right, down
new object[] { 1, 0, -1, -1, 7}, //index, left, up, right, down
new object[] { 2, -1, -1, 3, 8}, //index, left, up, right, down
new object[] { 3, 2, -1, 4, 9}, //index, left, up, right, down
new object[] { 4, 3, -1, -1, 10}, //index, left, up, right, down
new object[] { 5, -1, -1, -1, 11} //index, left, up, right, down
},
{
new object[] { 6, -1, 0, 7, -1}, //index, left, up, right, down
new object[] { 7, 6, 1, -1, 13}, //index, left, up, right, down
new object[] { 8, -1, 2, 9, 14}, //index, left, up, right, down
new object[] { 9, 8, 3, -1, -1}, //index, left, up, right, down
new object[] {10, -1, 4, 11, -1}, //index, left, up, right, down
new object[] {11, 10, 5, -1, 17} //index, left, up, right, down
},
{
new object[] {12, -1, -1, 13, 19}, //index, left, up, right, down
new object[] {13, 12, 7, 14, 20}, //index, left, up, right, down
new object[] {14, 13, 8, 15, 21}, //index, left, up, right, down
new object[] {15, 14, -1, -1, 22}, //index, left, up, right, down
new object[] {16, -1, -1, 17, 23}, //index, left, up, right, down
new object[] {17, 16, 11, -1, 24} //index, left, up, right, down
},
{
new object[] {18, -1, 12, 19, 24}, //index, left, up, right, down
new object[] {19, 18, 13, -1, 25}, //index, left, up, right, down
new object[] {20, -1, 14, 21, 26}, //index, left, up, right, down
new object[] {21, 20, 15, -1, 27}, //index, left, up, right, down
new object[] {22, -1, 16, 23, 28}, //index, left, up, right, down
new object[] {23, 22, 17, -1, 29} //index, left, up, right, down
},
{
new object[] {24, -1, 18, 25, -1}, //index, left, up, right, down
new object[] {25, 24, 19, 26, -1}, //index, left, up, right, down
new object[] {26, -1, 20, 27, -1}, //index, left, up, right, down
new object[] {27, 26, 21, 28, -1}, //index, left, up, right, down
new object[] {28, 27, 22, 29, -1}, //index, left, up, right, down
new object[] {29, 28, 23, -1, -1} //index, left, up, right, down
},
};
cell game = new cell(input);
}
}
public class cell
{
public static cell[,] board = new cell[5, 6];
public int index { get; set; } //row number * 6 + col
public int row { get; set;}
public int col { get; set;}
public cell up { get; set; }
public cell down { get; set; }
public cell left { get; set; }
public cell right { get; set; }
public cell() { }
public cell(object[,] input)
{
int cellNumber = 0;
int boardRow = 0;
int boardCol = 0;
int cellRow = 0;
int cellCol = 0;
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 6; col++)
{
board[row, col] = new cell();
}
}
for (int row = 0; row < 5; row++)
{
for (int col = 0; col < 6; col++)
{
object[] items = (object[])input[row, col];
cellNumber = (int)items[0];
boardRow = cellNumber / 6;
boardCol = cellNumber % 6;
board[boardRow, boardCol].index = cellNumber;
board[boardRow, boardCol].row = row;
board[boardRow, boardCol].col = col;
cellNumber = (int)items[1];
cellRow = cellNumber / 6;
cellCol = cellNumber % 6;
if (cellNumber == -1)
{
board[boardRow, boardCol].left = null;
}
else
{
board[boardRow, boardCol].left = board[cellRow, cellCol];
}
cellNumber = (int)items[2];
cellRow = cellNumber / 6;
cellCol = cellNumber % 6;
if (cellNumber == -1)
{
board[boardRow, boardCol].up = null;
}
else
{
board[boardRow, boardCol].up = board[cellRow, cellCol];
}
cellNumber = (int)items[3];
cellRow = cellNumber / 6;
cellCol = cellNumber % 6;
if (cellNumber == -1)
{
board[boardRow, boardCol].right = null;
}
else
{
board[boardRow, boardCol].right = board[cellRow, cellCol];
}
cellNumber = (int)items[4];
cellRow = cellNumber / 6;
cellCol = cellNumber % 6;
if (cellNumber == -1)
{
board[boardRow, boardCol].down = null;
}
else
{
board[boardRow, boardCol].down = board[cellRow, cellCol];
}
}
}
}
}
}
​

Use this code to initialize the game board for large arrays. Then add nulls for location of walls making sure you add the walls to two cells.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
cell game = new cell(90, 100);
}
}
public class cell
{
public static cell[,] board = null;
public int index { get; set; } //row number * 6 + col
public int row { get; set;}
public int col { get; set;}
public cell up { get; set; }
public cell down { get; set; }
public cell left { get; set; }
public cell right { get; set; }
public bool visited { get; set; }
public cell() { }
public cell(int rows, int cols)
{
board = new cell[rows, cols];
int cellNumber = 0;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
board[row, col] = new cell();
board[row, col].visited = false;
}
}
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
cellNumber = (row * cols) + col;
board[row, col].index = cellNumber;
board[row, col].row = row;
board[row, col].col = col;
if (col == 0)
{
board[row, col].left = null;
}
else
{
board[row, col].left = board[row, col - 1];
}
if (row == 0)
{
board[row, col].up = null;
}
else
{
board[row, col].up = board[row - 1, col];
}
if (col == cols - 1)
{
board[row, col].right = null;
}
else
{
board[row, col].right = board[row, col + 1];
}
if (row == rows - 1)
{
board[row, col].down = null;
}
else
{
board[row, col].down = board[row + 1, col];
}
}
}
}
}
}

Related

How to find level order traversal from Preorder and Inorder Traversal

Pre-order traversal of a binary tree is {8, 5, 9, 7, 1, 12, 4, 11, 3} and its in-order is {9, 5, 1, 7, 12, 8, 4, 3, 11}. A binary tree is constructed with it and level order traversal is performed. Then finally a Binary Search Tree (BST) is constructed taking the key values one at time as they appeared in the above level order traversal from left to right. What will be the level order traversal of this BST?
Here is my solution:
Build the Tree from Inorder and PreOrder traversal.
Iterate over the tree and find level order traversal.
public class PreAndInOrderToLevelOrderTraversal {
static class Node {
int val;
Node left;
Node right;
public Node(int val) {
this.val = val;
left = null;
right = null;
}
}
static int[] pre;
static int[] in;
static ConcurrentHashMap<Integer, Integer> map;
static Node treeRoot;
static int preIndex = 0;
public static void main(String[] args) {
map = new ConcurrentHashMap<>();
pre = new int[]{1, 2, 4, 5, 3};
in = new int[]{4, 2, 5, 1, 3};
treeRoot = buildTreeFromPreorderAndInOrder(pre, in, map);
System.out.println(treeRoot.val);
printLevelOrder();
}
public static void printLevelOrder() {
Queue<Node> queue = new LinkedList<Node>();
queue.add(treeRoot);
while (!queue.isEmpty()) {
/* poll() removes the present head.
For more information on poll() visit
http://www.tutorialspoint.com/java/util/linkedlist_poll.htm */
Node tempNode = queue.poll();
System.out.print(tempNode.val + " ");
/*Enqueue left child */
if (tempNode.left != null) {
queue.add(tempNode.left);
}
/*Enqueue right child */
if (tempNode.right != null) {
queue.add(tempNode.right);
}
}
}
private static Node buildTreeFromPreorderAndInOrder(int[] pre, int[] in, ConcurrentHashMap<Integer, Integer> map) {
// location of the item in the inorder traversal to find it quick in O(1)
for (int i = 0; i < in.length; i++) {
map.put(in[i], i);
}
return helper(in, pre, 0, pre.length - 1, map);
}
private static Node helper(int[] in, int[] pre, int inStart, int inEnd, ConcurrentHashMap<Integer, Integer> map) {
if (inStart > inEnd) return null;
int curr = pre[preIndex++];
Node tNode = new Node(curr);
if (inStart == inEnd) return tNode;
int inIndex = map.get(curr);
tNode.left = helper(in, pre, inStart, inIndex - 1, map);
tNode.right = helper(in, pre, inIndex + 1, inEnd, map);
return tNode;
}
}

Choose n unique elements from n lists

I have been thinking about a programing problem. If we have n lists, we want to output n diffrent elements (each one from a different list). I suspect this can be solved with some kind of a backtrack algorithm but I don't see how to correctly implement it.
Though you could solve this with backtracking as suggested in a comment, a more efficient solution would be to use a max-flow algorithm.
Model it as a graph. A Source, a Sink a node for each distinct element and a node for each list.
You have the source connected to each distinct element. Each element connected to every list it is in. and the lists connected to a sink node. Each edge with capacity 1.
The maximum flow is the maximum number of distinct elements from distinct lists you can select.
https://en.wikipedia.org/wiki/Maximum_flow_problem
https://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm
I'm not exactly sure that this has no bugs and solves what is being asked; and I hope I have understood the question right this time :)
//test
int[][] arr = new int[][] {
new int[] { 1, 1, 1, 1, 6 },
new int[] { 1, 1, 1, 1, 5 },
new int[] { 1, 1, 1, 4, 9 },
new int[] { 1, 1, 3, 8, 1 },
new int[] { 1, 2, 7, 1, 1 },
new int[] { 1, 1, 1, 1, 1 } };
int[] res = getItems(arr).ToArray(); //6,5,4,3,2,1
private static IEnumerable<T> getItems<T>(T[][] array)
{
int N = array.GetLength(0);
item<T>[] items = new item<T>[N];
HashSet<T> hs = new HashSet<T>();
for (int i = 0; i < N; i++)
{
bool ok = false;
T[] arr = array[i];
for (int j = items[i].Index; j < arr.Length; j++)
{
T val = arr[j];
if (hs.Add(val))
{
items[i] = new item<T>() { Val = val, Index = j };
ok = true;
break;
}
}
if (!ok)
{
item<T> item;
do
{
if (i == 0) throw new Exception("no solution");
items[i] = new item<T>();
item = items[--i];
item.Index++;
items[i] = item;
}
while (item.Index >= array[i].Length);
hs.Clear();
for (int j = 0; j < i; j++)
hs.Add(array[j][items[j].Index]);
i--;
}
}
return hs;
}
private struct item<T>
{
public T Val;
public int Index;
public override string ToString()
{
return string.Format("Val:{0} Index:{1}", Val, Index);
}
}

Navigating through a Maze using path-planning (Dijkstra)

I'm working on an robot that would be able to navigate through a maze, avoid obstacles and identify some of the objects in it. I have a monochromatic bitmap of the maze, that is supposed to be used in the robot navigation.
Up till now I have processed the bitmap image, and converted it into an adjacency list. I will now use the dijkstra's algorithm to plan the path.
However the problem is that I have to extract the entrance point/node and exit node from the bmp image itself for dijkstra's algorithm to plan the path.
The robots starting position will be slightly different (inch or two before the entrance point) from the entrance point of maze, and I am supposed to move to the entrance point using any "arbitrary method" and then apply dijkstra algorithm to plan path from maze's entrance to exit.
On the way I have to also stop at the "X's" marked in the bmp file I have attached below. These X's are basically boxes in which I have to pot balls. I will plan the path from entrance point to exit point , and not from the entrance to 1st box, then to second, and then to the exit point; because I think the boxes will always be placed at the shortest path.
Since the starting position is different from the entrance point, how will I match my robot's physical location with the coordinates in the program and move it accordingly. Even if the entrance position would have been same as starting position there may have been an error. How should I deal with it? Should I navigate only on the bases of the coordinates provided by dijkstra or use ultrasonics as well to prevent collisions? And if we yes, can you give me an idea of how should I use the both (ultrasonics, and coordinates)?
Here's the sample Bitmap image of the maze.
I know you need this for robotics but here is an example how to translate pixels to array in java to give some ideas?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class RobotDemo extends JFrame {
private static final long serialVersionUID = 1L;
public RobotDemo() {
super("Robot Demo");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
getContentPane().add(new RobotPanel(), BorderLayout.CENTER);
pack();
setResizable(false);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new RobotDemo();
frame.setVisible(true);
}
});
}
}
interface Constants {
public static final int TILE_WIDTH = 32;
public static final int TILE_HEIGHT = 32;
public static final int NUM_TILE_COLS = 20;
public static final int NUM_TILE_ROWS = 10;
public static final int PIXEL_STEPS = 3;
public static final int REFRESH_RATE = 200;
public static final Dimension PANEL_SIZE = new Dimension(TILE_WIDTH * NUM_TILE_COLS, TILE_HEIGHT * NUM_TILE_ROWS);
public static enum RobotState {
awaiting_instruction,
moving_north,
moving_south,
moving_east,
moving_west
};
public static enum RobotInstruction {
NORTH,
SOUTH,
EAST,
WEST
}
public void draw(Graphics g);
}
class RobotPanel extends JPanel implements Constants, ActionListener {
private static final long serialVersionUID = 1L;
private Timer timer = new Timer(REFRESH_RATE, this);
private Map map = new Map();
private Robot robot = new Robot(map);
public RobotPanel() {
timer.start();
}
public Dimension getPreferredSize() { return PANEL_SIZE; }
public Dimension getMinimumSize() { return PANEL_SIZE; }
public Dimension getMaximumSize() { return PANEL_SIZE; }
protected void paintComponent(Graphics g) {
super.paintComponent(g);
map.draw(g);
robot.draw(g);
draw(g);
}
public void actionPerformed(ActionEvent e) {
robot.update();
repaint();
}
public void draw(Graphics g) {
for(int r = 0; r < NUM_TILE_ROWS; r++) {
for(int c = 0; c < NUM_TILE_COLS; c++) {
g.drawRect(c * TILE_WIDTH, r * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
}
}
}
}
class Robot implements Constants {
private RobotState state = RobotState.moving_east;
private int row = TILE_HEIGHT;
private int col = TILE_WIDTH;
private int mapX = 1;
private int mapY = 1;
private Map map;
int nextRowCheck = 1;
int nextColCheck = 2;
public Robot(Map m) {
map = m;
}
public int getRow() {
return mapY;
}
public int getCol() {
return mapX;
}
private boolean needsNewInstruction(){
int newRow = row;
int newCol = col;
if(state == RobotState.moving_north) newRow -= PIXEL_STEPS;
if(state == RobotState.moving_south) newRow += PIXEL_STEPS;
if(state == RobotState.moving_east) newCol += PIXEL_STEPS;
if(state == RobotState.moving_west) newCol -= PIXEL_STEPS;
if((newRow / TILE_HEIGHT) != mapY) return true;
if((newCol / TILE_WIDTH) != mapX) return true;
return false;
}
public void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.GREEN);
g.fillRect(col, row, TILE_WIDTH, TILE_HEIGHT);
g.setColor(c);
}
public void update() {
System.out.println("UPDATE [" + row + "][" + col + "] = [" + (row / TILE_HEIGHT) + "][" + (col / TILE_WIDTH) + "]");
if(needsNewInstruction()) {
System.out.println("NEEDS NEW INSTRUCTION [" + row + "][" + col + "] = [" + (row / TILE_HEIGHT) + "][" + (col / TILE_WIDTH) + "]");
mapX = nextColCheck;
mapY = nextRowCheck;
System.out.println("UPDATED MAP REFERENCE [" + mapY + "][" + mapX + "]");
row = mapY * TILE_HEIGHT;
col = mapX * TILE_WIDTH;
System.out.println("UPDATED PIXEL REFERENCE [" + row + "][" + col + "]");
RobotInstruction instruction = map.getNextInstruction(this);
if(instruction == RobotInstruction.NORTH) {
state = RobotState.moving_north;
nextRowCheck = mapY - 1;
}
if(instruction == RobotInstruction.SOUTH) {
state = RobotState.moving_south;
nextRowCheck = mapY + 1;
}
if(instruction == RobotInstruction.EAST) {
state = RobotState.moving_east;
nextColCheck = mapX + 1;
}
if(instruction == RobotInstruction.WEST) {
state = RobotState.moving_west;
nextColCheck = mapX - 1;
}
}
move();
}
public void move() {
if(state == RobotState.moving_north) row -= PIXEL_STEPS;
if(state == RobotState.moving_south) row += PIXEL_STEPS;
if(state == RobotState.moving_east) col += PIXEL_STEPS;
if(state == RobotState.moving_west) col -= PIXEL_STEPS;
}
}
class Map implements Constants {
int[][] map = new int[][] {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
public Map() {
}
public RobotInstruction getNextInstruction(Robot robot) {
int row = robot.getRow();
int col = robot.getCol();
System.out.println("GET NEXT INSTRUCTION FOR [" + row + "][" + col + "]");
if(map[row][col + 1] == 0) return RobotInstruction.EAST;
if(map[row + 1][col] == 0) return RobotInstruction.SOUTH;
if(map[row - 1][col] == 0) return RobotInstruction.NORTH;
if(map[row][col - 1] == 0) return RobotInstruction.WEST;
return null;
}
public void draw(Graphics g) {
Color color = g.getColor();
for(int r = 0; r < NUM_TILE_ROWS; r++) {
for(int c = 0; c < NUM_TILE_COLS; c++) {
g.setColor(map[r][c] == 0 ? Color.CYAN : Color.RED);
g.fillRect(c * TILE_WIDTH, r * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
}
}
g.setColor(color);
}
}
Here is an example how to populate your navigational array with directions. the code above doesn't use the code below so you would have to do that yourself ...
public class Maze {
private static final char E = 'E'; // Ending position
private static final char X = 'X'; // Wall
private static final char O = ' '; // Space
private static final char L = 'L'; // Left
private static final char R = 'R'; // Right
private static final char U = 'U'; // Up
private static final char D = 'D'; // Down
private static final char FALSE = '0'; // Not accessible
private static final char TRUE = '1'; // Is accessible
private static final Node END_NODE = new Node(4, 4);
private static final int[] ROW_DIRECTIONS = {-1, 1, 0, 0};
private static final int[] COL_DIRECTIONS = { 0, 0, -1, 1};
private static final char[][] OPPOSITES = new char[][] {{O, D, O},{R, O, L},{O, U, O}};
public static void main(String[] args) {
char[][] maze = new char[][] {
{X, X, X, X, X, X},
{X, O, O, X, O, X},
{X, O, X, X, O, X},
{X, O, O, O, X, X},
{X, X, O, X, O, X},
{X, O, O, O, O, X},
{X, O, X, X, O, X},
{X, X, X, X, X, X}};
// PLOT THE DESTINATION CELL AND ADD IT TO LIST
List<Node> nodes = new ArrayList<Node>();
nodes.add(END_NODE);
maze[END_NODE.row][END_NODE.col] = E;
// PRINT THE MAZE BEFORE ANY CALCULATIONS
printMaze(maze);
// SOLVE THE MAZE
fillMaze(maze, nodes);
printMaze(maze);
// CONVERT MAZE TO AN ADJACENCY MATRIX
compileMaze(maze);
printMaze(maze);
}
/**
* The parallel arrays define all four directions radiating from
* the dequeued node's location.
*
* Each node will have up to four neighboring cells; some of these
* cells are accessible, some are not.
*
* If a neighboring cell is accessible, we encode it with a directional
* code that calculates the direction we must take should we want to
* navigate to the dequeued node's location from this neighboring cell.
*
* Once encoded into our maze, this neighboring cell is itself queued
* up as a node so that recursively, we can encode the entire maze.
*/
public static final void fillMaze(char[][] maze, List<Node> nodes) {
// dequeue our first node
Node destination = nodes.get(0);
nodes.remove(destination);
// examine all four neighboring cells for this dequeued node
for(int index = 0; index < ROW_DIRECTIONS.length; index++) {
int rowIndex = destination.row + ROW_DIRECTIONS[index];
int colIndex = destination.col + COL_DIRECTIONS[index];
// if this neighboring cell is accessible, encode it and add it
// to the queue
if(maze[rowIndex][colIndex] == O) {
maze[rowIndex][colIndex] = getOppositeDirection(ROW_DIRECTIONS[index], COL_DIRECTIONS[index]);
nodes.add(new Node(rowIndex, colIndex));
}
}
// if our queue is not empty, call this method again recursively
// so we can fill entire maze with directional codes
if(nodes.size() > 0) {
fillMaze(maze, nodes);
}
}
/**
* Converts the maze to an adjacency matrix.
*/
private static void compileMaze(char[][] maze) {
for(int r = 0; r < maze.length; r++) {
for(int c = 0; c < maze[0].length; c++) {
if(maze[r][c] == X || maze[r][c] == O) {
maze[r][c] = FALSE;
}
else {
maze[r][c] = TRUE;
}
}
}
}
/**
* prints the specified two dimensional array
*/
private static final void printMaze(char[][] maze) {
System.out.println("====================================");
for(int r = 0; r < maze.length; r++) {
for(int c = 0; c < maze[0].length; c++) {
System.out.print(maze[r][c] + " ");
}
System.out.print("\n");
}
System.out.println("====================================");
}
/**
* Simply returns the opposite direction from those specified
* by our parallel direction arrays in method fillMaze.
*
* coordinate 1, 1 is the center of the char[][] array and
* applying the specified row and col offsets, we return the
* correct code (opposite direction)
*/
private static final char getOppositeDirection(int row, int col) {
return OPPOSITES[1 + row][1 + col];
}
}
class Node {
int row;
int col;
public Node(int rowIndex, int colIndex) {
row = rowIndex;
col = colIndex;
}
}

Even-odd sort incompatibility

I am new to Java and I have faced the following problem. I need to sort array of integers in ascending order so that even numbers will be in one half and odd ones in the other.
So, I have a special comparator:
static class EvenOddSort implements Comparator<Integer> {
#Override
public int compare(Integer x, Integer y) {
if (x == y) {
return 0;
}
if (y % 2 == 0) {
if (x < y) {
return -1;
} else {
return 1;
}
}
if (x % 2 == 0) {
if (x < y) {
return 1;
} else {
return -1;
}
}
return 0;
}
}
And the following sort method:
public Integer[] sortEvenOdd(Integer[] nums) {
EvenOddSort customSort = new EvenOddSort();
Arrays.sort(nums, customSort);
return nums;
}
Also I have the following test:
#Test
public void testSortEvenOdd1() {
Integer[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Integer[] expected = { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 };
assertArrayEquals(expected, tasks5.sortEvenOdd(nums));
}
It fails when I run it on openJDK6 and successful on openJDK7.
arrays first differed at element [0]; expected:<2> but was:<1> junit.framework.AssertionFailedError: arrays first differed at element [0]; expected:<2> but was:<1>
Could you help me to make it compatible across all openJDK's?
Also, it would be great to know what I am doing wrong.
Any ideas are welcome!
Your whole comparator is broken, I kept seeing more problems with it.
Just do something like this:
if (x%2 != y%2) {
if (x%2==0) {
return -1;
} else {
return 1;
}
} else {
return x.compareTo(y);
}
First check to see if they are not both odd or both even. If they are different then sort based on odd or even.
Then if they are both odd or both even fall back to the standard Integer compare functionality.

An even and sorted distribution problem

I have a given number of boxes in a specific order and a number of weights in a specific order. The weights may have different weights (ie one may weigh 1kg, another 2kg etc).
I want to put the weights in the boxes in a way so that they are as evenly distributed as possible weight wise. I must take the weights in the order that they are given and I must fill the boxes in the order that they are given. That is if I put a weight in box n+1 I cannot put a weight in box n, and I cannot put weight m+1 in a box until I've first put weight m in a box.
I need to find an algorithm that solves this problem for any number of boxes and any set of weights.
A few tests in C# with xUnit (Distribute is the method that should solve the problem):
[Fact]
public void ReturnsCorrectNumberOfBoxes()
{
int[] populatedColumns = Distribute(new int[0], 4);
Assert.Equal<int>(4, populatedColumns.Length);
}
[Fact]
public void Test1()
{
int[] weights = new int[] { 1, 1, 1, 1 };
int[] boxes = Distribute(weights, 4);
Assert.Equal<int>(weights[0], boxes[0]);
Assert.Equal<int>(weights[1], boxes[1]);
Assert.Equal<int>(weights[2], boxes[2]);
Assert.Equal<int>(weights[3], boxes[3]);
}
[Fact]
public void Test2()
{
int[] weights = new int[] { 1, 1, 17, 1, 1 };
int[] boxes = Distribute(weights, 4);
Assert.Equal<int>(2, boxes[0]);
Assert.Equal<int>(17, boxes[1]);
Assert.Equal<int>(1, boxes[2]);
Assert.Equal<int>(1, boxes[3]);
}
[Fact]
public void Test3()
{
int[] weights = new int[] { 5, 4, 6, 1, 5 };
int[] boxes = Distribute(weights, 4);
Assert.Equal<int>(5, boxes[0]);
Assert.Equal<int>(4, boxes[1]);
Assert.Equal<int>(6, boxes[2]);
Assert.Equal<int>(6, boxes[3]);
}
Any help is greatly appreciated!
See the solution below.
Cheers,
Maras
public static int[] Distribute(int[] weights, int boxesNo)
{
if (weights.Length == 0)
{
return new int[boxesNo];
}
double average = weights.Average();
int[] distribution = new int[weights.Length];
for (int i = 0; i < distribution.Length; i++)
{
distribution[i] = 0;
}
double avDeviation = double.MaxValue;
List<int> bestResult = new List<int>(boxesNo);
while (true)
{
List<int> result = new List<int>(boxesNo);
for (int i = 0; i < boxesNo; i++)
{
result.Add(0);
}
for (int i = 0; i < weights.Length; i++)
{
result[distribution[i]] += weights[i];
}
double tmpAvDeviation = 0;
for (int i = 0; i < boxesNo; i++)
{
tmpAvDeviation += Math.Pow(Math.Abs(average - result[i]), 2);
}
if (tmpAvDeviation < avDeviation)
{
bestResult = result;
avDeviation = tmpAvDeviation;
}
if (distribution[weights.Length - 1] < boxesNo - 1)
{
distribution[weights.Length - 1]++;
}
else
{
int index = weights.Length - 1;
while (distribution[index] == boxesNo - 1)
{
index--;
if (index == -1)
{
return bestResult.ToArray();
}
}
distribution[index]++;
for (int i = index; i < weights.Length; i++)
{
distribution[i] = distribution[index];
}
}
}
}
Second try: i think the A* (pronounced "a star") algorithm would work well here, even if it would consume a lot of memory. you are guranteed to get an optimal answer, if one exists.
Each "node" you are searching is a possible combination of weights in boxes. The first node should be any weight you pick at random, put into a box. I would recommend picking new weights randomly as well.
Unforetunately, A* is complex enough that I don't have time to explain it here. It is easy enough to understand by reading on your own, but mapping it to this problem as I described above will be more difficult. Please post back questions on that if you choose this route.

Resources