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.
Related
Closely related to Java programming - nested for loops for minesweeper game, my Minesweeper program is designed to loop through cells, check each adjacent cell, perform a logic test to check if it's a Mine, and then jump to the next one. However, when I run it, it somehow becomes an infinite loop. I've tried changing variables, reversing signs (< becomes > and + becomes -), and googling other solutions, but I can't find anything.
Printouts are for debugging, gameboard is set to [10][10],
public static void assignNumbers(int[][] gameBoard)
{
for(int r = 0; r <= (gameBoard.length - 1); r++){ //row
for(int c = 0; c <= (gameBoard[0].length - 1); r++){ //column
System.out.print("New Cell ");
for(int vR = r+1; vR > r-2; vR --){ //vR is visiting Row
for(int vC = c+1; vC > c-2; vC --){ //vC is visiting Column
System.out.print("new item ");
if (isValid(vR, vC, gameBoard)){
System.out.print("isMine? ");
if (isMine(vR, vC, gameBoard)){
gameBoard[r][c] += 1;
System.out.print(" MINE ");
}
else {
System.out.print(" NO ");
}
}
}
}
System.out.println();
}
}
}
public static boolean isMine(int r, int c, int[][] gameBoard){
if(gameBoard[r][c] != 100){
return false;
}
else{
return true;
}
}
public static boolean isValid(int r, int c, int[][] gameBoard)
{
// Returns true if row number and column number
// is in range
return ((r >= 0) && (r < SIDE)) && ((c >= 0) && (c < SIDE)) && !isMine(r, c, gameBoard);
}
When I try to run it, I get an infinite printout saying :
"New Cell" followed by 9 "new items". This should only print out 100 times (once for each cell), however it doesn't stop after 100. I assume it's a logic error in one of the for loops, but I can't find it for the life of me. Any help is appreciated, and I'll do my best to answer any questions.
EDIT: punctuation
Try to replace r++ with c++
for(int c = 0; c <= (gameBoard[0].length - 1); c++){ //column
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 '*')
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.
I am trying to make a connect 4 program in java and I am stuck on the winner check. I know that I could make a very long list of if and else if's but I think loops would work better. I'm open to any other way of solving this problem but on what I've been looking at makes it seem the best. I have an idea of what to do with the rows and columns but I don't even know where to start with the diagonals. This is what I have so far:
edit:
int p1counter = 0;
int p2counter = 0;
int r = 1;//x
int c = 1;//y
for(r = 1; r <= 6; r++)
{
while(c <= 7)
{
if(grid[r][c].equals("_"))
{
c++;
p1counter = 0; p2counter = 0;
}
else if(grid[r][c].equals("1"))//player 1 counter
{
c++;
p1counter++;
}
else if(grid[r][c].equals("2"))//player 2 counter
{
c++;
p2counter++;
}
}
if(p1counter >= 4)
{
JOptionPane.showMessageDialog(null, "Player 1 is the winner!");
done = true;
}
else if(p2counter >= 4)
{
JOptionPane.showMessageDialog(null, "Player 2 is the winner!");
done = true;
}
return done;
}
In similar situations I have done the following:
Create an array of strings; as many strings as there are rows+columns+diagonals
Traverse the grid in the four possible directions (this does not include every possible diagonal since diagonals must be at least 4 long) and enter a corresponding character in the string: for example 0 (empty), 1, 2
Search the string array for 1111 and 2222.
By first organizing the data, the comparison can be done with a built in function. Much faster and cleaner.
Here is how it might be done (this is the "slow and careful way"):
class c4check {
public static void main(String[] args) {
char grid[][] = {{'e','e','e','e','a','b','a'},
{'e','a','b','a','b','b','a'},
{'e','b','a','a','b','b','a'},
{'e','a','b','b','a','b','b'},
{'e','b','a','b','b','a','a'},
{'e','a','b','a','b','b','a'}};
int ii, jj, ri, ci, di;
String checkGrid[] = new String[25];
// copy rows:
for(ri = 0; ri < 6; ri++) {
String temp = "";
for(ci = 0; ci < 7; ci++) {
temp += grid[ri][ci];
}
checkGrid[ri] = temp;
}
// copy columns:
for(ci = 0; ci < 7; ci++) {
String temp = "";
for(ri = 0; ri < 6; ri++) {
temp += grid[ri][ci];
}
checkGrid[ci + 6] = temp;
}
// copy first diagonals:
for(di = 0; di < 6; di++) {
String temp = "";
for(ri = 0; ri < 6; ri++) {
ci = di - 2;
ri = 0;
while(ci < 0) {
ri++;
ci++;
}
for(; ri < 6; ri++, ci++) {
if( ci > 6 ) continue;
temp += grid[ri][ci];
}
}
checkGrid[di+13] = temp;
}
// diagonals in the other direction:
for(di = 0; di < 6; di++) {
String temp = "";
for(ri = 0; ri < 6; ri++) {
ci = 8 - di;
ri = 0;
while(ci > 6) {
ri++;
ci--;
}
for(; ri < 6; ri++, ci--) {
if( ci < 0 ) continue;
temp += grid[ri][ci];
}
}
checkGrid[di+19] = temp;
}
for(ii = 0; ii < 25; ii++) {
System.out.println("Checking '" + checkGrid[ii] + "'");
if (checkGrid[ii].contains("aaaa")) System.out.println("Player A wins!");
if (checkGrid[ii].contains("bbbb")) System.out.println("Player B wins!");
}
}
}
Obviously, instead of copying temp to an array element, and then checking at the end, you could check for "aaaa" or "bbbb" each time, and return from the function as soon as you found a match.
Output of this particular code (which has more than one "winning" combination, so it's not a "real" situation - but it allowed me to check that all the diagonals were visited correctly):
Checking 'eeeeaba'
Checking 'eababba'
Checking 'ebaabba'
Checking 'eabbabb'
Checking 'ebabbaa'
Checking 'eababba'
Checking 'eeeeee'
Checking 'eababa'
Checking 'ebabab'
Checking 'eaabba'
Checking 'abbabb'
Checking 'bbbbab'
Player B wins!
Checking 'aaabaa'
Checking 'eaaa'
Checking 'ebbbb'
Player B wins!
Checking 'eaabbb'
Checking 'ebaaaa'
Player A wins!
Checking 'eabba'
Checking 'ebbb'
Checking 'abba'
Checking 'ababb'
Checking 'abbbaa'
Checking 'bbabbe'
Checking 'aaaae'
Player A wins!
Checking 'ebbe'
Here is way to maintain the track of winner :-
maintain 4 types of sets (horizontal,vertical,two diagonal).
whenever a point on grid is colored check with corresponding neighbour in the same type eg. if grid point (x,y) is colored then for horizontal type we check (x,y+1) and (x,y-1).
find union of two similar colored neighbour.
If size of any set is equal to four then you have found the winner. You can check while updating neighbours of point currently colored.
Suggestions: Use Union-Find datastructure to achieve good time complexity (Note as your sets are small you can do without it as well).
Background
I am trying to code Dijkstra's algorithm in O(mlogn) time, where m is the number of edges and n is the number of nodes. I am using to find the shortest path between a given starting node and a given ending node. And I'm pretty new at this.
Here is the algorithm I have come up with:
Assume the graph is represented by an adjacency matrix and each node has a row index.
Initialize starting node distance to zero, and all other nodes to inifinity, in the heap.
Create a list of shortest paths, equal to the number of nodes in the graph, set to 0.
While the index of the node that corresponds to the minimum element in the heap
has no value in the list of shortest paths and heap has node distances, do:
Remove the minimum node distance from the heap, and bubble as necessary to fill the removed node.
Put the minimum node distance into the list of shortest paths at its row index.
For all nodes that were adjacent to the node with the minimum distance (that was just removed), do:
Update the distances in the heap for the current node, using the following calculation:
min((deleted node distance + adjacent edge weight), current node's distance)
Reorganize the heap to be a minimum heap.
Return value in the list of shortest paths at the location of the end node.
This is O(mlogn) because you only update the distances once per edge.
"It takes linear time
to initialize the heap, and then we perform m updates at a cost of O(log n) each for a total time of O(mlog n)." - http://www.cs.cmu.edu/~avrim/451f07/lectures/lect1011.pdf
Problem
In order to update the distances from the starting vertex in the correct location in the heap, insertions to the heap must be key-value pairs - with the key being the node (row index) and the value being the distance.
There are lecture slides online that say each entry in a priority queue ADT is a key-value pair (otherwise, how could it prioritize?).
Question
The methods for PriorityQueue have at most one parameter, so how do you insert a key associated with a value?
This must be done in a single file with a specific name (i.e. It is my understanding that I can't make a KeyValuePair class implementing Comparator).
I'd love to hear your thoughts.
To use JDK's implementation of priority queue for your application, you can maintain a Map<Key, Value> in addition to PriorityQueue<Value>. In your case, Key represents a node and Value is an object that holds the shortest distance to a node. To update the distance to a node, you first look up its corresponding distance object in the map. Then, you remove the distance object from the priority queue. Next, you update the distance object. Finally, you insert the distance object back in the priority queue.
Below is the Dijkstra implementation using priority_queue .
Here ignore the InputReader class as it is for fast input . We can maintain priority according to "Value" of pair in key value pair . Then choose the Pair with minimum cost i.e value .
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.PriorityQueue;
/**
* By: Rajan Parmar
* At : HackerRank
**/
public class Dijkstra {
// node ,pair ( neighbor , cost)
static HashMap < Integer , HashSet <Pair>> node;
static PrintWriter w;
public static void main(String [] s) throws Exception{
InputReader in;
boolean online = false;
String fileName = "input";
node = new HashMap<Integer, HashSet<Pair>>();
//ignore online if false it is for online competition
if (online) {
//ignore
in = new InputReader(new FileInputStream(
new File(fileName + ".txt")));
w = new PrintWriter(new FileWriter(fileName + "Output.txt"));
} else {
// for fast input output . You can use any input method
in = new InputReader(System.in);
w = new PrintWriter(System.out);
}
// Actual code starts here
int t;
int n, m;
t = in.nextInt();
while(t-- > 0){
n = in.nextInt();
m = in.nextInt();
while(m-- > 0){
int x,y,cost;
x = in.nextInt();
y = in.nextInt();
cost = in.nextInt();
if(node.get(x)==null){
node.put(x, new HashSet());
node.get(x).add(new Pair(y,cost));
}
else{
node.get(x).add(new Pair(y,cost));
}
if(node.get(y)==null){
node.put(y, new HashSet());
node.get(y).add(new Pair(x,cost));
}
else{
node.get(y).add(new Pair(x,cost));
}
}
int source = in.nextInt();
Dijkstra(source,n);
node.clear();
System.out.println("");
}
}
static void Dijkstra(int start , int n) {
int dist[] = new int[3001];
int visited[] = new int[3001];
Arrays.fill(dist, Integer.MAX_VALUE);
Arrays.fill(visited, 0);
dist[start] = 0 ;
PriorityQueue < Pair > pq = new PriorityQueue();
//this will be prioritized according to VALUES (i.e cost in class Pair)
pq.add(new Pair(start , 0));
while(!pq.isEmpty()){
Pair pr = pq.remove();
visited[pr.neighbor] = 1;
for(Pair p:node.get(pr.neighbor)){
if(dist[p.neighbor] > dist[pr.neighbor] + p.cost){
dist[p.neighbor] = dist[pr.neighbor] + p.cost;
//add updates cost to vertex through start vertex
if(visited[p.neighbor]==0)
pq.add(new Pair(p.neighbor ,dist[p.neighbor] ));
}
}
}
for(int i=1;i<=n;i++){
if(i==start) continue;
if(visited[i]==0)
dist[i]=-1;
System.out.print(dist[i]+" ");
}
}
static class Pair implements Comparable {
int neighbor;
int cost;
public Pair(int y, int cost) {
// TODO Auto-generated constructor stub
neighbor = y;
this.cost = cost;
}
#Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Pair pr = (Pair)o;
if(cost > pr.cost)
return 1;
else
return -1;
}
}
//Ignore this class , it is for fast input.
static class InputReader {
private InputStream stream;
private byte[] buf = new byte[8192];
private int curChar, snumChars;
private SpaceCharFilter filter;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int snext() {
if (snumChars == -1)
throw new InputMismatchException();
if (curChar >= snumChars) {
curChar = 0;
try {
snumChars = stream.read(buf);
} catch (IOException e) {
throw new InputMismatchException();
}
if (snumChars <= 0)
return -1;
}
return buf[curChar++];
}
public int nextInt() {
int c = snext();
while (isSpaceChar(c))
c = snext();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = snext();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = snext();
} while (!isSpaceChar(c));
return res * sgn;
}
public long nextLong() {
int c = snext();
while (isSpaceChar(c))
c = snext();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = snext();
}
long res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = snext();
} while (!isSpaceChar(c));
return res * sgn;
}
public int[] nextIntArray(int n) {
int a[] = new int[n];
for (int i = 0; i < n; i++)
a[i] = nextInt();
return a;
}
public String readString() {
int c = snext();
while (isSpaceChar(c))
c = snext();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = snext();
} while (!isSpaceChar(c));
return res.toString();
}
public boolean isSpaceChar(int c) {
if (filter != null)
return filter.isSpaceChar(c);
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
public interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
}
This will take input in following format .
First line be T (no. of test case).
For each test case next line input will be N and M , where N is no of nodes , M is no of edges.
Next M line contains 3 integers i.e x,y,W. It represents edge between node x and y with weight W.
Next line contain single integer i.e. Source node .
Output :
Print shortest distance to all node from given source node . If node is unreachable print -1.
e.g
Input :
1
6 8
1 2 1
1 5 4
2 5 2
2 3 2
5 6 5
3 6 2
3 4 1
6 4 3
1
Output : (shortest distance of all node from node 1)
1 3 4 3 5
I appreciate the answers to my question and at the time I chose the Map answer because given my limited understanding of the language, it seemed easier for me to implement.
It turns out that I overlooked an important detail that made the problem much simpler than I thought it was: if I maintain an array of distances and insert the nodes into the heap (instead of the distances), to use as references to the distance array, I was able to sort the nodes based on their values.
In this implementation, I didn't need to contrive a key-value property after all. After updating the values in the distance array, I had to remove and re-add those specific nodes to the heap in order for the heap to stay current and sorted, as suggested by #reprogrammer.
Once I changed what I was putting into the heap, the algorithm was very similar to the one found on Wikipedia.
Here is the code I ended up using, in case anyone has the same problem. Note: the magic part is the creation of the PriorityQueue (which is similar to what was suggested by #stevevls):
import java.util.*;
import java.io.File; //Because files were used to test correctness.
import java.lang.Math;
public class Dijkstra{
//This value represents infinity.
public static final int MAX_VAL = (int) Math.pow(2,30);
/* Assumptions:
If G[i][j] == 0, there is no edge between vertex i and vertex j
If G[i][j] > 1, there is an edge between i and j and the value of G[i][j] is its weight.
No entry of G will be negative.
*/
static int dijkstra(int[][] G, int i, int j){
//Get the number of vertices in G
int n = G.length;
// The 'i' parameter indicates the starting node and the 'j' parameter
// is the ending node.
//Create a list of size n of shortest paths, initialize each entry to infinity
final int[] shortestPaths = new int[n];
for(int k = 0; k < n; k++){
shortestPaths[k] = MAX_VAL;
}
//Initialize starting node distance to zero.
shortestPaths[i] = 0;
//Make a Priority Queue (a heap)
PriorityQueue<Integer> PQ = new PriorityQueue<Integer>(n,
new Comparator<Integer>()
{
public int compare(Integer p, Integer q)
{
return shortestPaths[p] - shortestPaths[q];
}
} );
//Populate the heap with the nodes of the graph
for(int k = 0; k < n; k++){
PQ.offer(k);
}
//While the heap has elements.
while(PQ.size() > 0){
// Remove the minimum node distance from the heap.
int minimum = PQ.poll();
// Check if graph is disconnected, if so, return -1.
if(shortestPaths[minimum] == MAX_VAL)
{
return -1;
}
// End node has been reached (i.e. you've found the shortest path), return the distance.
if( minimum == j){
return shortestPaths[j];
}
// Take the current node and look through the row to see the vertices adjacent to it (neighbours)
for(int columnIt = 0; columnIt < n; columnIt ++){
// Update the distances in the heap for the current node, using the following calculation:
// min((deleted node distance + adjacent edge weight), current node's distance)
if(G[minimum][columnIt] > 0){
int sum = shortestPaths[minimum] + G[minimum][columnIt];
shortestPaths[columnIt]= Math.min(sum, shortestPaths[columnIt]);
if(shortestPaths[columnIt]==sum)
{
PQ.remove(columnIt);
PQ.offer(columnIt);
}
}
}
}
return -1;
}
Thank you for your answers and advice.
I am resolving the same issue. I know where you can find the answer on you question.
It's a great book with example of code - Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
Site book and Example of code (including an implementation of Dijkstra's algorithm using a PriorityQueue)
This implementation of Dijkstra's algorithm doesn't use Java's standard PriorityQueue implementation. Instead it implements IndexMinPQ, which was discussed earlier in the book with a detailed explanation!