Path planning to get close to an unreachable target - path-finding

I'm working on a game which has tank battles on a tiled map. If a tank is on a cell, that cell is considered unpassable in the A* algorithm, therefore, whenever an unit needs to attack another, I need to plan a path which brings the attacker into range (if range=1, then next to the target).
Currently, I use an iterative approach with increasing radius to find a path to a nearby cell and choose a cell which minimizes the A-Cell-B distance. Unfortunately, this is slow for one unit, not to mention for 50 units.
Is there a way to extract a partial path from a regular A* search data structures?
Just for reference, here is the implementation I have.
Set<T> closedSet = U.newHashSet();
Map<T, T> cameFrom = U.newHashMap();
final Map<T, Integer> gScore = U.newHashMap();
final Map<T, Integer> hScore = U.newHashMap();
final Map<T, Integer> fScore = U.newHashMap();
final Comparator<T> smallestF = new Comparator<T>() {
#Override
public int compare(T o1, T o2) {
int g1 = fScore.get(o1);
int g2 = fScore.get(o2);
return g1 < g2 ? -1 : (g1 > g2 ? 1 : 0);
}
};
Set<T> openSet2 = U.newHashSet();
List<T> openSet = U.newArrayList();
gScore.put(initial, 0);
hScore.put(initial, estimation.invoke(initial, destination));
fScore.put(initial, gScore.get(initial) + hScore.get(initial));
openSet.add(initial);
openSet2.add(initial);
while (!openSet.isEmpty()) {
T current = openSet.get(0);
if (current.equals(destination)) {
return reconstructPath(cameFrom, destination);
}
openSet.remove(0);
openSet2.remove(current);
closedSet.add(current);
for (T loc : neighbors.invoke(current)) {
if (!closedSet.contains(loc)) {
int tentativeScore = gScore.get(current)
+ distance.invoke(current, loc);
if (!openSet2.contains(loc)) {
cameFrom.put(loc, current);
gScore.put(loc, tentativeScore);
hScore.put(loc, estimation.invoke(loc, destination));
fScore.put(loc, gScore.get(loc) + hScore.get(loc));
openSet.add(loc);
Collections.sort(openSet, smallestF);
openSet2.add(loc);
} else
if (tentativeScore < gScore.get(loc)) {
cameFrom.put(loc, current);
gScore.put(loc, tentativeScore);
hScore.put(loc, estimation.invoke(loc, destination));
fScore.put(loc, gScore.get(loc) + hScore.get(loc));
Collections.sort(openSet, smallestF);
}
}
}
}
return Collections.emptyList();

A solution that seems to work (replacing the last return Collections.emptyList();):
// if we get here, there was no direct path available
// find a target location which minimizes initial-L-destination
if (closedSet.isEmpty()) {
return Pair.of(false, Collections.<T>emptyList());
}
T nearest = Collections.min(closedSet, new Comparator<T>() {
#Override
public int compare(T o1, T o2) {
int d1 = trueDistance.invoke(destination, o1);
int d2 = trueDistance.invoke(destination, o2);
int c = U.compare(d1, d2);
if (c == 0) {
d1 = trueDistance.invoke(initial, o1);
d2 = trueDistance.invoke(initial, o2);
c = U.compare(d1, d2);
}
return c;
}
});
return Pair.of(true, reconstructPath(cameFrom, nearest));
Where the trueDistance gives the eucleidian distance of two points. (The base algorithm uses a simpler function yielding 1000 for X-X or YY neightbor, 1414 for XY neighbor).

Related

2D array traversal to get distinct 7 digit number combos

I ran into a tricky question from an interview prep book which goes..
You have a 3 by 3 matrix containing integers 1 to 9 as shown below
1 2 3
4 5 6
7 8 9
How do you get unique 7 digit number combos with the first numbers all starting with 4 (matrix[1][0]). The traversal is meant to be like that of a rook on a chess board.. 1 way either horizontally or vertically...(Having 4125874 is valid 7 digit combo btw).
I tried writing some code and doing regular 2D matrix traversal with a boolean visited flag here to get an answer and storing each combo in a hashSet to ensure uniqueness but I am stuck. Any kind comments, hints and code revisions to get me code working would be appreciated.
class Ideone
{
void dfs(int[][] matrix, boolean visited) //considered dfs with a boolean visited flag but I am stuck. I want to make my solution recursive
{
boolean visited = false;
}
public static HashSet<String> get7DigitCombo(int[][] matrix)
{
String result = "";
int[][] cache = matrix.clone();
Set<String> comboSet = new HashSet<String>();
boolean visited = false;
int resultStart = matrix[1][0];
for(int row = 1; row < matrix.length; row++)
{
for(int col = 0; col < matrix[0].length; col++)
{
if (visited == false & result.length < 7)
{
result += "" + (matrix[row + 1][col] || matrix[row -1][col] || matrix[row][col+1] || matrix[row][col-1]);
}
}
}
comboSet.add(result);
return comboSet;
}
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int[][] matrix = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
};
HashSet<String> comboSet = get7DigitCombo(matrix);
System.out.print(comboSet);
}
}
The following mcve demonstrates recursively getting neighbors and accumulating then into
unique combinations.
The code is documented with comments:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Ideone
{
private static final int SIZE = 7; //size of combo
private static int[][] directions = { //represents moving directions
{-1, 0}, //up
{ 0,-1}, //left
{ 0, 1}, //right
{ 1, 0} //down
};
public static void main (String[] args) throws java.lang.Exception
{
int[][] matrix = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
};
Set<String> comboSet = get7DigitCombo(matrix);
System.out.print(comboSet.size());
}
public static Set<String> get7DigitCombo(int[][] matrix)
{
Set<String> comboSet = new HashSet<>();
get7DigitCombo(1, 0, matrix, String.valueOf(matrix[1][0]), comboSet);
return comboSet;
}
//recursively get all neighbors. generate combos by appending each neighbor
//combo represents a single combination. combos accumulates combination
static void get7DigitCombo(int row, int col, int[][] matrix, String combo, Set<String> combos){
if(combo !=null && combo.length() == SIZE) { //when combo reached the right size, add it
//System.out.println(combo);
combos.add(combo);
return;
}
//get and iterate over all adjacent neighbors
for(int[] neighbor : getNeighbors(row, col, matrix)){
get7DigitCombo(neighbor[0], neighbor[1], matrix, combo+neighbor[2], combos);
}
}
//return list of adjacent neighbors. each neighbor is represented by
//int[3]: row, column, value
private static List<int[]> getNeighbors(int row, int col, int[][] matrix) {
List<int[]> neighbors = new ArrayList<>();
for(int[] dir : directions){
int newRow = row + dir[0] ; int newCol = col + dir[1];
if(isValidAddress(newRow, newCol, matrix)) {
neighbors.add( new int[]{newRow,newCol, matrix[newRow][newCol]});
}
}
return neighbors;
}
private static boolean isValidAddress(int row, int col, int[][] matrix) {
if(row < 0 || col < 0) return false;
if(row >= matrix.length || col >= matrix[row].length) return false;
return true;
}
}
This is a pacman problem.
You must look for or define the neighbors of each matrix value.
Then cross the matrix fallowing the neighbors of each matrix value.
It usually resolves with recursive functions.
I think you code must be change from the ground using a different approach.

Kinect skeleton Scaling strange behaviour

I am trying to scale a skeleton to match to the sizes of another skeleton.
My algoritm do the following:
Find the distance between two joints of the origin skeleton and the destiny skeleton using phytagorean teorem
divide this two distances to find a multiply factor.
Multiply each joint by this factor.
Here is my actual code:
public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny)
{
Joint newJoint = new Joint();
double distanciaOrigem = 0;
double distanciaDestino = 0;
double fator = 1;
SkeletonPoint pos = new SkeletonPoint();
foreach (BoneOrientation bo in skToBeScaled.BoneOrientations)
{
distanciaOrigem = FisioKinectCalcs.Distance3DBetweenJoint(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]);
distanciaDestino = FisioKinectCalcs.Distance3DBetweenJoint(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]);
if (distanciaOrigem > 0 && distanciaDestino > 0)
{
fator = (distanciaDestino / distanciaOrigem);
newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges.
// applying the new values to the joint
pos = new SkeletonPoint()
{
X = (float)(newJoint.Position.X * fator),
Y = (float)(newJoint.Position.Y * fator),
Z = (float)(newJoint.Position.Z * fator)
};
newJoint.Position = pos;
skToBeScaled.Joints[bo.EndJoint] = newJoint;
}
}
return skToBeScaled;
}
Every seems to work fine except for the hands and foots
Look at this images
I have my own skeleton over me, and my skeleton scaled to the sizes of another person, but the hands and foots still crazy. (but code looks right)
Any suggestion?
It's hard to say without running the code, but it somewhat "looks good".
What I would validate though, is your
if (distanciaOrigem > 0 && distanciaDestino > 0)
If distanciaOrigem is very close to 0, but even just epsilon away from 0, it won't be picked up by the if, and then
fator = (distanciaDestino / distanciaOrigem);
Will result in a very large number!
I would suggest to smooth the factor so it generally fits the proper scale. Try this code:
private static Dictionary<JointType, double> jointFactors = null;
static CalibrationUtils()
{
InitJointFactors();
}
public static class EnumUtil
{
public static IEnumerable<T> GetValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
private static void InitJointFactors()
{
var jointTypes = EnumUtil.GetValues<JointType>();
jointFactors = new Dictionary<JointType, double>();
foreach(JointType type in jointTypes)
{
jointFactors.Add(type, 0);
}
}
private static double SmoothenFactor(JointType jointType, double factor, int weight)
{
double currentValue = jointFactors[jointType];
double newValue = 0;
if(currentValue != 0)
newValue = (weight * currentValue + factor) / (weight + 1);
else
newValue = factor;
jointFactors[jointType] = newValue;
return newValue;
}
When it comes to factor usage just use the SmoothenFactor method first:
public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny, double additionalFactor = 1)
{
Joint newJoint = new Joint();
double distanceToScale = 0;
double distanceDestiny = 0;
double factor = 1;
int weight = 500;
SkeletonPoint pos = new SkeletonPoint();
Skeleton newSkeleton = null;
KinectHelper.CopySkeleton(skToBeScaled, ref newSkeleton);
SkeletonPoint hipCenterPosition = newSkeleton.Joints[JointType.HipCenter].Position;
foreach(BoneOrientation bo in skToBeScaled.BoneOrientations)
{
distanceToScale = Distance3DBetweenJoints(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]);
distanceDestiny = Distance3DBetweenJoints(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]);
if(distanceToScale > 0 && distanceDestiny > 0)
{
factor = (distanceDestiny / distanceToScale) * additionalFactor;
newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges.
factor = SmoothenFactor(newJoint.JointType, factor, weight);
pos = new SkeletonPoint()
{
X = (float)((newJoint.Position.X - hipCenterPosition.X) * factor + hipCenterPosition.X),
Y = (float)((newJoint.Position.Y - hipCenterPosition.Y) * factor + hipCenterPosition.Y),
Z = (float)((newJoint.Position.Z - hipCenterPosition.Z) * factor + hipCenterPosition.Z)
};
newJoint.Position = pos;
newSkeleton.Joints[bo.EndJoint] = newJoint;
}
}
return newSkeleton;
}
I also modified your ScaleToMatch method as you see. There was a need to move joints in relation to HipCenter position. Also new positions are saved to a new Skeleton instance so they are not used in further vector calculations.
Experiment with the weight but since our bones length is constant you can use big numbers like 100 and more to be sure that wrong Kinect readings do not disturb the correct scale.
Here's an example of how it helped with scaling HandRight joint position:
The weight was set to 500. The resulting factor is supposed to be around 2 (because the base skeleton was purposely downscaled by a factor of 2).
I hope it helps!

Recursively searching a tree to get the binary coding for a character

Hi im trying to figure out how to recursively search a tree to find a character and the binary code to get to that character. basically the goal is to go find the code for the character and then write it to a file. the file writer part i can do no problem but the real problem is putting the binary code into a string. while im searching for the character. please help!
this is the code for the recursive method:
public String biNum(Frequency root, String temp, String letter)
{
//String temp = "";
boolean wentLeft = false;
if(root.getString() == null && !wentLeft)
{
if(root.left.getString() == null)
{
temp = temp + "0";
return biNum(root.left, temp, letter);
}
if(root.left.getString().equals(letter))
{
return temp = temp + "0";
}
else
{
wentLeft = true;
temp = temp.substring(0, temp.length() - 1);
return temp;
}
}
if(root.getString() == null && wentLeft)
{
if(root.right.getString() == null)
{
temp = temp + "1";
return (biNum(root.right, temp, letter));
}
if(root.right.getString().equals(letter))
{
return temp = temp + "1";
}
else
{
wentLeft = false;
temp = temp.substring(0, temp.length() - 1);
return temp;
}
}
return temp;
}
and this is the Frequency class:
package huffman;
public class Frequency implements Comparable {
private String s;
private int n;
public Frequency left;
public Frequency right;
private String biNum;
private String leaf;
Frequency(String s, int n, String biNum)
{
this.s = s;
this.n = n;
this.biNum = biNum;
}
public String getString()
{
return s;
}
public int getFreq()
{
return n;
}
public void setFreq(int n)
{
this.n = n;
}
public String getLeaf()
{
return leaf;
}
public void setLeaf()
{
this.leaf = "leaf";
}
#Override
public int compareTo(Object arg0) {
Frequency other = (Frequency)arg0;
return n < other.n ? -1 : (n == other.n ? 0 : 1);
}
}
In your updated version, I think you should re-examine return biNum(root.left, temp, letter);. Specifically, what happens if the root node of the entire tree has a left child which is not a leaf (and thus root.left.getString() == null) but the value you seek descends from the right child of the root node of the entire tree.
Consider this tree, for example:
26
/ \
/ \
/ \
11 15
/ \ / \
/ B A \
6 5 6 9
/ \ / \
D \ C sp
3 3 4 5
/ \
E F
2 1
and trace the steps your function will follow looking for the letter C.
Perhaps you should consider traversing the entire tree (and building up the pattern of 1s and 0s as you go) without looking for any specific letter but taking a particular action when you find a leaf node?

Are there any example of Mutual recursion?

Are there any examples for a recursive function that calls an other function which calls the first one too ?
Example :
function1()
{
//do something
function2();
//do something
}
function2()
{
//do something
function1();
//do something
}
Mutual recursion is common in code that parses mathematical expressions (and other grammars). A recursive descent parser based on the grammar below will naturally contain mutual recursion: expression-terms-term-factor-primary-expression.
expression
+ terms
- terms
terms
terms
term + terms
term - terms
term
factor
factor * term
factor / term
factor
primary
primary ^ factor
primary
( expression )
number
name
name ( expression )
The proper term for this is Mutual Recursion.
http://en.wikipedia.org/wiki/Mutual_recursion
There's an example on that page, I'll reproduce here in Java:
boolean even( int number )
{
if( number == 0 )
return true;
else
return odd(abs(number)-1)
}
boolean odd( int number )
{
if( number == 0 )
return false;
else
return even(abs(number)-1);
}
Where abs( n ) means return the absolute value of a number.
Clearly this is not efficient, just to demonstrate a point.
An example might be the minmax algorithm commonly used in game programs such as chess. Starting at the top of the game tree, the goal is to find the maximum value of all the nodes at the level below, whose values are defined as the minimum of the values of the nodes below that, whose values are defines as the maximum of the values below that, whose values ...
I can think of two common sources of mutual recursion.
Functions dealing with mutually recursive types
Consider an Abstract Syntax Tree (AST) that keeps position information in every node. The type might look like this:
type Expr =
| Int of int
| Var of string
| Add of ExprAux * ExprAux
and ExprAux = Expr of int * Expr
The easiest way to write functions that manipulate values of these types is to write mutually recursive functions. For example, a function to find the set of free variables:
let rec freeVariables = function
| Int n -> Set.empty
| Var x -> Set.singleton x
| Add(f, g) -> Set.union (freeVariablesAux f) (freeVariablesAux g)
and freeVariablesAux (Expr(loc, e)) =
freeVariables e
State machines
Consider a state machine that is either on, off or paused with instructions to start, stop, pause and resume (F# code):
type Instruction = Start | Stop | Pause | Resume
The state machine might be written as mutually recursive functions with one function for each state:
type State = State of (Instruction -> State)
let rec isOff = function
| Start -> State isOn
| _ -> State isOff
and isOn = function
| Stop -> State isOff
| Pause -> State isPaused
| _ -> State isOn
and isPaused = function
| Stop -> State isOff
| Resume -> State isOn
| _ -> State isPaused
It's a bit contrived and not very efficient, but you could do this with a function to calculate Fibbonacci numbers as in:
fib2(n) { return fib(n-2); }
fib1(n) { return fib(n-1); }
fib(n)
{
if (n>1)
return fib1(n) + fib2(n);
else
return 1;
}
In this case its efficiency can be dramatically enhanced if the language supports memoization
In a language with proper tail calls, Mutual Tail Recursion is a very natural way of implementing automata.
Here is my coded solution. For a calculator app that performs *,/,- operations using mutual recursion. It also checks for brackets (()) to decide the order of precedence.
Flow:: expression -> term -> factor -> expression
Calculator.h
#ifndef CALCULATOR_H_
#define CALCULATOR_H_
#include <string>
using namespace std;
/****** A Calculator Class holding expression, term, factor ********/
class Calculator
{
public:
/**Default Constructor*/
Calculator();
/** Parameterized Constructor common for all exception
* #aparam e exception value
* */
Calculator(char e);
/**
* Function to start computation
* #param input - input expression*/
void start(string input);
/**
* Evaluates Term*
* #param input string for term*/
double term(string& input);
/* Evaluates factor*
* #param input string for factor*/
double factor(string& input);
/* Evaluates Expression*
* #param input string for expression*/
double expression(string& input);
/* Evaluates number*
* #param input string for number*/
string number(string n);
/**
* Prints calculates value of the expression
* */
void print();
/**
* Converts char to double
* #param c input char
* */
double charTONum(const char* c);
/**
* Get error
*/
char get_value() const;
/** Reset all values*/
void reset();
private:
int lock;//set lock to check extra parenthesis
double result;// result
char error_msg;// error message
};
/**Error for unexpected string operation*/
class Unexpected_error:public Calculator
{
public:
Unexpected_error(char e):Calculator(e){};
};
/**Error for missing parenthesis*/
class Missing_parenthesis:public Calculator
{
public:
Missing_parenthesis(char e):Calculator(e){};
};
/**Error if divide by zeros*/
class DivideByZero:public Calculator{
public:
DivideByZero():Calculator(){};
};
#endif
===============================================================================
Calculator.cpp
//============================================================================
// Name : Calculator.cpp
// Author : Anurag
// Version :
// Copyright : Your copyright notice
// Description : Calculator using mutual recursion in C++, Ansi-style
//============================================================================
#include "Calculator.h"
#include <iostream>
#include <string>
#include <math.h>
#include <exception>
using namespace std;
Calculator::Calculator():lock(0),result(0),error_msg(' '){
}
Calculator::Calculator(char e):result(0), error_msg(e) {
}
char Calculator::get_value() const {
return this->error_msg;
}
void Calculator::start(string input) {
try{
result = expression(input);
print();
}catch (Unexpected_error e) {
cout<<result<<endl;
cout<<"***** Unexpected "<<e.get_value()<<endl;
}catch (Missing_parenthesis e) {
cout<<"***** Missing "<<e.get_value()<<endl;
}catch (DivideByZero e) {
cout<<"***** Division By Zero" << endl;
}
}
double Calculator::expression(string& input) {
double expression=0;
if(input.size()==0)
return 0;
expression = term(input);
if(input[0] == ' ')
input = input.substr(1);
if(input[0] == '+') {
input = input.substr(1);
expression += term(input);
}
else if(input[0] == '-') {
input = input.substr(1);
expression -= term(input);
}
if(input[0] == '%'){
result = expression;
throw Unexpected_error(input[0]);
}
if(input[0]==')' && lock<=0 )
throw Missing_parenthesis(')');
return expression;
}
double Calculator::term(string& input) {
if(input.size()==0)
return 1;
double term=1;
term = factor(input);
if(input[0] == ' ')
input = input.substr(1);
if(input[0] == '*') {
input = input.substr(1);
term = term * factor(input);
}
else if(input[0] == '/') {
input = input.substr(1);
double den = factor(input);
if(den==0) {
throw DivideByZero();
}
term = term / den;
}
return term;
}
double Calculator::factor(string& input) {
double factor=0;
if(input[0] == ' ') {
input = input.substr(1);
}
if(input[0] == '(') {
lock++;
input = input.substr(1);
factor = expression(input);
if(input[0]==')') {
lock--;
input = input.substr(1);
return factor;
}else{
throw Missing_parenthesis(')');
}
}
else if (input[0]>='0' && input[0]<='9'){
string nums = input.substr(0,1) + number(input.substr(1));
input = input.substr(nums.size());
return stod(nums);
}
else {
result = factor;
throw Unexpected_error(input[0]);
}
return factor;
}
string Calculator::number(string input) {
if(input.substr(0,2)=="E+" || input.substr(0,2)=="E-" || input.substr(0,2)=="e-" || input.substr(0,2)=="e-")
return input.substr(0,2) + number(input.substr(2));
else if((input[0]>='0' && input[0]<='9') || (input[0]=='.'))
return input.substr(0,1) + number(input.substr(1));
else
return "";
}
void Calculator::print() {
cout << result << endl;
}
void Calculator::reset(){
this->lock=0;
this->result=0;
}
int main() {
Calculator* cal = new Calculator;
string input;
cout<<"Expression? ";
getline(cin,input);
while(input!="."){
cal->start(input.substr(0,input.size()-2));
cout<<"Expression? ";
cal->reset();
getline(cin,input);
}
cout << "Done!" << endl;
return 0;
}
==============================================================
Sample input-> Expression? (42+8)*10 =
Output-> 500
Top down merge sort can use a pair of mutually recursive functions to alternate the direction of merge based on level of recursion.
For the example code below, a[] is the array to be sorted, b[] is a temporary working array. For a naive implementation of merge sort, each merge operation copies data from a[] to b[], then merges b[] back to a[], or it merges from a[] to b[], then copies from b[] back to a[]. This requires n ยท ceiling(log2(n)) copy operations. To eliminate the copy operations used for merging, the direction of merge can be alternated based on level of recursion, merge from a[] to b[], merge from b[] to a[], ..., and switch to in place insertion sort for small runs in a[], as insertion sort on small runs is faster than merge sort.
In this example, MergeSortAtoA() and MergeSortAtoB() are the mutually recursive functions.
Example java code:
static final int ISZ = 64; // use insertion sort if size <= ISZ
static void MergeSort(int a[])
{
int n = a.length;
if(n < 2)
return;
int [] b = new int[n];
MergeSortAtoA(a, b, 0, n);
}
static void MergeSortAtoA(int a[], int b[], int ll, int ee)
{
if ((ee - ll) <= ISZ){ // use insertion sort on small runs
InsertionSort(a, ll, ee);
return;
}
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoB(a, b, ll, rr);
MergeSortAtoB(a, b, rr, ee);
Merge(b, a, ll, rr, ee); // merge b to a
}
static void MergeSortAtoB(int a[], int b[], int ll, int ee)
{
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoA(a, b, ll, rr);
MergeSortAtoA(a, b, rr, ee);
Merge(a, b, ll, rr, ee); // merge a to b
}
static void Merge(int a[], int b[], int ll, int rr, int ee)
{
int o = ll; // b[] index
int l = ll; // a[] left index
int r = rr; // a[] right index
while(true){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}
static void InsertionSort(int a[], int ll, int ee)
{
int i, j;
int t;
for (j = ll + 1; j < ee; j++) {
t = a[j];
i = j-1;
while(i >= ll && a[i] > t){
a[i+1] = a[i];
i--;
}
a[i+1] = t;
}
}

Formula for the max number of paths through a grid?

Given a grid of open spots, and a certain number of tiles to place in those spots, what function f(openSpots, tilesToPlace) will give you the number of continuous paths you can form?
Continuous paths are placements of the tiles such that each tile shares an edge with another. (Only corners touching is not good enough. So (0, 1) and (0, 0) are legal, but (1, 1) and (2, 2) is not.)
I already have a function that will find all these paths. However, it only works for small numbers. For larger values, all I need is a count of how many could possibly exist. Here is some data:
For 1 tiles, there are 1 paths.
For 2 tiles, there are 4 paths.
For 3 tiles, there are 22 paths.
For 4 tiles, there are 89 paths.
For 5 tiles, there are 390 paths.
For 6 tiles, there are 1476 paths.
For 7 tiles, there are 5616 paths.
For 8 tiles, there are 19734 paths.
For 9 tiles, there are 69555 paths.
This gets really slow to calculate as the puzzle size increases. I think the asymptotic complexity of my path finding solution is pretty bad.
If there are n tiles, the grid is at most n spots long and wide.
Your problem seems to be at least as difficult as enumerating polyominoes. There are no known fast algorithms for doing this, and the best known algorithms struggle after n=50. I doubt there is a fast way to solve this problem.
I'm not even going to pretend that this is an optimal solution but it might be useful as a reference solution. I think it at least gives the correct answer, although it takes some time. It solves the problem recursively by finding all paths of length n-1, then checking for all possible places it can add one more tile and removing duplicate solutions. It has a particularly ugly part where it checks for duplicate by converting the path to a string and comparing the strings, but it was fast to write.
Here's the output it generates:
n = 1, number of paths found = 1
n = 2, number of paths found = 4
n = 3, number of paths found = 22
n = 4, number of paths found = 113
n = 5, number of paths found = 571
n = 6, number of paths found = 2816
n = 7, number of paths found = 13616
n = 8, number of paths found = 64678
n = 9, number of paths found = 302574
And here's the code:
using System;
using System.Collections.Generic;
using System.Linq;
public struct Tile
{
public Tile(int x, int y) { X = x; Y = y; }
public readonly int X;
public readonly int Y;
public IEnumerable<Tile> GetNeighbours(int gridSize)
{
if (X > 0)
yield return new Tile(X - 1, Y);
if (X < gridSize - 1)
yield return new Tile(X + 1, Y);
if (Y > 0)
yield return new Tile(X, Y - 1);
if (Y < gridSize - 1)
yield return new Tile(X, Y + 1);
}
public override string ToString()
{
return string.Format("({0},{1})", X, Y);
}
}
public class Path
{
public Path(Tile[] tiles) { Tiles = tiles; }
public Tile[] Tiles { get; private set; }
public override string ToString()
{
return string.Join("", Tiles.Select(tile => tile.ToString()).ToArray());
}
}
public class PathFinder
{
public IEnumerable<Path> FindPaths(int n, int gridSize)
{
if (n == 1)
{
for (int x = 0; x < gridSize; ++x)
for (int y = 0; y < gridSize; ++y)
yield return new Path(new Tile[] { new Tile(x, y) });
}
else
{
Dictionary<string, object> pathsSeen = new Dictionary<string, object>();
foreach (Path shortPath in FindPaths(n - 1, gridSize))
{
foreach (Tile tile in shortPath.Tiles)
{
foreach (Tile neighbour in tile.GetNeighbours(gridSize))
{
// Ignore tiles that are already included in the path.
if (shortPath.Tiles.Contains(neighbour))
continue;
Path newPath = new Path(shortPath.Tiles
.Concat(new Tile[] { neighbour })
.OrderBy(t => t.X)
.ThenBy(t => t.Y)
.ToArray());
string pathKey = newPath.ToString();
if (!pathsSeen.ContainsKey(pathKey))
{
pathsSeen[pathKey] = null;
yield return newPath;
}
}
}
}
}
}
static void Main()
{
PathFinder pathFinder = new PathFinder();
for (int n = 1; n <= 9; ++n)
{
List<Path> paths = pathFinder.FindPaths(n, n).ToList();
Console.WriteLine("n = {0}, number of paths found = {1}", n, paths.Count);
//foreach (Path path in paths)
// Console.WriteLine(path.ToString());
}
}
}

Resources