Order by pair comparisons
Sorting Algorithm
This is a sorting algorithm. It may be applied to a set of data in order to sort it.
For comparing various sorts, see compare sorts.
For other sorting algorithms, see sorting algorithms, or:
Heap sort | Merge sort | Patience sort | Quick sort
O(n log2n) sorts
Shell Sort
O(n2) sorts
Bubble sort |
Cocktail sort |
Cocktail sort with shifting bounds |
Comb sort |
Cycle sort |
Gnome sort |
Insertion sort |
Selection sort |
Strand sort
other sorts
Bead sort |
Bogo sort |
Common sorted list |
Composite structures sort |
Custom comparator sort |
Counting sort |
Disjoint sublist sort |
External sort |
Jort sort |
Lexicographical sort |
Natural sorting |
Order by pair comparisons |
Order disjoint list items |
Order two numerical lists |
Object identifier (OID) sort |
Pancake sort |
Quickselect |
Permutation sort |
Radix sort |
Ranking methods |
Remove duplicate elements |
Sleep sort |
Stooge sort |
[Sort letters of a string] |
Three variable sort |
Topological sort |
Tree sort
Assume we have a set of items that can be sorted into an order by the user.
The user is presented with pairs of items from the set in no order, the user states which item is less than, equal to, or greater than the other (with respect to their relative positions if fully ordered).
Write a function that given items that the user can order, asks the user to give the result of comparing two items at a time and uses the comparison results to eventually return the items in order.
Try and minimise the comparisons the user is asked for.
Show on this page, the function ordering the colours of the rainbow:
violet red green indigo blue yellow orange
The correct ordering being:
red orange yellow green blue indigo violet
Note:
- Asking for/receiving user comparisons is a part of the task.
- Code inputs should not assume an ordering.
- The seven colours can form twenty-one different pairs.
- A routine that does not ask the user "too many" comparison questions should be used.
Julia
Using external function
Uses shell sort, just because it sort of fits the task, metaphorically, as if it were with variously colored peas. <lang julia>const nrequests = [0] const ordering = Dict("violet" => 7, "red" => 1, "green" => 4, "indigo" => 6, "blue" => 5,
"yellow" => 3, "orange" => 2)
tellmeifgt(x, y) = (nrequests[1] += 1; ordering[x] > ordering[y])
function orderbypair!(a::Vector)
incr = div(length(a), 2) while incr > 0 for i in incr+1:length(a) j = i tmp = a[i] while j > incr && tellmeifgt(a[j - incr], tmp) a[j] = a[j-incr] j -= incr end a[j] = tmp end if incr == 2 incr = 1 else incr = floor(Int, incr * 5.0 / 11) end end return a
end
const words = String.(split("violet red green indigo blue yellow orange", r"\s+")) println("Unsorted: $words") println("Sorted: $(orderbypair!(words)). Total requests: $(nrequests[1]).")
</lang>
- Output:
Unsorted: ["violet", "red", "green", "indigo", "blue", "yellow", "orange"] Sorted: ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]. Total requests: 14.
Using the builtin sort function
Probably this uses MergeSort internally, per the Julia documentation. <lang julia>const nrequests = [0] const ordering = Dict("violet" => 7, "red" => 1, "green" => 4, "indigo" => 6, "blue" => 5,
"yellow" => 3, "orange" => 2)
tellmeiflt(x, y) = (nrequests[1] += 1; ordering[x] < ordering[y]) const words = String.(split("violet red green indigo blue yellow orange", r"\s+")) println("Unsorted: $words") println("Sorted: $(sort!(words, lt=tellmeiflt)). Total requests: $(nrequests[1]).")
</lang>
- Output:
Unsorted: ["violet", "red", "green", "indigo", "blue", "yellow", "orange"] Sorted: ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]. Total requests: 19.
Python
Uses binary search to insert successive items into a growing ordered list. Comparisons are asked for.
<lang python>def _insort_right(a, x, q):
""" Insert item x in list a, and keep it sorted assuming a is sorted. If x is already in a, insert it to the right of the rightmost x. """
lo, hi = 0, len(a) while lo < hi: mid = (lo+hi)//2 q += 1 less = input(f"{q:2}: IS {x:>6} LESS-THAN {a[mid]:>6} ? y/n: ").strip().lower() == 'y' if less: hi = mid else: lo = mid+1 a.insert(lo, x) return q
def order(items):
ordered, q = [], 0 for item in items: q = _insort_right(ordered, item, q) return ordered, q
if __name__ == '__main__':
items = 'violet red green indigo blue yellow orange'.split() ans, questions = order(items) print('\n' + ' '.join(ans))</lang>
- Output:
1: IS red LESS-THAN violet ? y/n: y 2: IS green LESS-THAN violet ? y/n: y 3: IS green LESS-THAN red ? y/n: n 4: IS indigo LESS-THAN green ? y/n: n 5: IS indigo LESS-THAN violet ? y/n: y 6: IS blue LESS-THAN indigo ? y/n: y 7: IS blue LESS-THAN green ? y/n: n 8: IS yellow LESS-THAN blue ? y/n: y 9: IS yellow LESS-THAN green ? y/n: y 10: IS yellow LESS-THAN red ? y/n: n 11: IS orange LESS-THAN blue ? y/n: y 12: IS orange LESS-THAN yellow ? y/n: y 13: IS orange LESS-THAN red ? y/n: n red orange yellow green blue indigo violet