Pair-Comparison input for sorting - sorting

if A is taller than B, but shorter than C. D is taller than B, but shorter than A. Print the persons in descending order of height. How can we solve this by code ?
I referred to
Comparison-based ranking algorithm,
Simple ranking algorithm
I understand that the ELO rating algorithm could help solve this problem. But ELO algoritm seems like doing over work for a much simpler problem. Is there any other well known algorithm for such kind of questions ?
Input :
AtB -> A is taller than B
AsC -> A is shorter than C
DtB -> D is taller than B
DsA -> D is shorter than A
Expected Output :
CADB

Related

Dynamic Programming / Subproblems + Transition

I am kind of stuck, I decided to try this problem https://icpcarchive.ecs.baylor.edu/external/71/7113.pdf
to prevent it 404'ing here's the basic assignment
a hopper only visits arrays with integer entries,
• a hopper always explores a sequence of array elements using the following rules:
– a hopper cannot jump too far, that is, the next element is always at most D indices away
(how far a hopper can jump depends on the length of its legs),
– a hopper doesn't like big changes in values — the next element differs from the current
element by at most M, more precisely the absolute value of the difference is at most M (how
big a change in values a hopper can handle depends on the length of its arms), and
– a hopper never visits the same element twice.
• a hopper will explore the array with the longest exploration sequence.
n is the length of the array (as described above, D is the maximum length of a jump the
hopper can make, and M is the maximum difference in values a hopper can handle). The next line
contains n integers — the entries of the array. We have 1 ≤ D ≤ 7, 1 ≤ M ≤ 10, 000, 1 ≤ n ≤ 10, 000
and the integers in the array are between -1,000,000 and 1,000,000.
EDIT: I am doing this out of pure curiosity this is not a assignment I need to do for any particular reason other than challenging myself
basically its building a sparse graph out of an array,
the graph is undirected and due to the symmetry of the -d ... d jumps, its also either a complete graph (all edges are included) or mutually disjoint graph components
As first step I tried to simply exhaustive DFS search the graph, which works but has the infamous O(n!) runtime, the first iteration of this was written in F# which was horrible slow the second in C which still plateaus pretty fast too
so I know the longest path problem is NP hard but I thought I would give it a try with dynamic programming
The next approach was to simply use the common DP solution (bitmasked path) to DFS on the graph but at this at this point I already traversed the array and built the entire graph which may contain up to 1000 nodes so its not feasible
My next approach was to build a DFS Tree (tree of all the paths) which is a bit faster but then needs to store all entire path in memory for each iteration already which isn't what I really want, I am thinking I can reduce it to substates while already traversing the array
next I tried to memoize all paths I've already walked by simply using a bitmask and a simple memoization functions as seen here:
let xf = memoizedEdges (fun r i' p mask ->
let mask' = (addBit i' mask)
let nbs = [-d .. -1] # [ 1 .. d]
|> Seq.map (fun f -> match f with
| x when (i' + x) < 0 -> None
| x when (i' + x) >= a.Length -> None
| x when (diff a.[i'+x] a.[i']) > m -> None
| x when (i' + x) = i -> None
| x when (isSet (i'+x) mask') -> None
| x -> Some (i' + x )
)
let ec = nbs
|> Seq.choose id
|> Seq.toList
|> List.map (fun f ->
r f i' mask'
)
max (bitcount mask) (ec |> mxOrZero)
)
So memoized edges works by 3 int parameters the current index (i'), the previous (p) and the path as bitmask, the momizedEdges function itself will check on each recursive call it if has seen i' and p and the mask ... or p and i' and the mask with the i' and p bits flipped to mask the path in the other way (basically if we have seen this path coming from the other side already)
this works as I would expect, but the assignment states its up to 1000 indices which would cause the int32 mask to be too short
so I've been thinking for days now and there must be a way to encode each of the -d ... d steps into a start and end vertice and calculate the path for each step in that window based on the previous steps
I've come up with basically this
0.) Create a container to hold starting and endvertex as key with the current pathlength as value
1.) Check neighbors of i
2.) Have I seen either this combination either as (from -> to) or (to -> from) then I do not add or increase
3.) Check whatever any other predecessors to this node exist and increase the path of those by 1
but this would lead to having all paths stored and I would basically result in tuples and then I am back at my graph with DFS in another form
I am very thankful for any pointers (I just need some new ideas I am really stuck rn) how I could encode each subproblem from -d..d that I can use just intermediate results for calculating the next step (if this is even possible)
Partial answer
This is a difficult problem. Indeed, on competitive programming problem compendium Kattis it is (at the time of writing) in the top 5 of most difficult problems.
Only you know if this sort of problem is possible for you to solve, but there is a fair chance no one on this site can help you completely, hence this partial answer.
Longest path
What we're asked to do here is solve the longest path problem for a particular graph. This problem is known to be NP-complete in general, even for undirected unweighted graphs as ours is. Because the graph can have 1000 vertices, a (sub-)exponential algorithm in N will not work, and we're likely not asked to prove that P=NP, so the only option we have left is to somehow exploit the structure of the graph.
The most promising avenue is through D. D is at most 7, because of which the maximum degree of the graph is at most 14, and all edges are—in a sense—local.
Now, according to Wikipedia, the longest path problem can be solved polynomially on various classes of graphs, such as noncyclic ones. Our graph is of course not noncyclic, but unfortunately this is largely where my knowledge ends. I am not sufficiently familiar with graph theory to see whether the implied graph of the problem is in any of the classes Wikipedia mentions.
Of particular note is that the longest path problem can be solved in polynomial time given bounded-by-a-constant clique-width (or tree-width, which implies the former). I am unable to confirm or prove that our graph has bounded clique-width because of the bound on D, but perhaps you yourself know more about this, or you could try asking on the math or CS stackexchange, as at this point we're pretty far from any actual programming.
Regardless, if you're able to confirm that the graph is clique-width-bounded, this paper may help you further.
I hope this answer is of some use despite not being entirely fulfilling, and good luck!
Citation for the paper in case of link decay
Fomin, F. V., Golovach, P. A., Lokshtanov, D., & Saurabh, S. (2009, January). Clique-width: on the price of generality. In Proceedings of the twentieth annual ACM-SIAM symposium on Discrete algorithms (pp. 825-834). Society for Industrial and Applied Mathematics.

Build a ranking from a series of transitive relationships that can be noisy, inconsistent, or incomplete

I have a list of ~1000 different assets that I would like to rank by value for a game that I am making.
Players are given the opportunity to select one of two baskets of assets. For instance, they might be asked if they would rather have A + B or C.
From a huge list of basket preferences, I wish to rank the assets by perceived value.
Here is some example input, where accordingly players have said:
A > B
A + A > B + C
C > B
I.e. they would rather have an A than a B. they would rather have 2 As than a B and a C. Etc.
From this input, I believe the most likely value ranking is:
A > C > B
What class of algorithm should I use to attack this problem?
Sometimes the list of preferences will be contradictory (some players think A > B, others might say B > A). If I have a separate measure of player skill level, how can I leverage this to get a more accurate ranking?
I also need to be able to handle the case where there are "islands" in the relationships between baskets. For example:
A > B
C > D
I.e. you cannot say if A <> C.
This seems to me like an optimization problem similar to various packing algorithms. Is this ranking problem NP-hard?
It actually sounds more like graph theory to me.
Suppose you would have a digraph with A -> B indicating that A < B. Then you could
Run a minimum feedback set algorithm for the ordering (which, in the absence of contradictions, is simply Topological Sort).
Run DFS for the "islands" you mention.
So the question is how to build such a graph. I have a hunch (unfortunately not more than that yet), that the only multiple-variable rules that matter are of the form:
A_1 + A1 + ... + A_i < A_{i + 1}
And they should be simplified to
A_j < A_{i + 1}, j = 1, .., i.
(Asides from that, the only use of RHS multiple value rules would be for transitive deductions (according to my hunch), that is
A < B + C and B + C < D implies A < D. But this can be dealt with using dummy variables for the sums.)
Perhaps you should see if you can verify or contradict this.
What you are trying to do is in general impossible under reasonable assumptions by Arrow's Theorem.
A better approach would be to ask the players to score rather than rank; e.g., ask them, "How many zlotys would you pay for A? For B? For C?", then average the scores for each item by the players who answered. So if only players 2, 5, and 11 answered with their estimates of the value of item A, you would add their answers and divide by 3. You could also give more weight to the answers of more experienced players.
If you still want to use baskets of assets, you can probably use linear algebra to disentangle scores for A and B based on scores for A+B and A-B, say.
If you want to make do with ranking data (e.g., if that's all you have and you can't ask any more questions), then Ami's approach is probably the best you can do.

This puzzle- subset sum?

In today's edition of the Guardian (a newspaper in the UK), in the "Pyrgic puzzles" section on page 43 by Chris Maslanka, the following puzzle was given:
The 3 wise men ... went to Herrods to do their Christmas shopping. Caspar bought Gold, Melchior bought Frankincense, and Balthazar bought a copy of the Daily Myrrh. The cashier tapped in the number of euros of each of these things cost, and meant to add the three numbers, but multiplied them instead. ... the marvel of the thing was that the result was exactly the same: €65.52. What were the three sums [I assume he meant the three numbers]?
My interpretation is: Find an a, b and c such that a + b + c = abc = 65.52 (exactly) where a, b and c are positive decimal numbers with no more than two decimal places. It follows that a, b and c must also be less than 65.52 (approximately).
My approach is thus: I shall find all the candidate sets of a, b and c where a + b + c = 6552 and a, b and c are integers from {1 ... 6550} (Notionally I have multiplied all the operands by 100 for convenience). Then, for all the candidate sets, it is trivial to satisfy the other condition by dividing all the operands by 100 then multiplying them (with arbitrary-precision arithmetic).
This, as I see it, is an instance of the subset sum problem. So I implemented a dirty (exponential time) algorithm which found one distinct solution: a=0.52, b=2, c=63.
Ok, there are better algorithms for the subset sum problem, but don't you think this is getting a little out-of-reach for an average Guardian reader?
On page 40 the answer is listed:
This is easy, by trial and error. Guess 52p for the Daily Myrrh. But by multiplying by 0.52 is roughly halving, so we need one sum to be about 2; so try 2 X 63 X 0.52. Et voilà. Is this answer unique?
Well, we know that the answer is unique (disregarding the other permutations of 2, 63 and 0.52).
What I want to know is: How can this be "easy"? Am I right in characterising the puzzle as an instance of the subset sum problem? Have I overlooked some characteristic of the puzzle which can be utilized to simplify the solution? Was anyone able to adopt a similar "trial and error" approach and if so can they take me through it? Is Chris Maslanka simply undaunted by NP-complete problems?
No, it is not an instance of the subset sum problem, because:
The subset size is limited to 3, making it O(n^3) solution worst case with naive exhaustive search (and not exponential)
There is additional data in here, the product of the numbers.
You are not actually given a set, a set of all integers is just a subproblem of subset-sum, a much easier one.
The important thing to understand here is: if a problem can be solved by an NP-Hard problem - it doesn't mean it is NP-Hard as well, the other way around holds - if you have a problem, and you can solve some NP-Hard problem (polynomially) with it, then your problem is NP-Hard. It is called polynomial reduction1.
The approach is easy because all you have to do is "guess" (by iterating all candidates) a value for a, and from this you can derive what is the possible solution for b,c - (2 variables, two equations if a is known - and in each iteration - it is), thus the solution is even linear - not only sub exponential.
It might even be optimized to use a variation of binary search to get a sub-linear optimization, but I cannot think of that optimization at the moment.
(1) Note: this is some intuitive explanation, and not a formal definition.

A greedy or dynamic algorithm to subset selection

I have a simple algorithmic question. I would be grateful if you could help me.
We have some 2 dimensional points. A positive weight is associated to them (a sample problem is attached). We want to select a subset of them which maximizes the weights and neither of two selected points overlap each other (for example, in the attached file, we cannot select both A and C because they are in the same row, and in the same way we cannot select both A and B, because they are in the same column.) If there is any greedy (or dynamic) approach I can use. I'm aware of non-overlapping interval selection algorithm, but I cannot use it here, because my problem is 2 dimensional.
Any reference or note is appreciated.
Regards
Attachment:
A simple sample of the problem:
A (30$) -------- B (10$)
|
|
|
|
C (8$)
If you are OK with a good solution, and do not demand the best solution - you can use heuristical algorithms to solve this.
Let S be the set of points, and w(s) - the weightening function.
Create a weight function W:2^S->R (from the subsets of S to real numbers):
W(U) = - INFINITY is the solution is not feasible
Sigma(w(u)) for each u in U otherwise
Also create a function next:2^S -> 2^2^S (a function that gets a subset of S, and returns a set of subsets of S)
next(U) = V you can get V from U by adding/removing one element to/from U
Now, given that data - you can invoke any optimization algorithm in the Artificial Intelligence book, such as Genetic Algorithm or Hill Climbing.
For example, Hill Climbing with random restarts, will be something like that:
1. best<- -INFINITY
2. while there is more time
3. choose a random subset s
4. NEXT <- next(s)
5. if max{ W(v) | for each v in NEXT} < W(s): //s is a local maximum
5.1. if W(s) > best: best <- W(s) //if s is better then the previous result - store it.
5.2. go to 2. //restart the hill climbing from a different random point.
6. else:
6.1. s <- max { NEXT }
6.2. goto 4.
7. return best //when out of time, return the best solution found so far.
The above algorithm is anytime - meaning it will produce better results if given more time.
This can be treated as a linear assignment problem, which can be solved using an algorithm like the Hungarian algorithm. The algorithm tries to minimize the sum of costs, so just negate your weights, and use them as the costs. The assignment of rows to columns will give you the subset of points that you need. There are sparse variants for cases where not every (row,column) pair has an associated point, but you can also just use a large positive cost for these.
Well you can think of this as a binary constraint optimization problem, and there are various algorithms. The easiest algorithm for this problem is backtracking and arc propogation. However, it takes exponential time in the worst case. I am not sure if there are any specific algorithms to take advantage of the geometrical nature of the problem.
This can be solved by a pretty straight forward dynamic programming approach with a exponential time complexity
s = {A, B, C ...}
getMaxSum(s) = max( A.value + getMaxSum(compatibleSubSet(s, A)),
B.value + getMaxSum(compatibleSubSet(s, B)),
...)
where compatibleSubSet(s, A) gets the subset of s that does not overlap with A
To optimize it, you can memorize the result for each subset
Some way to do it:
Write a function that generates subsets ordered from the subset off maximum weight to the subset off minimum weight while ignoring the constraints.
Then call this function repeatedly until a subset that honors the constraints pops up.
In order to improve the performance, you can write a not so dumb generator function that for instance honors the not-on-the-same-row constraint but that ignores the not-on-the-same-column one.

Pecking order of pigeons?

I was going though problems on graph theory posted by Prof. Ericksson from my alma-mater and came across this rather unique question about pigeons and their innate tendency to form pecking orders. The question goes as follows:
Whenever groups of pigeons gather,
they instinctively establish a pecking
order. For any pair of pigeons, one
pigeon always pecks the other, driving
it away from food or potential mates.
The same pair of pigeons always
chooses the same pecking order, even
after years of separation, no matter
what other pigeons are around.
Surprisingly, the overall pecking
order can contain cycles—for example,
pigeon A pecks pigeon B, which pecks
pigeon C, which pecks pigeon A.
Prove that any finite set of pigeons
can be arranged in a row from left to
right so that every pigeon pecks the
pigeon immediately to its left.
Since this is a question on Graph theory, the first things that crossed my mind that is this just asking for a topological sort of a graphs of relationships(relationships being the pecking order). What made this a little more complex was the fact that there can be cyclic relationships between the pigeons. If we have a cyclic dependency as follows:
A->B->C->A
where A pecks on B,B pecks on C and C goes back and pecks on A
If we represent it in the way suggested by the problem, we have something as follows:
C B A
But the above given row ordering does not factor in the pecking order between C and A.
I had another idea of solving it by mathematical induction where the base case is for two pigeons arranged according to their pecking order, assuming the pecking order arrangement is valid for n pigeons and then proving it to be true for n+1 pigeons.
I am not sure if I am going down the wrong track here. Some insights into how I should be analyzing this problem will be helpful.
Thanks
I would prove that using induction indeed (a>b means a peacks b):
for k=2 it obviously holds
let for k=n there's always required order, lets prove that it exists for n+1. Choose and order any n pigeons (A1>A2...>An) from given n+1. And let C is a (n+1)th pigeon.
If C pecks A1 then it can be added to the start of the "line" and statement proved. If A1 pecks C then lets compare C with A2 - if C pecks A2 then it can be inserted between A1 and A2 and statement holds. If not - repeat that comparing process till last pair - A(n-1) and An, as process goes we assume that A(n-1) > C. If C>An then C can be inserted between A(n-1) and An, if not - it can be inserted to the end of the "line".
qed
P.S. Note that "pecking cycles" do not necessarily exist - if we assign pigeons number from 1 to n and assume that pigeon pecks another if his number is greater then we obviously can order them in line but not in circle so that each pigeon pecks his left neighbour.
P.P.S. That proof also gives an algorithm to construct the required order.
Have you considered constructing a directed graph then looking for a Hamiltonian Path that visits every point (pigeon) once? The Hamiltonian path should reveal the sequence - this isn't a proof, though. Just a solution.

Resources