I know that there's a lot of other maze solver here. Though I would like to have my own approach and I think my problem is a bit different from the others.
As of now, here's what I've started and hopefully I can achieve what I have in mind at the moment.
private static int getPossiblePaths(File f) throws IOException {
int counts = 0; // hope to return all possible paths
// read input file then put it on list string
List<String> lines = Files.lines(f.toPath()).collect(Collectors.toList());
// get the row and column (dimensions)
String[] dimensions = lines.get(0).split(",");
//initalize sub matrix of the maze dimensions and ignoring the top and bottom walls
int[][] mat = new int[Integer.valueOf(dimensions[0]) - 2 ][Integer.valueOf(dimensions[1]) - 2];
//for each line in the maze excluding the boundaries (top and bottom)
for( int i = 2 ; i < lines.size() - 1 ; i++) {
String currLine = lines.get(i);
int j = 0;
for(char c : currLine.toCharArray()) {
mat[i-2][j] = (c=='*' ? 'w' : c=='A' ? 'a' : c=='B' ? 'b' : 's');
// some conditional statements here
}
}
// or maybe some conditional statements here outside of the loop
return counts;
}
And the maze from a text file is look like this. Please note that the A could be anywhere and same as B. The only movements allowed is to right and down.
5,5
*****
*A *
* *
* B*
*****
Expected output for the maze above is 6 (possible paths from A to B).
EDIT: Also the maze from the text file could be like this:
8,5
********
* A *
* B*
* *
********
So with my current code, it is getting the dimensions (first line) and removing the top and bottom part of the maze (boundaries). So there's only 3 lines of characters currently stored in the mat array. And some encoding of each characters of the text file (#=w(wall), A=a(start), B=b(end), else s(space))
I would like to have some conditional statements inside of the foreach to probably store the each of characters inside of an ArrayList. Though I'm not sure if this approach will just make my life harder.
Any suggestions, tips, advice or other easier approach from you guys will greatly appreciated! Thank you
The idea to create mat is fine. I would not bother to strip off the first and last line, as in fact it will be easier to work with when you keep them. That way a row reference like i-1 will not go out of range when you are at a non-wall location.
I would also not store characters like w in there, but specific numbers, like -1 for wall, 0 for free. Also store 0 for "A" and "B". When encountering those two letters, you could store their coordinates in specific variables (e.g. rowA, colA, rowB, colB). You may need to check whether B is down-right from A, as otherwise B is certainly not reachable from A.
So I would define mat as follows (note that I reversed the dimensions, because your second example demonstrates that the first line of the input has them in that order):
int[][] mat = new int[Integer.valueOf(dimensions[1])]
[Integer.valueOf(dimensions[0])];
int colA = mat[0].length;
int rowA = 0;
int colB = colA;
int rowB = 0;
for (int i = 0; i < mat.length; i++) {
String currLine = lines.get(i+1);
int j = 0;
for (char c : currLine.toCharArray()) {
mat[i][j] = c == '*' ? -1 : 0;
if (c == 'B') {
if (colA > j) return 0; // B unreachable from A
rowB = i;
colB = j;
} else if (c == 'A') {
if (colB < j) return 0; // B unreachable from A
rowA = i;
colA = j;
}
j++;
}
}
With this setup you can reuse mat to store the number of paths from A to the current position. The value 0 at A should be set to 1 (there is one path from A to A), and then it is a matter of adding up the value from the cell above and left, making sure that -1 is treated as a 0.
mat[rowA][colA] = 1;
for (int i = rowA; i <= rowB; i++) {
for (int j = colA; j <= colB; j++) {
if (mat[i][j] == 0) { // not a wall?
// count the number of paths that come from above,
// plus the number of paths that come from the left
mat[i][j] = Math.max(0, mat[i-1][j]) + Math.max(0, mat[i][j-1]);
}
}
}
return mat[rowB][colB]; // now this has the number of paths we are looking for
Although a recursive method will also work, I would suggest the above dynamic programming approach, since that way you avoid to recalculate counts for a certain cell several times (when coming there via different DFS paths). This solution has a linear time complexity.
I propose a simple recursion with 2 calls: down and right.
This is the code:
import java.io.File;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class JavaMazeInsideOfWallsAndGetAllPossiblePaths {
public static void main(String[] args) throws IOException, URISyntaxException {
Path mazePath = Paths.get( MethodHandles.lookup().lookupClass().getClassLoader()
.getResource("maze.txt").toURI());
File mazeFile = mazePath.toFile();
System.out.println(getPossiblePaths(mazeFile));
}
private static int getPossiblePaths(File f) throws IOException {
// read input file then put it on list string
List<String> lines = Files.lines(f.toPath()).collect(Collectors.toList());
// get the row and column (dimensions)
String[] dimensions = lines.get(0).split(",");
//initalize sub matrix of the maze dimensions and ignoring the top and bottom walls
int[][] mat = new int[Integer.valueOf(dimensions[0]) - 2 ][Integer.valueOf(dimensions[1]) - 2];
int fromRow = -1, fromCol = -1, toRow = -1, toCol = -1;
for( int i = 2 ; i < lines.size() - 1 ; i++) {
String currLine = lines.get(i);
int j = 0;
for(char c : currLine.toCharArray()) {
switch(c) {
case '*':
continue; // for loop
case 'A':
mat[i-2][j] = 0;
fromRow = i-2;
fromCol = j;
break;
case 'B':
mat[i-2][j] = 2;
toRow = i-2;
toCol = j;
break;
default:
mat[i-2][j] = 1;
}
j++;
}
}
return getPossiblePathsRecursive(mat, fromRow, fromCol, toRow, toCol);
}
private static int getPossiblePathsRecursive(int[][] mat, int i, int j, int rows, int columns) throws IOException {
if(i > rows || j > columns) {
return 0;
}
if(mat[i][j] == 2) {
return 1;
}
return getPossiblePathsRecursive(mat, i+1, j, rows, columns) +
getPossiblePathsRecursive(mat, i, j + 1, rows, columns);
}
}
Notes:
1. The validation step is skipped (assuming that the input data is in a valid format)
2. The walls are ignored (assuming that there are always 4 walls - first row, last row, first column, last column. These walls are assumed to be represented as '*')
Related
Algorithm is required for Finding the group of 1s in a matrix, but the group of 1s should contain only vertical entry
This is more in the brain-teaser category.
For small matrices, we just access it column by column.
Assuming input is a 2 dimension array of integer, and output is a list of the following class:
class GroupIdentifier {
int col;
int rowStart;
int colStart;
/* the corresponding getter/setter/constructor etc */
}
Here is the function you are looking for:
int FIRST_ONE = 2;
int IN_GROUP = 1;
int OUT_GROUP = 0;
public List<GroupIdentifier> findVerticalGroupsOf1 (int[][] a,
int numRow, int numCol) {
List<GroupIdentifier> answer = new ArrayList<GroupIdentifier>();
for (col = 0; col < numCol; col = col + 1) {
// let's create the tempArr holding the current col
int[] tempArr = new int[numRow];
for (row = 0; row < numRow; row = row + 1 =) {
tempArr[row] = a[row][col];
}
// let's find the groups
// first, init the state
int state = (tempArr[0] == 1) ? FIRST_ONE : OUT_GROUP;
int start = (state == FIRST_ONE) ? 0 : -1;
// I see this problem as a simple state-machine
// We have three states: FIRST_ONE encountered (0 to 1),
// still tracking the 1s IN_GROUP ... (1 to 1) and
// get OUT_GROUP (1 to 0).
// the switch case in the following loop does exactly that.
// So, whenever we get an OUT_GROUP event, we get an answer.
for (int i = 1; i < numRow; i = i + 1) { // edit: changed to numRow as
// it was a typo error
switch (state) :
case FIRST_ONE :
if (tempArr[i] == 0)
state = OUT_GROUP;
else
state = IN_GROUP;
break;
case IN_GROUP :
if (tempArr[i] == 0) {
GroupIdentifier gi = new GroupIdentifier (col, start, i - 1);
answer.add(gi);
}
break;
case OUT_GROUP :
if (tempArr[i] == 1) {
start = i;
state = FIRST_ONE;
}
break;
}
}
// since this question looks like homework,
// i will leave out the boundary case handling
// here. it's not that hard; just copy/paste the
// switch statement and fondle around.
return answer;
}
As a computer scientist myself, I think of ways to optimize it.
For larger matrices, what I would do is to precompute the all combinations of tempArr and store them as Integer --> List map. Then, I will traverse the columns without computing again.
When I say efficient I mean code that isn't cpu intensive.
The Problem:
I have a field of blocks. Like in the following image:
Every single one of these blocks represents an instance of a self-made Block class. This block class has a List<Block> neighBours, where the neighbours of the block are stored. So every single block in the image knows which blocks are next to it.
What I want to do is to pick any block from this image, and compute how many "steps" away this block is. For example if I pick the block in the top left, I want to have a Map<Block, Integer> representing how many "steps" away each block is from the picked block. Like this:
Now before you say "Just store it's position X and Y in the block class and calculate the difference X + difference Y", that wouldn't work because the field can have gaps(represented by red color) between them like the following image:
And as you might notice, the block next to the gap that was first 4 steps away, is now 6 steps away. Thus the best way(I presume) to get how many steps away the other blocks are is by using a recursive algorith that makes use of the neighbour info. I couldn't make an efficient one myself and I was hoping someone might know something that works well.
Several problems I came across are the fact that because all blocks know their neighbours, the recursive algorithm would go indefinately back and forth between the first and second block. Or the fact that when using the algorithm on a 11x11 field, there were 3284 method calls, which seems waaay too high for an 11x11 field.
Question:
So the question I have is: What is an efficient way, using the knowledge of what neighbours each block has, to get how many steps away each block is.
Code:
This is the current code that I have incase anyone wants to see it.
public class Block
{
List<Block> neighBours;
public Block(List<Block> neighBours)
{
this.neighBours = neighBours;
}
public Map<Block, Integer> getStepsAway()
{
Map<Block, Integer> path = new HashMap<Block, Integer>();
getPaths(path, 0, 100);
return path;
}
public void getPaths(Map<Block, Integer> path, int pathNumber, int maxPathNumber)
{
if(pathNumber <= maxPathNumber)
{
for(Block block : neighBours)
{
Integer thePathNumber = path.get(block);
if(thePathNumber != null)
{
if(pathNumber < thePathNumber)
{
path.put(block, pathNumber);
block.getPaths(path, pathNumber + 1, maxPathNumber);
}
}
else
{
path.put(block, pathNumber);
block.getPaths(path, pathNumber + 1, maxPathNumber);
}
}
}
}
}
Recursive algorithms are doomed to fail on a large grid. Java is not designed for deep recursions and can only withstand a few thousands recursive calls before failing with a StackOverflowException. Only iterative solutions are a reasonible approach for large pathfinding problems in Java.
Of course you can always use a classic pathfinding algorithm such as A*, but you would have to apply it for each cell, which would be extremely expensive.
Indeed, your problem is a bit particular in the sense you want to calculate the minimum distance to all cells and not only just one. Therefore, you can do it in a more clever way.
One property of your problem is that given A and B, if the minimal path from A to B contains C then this path is also minimal from A to C and from C to B. That's what my intuition tells me, but it would need to be proven before implementing my suggestion.
The algorithm I propose is efficient, uses O(n) memory and has O(n^2) runtime complexity (cannot be faster since you need to set this many cells in the array):
start with your first point and set the distance of all its valid neighbours to 1. Doing so, you will record the border, which is all the cells at distance 1 from the first cell.
then, you iterate over the border and take all their neighbours which have not already been assigned a distance and assign them distance 2. All cells of distance 2 become your new border.
iterate until the border is empty
Below is a full working solution. The code may be improved in various ways using more convenience methods for initializing and printing matrices of objects and primitive integers, but you get the idea:
public class Solution {
public enum Cell { FREE, BLOCKED }
// assuming cells is a rectangular array with non-empty columns
public static int[][] distances(Cell[][] cells, ArrayCoordinate startingPoint) {
int[][] distances = new int[cells.length][cells[0].length];
// -1 will mean that the cell is unreachable from the startingPoint
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
distances[i][j] = -1;
}
}
distances[startingPoint.i][startingPoint.j] = 0;
Set<ArrayCoordinate> border = startingPoint.validNeighbours(cells);
for (int currentDistance = 1; !border.isEmpty(); currentDistance++) {
Set<ArrayCoordinate> newBorder = new HashSet<>();
for (ArrayCoordinate coord : border) {
distances[coord.i][coord.j] = currentDistance;
for (ArrayCoordinate neighbour : coord.validNeighbours(cells)) {
if (distances[neighbour.i][neighbour.j] < 0) {
newBorder.add(neighbour);
}
}
}
border = newBorder;
}
return distances;
}
private static class ArrayCoordinate {
public ArrayCoordinate(int i, int j) {
if (i < 0 || j < 0) throw new IllegalArgumentException("Array coordinates must be positive");
this.i = i;
this.j = j;
}
public final int i, j;
public Set<ArrayCoordinate> validNeighbours(Cell[][] cells) {
Set<ArrayCoordinate> neighbours = new HashSet<>();
// inlining for not doing extra work in a loop iterating over (-1, 1) x (-1, 1). If diagonals are allowed
// then switch for using a loop
addIfValid(cells, neighbours, 1, 0);
addIfValid(cells, neighbours, -1, 0);
addIfValid(cells, neighbours, 0, 1);
addIfValid(cells, neighbours, 0, -1);
return neighbours;
}
private void addIfValid(Cell[][] cells, Set<ArrayCoordinate> neighbours, int dx, int dy) {
int x = i + dx, y = j + dy;
if (0 <= x && 0 <= y && x < cells.length && y < cells[0].length && cells[x][y] == Cell.FREE) {
neighbours.add(new ArrayCoordinate(i + dx, j + dy));
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ArrayCoordinate point = (ArrayCoordinate) o;
if (i != point.i) return false;
if (j != point.j) return false;
return true;
}
#Override
public int hashCode() {
int result = i;
result = 31 * result + j;
return result;
}
}
public static void main(String[] args) {
int n = 11, m = 5;
Cell[][] cells = new Cell[n][m];
cells[1][1] = Cell.BLOCKED;
cells[1][2] = Cell.BLOCKED;
cells[2][1] = Cell.BLOCKED;
ArrayCoordinate startingPoint = new ArrayCoordinate(5, 2);
System.out.println("Initial matrix:");
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
if (cells[i][j] == null) {
cells[i][j] = Cell.FREE;
}
if (startingPoint.i == i && startingPoint.j == j) {
System.out.print("S ");
} else {
System.out.print(cells[i][j] == Cell.FREE ? ". " : "X ");
}
}
System.out.println();
}
int[][] distances = distances(cells, startingPoint);
System.out.println("\nDistances from starting point:");
for (int i = 0; i < distances.length; i++) {
for (int j = 0; j < distances[0].length; j++) {
System.out.print((distances[i][j] < 0 ? "X" : distances[i][j]) + " ");
}
System.out.println();
}
}
}
Output:
Initial matrix:
. . . . .
. X X . .
. X . . .
. . . . .
. . . . .
. . S . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Distances from starting point:
7 8 7 6 7
6 X X 5 6
5 X 3 4 5
4 3 2 3 4
3 2 1 2 3
2 1 0 1 2
3 2 1 2 3
4 3 2 3 4
5 4 3 4 5
6 5 4 5 6
7 6 5 6 7
Bonus
I almost cried when I saw all this boilerplate in my Java solution, so I wrote a shorter (perhaps slightly less efficient) version in Scala:
object ScalaSolution {
sealed abstract class Cell
object Free extends Cell
object Blocked extends Cell
// assuming cells is a rectangular array with non-empty columns
def distances(cells: Array[Array[Cell]], startingPoint: (Int, Int)) = {
// -1 will mean that the cell is unreachable from the startingPoint
val distances = Array.fill[Int](cells.length, cells(0).length)(-1)
distances(startingPoint._1)(startingPoint._2) = 0
var (currentDistance, border) = (1, validNeighbours(cells, startingPoint))
while (border.nonEmpty) {
border.foreach { case (i, j) => distances(i)(j) = currentDistance }
border = border.flatMap(validNeighbours(cells, _)).filter { case (i, j) => distances(i)(j) < 0 }
currentDistance += 1
}
distances
}
private def validNeighbours(cells: Array[Array[Cell]], startingPoint: (Int, Int)) = {
// inlining for not doing extra work in a for yield iterating over (-1, 1) x (-1, 1). If diagonals are allowed
// then switch for using a for yield
Set(neighbourIfValid(cells, startingPoint, ( 1, 0)),
neighbourIfValid(cells, startingPoint, (-1, 0)),
neighbourIfValid(cells, startingPoint, ( 0, 1)),
neighbourIfValid(cells, startingPoint, ( 0, -1)))
.flatten
}
private def neighbourIfValid(cells: Array[Array[Cell]], origin: (Int, Int), delta: (Int, Int)) = {
val (x, y) = (origin._1 + delta._1, origin._2 + delta._2)
if (0 <= x && 0 <= y && x < cells.length && y < cells(0).length && cells(x)(y) == Free) {
Some(x, y)
} else None
}
def main (args: Array[String]): Unit = {
val (n, m) = (11, 5)
val cells: Array[Array[Cell]] = Array.fill(n, m)(Free)
cells(1)(1) = Blocked
cells(1)(2) = Blocked
cells(2)(1) = Blocked
val startingPoint = (5, 2)
println("Initial matrix:")
printMatrix(cells)((i, j, value) => if ((i, j) == startingPoint) "S" else if (value == Free) "." else "X")
val distancesMatrix = distances(cells, startingPoint)
println("\nDistances from starting point:")
printMatrix(distancesMatrix)((i, j, value) => if (value < 0) "X" else value.toString)
}
private def printMatrix[T](matrix: Array[Array[T]])(formatter: (Int, Int, T) => String) = {
for (i <- 0 until matrix.length) {
for (j <- 0 until matrix(0).length) {
print(formatter(i, j, matrix(i)(j)) + " ")
}
println()
}
}
}
I believe there is a DP (dynamic programming) solution to this problem, looking at this, code below. I realize this is for finding all possible paths to a cell but it can give insight on your condition about 'blanks' or 'walls'
#include <iostream>
using namespace std;
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// Create a 2D table to store results of subproblems
int count[m][n];
// Count of paths to reach any cell in first column is 1
for (int i = 0; i < m; i++)
count[i][0] = 1;
// Count of paths to reach any cell in first column is 1
for (int j = 0; j < n; j++)
count[0][j] = 1;
// Calculate count of paths for other cells in bottom-up manner using
// the recursive solution
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
// By uncommenting the last part the code calculatest he total
// possible paths if the diagonal Movements are allowed
count[i][j] = count[i-1][j] + count[i][j-1]; //+ count[i-1][j-1];
}
return count[m-1][n-1];
}
So I've been working on the following problem:
I buried my sapphire then started walking. I always walked in a
straight line following a compass direction (N, S, E, W). When I
stopped, I made a 90 degree turn and continued walking. I might have
crossed my path, but I don’t remember. Below are the number of meters
I travelled in each direction. I’m now lost and must abandon this
record while I search for a way out. I’m placing this note under a
rock at my final location. Perhaps some lucky adventurer will decode
my note and retrace my steps to earn the treasure. Unfortunately,
there is no record of where in the ruins the note was found. Instead,
you must write a program to find the treasure. Input The first
line contains two integers X Y, representing the number of rows and
columns in the ruins. Maximum of 20 rows and 50 columns. The next X
lines show a grid map of the space. A period “.” is an empty square. A
hash “#” is a large boulder, marking a square that cannot be entered.
The next line has an integer N, the count of the straight paths
walked. Maximum of 20 paths. The last line contains N integers
separated by spaces, showing the successive path-lengths.. 5 10
####
........#
.#...##.#
...#....#
#### 8 2 4 2 2 2 5 2 1 Output Your program must print the same map, with the location of both the Sapphire (S) and the final
location of the message (F) marked. Also, label every turning point
with successive lowercase letters (if the same point is used more
than once, print the letter for the later turn.) There is only one
route which follows the path-lengths in the list.
####
b.e.a..f#
.#...##.#
c.d#S.Fg#
#
and I have made a recursive method that checks every direction starting from every open position of the maze until it finds the solution, however the output of the problem needs to be the mazes with the turns.
The problem is, when I use a recursive solution and edit the actual char[][] map, it never knows which path will lead to the actual finish, so it will create output like this:
d...d
.....
cbabc
d...d
but instead I would like it to show only one path, like this:
....d
.....
..abc
.....
Here is my incomplete solution:
import java.util.Scanner;
public class SapphireSearch {
private static int rs; // Row Size
private static int cs; // Column Size
private static int sr; // Save row (saves solution row)
private static int sc; // Save col (saves solution col)
private static Direction sd; // Save direction (saves solution dir)
private static char[][] map; // the maze to traverse
private static int n; // number of turns
private static int[] go; // length of the turns
public static void main(String[] args) {
getInput();
for (int r = 0; r < rs; r++)
for (int c = 0; c < cs; c++)
for (Direction d : Direction.values())
solve(sr = r, sc = c, sd = d, 0, false);
}
public static void solve(int r, int c, Direction d, int start,
boolean printing) {
if (isSolid(r, c))
return;
if (printing) {
if (start == 0)
map[r][c] = 'S';
else
map[r][c] = (char) (start - 1 + 'a');
if (start == n) {
map[r][c] = 'F';
return;
}
}
if (start == n - 1 && !printing) {
solve(sr, sc, sd, 0, true);
printArray(map);
System.exit(0);
}
int count = 0;
while (start < go.length && count < go[start]) {
count++;
r += d.dr;
c += d.dc;
if (isSolid(r, c))
return;
}
for (Direction t : d.turn())
solve(r, c, t, start + 1, printing);
}
public static boolean isSolid(int r, int c) {
return map[r][c] == '#';
}
public static void printArray(char[][] o) {
for (int r = 0; r < o.length; r++) {
for (int c = 0; c < o[r].length; c++)
System.out.print(o[r][c]);
System.out.println();
}
}
private static void getInput() {
Scanner s = new Scanner(System.in);
rs = s.nextInt();
cs = s.nextInt();
s.nextLine(); // clear buffer
map = new char[rs][cs];
for (int r = 0; r < rs; r++) {
int c = 0;
char[] f = s.nextLine().trim().toCharArray();
for (char t : f)
map[r][c++] = t;
}
n = s.nextInt();
go = new int[n];
for (int i = 0; i < n; i++)
go[i] = s.nextInt();
}
}
enum Direction {
// deltaR, deltaC
up(-1, 0), down(1, 0), left(0, -1), right(0, 1);
public int dr;
public int dc;
private Direction(int dr, int dc) {
this.dr = dr;
this.dc = dc;
}
public Direction[] turn() {
Direction[] out = new Direction[2];
switch (this) {
case up:
case down:
out[0] = left;
out[1] = right;
break;
case left:
case right:
out[0] = up;
out[1] = down;
}
return out;
}
}
The question is: building upon my recursive solve algorithm, what would be the best way to print the solution path (where it doesn't print out every path it tries to take)?
You need to build up your list of turns as you do the recursive search (I'm just listing the direction here for simplicity but you could store an object with co-ordinates as well for example).
If the path is (N,E,N,W,S) and then save that as you exit.
To do that keep the partial list so far and each recursive call COPY the list so far and add to it.
i.e.:
n
ne
nw Fail
nen
nes Fail
nenw
etc.
At the end you can either return the completed solution or if you need to handle multiple solutions have a final results list of lists that you insert the completed one into.
The key step is to copy the list so far so that recursion branches cannot interfere with each other.
Ok so my problem is basically, I have a matrix for example
010
101
111
just random 1s and 0s. So I have arrays that are rowcount and colcount, which count the number of ones in each row and column. So rowcount for this is {1,2,3} and colcount is {2,2,2}. Now in another method, I am given the arrays rowcount and colcount, and in that method, I am supposed to create a matrix with the counts in rowcount and colcount, but the end matrix can be different. Than the original. I think I'm supposed to exhaust all permutations until a matrix works. The base case must stay the same.
Note: Math.random cannot be used.
private static void recur(int[][] m, int[] rowcount, int[] colcount, int r, int c)
//recursive helper method
{
if(compare(m, rowcount, colcount)) //base case: if new matrix works
{
System.out.println();
System.out.println("RECREATED");
display(m, rowcount, colcount); //we're done!
System.exit(0);
}
else
{
int[] temp_r = new int[m.length];
int[] temp_c = new int[m[0].length];
count(m, temp_r, temp_c);
if(rowcount[r] > temp_r[r] && colcount[c] > temp_c[c])
m[r][c] = 1;
if(r+1 < m.length)
recur(m,rowcount,colcount,r+1,c);
if(rowcount[r] < temp_r[r] || colcount[c] < temp_c[c])
m[r][c] = 0;
if(c+1 < m[0].length)
recur(m,rowcount,colcount,r,c+1);
}
}
private static boolean compare(int[][] m, int[] rowcount, int[] colcount)
{
int[] temp_r = new int[m.length];
int[] temp_c = new int[m[0].length];
count(m, temp_r, temp_c);
for (int x = 0; x < temp_r.length; x++)
{
if(temp_r[x] != rowcount[x])
return false;
}
for (int y = 0; y < temp_c.length; y++)
{
if(temp_c[y] != colcount[y])
return false;
}
return true;
}
public static void count(int[][] matrix, int[] rowcount, int[] colcount)
{
for(int x=0;x<matrix.length;x++)
for(int y=0;y<matrix[0].length;y++)
{
if(matrix[x][y]==1)
{
rowcount[x]++;
colcount[y]++;
}
}
}
Well, I decided I'd implement a solution, but instead of Java (which you haven't actually specified the solution needs to be in), I'm going to use Groovy (which is Java based anyway)! I've tried to use Java syntax where possible, it's not hard to extrapolate the Java code from this (but it is much more verbose!)
Note:
*Generating a random bit matrix, not using Math.random()
*I'm storing my matrix in a string i.e. [[0,1],[1,0]] = "0110"
*My solution relies heavily, on converting Integers to/from BinaryStrings (which is essentially what your matrix is!)
// Generate random matrix
int colSize = 3;
int rowSize = 4;
String matrix = '';
for (int i = 0; i < rowSize; i++){
String bits = Integer.toBinaryString(System.currentTimeMillis().toInteger());
matrix += bits.substring(bits.length() - colSize);
Thread.sleep((System.currentTimeMillis() % 1000) + 1);
}
def (cols1,rows1) = getCounts(matrix, colSize)
println "matrix=$matrix rows1=$rows1 cols1=$cols1"
// Find match (brute force!)
int matrixSize = colSize * rowSize
int start = 0
int end = Math.pow(Math.pow(2, colSize), rowSize) // 2 is number of variations, i.e. 0 and 1
for (int i = start; i <= end; i++){
String tmp = leftPad(Integer.toBinaryString(i), matrixSize, '0')
def (cols2,rows2) = getCounts(tmp, colSize)
if (cols1 == cols2 && rows1 == rows2){
println "Found match! matrix=$tmp"
break;
}
}
println "Finished."
String leftPad(String input, int totalWidth, String padchar){ String.format('%1$' + totalWidth + "s", input).replace(' ',padchar) }
int[][] getCounts(String matrix, int colSize){
int rowSize = matrix.length() / colSize
int[] cols = (1..colSize).collect{0}, rows = (1..rowSize).collect{0}
matrix.eachWithIndex {ch, index ->
def intval = Integer.parseInt(ch)
cols[index % colSize] += intval
rows[(int)index / colSize] += intval
}
[cols,rows]
}
Gives output:
matrix=001100011000 rows1=[1, 1, 2, 0] cols1=[1, 1, 2]
Found match! matrix=001001110000
Finished.
Brute force search logic:
Given a rowcount of [1,2,3]
And a colcount of [2,2,2]
Iterate over all matrix combinations (i.e. numbers 0 - 511 i.e. "000000000" -> "111111111")
Until the new matrix combination's rowcount and colcount matches the supplied rowcount and colcount
OK, your question and comments indicate you are on the right track. The code itself is a bit messy and it has obviously gone through some iterations. That's not great, but it's OK.
You are right, I believe, that you have to 'exhaust' the recursion until you find a new result that matches the existing column/row counts. So, attack the problem logically. First, create a method that can compare a matrix with a row/column count. You call it 'compare(...)'. I assume this method you have already works ;-). This is the method that marks the end of the recursion. When compare returns true, you should return up the recursion 'stack'. You should not do a System.exit(...).
So, the basic rule of recursion, you need an input, output, a method body that contains an exit-condition check, and a recursive call if the condition is not met....
Your problem has a specific issue which complicates things - you need to make copies if the input matrix every time you go down a recursion level. Alternatively you need to 'undo' any changes you make when you come up a level. The 'undo' method is faster (less memory copies).
So, the process is as follows, start with an all-zero matrix. Call your recursive function for the all-zero start point.
int[][] matrix = new int[width][height];
int rpos = 0;
boolean found = recur(matrix, rowcount, colcount, 0, 0);
This is how it will be called, and found will be true if we found a solution.
The difference here from your code is that recur now returns a boolean.
So, our recur method needs to do:
1. check the current matrix - return true if it matches.
2. make meaningful changes (within the limits that we've added)
3. recursively check the change (and add other changes).
Your method does not have an output, so there's no way to escape the recursion. So, add one (boolean in this case).
The way this can work is that we start in the top left, and try it with that bit set, and with it unset. For each contition (set or unset) we recursively test whether the next bit matches when set, or unset, and so on.... :
private static boolean recur(int[][] m, int[] rowcount, int[] colcount,
int row, int col) {
if (compare(m, rowcount, colcount)) {
// our matrix matches the condition
return true;
}
if (row >= m.length) {
return false;
}
int nextcol = col + 1;
int nextrow = row;
if (nextcol >= m[row].length) {
nextcol = 0;
nextrow++;
if (nextrow > m.length) {
return false;
}
}
// OK, so nextrow and nextcol are the following position, and are valid.
// let's set our current position, and tell the next level of recursion to
// start playing from the next spot along
m[row][col] = 1;
if (recur(m, rowcount, colcount, nextrow, nextcol)) {
return true;
}
// now unset it again
m[row][col] = 0;
if (recur(m, rowcount, colcount, nextrow, nextcol)) {
return true;
}
return false;
}
The above code is just hand-written, it may have bugs, etc. but try it. The lesson in here is that you need to test your consitions, and you need a strategy....
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Broken Necklace
You have a necklace of N red, white, or blue beads (3<=N<=350) some of which are red, others blue, and others white, arranged at random. Here are two examples for n=29:
1 2 1 2
r b b r b r r b
r b b b
r r b r
r r w r
b r w w
b b r r
b b b b
b b r b
r r b r
b r r r
b r r r
r r r b
r b r r r w
Figure A Figure B
r red bead
b blue bead
w white bead
The beads considered first and second in the text that follows have been marked in the picture.
The configuration in Figure A may be represented as a string of b's and r's, where b represents a blue bead and r represents a red one, as follows: brbrrrbbbrrrrrbrrbbrbbbbrrrrb .
Suppose you are to break the necklace at some point, lay it out straight, and then collect beads of the same color from one end until you reach a bead of a different color, and do the same for the other end (which might not be of the same color as the beads collected before this).
Determine the point where the necklace should be broken so that the most number of beads can be collected.
Example
For example, for the necklace in Figure A, 8 beads can be collected, with the breaking point either between bead 9 and bead 10 or else between bead 24 and bead 25.
In some necklaces, white beads had been included as shown in Figure B above. When collecting beads, a white bead that is encountered may be treated as either red or blue and then painted with the desired color. The string that represents this configuration will include the three symbols r, b and w.
Write a program to determine the largest number of beads that can be collected from a supplied necklace.
INPUT FORMAT
Line 1: N, the number of beads
Line 2: a string of N characters, each of which is r, b, or w
29
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
OUTPUT FORMAT
A single line containing the maximum of number of beads that can be collected from the supplied necklace.
11
OUTPUT EXPLANATION
Consider two copies of the beads (kind of like being able to runaround the ends). The string of 11 is marked.
Two necklace copies joined here
wwwbbrwrbrbrrbrbrwrwwrbwrwrrb | wwwbbrwrbrbrrbrbrwrwwrbwrwrrb
******|*****
rrrrrb|bbbbb <-- assignments
5xr .....#|##### 6xb
5+6 = 11 total
This is a USACO training problem i'm having trouble with; i keep getting incorrect answers. ...and please don't tell me this is stupid or silly; that's not helping! :D
Heh, I'm up to this one but I haven't been bothered to code it up. Anyway, my ideas are this.
Firstly, you don't need to store all the bead colours (Go Australian spelling!), you just need to store how many beads of the same colour are in a row. So for:
RRBBBWRR
you just need to store:
2R 3B 1W 2R
One thing to note is if the ending and the starting beads are the same colour you have to account for that, so
RRBBBRR
should be stored as
4R 3B
or
3B 4R
Same thing. Note that the reason for this is not to save memory or anything, but to ensure that beads next to each other are different colours. We have done this by combining beads of the same colour.
Next is you go through each one:
- If it's red, you add up all the ones after that till you find a blue and then continue adding until you find another red
- If it's blue, do similarly except reversed
- If it's white, then the next bead will be red or blue. Do as above except with the number of white beads added
Here are some examples. The |'s mark where the sequence begins and ends.
B|RB|R
we find a R then a B then another R. Therefore we have to stop at the B. In
B|RWRB|R
We find an R and then another R but we haven't found a B yet so we continue. Then we find a B and then another R. This time, since we've found a B we have to stop.
B|RBW|R
we find a R then a B but we can continue since the next one is a W, then we find another R so we have to stop. In
B|WRBWB|R
we count the W then we find a R. Therefore we continue till we find a B and then continue till we find another R. This
B|WBRWR|B
is a reverse case.
Now all you have to do is implement it :D. Of course this doesn't take into account the actual number of beads in the the R, B and W and are just examples of single bead sequences. You will have to check all possible sequences. You also have to take care of the sequences which wrap around from the back to the start.
Lastly, you may notice that this algorithm is sometimes wasteful but N < 350 so even an O(N^3) should work in 1 second. Maybe 2. Anyway, I believe this is O(N^2) so you should be able to run this program 350 times in one second. Please comment if something's confusing because I'm not the best explainer. Happy coding.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(){
int numBeads;
char temp1[705];
char temp2[705];
int i,j,k,lim;
int count1 = 0;
int count2 = 0;
int maxcount1 = 0;
char virgin = ' ';
bool flag = false; //flag == true if virgin doesn't match
FILE* fin = fopen("beads.in","r");
FILE* fout = fopen("beads.out","w");
fscanf(fin,"%d",&numBeads);
fscanf(fin,"%s",temp1);
strcpy(temp2,temp1);
strcat(temp1,temp2);
for(i=0,j=numBeads-1;i<numBeads;i++,j++){
count1 =0;
count2 = 0;
flag = false;
virgin = ' ';
for(k=i;flag==false && k < (i+numBeads);k++){
if(temp1[k]=='w'){
count1++;
}
else if(temp1[k]=='r'){
if(virgin==' '){
virgin = 'r';
}
if(virgin=='r')
count1++;
else{
flag = true;
k--;
}
}
else if(temp1[k]=='b'){
if(virgin==' '){
virgin = 'b';
}
if(virgin=='b')
count1++;
else{
flag = true;
k--;
}
}
}
/* Block 2*/
lim = k;
flag = false;
virgin = ' ';
for(k=j;flag==false && k < (j+numBeads) && k>=lim;k--){
if(temp1[k]=='w'){
count2++;
}
else if(temp1[k]=='r'){
if(virgin==' '){
virgin = 'r';
}
if(virgin=='r')
count2++;
else{
flag = true;
k--;
}
}
else if(temp1[k]=='b'){
if(virgin==' '){
virgin = 'b';
}
if(virgin=='b')
count2++;
else{
flag = true;
k--;
}
}
}
if(maxcount1 < (count1+ count2))maxcount1 = count1 + count2;
}
fprintf(fout,"%d\n",maxcount1);
return 0;
}
Here is my code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
/**
*
* #author Bansari
*/
public class beads {
public static void main(String args[]){
try{
BufferedReader f = new BufferedReader(new FileReader("beads.in"));
// input file name goes above
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("str.txt")));
int len = Integer.parseInt(f.readLine());
String s=f.readLine();
int c1=0,c2=0;
int breakpoint=0;
int max = 0;
for(int i = 1;i<=len;i++){
char before = s.charAt((i-1)%len);
char after = s.charAt(i%len);
if(before != after){
c1=0;
c2=0;
int index = i-1;
while(s.charAt(index)==before || s.charAt(index)=='w'){
char sc = s.charAt(index);
c1++;
if(index==0)
index = len-1;
else
index--;
}
index = i;
while(s.charAt(index%len)==after || s.charAt(index%len)=='w'){
c2++;
if(index == len-1)
index = 0;
else
index++;
}
if(max < (c1 + c2)){
breakpoint=i;
max = c1+c2;
}
}
}
out.println(max);
out.close();
System.exit(0);
}catch(Exception e){
}
}
}
When you're presented with a weird problem in a computing contest, it's odds-on it'll be dynamic programming (the Bellman kind, not the Ruby kind.)
Have a look at this tutorial.
The basic idea of dynamic programming is to build up a "big" answer by answering small subproblems. My first intuitive thought is to think about longer and longer necklaces, starting with, like, one bead, but I'm honestly not particularly good at dynamic programming problems. (I've also noticed that the most common place to run into DP problems in the real world is in computing olympiads and problem sets in computer science classes.)
RETRACTED -- THIS IS WRONG because it does not consider white beads.
i can either see a simpler than the accepted answer, or the explanation is too complex. here's the algorithm in pseudocode (ignoring the case of all same color):
p = position of first bead of different color than bead 0
create array of run-lengths: r={5,15,2,9,13}
create array of sums of adjacents s={20,17,11,22,18} (wrap last)
find index, k, in s[] of max sum: here it is s[3]
position = p + r[0] + r[1] + ... + r[k]
I did this a long long time ago when I was learning programming. I just searched my computer and found the solution that I had submitted. I can provide the code but its all messed up . =P
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
public class beads {
/**
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
new beads().go();
}
private void go() throws Exception {
// TODO Auto-generated method stub
BufferedReader bin = new BufferedReader(new FileReader("beads.in"));
PrintWriter pout = new PrintWriter(new BufferedWriter(new FileWriter("beads.out")));
int count = Integer.parseInt(bin.readLine());
String beads = bin.readLine();
int ans = compute(beads);
pout.println(ans);
pout.close();
}
private int compute(String beads) {
// TODO Auto-generated method stub
int length = beads.length();
int maxbeads = 0;
for(int i = 0; i < length; i++){
int left = 0;
int right = 0;
left = computeLeft(beads,i);
if(left == length){ maxbeads = left; break;}
right = computeRigtht(beads,i);
if(right == length){ maxbeads = right; break;}
if((left+right) > maxbeads) maxbeads = left+right;
if(maxbeads == length) break;
}
return maxbeads;
}
private int computeLeft(String beads, int i) {
// TODO Auto-generated method stub
int l = beads.length();
int j = i;
int count = 0;
char ch = beads.charAt(i);
for(; j >=0; j--){
if(ch == 'w'){//Didnt notice this kind of case before
ch = beads.charAt(j);
count++;
}
else if(beads.charAt(j) == ch || beads.charAt(j)== 'w'){
count++;
}
else break;
}
if(j < 0) j = l-1;
for(; j > i; j--){
if(beads.charAt(j) == ch || beads.charAt(j)== 'w'){
count++;
}
else break;
}
return count;
}
private int computeRigtht(String beads, int i) {
// TODO Auto-generated method stub
int l = beads.length();
int j = 0;
if(i == l-1) j = 0;
else j = i+1;
int k = j;
int count = 0;
int ch = beads.charAt(j);
for(; j <l; j++){
if(ch == 'w'){
ch = beads.charAt(j);
count++;
}
else if(beads.charAt(j)== ch || beads.charAt(j)=='w'){
count++;
}
else break;
}
if(j == l) j = 0;
for(; j < k-1; j++){
if(beads.charAt(j) == ch || beads.charAt(j)== 'w'){
count++;
}
else break;
}
return count;
}
}
I used quasiverse's algo and solved it.
The USACO server is down and I am not able to test it on their judge, but I think I have solved it.
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
#include<cstdlib>
#define MAXLEN 350
using namespace std;
ofstream fout ("beads.out");
typedef struct node
{
char color;
int times;
int lenMax;
struct node* next;
} nodeList;
nodeList * getnode()
{
nodeList* temp=(nodeList*) malloc (sizeof(nodeList));
temp->next=NULL;
temp->lenMax=0;
return temp;
}
void append(nodeList **head,char tColor,int m)
{
nodeList *p=NULL,*newNode=NULL;
newNode =getnode();
newNode->color=tColor;
newNode->times=m;
newNode->lenMax=0;
if(*head==NULL)
{
*head=newNode;
return;
}
p=*head;
while(p->next)
p=p->next;
p->next=newNode;
}
void shiftNodes(nodeList **head)
{
int mon=0;
nodeList *last=NULL,*p=NULL,*t=NULL;
p=*head;
do
{
//cout<<p->color<<" "<<p->times<<endl;
last=p;
p=p->next;
}
while(p!=NULL);
p=*head;
last->next=*head;
t=*head;
do
{
if(((*head)->color=='w' || (last)->color=='w' ) || (*head)->color==last->color)
{
(*head)=(*head)->next;
last=last->next;
}
else if((*head)->color!=last->color )
{
break;
}
p=p->next;
}
while(p!=t);
}
void computeLenMaxB(nodeList ** head)
{
nodeList *p =NULL,*t=NULL,*s=NULL;
t=p=*head;
bool gotR=false;
int tempLenMax=0;
do
{
if(p->color=='b' && gotR){
break;
}
else if(p->color=='b' && !gotR){
tempLenMax+=p->times;
}
else if(p->color=='r' && !gotR){
tempLenMax+=p->times;
gotR=true;
}
else if(p->color=='r' && gotR){
tempLenMax+=p->times;
}
else if(p->color=='w' ){
tempLenMax+=p->times;
}
p=p->next;
}
while(p!=t);
(*head)->lenMax=tempLenMax;
}
void computeLenMaxR(nodeList ** head)
{
nodeList *p =NULL,*t=NULL,*s=NULL;
t=p=*head;
bool gotR=false;
int tempLenMax=0;
do
{
if(p->color=='r' && gotR){
break;
}
else if(p->color=='r' && !gotR){
tempLenMax+=p->times;
}
else if(p->color=='b' && !gotR){
tempLenMax+=p->times;
gotR=true;
}
else if(p->color=='b' && gotR){
tempLenMax+=p->times;
}
else if(p->color=='w' ){
tempLenMax+=p->times;
}
p=p->next;
}
while(p!=t);
(*head)->lenMax=tempLenMax;
}
void fillLenMax(nodeList ** head)
{
nodeList *p =NULL,*t=NULL,*s=NULL;
t=p=*head;
int wBeads=0;
do
{
s=p;
if(p->color=='b')
{
computeLenMaxB(&p);
}
else if(p->color=='r')
{
computeLenMaxR(&p);
}
else if(p->color=='w')
{
if(p->next->color=='b'){
computeLenMaxB(&p);
}
else if(p->next->color=='r'){
computeLenMaxR(&p);
}
}
p=p->next;
}
while(p!=t);
}
int calcMaxLenMax(nodeList *head)
{
nodeList *p=NULL;
p=head;
int max=0;
do
{
//fout<<p->color<<" "<<p->times<<" "<<p->lenMax<<endl;
max=(max>p->lenMax)?max:p->lenMax;
p=p->next;
}
while(p!=head);
return max;
}
int main()
{
ifstream fin ("beads.in");
char necklace[MAXLEN];
int i,j,max;
fin>>necklace;
nodeList* list=NULL;
int repeat = 0;
i=0;
while(i<strlen(necklace))
{
repeat = 0;
for(j=i; necklace[j]==necklace[i]; j++)
{
repeat++;
}
append(&list ,necklace[i],repeat);
i=i+repeat;
}
shiftNodes(&list);
fillLenMax(&list);
max=calcMaxLenMax(list);
fout<<max<<endl;
return 0;
}
Its an old thread, but might be useful to people learning programming. Here is a simple solution using brute force. The idea is that we make one pass through the data to count colours. In the second loop we perform pairwise comparison of sums from the left and the right part. Code should be easy to follow:
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;
public class beads {
public static void main(String[] args) throws IOException {
BufferedReader f = new BufferedReader(new FileReader("beads.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("beads.out")));
f.readLine();//length
String s1 = f.readLine();
List<String> counts = new LinkedList<String>();
char[] colors = (s1.concat(s1)).toCharArray();
char previousColor = ' ';
int count = 0;
for (char color : colors) {
if (previousColor != color && count > 0) {
counts.add(count + "-" + previousColor);
count = 0;
}
count++;
previousColor = color;
}
if (counts.isEmpty()) {//special case when there is only one color
out.println(count/2);
out.close();
System.exit(0);
}
TreeSet<Integer> result = new TreeSet<Integer>();
for (int i = 1; i < counts.size(); i++) {
if(counts.get(i).split("-")[1].charAt(0)=='w')continue;
int left = getLeft(counts, i);
int right = getRight(counts, i);
result.add((left+right));
}
out.println(result.last());
out.close();
System.exit(0);
}
private static int getLeft(List<String> counts, int i) {
char start = counts.get(i - 1).split("-")[1].charAt(0);
boolean doContinue = true;
int count = 0;
while (doContinue) {
String[] s = counts.get(--i).split("-");
char color=s[1].charAt(0);
if(start=='w' && color!='w')start=color;
boolean incr = (color == 'w' || color==start);
if(incr)
count += Integer.parseInt(s[0]);
else doContinue=false;
doContinue = doContinue && i > 0;
}
return count;
}
private static int getRight(List<String> counts, int i) {
char start = counts.get(i).split("-")[1].charAt(0);
boolean doContinue = true;
int count = 0;
while (doContinue) {
String[] s = counts.get(i).split("-");
char color=s[1].charAt(0);
if(start=='w' && color!='w')start=color;
boolean incr = (color == 'w' || color == start);
if(incr)
count += Integer.parseInt(s[0]);
else doContinue=false;
doContinue = doContinue && ++i < counts.size()-1;
}
return count;
}
}
This is a teaser! Every time solution is just so, so close!
In the meantime the white beads are cause of black despair.
Here is the algorithm (I passed Usaco grader)
1) find first colored bead. say it is at position k in the n bead necklace
2) rearrange necklace: move the section 0-k to the end ,so it starts with true color.
e.g {wwbrwbrb{ becomes {brwbrbww}
3) cut up the necklace into sub-sections (array of strings), so that each section starts with a color e.g. {b rw b r bww}
4) if first and last segment are the same color, join them
e.g. {b rw bw rw bww} becomes {bwwb rw bw rw} (sequence is preserved)
5) Notice!!!! the second last element (bw) ends with white. So white can be joined to rw that follows.
Also notice that following sequence will never starts with white.
6) for each entry in the array of sub sequences add lengths of entry k and k+1.
Then skim the white spaces (if any) from the entry k-1 and add to the above (since this is a circle then k-1 entry may be the last in the array).
if bigger than max then change max.
There is some tricky accounting for less than three sub sequences in the necklace but it is just tedious, no trick to it.