Move along a path of points with even speed - algorithm

I have a sequence of points and i have an object that should move along the path described by these points.
I know that i need to find the corresponding segment depending on the time, but i dont know how to do this precisely.
Note that the speed should be constant along the path, so you have to take the distance of a segment into account.

Something like this? To find the segment at a particular time, loop through all the segments, add the length of the segment until you reach the target time.
public int findSegment(int [] segments, int time) {
time_so_far = 0;
int i = 0;
while (time_so_far < time) {
time_so_far += segments[i];
i++;
}
return i-1;
}
If the segment lengths are distances, and you are considering a speed that isn't 1, then you'd need to do time_so_far += segments[i] / speed

Beofre start assign time moments to each point: the first point gets time=0, every next point gets time[i+1]=time[i]+distance(i,i+1)/velocity.
Then for each time moment you can calculate position in the following way:
Find first point, for which time[i]<=current_time
Find exact position: point[i]+(current_time-time[i])*(point[i+1]-point[i])

Related

Standard Algorithm for subdividing a grid into smaller and smaller parts

I'm running a simulation over a grid of parameters and I'd like to run it for as long as possible, but I don't know yet when the simulation will be terminated (think power cut). So what I'd like to do is specify the min and max values for each parameter and then let the loop pick the next best point on the grid, regularly saving the current result.
So given in 1d space a parameter a from 0 to 1 I'd like the loop to simulate for values 0, 1, 0.5, 0.75, 0.25, 0.875, 0.625, 0.375, 0.125, ... The exact order does not matter too much, as long as the next point always lies in between the previous ones.
So probably I could come up with some piece of code that generates this sequence, but I'm wondering if there are standard formulations for such an algorithm, especially for higher dimensional spaces?
One way to achieve this in one dimension is to maintain a binary tree, where each node keeps track of an interval, and its midpoint.
The left child of a node contains the left half of its interval, and the right child contains the right half.
Performing a breadth-first search in such a tree and keeping track of all the mid points of the traversed nodes, will yield the sequence you are after.
For several dimensions, depending on your needs, you can e.g. keep track of one such tree for each dimension, and generate your parameters in the order you like.
In practice this can be implemented using lazy initialisation and a queue to perform the BFS.
To demonstrate (but in practice, you would do it in a more memory-efficient way), I've added a simple binary tree DFS implementation in JavaScript (since it can be tried in the browser):
class Node {
constructor(min, max) {
this.min = min;
this.max = max;
this.mid = (min + max) / 2;
}
get left() { return new Node(this.min, this.mid); }
get right() { return new Node(this.mid, this.max); }
}
function getSequence(start, end, n) {
const res = [start, end];
const queue = [new Node(start, end)];
for (let i=0; i<n; ++i) {
const n = queue.shift();
res.push(n.mid);
queue.push(n.right, n.left);
}
return res;
}
getSequence(0, 1, 100);

What is a greedy algorithm for this problem that is minimally optimal + proof?

The details are a bit cringe, fair warning lol:
I want to set up meters on the floor of my building to catch someone; assume my floor is a number line from 0 to length L. The specific type of meter I am designing has a radius of detection that is 4.7 meters in the -x and +x direction (diameter of 9.4 meters of detection). I want to set them up in such a way that if the person I am trying to find steps foot anywhere in the floor, I will know. However, I can't just setup a meter anywhere (it may annoy other residents); therefore, there are only n valid locations that I can setup a meter. Additionally, these meters are expensive and time consuming to make, so I would like to use as few as possible.
For simplicity, you can assume the meter has 0 width, and that each valid location is just a point on the number line aformentioned. What is a greedy algorithm that places as few meters as possible, while being able to detect the entire hallway of length L like I want it to, or, if detecting the entire hallway is not possible, will output false for the set of n locations I have (and, if it isn't able to detect the whole hallway, still uses as few meters as possible while attempting to do so)?
Edit: some clarification on being able to detect the entire hallway or not
Given:
L (hallway length)
a list of N valid positions to place a meter (p_0 ... p_N-1) of radius 4.7
You can determine in O(N) either a valid and minimal ("good") covering of the whole hallway or a proof that no such covering exists given the constraints as follows (pseudo-code):
// total = total length;
// start = current starting position, initially 0
// possible = list of possible meter positions
// placed = list of (optimal) meter placements, initially empty
boolean solve(float total, float start, List<Float> possible, List<Float> placed):
if (total-start <= 0):
return true; // problem solved with no additional meters - woo!
else:
Float next = extractFurthestWithinRange(start, possible, 4.7);
if (next == null):
return false; // no way to cover end of hall: report failure
else:
placed.add(next); // placement decided
return solve(total, next + 4.7, possible, placed);
Where extractFurthestWithinRange(float start, List<Float> candidates, float range) returns null if there are no candidates within range of start, or returns the last position p in candidates such that p <= start + range -- and also removes p, and all candidates c such that p >= c.
The key here is that, by always choosing to place a meter in the next position that a) leaves no gaps and b) is furthest from the previously-placed position we are simultaneously creating a valid covering (= no gaps) and an optimal covering (= no possible valid covering could have used less meters - because our gaps are already as wide as possible). At each iteration, we either completely solve the problem, or take a greedy bite to reduce it to a (guaranteed) smaller problem.
Note that there can be other optimal coverings with different meter positions, but they will use the exact same number of meters as those returned from this pseudo-code. For example, if you adapt the code to start from the end of the hallway instead of from the start, the covering would still be good, but the gaps could be rearranged. Indeed, if you need the lexicographically minimal optimal covering, you should use the adapted algorithm that places meters starting from the end:
// remaining = length (starts at hallway length)
// possible = positions to place meters at, starting by closest to end of hallway
// placed = positions where meters have been placed
boolean solve(float remaining, List<Float> possible, Queue<Float> placed):
if (remaining <= 0):
return true; // problem solved with no additional meters - woo!
else:
// extracts points p up to and including p such that p >= remaining - range
Float next = extractFurthestWithinRange2(remaining, possible, 4.7);
if (next == null):
return false; // no way to cover start of hall: report failure
else:
placed.add(next); // placement decided
return solve(next - 4.7, possible, placed);
To prove that your solution is optimal if it is found, you merely have to prove that it finds the lexicographically last optimal solution.
And you do that by induction on the size of the lexicographically last optimal solution. The case of a zero length floor and no monitor is trivial. Otherwise you demonstrate that you found the first element of the lexicographically last solution. And covering the rest of the line with the remaining elements is your induction step.
Technical note, for this to work you have to be allowed to place monitoring stations outside of the line.

stuck on minimax algorithm

I'm attempting my first chess engine. Anyone who is familiar with the subject will know a thing or two about the minimax algorithm. I need to generate a combination of every possible move on the board for every piece. I've looked up a number of examples but can't get mine to work. I don't know what I am doing wrong. I'm just focused on the generation of every possible moves, to a certain depth, to get the leaf nodes.
The problem I'm facing is that my current implementation is making one move for black then making continuous moves for white without letting the black move again when it should be alternating back and fourth. I use Direct recursion to and loop through the available moves. I expect the function to start from the top every time but the direct recursion isn't working the way I thought it would. The loop keeps getting iterated through without starting from the top of the function and I don't know why. This means that the getAvailableMoves(maximizer) isn't being called every time like it should be (I think).
if anyone could point out what I'm doing wrong it would be appreciated.
public int miniMax(int depth, boolean maximizer)
{
if(depth == 0) { return 1234; }
int countMoves = 0;
Map<ChessPiece, Position> availableMoves = getAvailableMoves(maximizer);
int bestMove = 0;
for(Map.Entry<ChessPiece, Position> entry : availableMoves.entrySet())
{
ChessPiece piece = entry.getKey();
Position pos = entry.getValue();
piece.move(board, pos.getX(), pos.getY());
maximizer = !maximizer;
miniMax(depth-1, maximizer);
}
return 1234;
}

Weighted Interval Scheduling: How to capture *all* maximal fits, not just a single maximal fit?

In the weighted interval scheduling problem, one has a sequence of intervals {i_1, i_2, ..., i_n} where each interval i_x represents a contiguous range (in my case, a range of non-negative integers; for example i_x = [5,9)). The usual goal is to set the weight of each interval equal to its width, and then determine the subset of non-overlapping intervals whose total weight is a maximum. An excellent solution is given at the link I just provided.
I have implemented the solution in C++, starting with the algorithm provided at the given link (which is written in Python in a GitHub repository here.
However, the current solution at the link given - and everywhere else I have seen it discussed - only provides a way to capture a single maximal fit. Of course, in some cases there can be multiple maximal fits, each with the same total (globally maximal) weight.
I have implemented a "brute force" approach to capturing all maximal fits, which I describe below.
However, before discussing the specific details of the brute force approach I've used, the key problem in my brute force approach that I'd like resolved is that my brute-force approach captures many false positives, in addition to the true maximal fits. It is not necessary to delve into the specifics of my brute-force approach if you can just answer the following question:
I'd like to know what is the (or a) most efficient enhancement to the basic O(n log(n)) solution that supports capturing all maximal fits, rather than just one maximal fit (but if anyone can answer how to avoid false positives, that will also satisfy me).
I am making no progress on this, and the brute force approach I'm using starts to explode unmanageably in cases where there are in excess of thousands (perhaps less) maximal fits.
Thank you!
Details of the brute force approach I am using, only if interested or useful:
There is a single line of code in the existing source code I've linked above that is responsible for the fact that the algorithm selects a single maximal fit, rather than proceeding down a path where it could capture all maximal fits. Click here to see that line of code. Here it is:
if I[j].weight + OPT[p[j]] > OPT[j - 1]:
Notice the > (greater than sign). This line of code successfully guarantees that any interval combination with a higher total weight than any other interval combination for the given sub-problem is kept. By changing > to >=, it is possible to capture scenarios where the current interval set under consideration has an equal total weight to the highest previous total weight, which would make it possible to capture all maximal fits. I wish to capture this scenario, so in my C++ migration I used the >= and, in the case where equality holds, I proceed down both paths in the fork via a recursive function call.
Below is the C++ code for the (critical) function that captures all optimum interval sets (and weights) for each sub-problem (noting that the final solution is obtained at the last index where the sub-problem corresponds to the entire problem).
Please note that OPTs is a list of all potential solutions (maximal interval sets) (i.e., each element of OPTs is itself a single complete solution of all sub-problems consisting of a set of intervals and a corresponding weight for every sub-problem), while OPT is used to describe a single such complete solution - a potential maximal fit with all intervals used to construct it, one for each sub-problem.
For the standard solution of the weighted interval scheduling problem that I've indicated above, the solution obtained is just OPT (a single one, not a list).
The RangeElement type in the code below is simply metadata unrelated to the problem I'm discussing.
RangesVec contains the set of intervals that is the input to the problem (properly sorted by ending value). PreviousIntervalVec corresponds to compute_previous_intervals discussed at the link above.
(Note: For anybody who is looking at the Python code linked above, please note that I think I have found a bug in it related to saving intervals in the maximal set; please see here for a comment about this bug, which I've fixed in my C++ code below.)
Here is my 'brute-force' implementation that captures all maximal fits. My brute force approach also captures some false positives that need to be removed at the end, and I would be satisfied with any answer that gives a most efficient approach to exclude false positives but otherwise uses an algorithm equivalent to the one below.
void CalculateOPTs(std::vector<std::pair<INDEX_TYPE, std::vector<RangeElement const *>>> & OPT, size_t const starting_index = 0)
{
++forks;
for (size_t index = starting_index; index < RangesVec.size(); ++index)
{
INDEX_TYPE max_weight_to_be_set_at_current_index {};
INDEX_TYPE max_weight_previous_index {};
INDEX_TYPE max_weight_previously_calculated_at_previous_interval {};
INDEX_TYPE current_index_weight = RangesVec[index]->range.second - RangesVec[index]->range.first;
if (index > 0)
{
max_weight_previous_index = OPT[index - 1].first;
}
size_t previous_interval_plus_one = PreviousIntervalVec[index];
if (previous_interval_plus_one > 0)
{
max_weight_previously_calculated_at_previous_interval = OPT[previous_interval_plus_one - 1].first;
}
INDEX_TYPE weight_accepting_current_index = current_index_weight + max_weight_previously_calculated_at_previous_interval;
INDEX_TYPE weight_rejecting_current_index = max_weight_previous_index;
max_weight_to_be_set_at_current_index = std::max(weight_accepting_current_index, weight_rejecting_current_index);
//if (false && weight_accepting_current_index == weight_rejecting_current_index)
if (weight_accepting_current_index == weight_rejecting_current_index)
{
// ***************************************************************************************** //
// Fork!
// ***************************************************************************************** //
// ***************************************************************************************** //
// This is one of the two paths of the fork, accessed by calling the current function recursively
// ***************************************************************************************** //
// There are two equal combinations of intervals with an equal weight.
// Follow the path that *rejects* the interval at the current index.
if (index == 0)
{
// The only way for the previous weight to equal the current weight, given that the current weight cannot be 0,
// is if previous weight is also not 0, which cannot be the case if index == 0
BOOST_THROW_EXCEPTION(std::exception((boost::format("Logic error: Forking a maximal fitting path at index == 0")).str().c_str()));
}
std::vector<std::pair<INDEX_TYPE, std::vector<RangeElement const *>>> newOPT = OPT;
OPTs.emplace_back(newOPT);
OPTs.back().push_back(std::make_pair(weight_rejecting_current_index, std::vector<RangeElement const *>())); // std::max returns first value if the two values are equal; so here create a fork using the second value
OPTs.back()[index].second = OPTs.back()[index-1].second; // The current index is being rejected, so the current set of intervals remains the same for this index as for the previous
CalculateOPTs(OPTs.back(), index + 1);
}
// ***************************************************************************************** //
// If we forked, this is the other path of the fork, which is followed after the first fork, above, exits.
// If we didn't fork, we proceed straight through here anyways.
// ***************************************************************************************** //
OPT.push_back(std::make_pair(max_weight_to_be_set_at_current_index, std::vector<RangeElement const *>()));
if (max_weight_to_be_set_at_current_index == weight_accepting_current_index)
{
// We are accepting the current interval as part of a maximal fitting, so track it.
//
// Note: this also works in the forking case that hit the previous "if" block,
// because this code represents the alternative fork.
//
// We here set the intervals associated with the current index
// equal to the intervals associated with PreviousIntervalVec[index] - 1,
// and then append the current interval.
//
// If there is no preceding interval, then leave the "previous interval"'s
// contribution empty (from the line just above where an empty vector was added),
// and just append the current interval (as the first).
if (previous_interval_plus_one > 0)
{
OPT.back().second = OPT[previous_interval_plus_one - 1].second;
}
OPT.back().second.push_back(RangesVec[index]); // We are accepting the current interval as part of the maximal set, so add the corresponding interval here
}
else
{
if (index == 0)
{
// If index is 0, we should always accept the current interval, not reject, so we shouldn't be here in that case
BOOST_THROW_EXCEPTION(std::exception((boost::format("Logic error: Rejecting current interval at index == 0")).str().c_str()));
}
// We are rejecting the current interval, so set the intervals associated with this index
// equal to the intervals associated with the previous index
OPT.back().second = OPT[index - 1].second;
}
}
}
When there is an equal weight optimal subsolution, you need to add the next interval to every subsolution, I don't see this happening. The general form would look like this
function go(lastend){
for(i=0;i<n;i++){
if(interval[i].start>lastend){
optimalsubs = go(interval[i].end)
if optimalsubs.cost + interval[i].cost > optimal.cost {
for(os in optimalsubs){
os.add(interval[i])
}
optimal = optimalsubs
optimal.cost = optimalsubs.cost + interval[i].cost
}
else if equal{
for(os in optimalsubs){
os.add(interval[i])
}
optimal.append(optimalsubs)
}
}
}
return optimal
}

Algorithm to find out all the possible positions

I need an algorithm to find out all the possible positions of a group of pieces in a chessboard. Like finding all the possible combinations of the positions of a number N of pieces.
For example in a chessboard numbered like cartesian coordinate systems any piece would be in a position
(x,y) where 1 <= x <= 8 and 1 <= y <= 8
I'd like to get an algorithm which can calculate for example for 3 pieces all the possible positions of the pieces in the board. But I don't know how can I get them in any order. I can get all the possible positions of a single piece but I don't know how to mix them with more pieces.
for(int i = 0; i<= 8; i++){
for(int j = 0; j<= 8; j++){
System.out.println("Position: x:"+i+", y:"+j);
}
}
How can I get a good algoritm to find all the posible positions of the pieces in a chessboard?
Thanks.
You got 8x8 board, so total of 64 squares.
Populate a list containing these 64 sqaures [let it be list], and find all of the possibilities recursively: Each step will "guess" one point, and invoke the recursve call to find the other points.
Pseudo code:
choose(list,numPieces,sol):
if (sol.length == numPieces): //base clause: print the possible solution
print sol
return
for each point in list:
sol.append(point) //append the point to the end of sol
list.remove(point)
choose(list,numPieces,sol) //recursive call
list.add(point) //clean up environment before next recursive call
sol.removeLast()
invoke with choose(list,numPieces,[]) where list is the pre-populated list with 64 elements, and numPieces is the pieces you are going to place.
Note: This solution assumes pieces are not identical, so [(1,2),(2,1)] and [(2,1),(1,2)] are both good different solutions.
EDIT:
Just a word about complexity, since there are (n^2)!/(n^2-k)! possible solutions for your problem - and you are looking for all of them, any algorithm will suffer from exponential run time, so trying to invoke it with just 10 pieces, will take ~400 years
[In the above notation, n is the width and length of the board, and k is the number of pieces]
You can use a recursive algorithm to generate all possiblities:
void combine(String instr, StringBuffer outstr, int index)
{
for (int i = index; i < instr.length(); i++)
{
outstr.append(instr.charAt(i));
System.out.println(outstr);
combine(instr, outstr, i + 1);
outstr.deleteCharAt(outstr.length() - 1);
}
}
combine("abc", new StringBuffer(), 0);
As I understand you should consider that some firgure may come block some potential position for figures that can reach them on the empty board. I guess it is the most tricky part.
So you should build some set of vertexes (set of board states) that is reached from some single vertex (initial board state).
The first algorithm that comes to my mind:
Pre-conditions:
Order figures in some way to form circle.
Assume initial set of board states (S0) to contain single element which represents inital board state.
Actions
Choose next figure to extend set of possible positions
For each state of board within S(n) walk depth-first all possible movements that new board states and call it F(n) (frame).
Form S(n+1) = S(n) ∪ F(n).
Repeat steps till all frames of updates during whole circle pass will not be empty.
This is kind of mix breath-first and depth-first search

Resources