I'm trying to find a simple path of length N in a RxC matrix, given a starting cell. The path should follow a restriction, given by a boolean function. The goal is to later use this to find the longest path in the matrix.
I got a solution set up, however I don't know how to modify it to know when a solution does not exist.
My solution consists of a DFS approach using backtracking. The solution is correct when there is one, but the program returns the longest path found instead of saying such path doesn't exist.
I know there are similar problems with solutions available but I'd like to understand where my logic is failing.
Here's the code (from a cell we can move in all 8 directions):
Bool DFS(Map *map,Point* srcPt,short steps,Bool (*restrictionCompare)(Point *p1, Point *p2))
{
Point *target;
short row = getPointRow(srcPt);
short col = getPointCol(srcPt);
// Found N-steps path!
if (steps == 0)
{
puts("Path found!\n");
return 1;
}
//Mark the M[row][col] as visited
markAsVisited(map,row,col);
// Iterate over all 8 directions of a cell
for (short i = 0; i < DIRECTIONS; ++i)
{
short coords[2];
// Get a valid adjacent cell
if (getNeighbour(map,srcPt,i,coords,restrictionCompare) == FALSE) continue;
target = getMapPoint(map,coords[0],coords[1]); // This is the valid neighbour
//if cell wasn't visited before...
if (isVisited(target) == FALSE)
{
// ..recursively call DFS from cell
if(DFS(map,target,--steps,restrictionCompare) == TRUE)
{
// Show point
showPoint(target);
return TRUE;
}
}
}
// Backtrack
markAsUnvisited(map,row,col);
return FALSE;
}
An example of path of length found by the program:
Any suggestions on how to improve the code's efficiency is also welcome.
Related
For example, string "AAABBB" will have permutations:
"ABAABB",
"BBAABA",
"ABABAB",
etc
What's a good algorithm for generating the permutations? (And what's its time complexity?)
For a multiset, you can solve recursively by position (JavaScript code):
function f(multiset,counters,result){
if (counters.every(x => x === 0)){
console.log(result);
return;
}
for (var i=0; i<counters.length; i++){
if (counters[i] > 0){
_counters = counters.slice();
_counters[i]--;
f(multiset,_counters,result + multiset[i]);
}
}
}
f(['A','B'],[3,3],'');
This is not full answer, just an idea.
If your strings has fixed number of only two letters I'll go with binary tree and good recursion function.
Each node is object that contains name with prefix of parent name and suffix A or B furthermore it have numbers of A and B letters in the name.
Node constructor gets name of parent and number of A and B from parent so it needs only to add 1 to number of A or B and one letter to name.
It doesn't construct next node if there is more than three A (in case of A node) or B respectively, or their sum is equal to the length of starting string.
Now you can collect leafs of 2 trees (their names) and have all permutations that you need.
Scala or some functional language (with object-like features) would be perfect for implementing this algorithm. Hope this helps or just sparks some ideas.
Since you actually want to generate the permutations instead of just counting them, the best complexity you can hope for is O(size_of_output).
Here's a good solution in java that meets that bound and runs very quickly, while consuming negligible space. It first sorts the letters to find the lexographically smallest permutation, and then generates all permutations in lexographic order.
It's known as the Pandita algorithm: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order
import java.util.Arrays;
import java.util.function.Consumer;
public class UniquePermutations
{
static void generateUniquePermutations(String s, Consumer<String> consumer)
{
char[] array = s.toCharArray();
Arrays.sort(array);
for (;;)
{
consumer.accept(String.valueOf(array));
int changePos=array.length-2;
while (changePos>=0 && array[changePos]>=array[changePos+1])
--changePos;
if (changePos<0)
break; //all done
int swapPos=changePos+1;
while(swapPos+1 < array.length && array[swapPos+1]>array[changePos])
++swapPos;
char t = array[changePos];
array[changePos] = array[swapPos];
array[swapPos] = t;
for (int i=changePos+1, j = array.length-1; i < j; ++i,--j)
{
t = array[i];
array[i] = array[j];
array[j] = t;
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
StringBuilder line = new StringBuilder();
generateUniquePermutations("banana", s->{
if (line.length() > 0)
{
if (line.length() + s.length() >= 75)
{
System.out.println(line.toString());
line.setLength(0);
}
else
line.append(" ");
}
line.append(s);
});
System.out.println(line);
}
}
Here is the output:
aaabnn aaanbn aaannb aabann aabnan aabnna aanabn aananb aanban aanbna
aannab aannba abaann abanan abanna abnaan abnana abnnaa anaabn anaanb
anaban anabna ananab ananba anbaan anbana anbnaa annaab annaba annbaa
baaann baanan baanna banaan banana bannaa bnaaan bnaana bnanaa bnnaaa
naaabn naaanb naaban naabna naanab naanba nabaan nabana nabnaa nanaab
nanaba nanbaa nbaaan nbaana nbanaa nbnaaa nnaaab nnaaba nnabaa nnbaaa
- mark[1,0]=1; top=1; stack[top].row=1; stack[top].col=0;
stack[top].dir=1; while (top>0) {
loc = pop();
cr=loc.row; cc=loc.col; cd=loc.dir;
while (cd <= 4) {
nr=cr+move[cd].r; nc=cc+move[cd].c;
if (nr==grow && nc==gcol) {
for(i=0; i<=top; i++) printLoc(stack[i]);
print(cr, cc); print(grow, gcol);
return;
}
if (maze[nr][nc]==0 && mark[nr][nc]==0) {
mark[nr][nc] = 1;
loc.row=cr; loc.col=cc; loc.dir=cd+1;
push(loc);
cr=nr; cc=nc; cd=1;
}
else cd=cd+1;
} } print(“no path in maze”);
I've been looking at this algorithm for about an hour but still can't understand it.
I understand that col/row/direction = column, row, direction, and mark means a 2-dimensional array. But I can't get how to implement this algorithm and turn it into code since I can't understand how it works.
Could someone explain this algorithm, please?
More info: 1 = 0,1(move right), 2 = 1,0(move down), 3 = 0, -1(move left), 4 = -1,0(move up). To store the path use stack. If you use stack choose depth-first search, if you use queue choose breadth-first search. 1 is the blocked path while 0 is the path you can walk on.
first question ever here...
I am coding a simple 3-card poker hand evaluator and am having problems finding/extracting multiple "straights" (sequential series of values) from an array of values.
I need to extract and return EVERY straight the array possibly has. Here's an example:
(assume array is first sorted numerically incrementing)
myArray = [1h,2h,3c,3h,4c]
Possible three-value sequences are:
[1h,2h,3c]
[1h,2h,3h]
[2h,3c,4c]
[2h,3h,4c]
Here is my original code to find sequences of 3, where the array contains card objects with .value and .suit. For simplicity in this question I just put "2h" etc here:
private var _pokerHand = [1h,2h,3c,3h,4c];
private function getAllStraights(): Array
{
var foundStraights:Array = new Array();
for (var i: int = 0; i < (_handLength - 2); i++)
{
if ((_pokerHand[i].value - _pokerHand[i + 1].value) == 1 && (_pokerHand[i + 1].value - _pokerHand[i + 2].value) == 1)
{
trace("found a straight!");
foundStraights.push(new Array(_pokerHand[i], _pokerHand[i + 1], _pokerHand[i + 2]));
}
}
return foundStraights;
}
but it of course fails when there are value duplicates (like the 3's above). I cannot discard duplicates because they could be of different suits. I need every possible straight as in the example above. This allows me to run the straights through a "Flush" function to find "straight flush".
What array iteration technique am I missing?
This is an interesting problem. Given the popularity of poker games (and Flash) I'm sure this has been solved many times before, but I couldn't find an example online. Here's how I would approach it:
Look at it like a path finding problem.
Begin with every card in the hand as the start of a possible path (straight).
While there are possible straights:
Remove one from the list.
Find all the next valid steps, (could be none, or up to 4 following cards with the same value), and for each next valid step:
If it reaches the goal (completes a straight) add it to a list of found straights.
Otherwise add the possible straight with the next step back to the stack.
This seems to do what you want (Card object has .value as int):
private function getAllStraights(cards:Vector.<Card>, straightLength:uint = 3):Vector.<Vector.<Card>> {
var foundStraights:Vector.<Vector.<Card>> = new <Vector.<Card>>[];
var possibleStraights:Vector.<Vector.<Card>> = new <Vector.<Card>>[];
for each (var startingCard:Card in cards) {
possibleStraights.push(new <Card>[startingCard]);
}
while (possibleStraights.length) {
var possibleStraight:Vector.<Card> = possibleStraights.shift();
var lastCard:Card = possibleStraight[possibleStraight.length - 1];
var possibleNextCards:Vector.<Card> = new <Card>[];
for (var i:int = cards.indexOf(lastCard) + 1; i < cards.length; i++) {
var nextCard:Card = cards[i];
if (nextCard.value == lastCard.value)
continue;
if (nextCard.value == lastCard.value + 1)
possibleNextCards.push(nextCard);
else
break;
}
for each (var possibleNextCard:Card in possibleNextCards) {
var possibleNextStraight:Vector.<Card> = possibleStraight.slice().concat(new <Card>[possibleNextCard]);
if (possibleNextStraight.length == straightLength)
foundStraights.push(possibleNextStraight);
else
possibleStraights.push(possibleNextStraight);
}
}
return foundStraights;
}
Given [1♥,2♥,3♣,3♥,4♣] you get: [1♥,2♥,3♣], [1♥,2♥,3♥], [2♥,3♣,4♣], [2♥,3♥,4♣]
It gets really interesting when you have a lot of duplicates, like [1♥,1♣,1♦,1♠,2♥,2♣,3♦,3♠,4♣,4♦,4♥]. This gives you:
[1♥,2♥,3♦], [1♥,2♥,3♠], [1♥,2♣,3♦], [1♥,2♣,3♠], [1♣,2♥,3♦], [1♣,2♥,3♠], [1♣,2♣,3♦], [1♣,2♣,3♠], [1♦,2♥,3♦], [1♦,2♥,3♠], [1♦,2♣,3♦], [1♦,2♣,3♠], [1♠,2♥,3♦], [1♠,2♥,3♠], [1♠,2♣,3♦], [1♠,2♣,3♠], [2♥,3♦,4♣], [2♥,3♦,4♦], [2♥,3♦,4♥], [2♥,3♠,4♣], [2♥,3♠,4♦], [2♥,3♠,4♥], [2♣,3♦,4♣], [2♣,3♦,4♦], [2♣,3♦,4♥], [2♣,3♠,4♣], [2♣,3♠,4♦], [2♣,3♠,4♥]
I haven't checked this thoroughly but it looks right at a glance.
This is a tough one, at least for my minimal c skills.
Basically, the user enters a list of prices into an array, and then the desired number of items he wants to purchase, and finally a maximum cost not to exceed.
I need to check how many combinations of the desired number of items are less than or equal to the cost given.
If the problem was a fixed number of items in the combination, say 3, it would be much easier with just three loops selecting each price and adding them to test.
Where I get stumped is the requirement that the user enter any number of items, up to the number of items in the array.
This is what I decided on at first, before realizing that the user could specify combinations of any number, not just three. It was created with help from a similar topic on here, but again it only works if the user specifies he wants 3 items per combination. Otherwise it doesn't work.
// test if any combinations of items can be made
for (one = 0; one < (count-2); one++) // count -2 to account for the two other variables
{
for (two = one + 1; two < (count-1); two++) // count -1 to account for the last variable
{
for (three = two + 1; three < count; three++)
{
total = itemCosts[one] + itemCosts[two] + itemCosts[three];
if (total <= funds)
{
// DEBUG printf("\nMatch found! %d + %d + %d, total: %d.", itemCosts[one], itemCosts[two], itemCosts[three], total);
combos++;
}
}
}
}
As far as I can tell there's no easy way to adapt this to be flexible based on the user's desired number of items per combination.
I would really appreciate any help given.
One trick to flattening nested iterations is to use recursion.
Make a function that takes an array of items that you have selected so far, and the number of items you've picked up to this point. The algorithm should go like this:
If you have picked the number of items equal to your target of N, compute the sum and check it against the limit
If you have not picked enough items, add one more item to your list, and make a recursive call.
To ensure that you do not pick the same item twice, pass the smallest index from which the function may pick. The declaration of the function may look like this:
int count_combinations(
int itemCosts[]
, size_t costCount
, int pickedItems[]
, size_t pickedCount
, size_t pickedTargetCount
, size_t minIndex
, int funds
) {
if (pickedCount == pickedTargetCount) {
// This is the base case. It has the code similar to
// the "if" statement from your code, but the number of items
// is not fixed.
int sum = 0;
for (size_t i = 0 ; i != pickedCount ; i++) {
sum += pickedItems[i];
}
// The following line will return 0 or 1,
// depending on the result of the comparison.
return sum <= funds;
} else {
// This is the recursive case. It is similar to one of your "for"
// loops, but instead of setting "one", "two", or "three"
// it sets pickedItems[0], pickedItems[1], etc.
int res = 0;
for (size_t i = minIndex ; i != costCount ; i++) {
pickedItems[pickedCount] = itemCosts[i];
res += count_combinations(
itemCosts
, costCount
, pickedItems
, pickedCount+1
, pickedTargetCount
, i+1
, funds
);
}
return res;
}
}
You call this function like this:
int itemCosts[C] = {...}; // The costs
int pickedItems[N]; // No need to initialize this array
int res = count_combinations(itemCosts, C, pickedItems, 0, N, 0, funds);
Demo.
This can be done by using a backtracking algorithm. This is equivalent to implementing a list of nested for loops. This can be better understood by trying to see the execution pattern of a sequence of nested for loops.
For example lets say you have, as you presented, a sequence of 3 fors and the code execution has reached the third level (the innermost). After this goes through all its iterations you return to the second level for where you go to the next iteration in which you jump again in third level for. Similarly, when the second level finishes all its iteration you jump back to the first level for which continues with the next iteration in which you jump in the second level and from there in the third.
So, in a given level you try go to the deeper one (if there is one) and if there are no more iterations you go back a level (back track).
Using the backtracking you represent the nested for by an array where each element is an index variable: array[0] is the index for for level 0, and so on.
Here is a sample implementation for your problem:
#define NUMBER_OF_OBJECTS 10
#define FORLOOP_DEPTH 4 // This is equivalent with the number of
// of nested fors and in the problem is
// the number of requested objects
#define FORLOOP_ARRAY_INIT -1 // This is a init value for each "forloop" variable
#define true 1
#define false 0
typedef int bool;
int main(void)
{
int object_prices[NUMBER_OF_OBJECTS];
int forLoopsArray[FORLOOP_DEPTH];
bool isLoopVariableValueUsed[NUMBER_OF_OBJECTS];
int forLoopLevel = 0;
for (int i = 0; i < FORLOOP_DEPTH; i++)
{
forLoopsArray[i] = FORLOOP_ARRAY_INIT;
}
for (int i = 0; i < NUMBER_OF_OBJECTS; i++)
{
isLoopVariableValueUsed[i] = false;
}
forLoopLevel = 0; // Start from level zero
while (forLoopLevel >= 0)
{
bool isOkVal = false;
if (forLoopsArray[forLoopLevel] != FORLOOP_ARRAY_INIT)
{
// We'll mark the loopvariable value from the last iterration unused
// since we'll use a new one (in this iterration)
isLoopVariableValueUsed[forLoopsArray[forLoopLevel]] = false;
}
/* All iterations (in all levels) start basically from zero
* Because of that here I check that the loop variable for this level
* is different than the previous ones or try the next value otherwise
*/
while ( isOkVal == false
&& forLoopsArray[forLoopLevel] < (NUMBER_OF_OBJECTS - 1))
{
forLoopsArray[forLoopLevel]++; // Try a new value
if (loopVariableValueUsed[forLoopsArray[forLoopLevel]] == false)
{
objectUsed[forLoopsArray[forLoopLevel]] = true;
isOkVal = true;
}
}
if (isOkVal == true) // Have we found in this level an different item?
{
if (forLoopLevel == FORLOOP_DEPTH - 1) // Is it the innermost?
{
/* Here is the innermost level where you can test
* if the sum of all selected items is smaller than
* the target
*/
}
else // Nope, go a level deeper
{
forLoopLevel++;
}
}
else // We've run out of values in this level, go back
{
forLoopsArray[forLoopLevel] = FORLOOP_ARRAY_INIT;
forLoopLevel--;
}
}
}
Context : I'm searching for all the words contained in a 2d array (horizontally,vertically and diagonaly).
So what I do is I get all the possible words, check if they're in the given dictionary and if they are store them in an array. The thing is, I don't want it to have duplicates.
Here's a snippet of the code:
for (i=l-1;i>=0;i--){
palavra[aux]=mat[i][caux];
for (j=i;j>=0;j--){
palavra[aux]=mat[j][caux];
palavra[aux+1]='\0';
for (it=0;encontradas[it]!=NULL;it++){
if (strcmp(palavra,encontradas[it])==0)flag=1;
else flag=0;
}
if (flag==0) {
r = palavra_existe(dic,palavra);
if (r!=0) {
found[auxenc]=mystrdup(palavra);
auxenc++;
}
}
flag=0;
aux++;
}
aux=0;
}
The
if (strcmp(palavra, found[it])==0)flag=1
line is there to check if the formed worded has been found already, to avoid creating a duplicate. The problem is it doesn't work, duplicates appear anyway (as the flag variable never takes the value 1).
What could I be missing here?
The flag variable does get the value 1, but then it turns back to 0 again in the next iteration.
Set flag to zero before the loop, and when you find a match you set it to 1 and exit the loop:
flag = 0;
for (it = 0; encontradas[it] != NULL; it++) {
if (strcmp(palavra,encontradas[it]) == 0) {
flag=1;
break;
}
}
(Exiting the loop isn't needed for the logic to work, but there is no point in looping through the rest of the items once you have found a match.)