I have this massive array of ints from 0-4 in this triangle. I am trying to learn dynamic programming with Ruby and would like some assistance in calculating the number of paths in the triangle that meet three criterion:
You must start at one of the zero points in the row with 70 elements.
Your path can be directly above you one row (if there is a number directly above) or one row up heading diagonal to the left. One of these options is always available
The sum of the path you take to get to the zero on the first row must add up to 140.
Example, start at the second zero in the bottom row. You can move directly up to the one or diagonal left to the 4. In either case, the number you arrive at must be added to the running count of all the numbers you have visited. From the 1 you can travel to a 2 (running sum = 3) directly above or to the 0 (running sum = 1) diagonal to the left.
0
41
302
2413
13024
024130
4130241
30241302
241302413
1302413024
02413024130
413024130241
3024130241302
24130241302413
130241302413024
0241302413024130
41302413024130241
302413024130241302
2413024130241302413
13024130241302413024
024130241302413024130
4130241302413024130241
30241302413024130241302
241302413024130241302413
1302413024130241302413024
02413024130241302413024130
413024130241302413024130241
3024130241302413024130241302
24130241302413024130241302413
130241302413024130241302413024
0241302413024130241302413024130
41302413024130241302413024130241
302413024130241302413024130241302
2413024130241302413024130241302413
13024130241302413024130241302413024
024130241302413024130241302413024130
4130241302413024130241302413024130241
30241302413024130241302413024130241302
241302413024130241302413024130241302413
1302413024130241302413024130241302413024
02413024130241302413024130241302413024130
413024130241302413024130241302413024130241
3024130241302413024130241302413024130241302
24130241302413024130241302413024130241302413
130241302413024130241302413024130241302413024
0241302413024130241302413024130241302413024130
41302413024130241302413024130241302413024130241
302413024130241302413024130241302413024130241302
2413024130241302413024130241302413024130241302413
13024130241302413024130241302413024130241302413024
024130241302413024130241302413024130241302413024130
4130241302413024130241302413024130241302413024130241
30241302413024130241302413024130241302413024130241302
241302413024130241302413024130241302413024130241302413
1302413024130241302413024130241302413024130241302413024
02413024130241302413024130241302413024130241302413024130
413024130241302413024130241302413024130241302413024130241
3024130241302413024130241302413024130241302413024130241302
24130241302413024130241302413024130241302413024130241302413
130241302413024130241302413024130241302413024130241302413024
0241302413024130241302413024130241302413024130241302413024130
41302413024130241302413024130241302413024130241302413024130241
302413024130241302413024130241302413024130241302413024130241302
2413024130241302413024130241302413024130241302413024130241302413
13024130241302413024130241302413024130241302413024130241302413024
024130241302413024130241302413024130241302413024130241302413024130
4130241302413024130241302413024130241302413024130241302413024130241
30241302413024130241302413024130241302413024130241302413024130241302
241302413024130241302413024130241302413024130241302413024130241302413
1302413024130241302413024130241302413024130241302413024130241302413024
02413024130241302413024130241302413024130241302413024130241302413024130
But I like homework :)
I find it easier to reason about the 'paths' problem when starting from the top, and following the rules the other way around.
This means:
a partial path can be the top zero, or an extended partial path
the extensions of a partial path Pr,c are, unless r is the last row, in which they're complete, the union of
the extensions of Pr,c + P(r+1),c
the extensions of Pr,c + P(r+1),c+1
The 'sum' rule just selects certain of all complete paths.
Related
So I came up with a problem that I can’t logically solve. I’ve fleshed out an example;
You have a list of numbers that you need to output (e.g. 3x number 1 & 2x number 2) - we’ll call them ‘target numbers’.
You’re also given a range of source numbers (e.g. 2, 3, 4 and 5).
The task is to return all valid combinations of the source numbers that would allow you to produce the target numbers. You can use any combination and quantity of source numbers.
The constraints are that you can break a source number down to get to target numbers (e.g. you could break down a 5 into a 2 and a 3) but you cannot add source numbers together to get to a target number (for example you can’t add a 1 to a 1 to get to a 2).
Remainders are perfectly acceptable (e.g. using a source 3 to get to a target 2 and the remaining 1 is part of the combination but not ‘used’ in getting to the target).
In the interests of limiting results you’d also want to have a constraint that an acceptable combination does not contain any ‘totally unused’ source numbers [i.e. neither a result of being split nor a target number in the result)
So in the example target & source numbers given, the following results would be valid;
[1,1,1,2,2],[3,4],[3,3,1],[4,4]
But a [1,1,1,1,1,2] would not be valid, because you cannot join two source 1’s together to make a target 2.
I’ve thought about this logic and am largely thinking the solution involves some level of recursion, but the only examples I’ve seen are where the constraints are reversed (i.e. you can add source numbers together to reach a target number, but cannot split them to reach one)
What kind of logic would you use to generate all valid permutations in code?
I read a article below about Constant Propagation for hotspot through lattice .
http://www.cliffc.org/blog/2012/02/27/too-much-theory-part-2/
And it described that " (top meet -1) == -1 == (-1 meet top), so this example works. So does: (1 meet 2,3) == bottom == (2,3 meet 1). So does: (0 meet 0,1) == 0,1 == (0,1 meet 0)"
However I cannot understand why (top meet -1)==1 , and (-1 meet top)==-1? also why (1 meet 2,3) and (2,3 meet 1)==bottom ? how the meet is calculated?
Jacky, from your question it seems that you don't get some basic concepts. Have you tried to read linked Lattice wiki article?
I'm not sure if I can be better than collective mind of the Wiki but I'll try.
Let's start with poset aka "Partially ordered set". Having a "poset" means that you have a set of some objects and some comparator <= that you can feed two objects to and it will say which one is less (or rather "less or equal"). What differs partially ordered set from totally ordered one is that in more usual totally ordered set at least one of a <= b and a >= b holds true. In "partially ordered" mean that both might be false at the same time. I.e. you have some elements that you can't compare at all.
Now lattice is a structure over poset (and potentially not every poset can be converted to a lattice). To define a lattice you need to define two methods meet and join. meet is a function from a pair of elements of the poset to an element of the poset such that (I will use meet(a, b) syntax instead of a meet b as it seems to be more friendly for Java-developers):
For every pair of elements a and b there is an element inf = meet(a,b) i.e. meet is defined for every pair of elements
For every pair of elements a and b meet(a,b) <= a and meet(a,b) <= b
For every pair of elements a and b if inf = meet(a,b) there is no other element c in the set such that c <= a AND c <= b AND NOT c <= inf i.e. meet(a,b) defines the largest common minimum element (or more technically an infimum) and such element is unique.
The same goes for join but the join is finding "maximum" of two elements or more technically supremum.
So now let's go back to the example you referenced. The poset in that example contains of 4 types or rather layers of elements:
Top - an artificial element added to poset such that it is greater than any other element
Single integers
Pairs of neighbor integers (range) such as "[0, 1]" (here unlike the author I will use "[" and "]" to define ranges to not confuse with application of meet)
Bottom - an artificial element added to poset such that it is less than any other element
Note that all elements in single layer are not comparable(!) but all elements in any higher layer are greater than all elements in any lower layer. So no 1 is not less than 2 under that poset structure but [1,2] is less than both 1 and 2.
Note that all elements in single layer are not comparable(!). So no 1 is not less than 2 under that poset structure but [1,2] is less than both 1 and 2. Top is greater than anything. Bottom is less than anything. And range [x,y] is comparable with raw number z if and only if z lines inside the range and in that case range is less, otherwise they are not comparable.
You may notice that the structure of the poset "induces" corresponding lattice. So given such structure it is easy to understand how to define the meet function to satisfy all the requirements:
meet(Top, a) = meet(a, Top) = a for any a
meet(Bottom, a) = meet(a, Bottom) = Bottom for any a
meet(x, y) where both x and y are integers (i.e. for layer #2) is either:
Just x if x = y
Range [x, y] if x + 1 = y
Range [y, x] if y + 1 = x
Bottom otherwise
(I'm not sure if this is the right definition, it might always be range [min(x,y), max(x,y)] unless x = y . It is not clear from examples but it is not very important)
meet([x,y], z) = meet(z, [x,y]) where x, y, and z are integers i.e. meet of an integer (layer #2) and range (layer #3) is:
Range [x, y] if x = z or y = z (in other words if [x,y] < z)
Bottom otherwise
So meet of a range and an integer is almost always Bottom except most trivial cases
meet(a, b) where both a and b are ranges i.e. meet of two ranges (layer #3) is:
Range a is a = b
Bottom otherwise
So meet of two ranges is also Bottom except most trivial cases
What that part of example is about is actually about "inducing" the lattice from the structure and verifying that most of the desirable features hold (except for symmetry which is added in the next example).
Hope this helps
Update (answers to comments)
It is hard to answer "why". This is because the author build his poset in that way (probably because that way will be useful later). I think you are confused because set of natural numbers has a "natural" (pun not intended) sort order that we all are used to. Put there is nothing that could prohibit me to get the same set (i.e. the same object = all natural numbers) and define some other sorting order. Are you familiar with java.util.Comparator interface? Using that interface you can specify any sorting rule for Integer type such as "all even numbers are greater than all odd ones and inside even or odd classes works "usual" comparison rule" and you can use such a Comparartor to sort collection if for some reason such sorting order makes sense for your task. This is the same case, for author's task it makes sense to define an alternative (custom) sorting order. Moreover he want to make it only a partial order (which is impossible with Comparator). An the way he defines his order is the way I described.
Also if it is possible to do compare for [1,2] with 0 or 3?
Yes, you can compare and the answer directly follows from "all elements in single layer are not comparable(!) but all elements in any higher layer are greater than all elements in any lower layer": any number such as 0, 3, 42 or Integer.MAX_VALUE from layer #2 is greater than any range (layer #3) including the [1,2] range.
After some more thinking about it, my original answer was wrong. To satisfy author's goal range [1,2] should be not comparable with 0 or 3. So the answer is No. Actually my specification of the meet is correct but my description of sorting order is wrong.
Also the explanation for top and bottom are different from you, the original author explained that "bottom” == “we don’t know what values this might take on , “top” == “we can pick any value we like", I have do idea if you both explanation for the top and bottom actual refer to the same thing.
Here you mix up how the author defines top and bottom as a part of a mathematical structure called "lattice" and how he uses them for his practical task.
What this article is about is that there is an algorithm that analyses code for optimization based on "analyses of constants" and the algorithm is build upon the lattice of the described structure. The algorithm is based on processing different objects of the defined poset and involves finding meet of them multiple times. What the quoted answer describes is how to interpret the final value that algorithm produces rather than how those values are define.
AFAIU the basic idea behind algorithm is following: we have some variable and we see a few places where the value is assigned to it. For various optimizations it is good to know what it the possible range of values that the variable can take without running the actual code with all possible inputs. So the suggested algorithm is based on a simple idea: if we have two assignments (probably conditional) to the variable and in the first we know that values are in range [L1, R1] and in the second one values are in the range [L2, R2], we can be sure that now value is in the range [min(L1, L2), max(R1, R2)] (and this is effectively how meet is defined on that lattice). So now we can analyze all assignments in a function and to each assign range of possible values. Note that this structure of numbers and unlimited ranges also forms a lattice that the author describes in the first article (http://www.cliffc.org/blog/2012/02/12/too-much-theory/).
Note that Top is effectively impossible in Java because it provide some guarantees, but in C/C++ as the author mentions, we can have a variable that is not assigned at all and in such case C Language standard allows the compiler to treat that variable as having any value by compiler's choice i.e. compiler might assume whatever is most useful for optimization and this is what Top stands for. On the other hand if some value comes in as a argument to a method, it is Bottom because it can be any value without any control by compiler i.e. compiler can not assume anything about the value.
In the second article author points out that although the lattice from the first article is good theoretically in practice it can be very inefficient computationally. Thus to simplify computations he reduces his lattice to a much simpler one but the general theory stays the same: we assign ranges to the variables at each assignment so later we can analyze code and optimize it. And when we finished computing all the ranges, the interpretation for optimization assuming that analyzed line is if in the:
if (variable > 0) {
block#1
}
else {
block#2
}
is following
Top - if the line of code might be optimized assuming the variable has some specific value, compiler is free to do that optimization. So in the example compiler is free to eliminate that branch and decide that code will always go to block#1 and remove block#2 altogether OR decide that code will always go to block#2 and remove block#1 whichever alternative seems better to the compiler.
x - i.e. some constant value x - if the line of code might be optimized assuming the variable has value exactly x, compiler is free to do that optimization. So in the example compiler can evaluate x > 0 with that constant and leave only the code branch that corresponds to the calculated boolean value removing the other branch.
[x, y] - i.e. range from x to y. If the line of code might be optimized assuming the variable has value between x and y, compiler is free to do that optimization. So in the example if x > 0 (and thus y > 0), then compiler can remove block #2; y <= 0 (and thus x <= 0) , then compiler can remove block #1; if x <= 0 and y > 0 compiler can't optimize that code
Bottom - compiler can't optimize that code.
I've written a simple A* path finding algorithm to quickly find a way through a tile based dungeon in which the tiles contain the information of walls.
An example of a dungeon (only 1 path for simplicity):
However now I'd like to add a variable amount of "Bombs" to the algorithm which would allow the path-finding to ignore 1 wall. However now it doesn't find the best paths anymore,
for example with use of only 1 bomb the generated path looks like the first image here:
Edit: actually it would look like this: https://i.stack.imgur.com/kPoAA.png
While the correct path would be the second image
The problem is that "Closed Nodes" now interfere with possible paths. Any ideas of how to tackle this problem would be greatly appreciated!
Your "game state" will no longer only be defined by your location, but also by an integer representing the number of bombs you have left. If you're following the pseudocode of A* on wikipedia, this means you cannot simply implement the closedSet as a grid of booleans. It should probably be implemented as, for example, a hash map / hash set, where every entry holds the following data:
x coordinate
y coordinate
number of bombs left
By visiting a certain position in the search process, you'll no longer mark just that position as closed. You'll mark the combination of position + number of bombs left as closed. That way, if later on in the same search process you run into a position where you're at the same location, but have more bombs left, you will not ignore it as closed but will actually continue searching that possibility.
Note that, if the maximum possible number of bombs is relatively low, you could also implement the closedSet as an array of boolean grids, where you first index by number of bombs, then by x and y coordinates to find out if a specific position is closed or not.
Doesn't this mean that you just pretend to not have any walls at all?
Use A* to find the shortest path from start to end and then check how many walls you'd have to go through. If you have enough bombs, you can use the path. Otherwise, try the next longest path and so on.
By the way: you might want to check http://gamedev.stackexchange.com for questions like this one.
You need to tweak the cost function to cost something for a bomb, then run the algorithm normally with an infinite cost for a second bomb. To get the bomb approximately halfway, play about with cost function, it should probably cost about the heuristic A-B distance times the cost for an empty tile. If you have two bombs, half the cost and of course then use of three bombs costs infinite.
But don't expect very good results. A* isn't designed for that kind of optimisation.
A dynamic array is an array that doubles its size, when an element is added to an already full array, copying the existing elements to a new place more details here. It is clear that there will be ceil(log(n)) of bulk copy operations.
In a textbook I have seen the number of movements M as being computed this way:
M=sum for {i=1} to {ceil(log(n))} of i*n/{2^i} with the argument that "half the elements move once, a quarter of the elements twice"...
But I thought that for each bulk copy operation the number of copied/moved elements is actually n/2^i, as every bulk operation is triggered by reaching and exceeding the 2^i th element, so that the number of movements is
M=sum for {i=1} to {ceil(log(n))} of n/{2^i} (for n=8 it seems to be the correct formula).
Who is right and what is wrong in the another argument?
Both versions are O(n), so there is no big difference.
The textbook version counts the initial write of each element as a move operation but doesn't consider the very first element, which will move ceil(log(n)) times. Other than that they are equivalent, i.e.
(sum for {i=1} to {ceil(log(n))} of i*n/{2^i}) - (n - 1) + ceil(log(n))
== sum for {i=1} to {ceil(log(n))} of n/{2^i}
when n is a power of 2. Both are off by different amounts when n is not a power of 2.
What I want to ask is mathematical/logical situation
I have nested tree which looks similar to
And I need the indexing number of each items order, ex:
Tube - 1
LCD -2
Plasma - 3
MP3 Player - 1
CD Player - 2
2 Way Radios -3
(1,2,3 ... values are not necessary to be exactly these)
This will be required for ordering the items by this value. After the order I need to get all first items, than all second items... and so on
It is easy to set an order number of each item but what I am looking for is a value calculated from the left-right values of each item and its parent
You can compute the index as one plus the index of the left sibling, or as one if there is no left sibling. If you can't control the order in which indices get computed, you might have to iterate over all left siblings, counting them, to compute the index.
There is no direct way. One way to see this is imagining a node being inserted into the tree with a pretty low index. Nodes other than its immediate siblings will have no way of knowing about this insertion, just by looking at parent and direct sibling pointers. But their indices will have to change nonetheless. Which means that these pointers can not be enough to compute indices directly.
To order them, you can use DFS (Depth First Search algorithm). Below is a possible Pseudo-code,
DFS(node)
{
index=1
for all child v of node
assign v the value of index
DFS (v)
increment index by 1
end for
}
assign the root the index 1
DFS (root)