Shape segmentation using Depth-First-Search - algorithm

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
} }

Related

Processing: Multiple bullets in top down shooter

I am trying to make a simple top down shooter. When the user presses W, A, S or D a 'bullet' (rectangle) will come out of the 'shooter'. With my code, you can only shoot one bullet per direction until it reaches the end of the screen. Is there a way to make it so they (the user) can shoot multiple bullets in one direction?
Here's my code:
package topdownshooter;
import processing.core.PApplet;
import processing.core.PImage;
public class TopDownShooter extends PApplet {
PImage shooter;
float shooterX = 400;
float shooterY = 300;
float u_bulletSpeed;
float l_bulletSpeed;
float d_bulletSpeed;
float r_bulletSpeed;
boolean shootUp = false;
boolean shootLeft = false;
boolean shootDown = false;
boolean shootRight = false;
public static void main(String[] args) {
PApplet.main("topdownshooter.TopDownShooter");
}
public void setup() {
shooter = loadImage("shooter.png");
}
public void settings() {
size(800, 600);
}
public void keyPressed() {
if(key == 'w') {
shootUp = true;
}
if(key == 'a') {
shootLeft = true;
}
if(key == 's') {
shootDown = true;
}
if(key == 'd') {
shootRight = true;
}
}
public void draw() {
background(206);
imageMode(CENTER);
image(shooter, shooterX, shooterY);
if(shootUp == true) {
rect(shooterX, shooterY-u_bulletSpeed, 5, 5);
u_bulletSpeed += 2;
if(u_bulletSpeed > 300) {
u_bulletSpeed = 0;
shootUp = false;
}
}
if(shootLeft == true) {
rect(shooterX-l_bulletSpeed, shooterY, 5, 5);
l_bulletSpeed += 2;
if(l_bulletSpeed > 400) {
l_bulletSpeed = 0;
shootLeft = false;
}
}
if(shootDown == true) {
rect(shooterX, shooterY+d_bulletSpeed, 5, 5);
d_bulletSpeed += 2;
if(d_bulletSpeed > 300) {
d_bulletSpeed = 0;
shootDown = false;
}
}
if(shootRight == true) {
rect(shooterX+r_bulletSpeed, shooterY, 5, 5);
r_bulletSpeed += 2;
if(r_bulletSpeed > 400) {
r_bulletSpeed = 0;
shootRight = false;
}
}
}
}
The language is processing and I am using the eclipse IDE.
Thanks!
Here's what I would do if I were you. First I'd encapsulate your bullet data into a class, like this:
class Bullet{
float x;
float y;
float xSpeed;
float ySpeed;
// you probably want a constructor here
void drawBullet(){
// bullet drawing code
}
}
Then I'd create an ArrayList that holds Bullet instances:
ArrayList<Bullet> bullets = new ArrayList<Bullet>();
To add a bullet, I'd create a new instance and add it to the ArrayList like this:
bullets.add(new Bullet(bulletX, bulletY));
Then to draw the bullets, I'd iterate over the ArrayList and call the corresponding function:
for(Bullet b : bullets){
b.drawBullet();
}
Shameless self-promotion:
Here is a tutorial on creating classes.
Here is a tutorial on using ArrayLists.

How to limit number of elements in a stream responsively?Java8

The problem I am having is turning this block of code into Java8 streams.Basically I have a list of cells that are either dead(false) or alive(true) and I need to check how many neighbours are alive for a given cell.
private static int checkMyLivingNeighbours(Cell cell,List<Cell> currentcells){
int neighbours = 0;
for (int y = cell.getY() - 1; y <= cell.getY() + 1; y++) {
for (int x = cell.getX() - 1; x <= cell.getX() + 1; x++) {
if(x!=cell.getX() || y!=cell.getY()){
for (Cell nowcell : currentcells) {
if (nowcell.getX() == x && nowcell.getY() == y) {
if (nowcell.getStatus()) {
neighbours++;
}
}
}
}
}
}
return neighbours;
}
I have tried something like this
private static void checkaliveneighbours(Cell cell,List<Cell> generation){
generation.stream().forEach(n->IntStream.range(cell.getY()-1,cell.getY()+1).
forEach(y -> IntStream.range(cell.getX()-1,cell.getX()+1)
.forEach(x->{if(n.getX()==x && n.getY()==y && n.getStatus())System.out.println(n.getDisplaychar());})));;//
}
where I am calling it like such
checkaliveneighbours(generation.get(0),generation);
SO I do get a print for the alive CELL but I actually need the total nr of alive CELLS surrounding the CELL being passed in and not just a print if the cell passed in is alive or not. Therefor the question how to limit number of elements in a stream(just the surrounding cells) responsively(based on the individual cell being passed in).
Here is the cell class
public class Cell {
private int x;
private int y;
private boolean alive;
public Cell(){}
public Cell(String x, String y, boolean alive ) {
this.x = Integer.valueOf(x);
this.y = Integer.valueOf(y);
this.alive = alive;
}
public int getX() {
return x;
}
public void setX(String x) {
this.x = Integer.valueOf(x);
}
public int getY() {
return y;
}
public void setY(String y) {
this.y = Integer.valueOf(y);
}
public boolean getStatus() {
return alive;
}
public void setStatus(boolean status) {
this.alive = status;
}
public char getDisplaychar() {
if(getStatus())
return 'X';
else
return '.';
}
}
If I understand correctly, by "limiting" you mean using Stream.filter() to filter only neighbors. Then you want to sum all living neighbors. I'd begin by defining a method that will return whether a specified cell is a neighboring cell or not:
private static boolean isNeighbor(final Cell cell, final Cell candidate) {
for (int y = cell.getY() - 1; y <= cell.getY() + 1; y++) {
for (int x = cell.getX() - 1; x <= cell.getX() + 1; x++) {
if (x != cell.getX() || y != cell.getY()) {
if (candidate.getX() == x && candidate.getY() == y) {
return true;
}
}
}
}
return false;
}
Then you can easily filter your list and compute the sum like so:
int sum = generation.stream()
.filter(c -> isNeighbor(cell, c))
.mapToInt(c -> c.getStatus() ? 1 : 0)
.sum();
Edit: If you're looking for a pure Java 8 solution for isNeighbor:
private boolean isNeighbor(final Cell cell, final Cell candidate) {
return IntStream.rangeClosed(cell.getX() - 1, cell.getX() + 1)
.anyMatch(x -> IntStream.rangeClosed(cell.getY() - 1, cell.getY() + 1)
.anyMatch(y -> (x != cell.getX() || y != cell.getY()) &&
x == candidate.getX() && y == candidate.getY()));
}

A* search algorithm infinite loop

Like the title says, This A* search algorithm never stops searching. I'm trying to create a working A* search algorithm for point-click walking in a 2D tile-based game, some tiles are walk-able and some tiles are solid.
PathFinder.java:
public class PathFinder {
public static List<Node> findPath(Map map, int sx, int sy, int dx, int dy) {
if(map.getTile(dx, dy).isSolid()) return null;
Node startNode = new Node(new Vector2i(sx, sy), null, 0, 0);
Vector2i goal = new Vector2i(dx, dy);
List<Node> open = new ArrayList<>();
HashSet<Node> closed = new HashSet<>();
open.add(startNode);
while(open.size() > 0) {
Node currentNode = open.get(0);
for(int i = 1; i < open.size(); i++) {
if(open.get(i).fCost < currentNode.fCost ||
open.get(i).fCost == currentNode.fCost && open.get(i).hCost < currentNode.hCost) {
currentNode = open.get(i);
}
}
open.remove(currentNode);
closed.add(currentNode);
if(currentNode.tile == goal){
System.out.println("returning path!");
return retracePath(startNode, currentNode);
}
for(Tile tile : map.getNeighbors(currentNode)) {
Vector2i neighbor = new Vector2i(tile.getTileX(), tile.getTileY());
if(tile.isSolid() || getNodeInHashSetForPosition(neighbor, closed) != null) {
continue;
}
double gCost = currentNode.gCost + getNodeDistance(currentNode.tile, neighbor);
if(currentNode.gCost < gCost || !vecInList(neighbor, open)) {
double hCost = getNodeDistance(neighbor, goal);
Node node = new Node(neighbor, currentNode, gCost, hCost);
if(!open.contains(node)) {
open.add(node);
}
}
}
}
return null;
}
private static List<Node> retracePath(Node startNode, Node endNode) {
List<Node> path = new ArrayList<>();
Node currentNode = endNode;
while(currentNode != startNode) {
path.add(currentNode);
currentNode = currentNode.parent;
}
List<Node> finalPath = new ArrayList<>();
for(int i = path.size() - 1; i > 0; i--) {
finalPath.add(path.get(i));
}
return finalPath;
}
private static boolean vecInList(Vector2i vec, List<Node> list) {
for(Node n : list) {
if(n.tile.equals(vec)) return true;
}
return false;
}
private static boolean vecInList(Vector2i vec, HashSet<Node> list) {
for(Node n : list) {
if(n.tile.equals(vec)) return true;
}
return false;
}
private static Node getNodeInHashSetForPosition(Vector2i position, HashSet<Node> hashSet) {
for(Node n : hashSet) {
if(n.tile.equals(position)) return n;
}
return null;
}
private static double getNodeDistance(Vector2i nodeA, Vector2i nodeB) {
int dstX = Math.abs(nodeA.x - nodeB.x);
int dstY = Math.abs(nodeA.y - nodeB.y);
if(dstX > dstY) return 14 * dstY + 10 * (dstX - dstY);
return (14 * dstX) + (10 * (dstY - dstX));
}
}
Node.java
public class Node {
public Vector2i tile;
public Node parent;
public double fCost, gCost, hCost; //a cost is like the distance it takes to get to that point. these are used to find the lowest cost way to get from start point A to end point B.
//gCost is the sum of all of our node to node, or tile to tile, distances.
//hCost is the direct distance from the start node to the end node.
//fCost is the total cost for all the ways we calculate to get to the end node/tile.
public Node(Vector2i tile, Node parent, double gCost, double hCost) { //NODE CONSTRUCTOR STARt
this.tile = tile;
this.parent = parent;
this.gCost = gCost;
this.hCost = hCost;
this.fCost = this.gCost + this.hCost;
}//NODE CONSTRUCTOR END
}
change the following:
if(!open.contains(node)) {
to:
if(!veckInList(neighbor, open) {

Optimizations for Solitaire SPOJ

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.

To check an input string is present in custom table of strings

Assume length of element in table is 1 or 2.
Table: { h, fe, na, o}
input string: nafeo
Output: true
Table: {ab,bc}
input string: abc
Output: false
Please advise my below code will cover all the cases and is this the best solution? Or am I missing anything, any alternate solutions?
import java.util.*;
public class CustomTable {
Set<String> table = new HashSet<String>();
public CustomTable(){
// add your elements here for more test cases
table.add("oh");
table.add("he");
}
public int checkTable( String prev, String curr, String next) {
System.out.print(prev+":"+curr+":"+next);
System.out.println();
if (prev!=null) if (table.contains(prev)) return -1;
if (table.contains(curr)) return 0;
if (table.contains(next)) return 1;
return 2;
}
// ohhe.
public static void main(String args[]) {
CustomTable obj = new CustomTable();
String inputStr = "ohheo"; //Tested ohe,ohhe,ohohe
int result = 0;
String curr, prev, next;
for (int i = 0; i < inputStr.length(); i++) {
// if prev element is found
if (result==-1){
prev = null;
}
else {
if (i > 0) {
prev = inputStr.substring(i - 1, i + 1);
} else {
prev = inputStr.substring(i, i + 1);
}
}
curr = inputStr.substring(i,i+1);
if (i < inputStr.length()-1) {
next = inputStr.substring(i, i+2);
} else {
next = inputStr.substring(i, i+1);
}
result = obj.checkTable(prev, curr, next);
if (result==2) {
System.out.print("false");
return;
}
}
System.out.print("true");
}
}
I think the problem have similarities to well known subset sum problem and you can use its solutions by some customization.

Resources