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()));
}
Related
I want to make a falling sand simulation using cellular automata, but when I update it, nothing happens, and when I want to do a line of diffrent material using lineDrawing() this material appear in random cells. This is update code:
void update()
{
for (int i = verticalNumberOfCells - 1; i > 0; i--)
{
for (int j = 0; j < horizontalNumberOfCells; j++)
{
world[j][i].update(false);
}
}
for (int y = verticalNumberOfCells - 1; y > 0; y--)
{
for (int x = 0; x < horizontalNumberOfCells; x++)
{
if (world[x][y].hasMoved) continue;
if (world[x][y].state == 0 && world[x][y].state == 1) continue;
if (canMove(world[x][y].state, x, y + 1))
{
move(x, y, x, y + 1);
}
}
}
}
The auxiliary functions that I use to check if the contents of a cell can change and to change the contents of a cell look like this:
boolean canMove(int state, int positionX, int positionY)
{
if (positionX < 0 || positionX >= horizontalNumberOfCells || positionY < 0 || positionY >= verticalNumberOfCells) return false;
int otherSubstance = world[positionX][positionY].state;
if (state == 5) return (otherSubstance == 4);
if (otherSubstance == 0) return true;
if (state == 2 && otherSubstance == 3 && random(1f) < 0.5f) return true;
return false;
}
void move(int fromX, int fromY, int toX, int toY)
{
Cells otherSubstance = world[toX][toY];
world[toX][toY] = world[fromX][fromY];
world[fromX][fromY] = otherSubstance;
world[fromX][fromY].hasMoved = true;
world[toX][toY].hasMoved = true;
world[fromX][fromY].velocityX = 0;
world[fromX][fromY].velocityY = 0;
if (toX > fromX)
{
world[toX][toY].velocityX = 1;
} else if (toX < fromX)
{
world[toX][toY].velocityX = -1;
} else
{
world[toX][toY].velocityX = 0;
}
if (toY > fromY)
{
world[toX][toY].velocityY = 1;
} else if (toY < fromY)
{
world[toX][toY].velocityY = -1;
} else
{
world[toX][toY].velocityY = 0;
}
}
I was able to fix this problem. The thing was, copying a cell in the move function didn't work. Here is the wrong version of the code:
Cells otherSubstance = world[toX][toY];
world[toX][toY] = world[fromX][fromY];
world[fromX][fromY] = otherSubstance;
and here is right version of the code:
int oldState = world[toX][toY].state;
world[toX][toY].state = world[fromX][fromY].state;
world[fromX][fromY].state = oldState;
I try to make a web application.
You can change cells of the array by pressing arrow keys here.
There is a class "Module" with methods display() and update(). These methods change the inner array data[].
class Module {
int i; // index
int x; // coordinate
int y; // coordinate
int[] data = new int[]{0,0,0,0,0};
// Contructor
Module(int x){
this.x = x;
}
void update() {
data[i]=_mas_stor;
}
void display(){
text(data[i], x, 100);
}
}
But how to set the initial value of the array _mass[] at the beginning of the program?
The whole program here.
There is no need of an array of data in the class Module. It is sufficient that each object has it single data member. Wirte a constructor, eher you can pass to the initial data (Module(int x, int d)):
class Module {
int i;
int x;
int y;
int data;
// Contructor
Module(int x, int d){
this.x = x;
this.data = d;
}
void update() {
data=_mas[global_i];
}
void display(){
textSize(30);
text(data, x, 100);
}
}
Now the object can be initialized in a loop with ease:
int[] _mas ={1,2,3,4,5};
int global_i = 0;
Module [] mods;
void setup() {
size(500, 400);
mods = new Module[5];
for (int i = 0; i < 5; ++ i ) {
mods[i] = new Module(i*50+50, _mas[i]);
}
}
Further you have to ensure that global_i doesn't go out of bounds in keyPressed:
void keyPressed() {
if (keyCode == UP) {
_mas[global_i]++;
}
if (keyCode == DOWN) {
_mas[global_i]--;
}
if (keyCode == LEFT) {
global_i--;
if (global_i < 0)
global_i = 4;
}
if (keyCode == RIGHT) {
global_i++;
if (global_i > 4)
global_i = 0;
}
}
Note, you can further improve you program, if you skip the global variable _mas and add a increment method (inc) and decrement method (dec) to the class Module, instead of the update method:
int global_i = 0;
Module [] mods;
void setup() {
size(500, 400);
mods = new Module[5];
for (int i = 0; i < 5; ++ i ) {
mods[i] = new Module(i*50+50, i);
}
}
void draw() {
background(50);
for (int i = 0; i < 5; ++ i ) {
mods[i].display();
}
}
void keyPressed() {
if (keyCode == UP) {
println("up");
mods[global_i].inc();
}
if (keyCode == DOWN) {
mods[global_i].dec();
}
if (keyCode == LEFT) {
global_i--;
if (global_i < 0)
global_i = 4;
}
if (keyCode == RIGHT) {
global_i++;
if (global_i > 4)
global_i = 0;
}
}
class Module {
int i;
int x;
int y;
int data;
// Contructor
Module(int x, int d){
this.x = x;
this.data = d;
}
void inc() {
this.data ++;
}
void dec() {
this.data --;
}
void display(){
textSize(30);
text(data, x, 100);
}
}
You usually set the initial value of an array using a for loop. Something like this:
String myArray = new String[10];
for(int i = 0; i < myArray.length; i++){
myArray[i] = "hello world";
}
What you put inside the for loop depends on what values you want your array to start with.
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
} }
A robot is located at the top-left corner of a 4x4 grid.
The robot can move either up, down, left, or right, but can not visit the same spot twice.
The robot is trying to reach the bottom-right corner of the grid.The number of ways it can reach the bottom-right corner of the grid is?
Now i know that if the robot can only move down or right ,then the answer would be 8C4 because it has to go 4 squares to the right and 4 squares down, in any order.
But i am having difficulty in solving the problem when the robot can move both left and up!?
I just need a hint to solve the problem! How should i approach the problem?
This will work fine. The answer is 184.
public class RobotMovementProblem
{
public static void main(String[] args)
{
int grid[][]=new int[4][4];
System.out.println(countPaths(grid, 0, 0));
}
static int countPaths(int grid[][],int i,int j)
{
if ( i < 0 || j < 0 || i >= 4 || j >= 4 ) return 0;
if ( grid[i][j] == 1 ) return 0;
if ( i == 3 && j == 3 ) return 1;
int arr[][]=new int[4][4];
for(int m=0;m<4;m++)
{
for(int n=0;n<4;n++)
{
arr[m][n]=grid[m][n];
}
}
arr[i][j] = 1;
return countPaths(arr, i, j+1) + countPaths(arr, i, j-1) + countPaths(arr, i+1, j) + countPaths(arr, i-1, j);
}
}
You can write a recursive program that calculates all possible paths, and whenever it arrives at the down right corner it increments the number of paths. I wrote something, but I didn't test it. (Think of it as pseudocode to give you a start). Basically what this does, is call the moveRobot function on the current position (0, 0) with an empty field (the robot hasn't moved yet). Then it tries to move up, down, left and right. This movement is described in the respective functions. If one of these movements succeds(or more than one), the new position is marked in the field with a 1 instead of a 0. 1 means the robot has passed through that position. Then you call moveRobot again. This because in the new position you want to try all four movements once more.
Main Function:
int field[4][4];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
field[i][j] = 0;
field[0][0] = 1;
numPaths = 0;
moveRobot(0, 0, field);
print numPaths;
MoveRobot Function:
moveRobot(int row, int column, int[][] field)
{
moveRobotUp(row, column, field);
moveRobotDown(row, column, field);
moveRobotLeft(row, column, field);
moveRobotRight(row, column, field);
}
Other Functions:
moveRobotUp(int row, int column, int[][] field)
{
if (row == 0) return;
else
{
if (field[row-1][column] == 1) return;
field[row-1][column] = 1;
moveRobot(row-1, column, field);
field[row-1][column] = 0;
}
}
moveRobotDown(int row, int column, int[][] field)
{
if (row == 3 && column == 3)
{
numPaths++;
return;
}
else if (row == 3) return;
else
{
if (field[row+1][column] == 1) return;
field[row+1][column] = 1;
moveRobot(row+1, column, field);
field[row+1][column] = 0;
}
}
moveRobotLeft(int row, int column, int[][] field)
{
if (column == 0) return;
else
{
if (field[row][column-1] == 1) return;
field[row][column-1] = 1;
moveRobot(row, column-1, field);
field[row][column-1] = 0;
}
}
moveRobotRight(int row, int column, int[][] field)
{
if (column == 3 && row == 3)
{
numPaths++;
return;
}
else if (column == 3) return;
else
{
if (field[row][column+1] == 1) return;
field[row][column+1] = 1;
moveRobot(row, column+1, field);
field[row][column+1] = 0;
}
}
/* building on red_eyes answer */
public static void main(String[] args) {
Main m = new Main();
boolean grid [][]= new boolean [4][4];
sol=0;
grid[0][0]= true;
m.start(0,1,grid);
System.out.println(sol);//output 184
}
private void start(int x, int y,boolean [][]grid){
grid[x][y]=true;
moveUp(x,y,grid);
moveDown(x,y,grid);
moveLeft(x,y,grid);
moveRight(x,y,grid);
}
private void moveUp(int x, int y, boolean [][] grid){
if(y==0) return;
else{
if (grid[x][y-1]) return;
grid[x][y-1]=true;
start(x,y-1,grid);
grid[x][y-1]=false;
}
}
private void moveLeft(int x, int y, boolean [][] grid){
if(x==0) return;
else{
if (grid[x-1][y]) return;
grid[x-1][y]=true;
start(x-1,y,grid);
grid[x-1][y]=false;
}
}
private void moveDown(int x, int y, boolean [][] grid){
if(x==3 && y==3){
sol++;
grid[x][y]=true;
return;
}
else if(y==3) return;
else{
if (grid[x][y+1]) return;
grid[x][y+1]=true;
start(x,y+1,grid);
grid[x][y+1]=false;
}
}
private void moveRight(int x, int y, boolean [][] grid){
if(x==3 && y==3){
sol++;
grid[x][y]=true;
return;
}else if(x==3) return;
else{
if (grid[x+1][y]) return;
grid[x+1][y]=true;
start(x+1,y,grid);
grid[x+1][y]=false;
}
}
Few lines of recursion will solve this.
public static int WaysToExit(int x, int y)
{
if (x==0 || y == 0)
{
return 1;
}
else
{
return (WaysToExit(x - 1, y) + WaysToExit(x , y-1));
}
}
I will explain in depth after. So here is my code, we have an Elevation[] variable and each Elevation gets a random number:
public void elevation()
{
for (x = (int)Width - 1; x >= 0; x--)
{
for (y = (int)Width - 1; y >= 0; y--)
{
y = rand.Next((int)MaxElevation); //random number for each y.
Elevation[x] = y; //each Elevation gets a random number.
}
}
}
After this I try to use this random number in the draw method like this:
public void Draw(SpriteBatch spriteBatch)
{
for (x = (int)Width - 1; x >= 0; x--)
{
spriteBatch.Draw(Pixel, new Rectangle((int)Position.X + x, (int)Position.Y - Elevation[x], 1, (int)Height), Color.White);
//HERE, I try to acces the random number for each Elevation (y value). But I get 0 everywhere.
}
}
How can I acces this random number?
If I do that:
public void Draw(SpriteBatch spriteBatch)
{
for (x = (int)Width - 1; x >= 0; x--)
{
for (y = (int)Width - 1; y >= 0; y--)
{
y = rand.Next((int)MaxElevation);
spriteBatch.Draw(Pixel, new Rectangle((int)Position.X + x, (int)Position.Y - Elevation[y], 1, (int)Height), Color.White);
}
}
}
I will be able to acces the random numbers, but it will update every frame and the random numbers will change. So I need to calculate them once and then use them.
Here is all the code:
namespace procedural_2dterrain
{
class Terrain
{
Texture2D Pixel;
Vector2 Position;
Random rand;
int[] Elevation;
float MaxElevation;
float MinElevation;
float Width;
float Height;
int x;
int y;
public void Initialize( ContentManager Content, float maxElevation, float minElevation, float width, float height, Vector2 position)
{
Pixel = Content.Load<Texture2D>("pixel");
rand = new Random();
Elevation = new int[(int)width];
MaxElevation = maxElevation;
MinElevation = minElevation;
Width = width;
Height = height;
Position = position;
elevation();
}
public void Update()
{
}
public void elevation()
{
for (x = (int)Width - 1; x >= 0; x--)
{
for (y = (int)Width - 1; y >= 0; y--)
{
y = rand.Next((int)MaxElevation);
Elevation[x] = y;
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
for (x = (int)Width - 1; x >= 0; x--)
{
spriteBatch.Draw(Pixel, new Rectangle((int)Position.X + x, (int)Position.Y - Elevation[x], 1, (int)Height), Color.White);
}
}
}
}
The problem is with your elevation() method. You are using y as your inner loop indexer and also assigning a value to it within the loop. So the loop starts, y is assigned a random value. As it continues the loop, it is decremented and then tested for being >=0. The only time this loop will exit is if y is assigned the random number of 0. So that is why all your Elevation are zero.
I am a little confused as to why you think you need an inner loop. Try:
public void elevation()
{
for (x = (int)Width - 1; x >= 0; x--)
{
Elevation[x] = rand.Next((int)MaxElevation);
}
}