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
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.
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()));
}
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) {
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.
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.