Sorting vector of x/y coordinates - sorting

I have a vector of (u32, u32) tuples which represent coordinates on a 10 x 10 grid. The coordinates are unsorted. Because the standard sort function also didn't yield the result I wanted, I wrote a sort function like this for them:
vec.sort_by(|a, b| {
if a.0 > b.0 { return Ordering::Greater; }
if a.0 < b.0 { return Ordering::Less; }
if a.1 > b.1 { return Ordering::Greater; }
if a.1 < b.1 { return Ordering::Less; }
return Ordering::Equal;
});
The resulting grid for my custom function looks like this:
(0/0) (0/1) (0/2) (0/3) (0/4) (0/5) (0/6) (0/7) (0/8) (0/9)
(1/0) (1/1) (1/2) (1/3) (1/4) (1/5) (1/6) (1/7) (1/8) (1/9)
(2/0) (2/1) (2/2) (2/3) (2/4) (2/5) (2/6) (2/7) (2/8) (2/9)
...
(9/0) (9/1) (9/2) (9/3) (9/4) (9/5) (9/6) (9/7) (9/8) (9/9)
This is not what I want, because the lower left should start with (0/0) as I would expect on a mathematical coordinates grid.
I probably can manage to add more cases to the sort algorithm, but is there an easier way to do what I want besides writing a big if .. return Ordering ...; block?

You didn't show how you are populating or printing your tuples, so this is a guess. Flip around and/or negate parts of your coordinates. I'd also recommend using sort_by_key as it's easier, as well as just reusing the existing comparison of tuples:
fn main() {
let mut points = [(0, 0), (1, 1), (1, 0), (0, 1)];
points.sort_by_key(|&(x, y)| (!y, x));
println!("{:?}", points);
}
Adding an extra newline in the output:
[(0, 1), (1, 1),
(0, 0), (1, 0)]
Originally, this answer suggested negating the value ((-y, x)). However, as pointed out by Francis Gagné, this fails for unsigned integers or signed integers when the value is the minimum value. Negating the bits happens to work fine, but is a bit too "clever".
Nowadays, I would use Ordering::reverse and Ordering::then for the clarity:
fn main() {
let mut points = [(0u8, 0u8), (1, 1), (1, 0), (0, 1)];
points.sort_by(|&(x0, y0), &(x1, y1)| y0.cmp(&y1).reverse().then(x0.cmp(&x1)));
println!("{:?}", points);
}
[(0, 1), (1, 1),
(0, 0), (1, 0)]

Related

Skyline of Buildings

I'm trying to understand the skyline problem. Given n rectangular building and we need to compute the skyline. I have trouble in understanding the output for this problem.
Input: (1,11,5), (2,6,7), (3,13,9), (12,7,16), (14,3,25), (19,18,22), (23,13,29), (24,4,28) }
Output Skylines: (1, 11), (3, 13), (9, 0), (12, 7), (16, 3), (19, 18), (22, 3), (25, 0)
The output is pair (xaxis, height). Why is the third pair (9,0)? If we see the skyline graph, the x-axis value 9 has height of 13, not 0. Why is it showing 0? In other words, if we take the first building (input (1,11,5)), the output is (1, 11), (5, 0). Can you guys explain why it is (5,0) instead of (5,11)?
Think of the rooftop intervals as closed on the left and open on the right.
Your output does not signify "at x the height is y", but rather "at x the height changes to y".
using the sweep line algorithm; here is my python version solution:
class Solution:
# #param {integer[][]} buildings
# #return {integer[][]}
def getSkyline(self, buildings):
if len(buildings)==0: return []
if len(buildings)==1: return [[buildings[0][0], buildings[0][2]], [buildings[0][1], 0]]
points=[]
for building in buildings:
points+=[[building[0],building[2]]]
points+=[[building[1],-building[2]]]
points=sorted(points, key=lambda x: x[0])
moving, active, res, current=0, [0], [],-1
while moving<len(points):
i=moving
while i<=len(points):
if i<len(points) and points[i][0]==points[moving][0]:
if points[i][1]>0:
active+=[points[i][1]]
if points[i][1]>current:
current=points[i][1]
if len(res)>0 and res[-1][0]==points[i][0]:
res[-1][1]=current
else:
res+=[[points[moving][0], current]]
else:
active.remove(-points[i][1])
i+=1
else:
break
if max(active)<current:
current=max(active)
res+=[[points[moving][0], current]]
moving=i
return res
static long largestRectangle(int[] h) {
int k=1;
int n=h.length;
long max=0;
while(k<=n){
long area=0;
for(int i=0;i<n-k+1;i++){
long min=Long.MAX_VALUE;
for(int j=i;j<i+k;j++){
//System.out.print(h[j]+" ");
min=Math.min(h[j],min);
}
// System.out.println();
area=k*min;
//System.out.println(area);
max=Math.max(area,max);
}
//System.out.println(k);
k++;
}
return max;
}

How to make this sparse matrix and trie work in tandem

I have a sparse matrix that has been exported to this format:
(1, 3) = 4
(0, 5) = 88
(6, 0) = 100
...
Strings are stored into a Trie data structure. The numbers in the previous exported sparse matrix correspond to the result of the lookup on the Trie.
Lets say the word "stackoverflow" is mapped to number '0'. I need to iterate the exported sparse matrix where the first element is equals to '0' and find the highest value.
For example:
(0, 1) = 4
(0, 3) = 8
(0, 9) = 100 <-- highest value
(0, 9) is going to win.
What would be the best implementation to store the exported sparse matrix?
In general, what would be the best approach (data structure, algorithm) to handle this functionality?
Absent memory or dynamism constraints, probably the best approach is to slurp the sparse matrix into a map from first number to the pairs ordered by value, e.g.,
matrix_map = {} # empty map
for (first_number, second_number, value) in matrix_triples:
if first_number not in matrix_map:
matrix_map[first_number] = [] # empty list
matrix_map[first_number].append((second_number, value))
for lst in matrix_map.values():
lst.sort(key=itemgetter(1), reverse=True) # sort by value descending
Given a matrix like
(0, 1) = 4
(0, 3) = 8
(0, 5) = 88
(0, 9) = 100
(1, 3) = 4
(6, 0) = 100,
the finished product looks like this:
{0: [(9, 100), (5, 88), (3, 8), (1, 4)],
1: [(3, 4)],
6: [(0, 100)]}.

top down ranges merge?

I want to merge some intervals like this:
>>> ranges = [(30, 45), (40, 50), (10, 50), (60, 90), (90, 100)]
>>> merge(ranges)
[(10, 50), (60, 100)]
I'm not in cs field. I know how to do it by iteration, but wonder if there's a more efficient "top-down" approach to merge them more efficiently, maybe using some special data structure?
Thanks.
Interval tree definitely works, but it is more complex than what you need. Interval tree is an "online" solution, and so it allows you to add some intervals, look at the union, add more intervals, look again, etc.
If you have all the intervals upfront, you can do something simpler:
Start with the input
ranges = [(30, 45), (40, 50), (10, 50)]
Convert the range list into a list of endpoints. If you have range (A, B), you'll convert it to two endpoints: (A, 0) will be the left endpoint and (B, 1) wil be the right endpoint.
endpoints = [(30, 0), (45, 1), (40, 0), (50, 1), (10, 0), (50, 1)]
Sort the endpoints
endpoints = [(10, 0), (30, 0), (40, 0), (45, 1), (50, 1), (50, 1)]
Scan forward through the endpoints list. Increment a counter when you see a left endpoint and decrement the counter when you see a right endpoint. Whenever the counter hits 0, you close the current merged interval.
This solution can be implemented in a few lines.
Yeah, the efficient way to do it is to use an interval tree.
The following algorithm in C# does what you want. It uses DateTime interval ranges, but you can adapt it however you like. Once the collection is sorted in ascending start order, if the start of the next interval is at or before the end of the previous one, they overlap, and you extend the end time outward if needed. Otherwise they don't overlap, and you save the prior one off to the results.
public static List<DateTimeRange> MergeTimeRanges(List<DateTimeRange> inputRanges)
{
List<DateTimeRange> mergedRanges = new List<DateTimeRange>();
// Sort in ascending start order.
inputRanges.Sort();
DateTime currentStart = inputRanges[0].Start;
DateTime currentEnd = inputRanges[0].End;
for (int i = 1; i < inputRanges.Count; i++)
{
if (inputRanges[i].Start <= currentEnd)
{
if (inputRanges[i].End > currentEnd)
{
currentEnd = inputRanges[i].End; // Extend range.
}
}
else
{
// Save current range to output.
mergedRanges.Add(new DateTimeRange(currentStart, currentEnd));
currentStart = inputRanges[i].Start;
currentEnd = inputRanges[i].End;
}
}
mergedRanges.Add(new DateTimeRange(currentStart, currentEnd));
return mergedRanges;
}

How to generate cross product of sets in specific order

Given some sets (or lists) of numbers, I would like to iterate through the cross product of these sets in the order determined by the sum of the returned numbers. For example, if the given sets are { 1,2,3 }, { 2,4 }, { 5 }, then I would like to retrieve the cross-products in the order
<3,4,5>,
<2,4,5>,
<3,2,5> or <1,4,5>,
<2,2,5>,
<1,2,5>
I can't compute all the cross-products first and then sort them, because there are way too many. Is there any clever way to achieve this with an iterator?
(I'm using Perl for this, in case there are modules that would help.)
For two sets A and B, we can use a min heap as follows.
Sort A.
Sort B.
Push (0, 0) into a min heap H with priority function (i, j) |-> A[i] + B[j]. Break ties preferring small i and j.
While H is not empty, pop (i, j), output (A[i], B[j]), insert (i + 1, j) and (i, j + 1) if they exist and don't already belong to H.
For more than two sets, use the naive algorithm and sort to get down to two sets. In the best case (which happens when each set is relatively small), this requires storage for O(√#tuples) tuples instead of Ω(#tuples).
Here's some Python to do this. It should transliterate reasonably straightforwardly to Perl. You'll need a heap library from CPAN and to convert my tuples to strings so that they can be keys in a Perl hash. The set can be stored as a hash as well.
from heapq import heappop, heappush
def largest_to_smallest(lists):
"""
>>> print list(largest_to_smallest([[1, 2, 3], [2, 4], [5]]))
[(3, 4, 5), (2, 4, 5), (3, 2, 5), (1, 4, 5), (2, 2, 5), (1, 2, 5)]
"""
for lst in lists:
lst.sort(reverse=True)
num_lists = len(lists)
index_tuples_in_heap = set()
min_heap = []
def insert(index_tuple):
if index_tuple in index_tuples_in_heap:
return
index_tuples_in_heap.add(index_tuple)
minus_sum = 0 # compute -sum because it's a min heap, not a max heap
for i in xrange(num_lists): # 0, ..., num_lists - 1
if index_tuple[i] >= len(lists[i]):
return
minus_sum -= lists[i][index_tuple[i]]
heappush(min_heap, (minus_sum, index_tuple))
insert((0,) * num_lists)
while min_heap:
minus_sum, index_tuple = heappop(min_heap)
elements = []
for i in xrange(num_lists):
elements.append(lists[i][index_tuple[i]])
yield tuple(elements) # this is where the tuple is returned
for i in xrange(num_lists):
neighbor = []
for j in xrange(num_lists):
if i == j:
neighbor.append(index_tuple[j] + 1)
else:
neighbor.append(index_tuple[j])
insert(tuple(neighbor))

Algorithm to generate all unique permutations of fixed-length integer partitions?

I'm searching for an algorithm that generates all permutations of fixed-length partitions of an integer. Order does not matter.
For example, for n=4 and length L=3:
[(0, 2, 2), (2, 0, 2), (2, 2, 0),
(2, 1, 1), (1, 2, 1), (1, 1, 2),
(0, 1, 3), (0, 3, 1), (3, 0, 1), (3, 1, 0), (1, 3, 0), (1, 0, 3),
(0, 0, 4), (4, 0, 0), (0, 4, 0)]
I bumbled about with integer partitions + permutations for partitions whose length is lesser than L; but that was too slow because I got the same partition multiple times (because [0, 0, 1] may be a permutation of [0, 0, 1] ;-)
Any help appreciated, and no, this isn't homework -- personal interest :-)
Okay. First, forget about the permutations and just generate the partitions of length L (as suggested by #Svein Bringsli). Note that for each partition, you may impose an ordering on the elements, such as >. Now just "count," maintaining your ordering. For n = 4, k = 3:
(4, 0, 0)
(3, 1, 0)
(2, 2, 0)
(2, 1, 1)
So, how to implement this? It looks like: while subtracting 1 from position i and adding it to the next position maintains our order, subtract 1 from position i, add 1 to position i + 1, and move to the next position. If we're in the last position, step back.
Here's a little python which does just that:
def partition_helper(l, i, result):
if i == len(l) - 1:
return
while l[i] - 1 >= l[i + 1] + 1:
l[i] -= 1
l[i + 1] += 1
result.append(list(l))
partition_helper(l, i + 1, result)
def partition(n, k):
l = [n] + [0] * (k - 1)
result = [list(l)]
partition_helper(l, 0, result)
return result
Now you have a list of lists (really a list of multisets), and generating all permutations of each multiset of the list gives you your solution. I won't go into that, there's a recursive algorithm which basically says, for each position, choose each unique element in the multiset and append the permutations of the multiset resulting from removing that element from the multiset.
Given that you ask this out of interest, you would probably be interested an authorative answer! It can be found in "7.2.1.2 - Generating all permutations" of Knuth's The Art of Computer Programming (subvolume 4A).
Also, 3 concrete algorithms can be found here.
As noted by #pbarranis, the code by #rlibby does not include all lists when n equals k. Below is Python code which does include all lists. This code is non-recursive, which may be more efficient with respect to memory usage.
def successor(n, l):
idx = [j for j in range(len(l)) if l[j] < l[0]-1]
if not idx:
return False
i = idx[0]
l[1:i+1] = [l[i]+1]*(len(l[1:i+1]))
l[0] = n - sum(l[1:])
return True
def partitions(n, k):
l = [0]*k
l[0] = n
results = []
results.append(list(l))
while successor(n, l):
results.append(list(l))
return results
The lists are created in colexicographic order (algorithm and more description here).
I found that using a recursive function was not good for larger lengths and integers because it chews up too much RAM, and using a generator / resumable-function (that 'yields' values) was too slow and required a large library to make it cross-platform.
So here's a non-recursive solution in C++ that produces the partitions in sorted order (which is ideal for permutations too). I've found this to be over 10 times faster than seemingly clever and concise recursive solutions I tried for partition lengths of 4 or greater, but for lengths of 1-3 the performance is not necessarily better (and I don't care about short lengths because they're fast with either approach).
// Inputs
unsigned short myInt = 10;
unsigned short len = 3;
// Partition variables.
vector<unsigned short> partition(len);
unsigned short last = len - 1;
unsigned short penult = last - 1;
short cur = penult; // Can dip into negative value when len is 1 or 2. Can be changed to unsigned if len is always >=3.
unsigned short sum = 0;
// Prefill partition with 0.
fill(partition.begin(), partition.end(), 0);
do {
// Calculate remainder.
partition[last] = max(0, myInt - sum); // Would only need "myInt - sum" if partition vector contains signed ints.
/*
*
* DO SOMETHING WITH "partition" HERE.
*
*/
if (partition[cur + 1] <= partition[cur] + 1) {
do {
cur--;
} while (
cur > 0 &&
accumulate(partition.cbegin(), partition.cbegin() + cur, 0) + (len - cur) * (partition[cur] + 1) > myInt
);
// Escape if seeked behind too far.
// I think this if-statement is only useful when len is 1 or 2, can probably be removed if len is always >=3.
if (cur < 0) {
break;
}
// Increment the new cur position.
sum++;
partition[cur]++;
// The value in each position must be at least as large as the
// value in the previous position.
for (unsigned short i = cur + 1; i < last; ++i) {
sum = sum - partition[i] + partition[i - 1];
partition[i] = partition[i - 1];
}
// Reset cur for next time.
cur = penult;
}
else {
sum++;
partition[penult]++;
}
} while (myInt - sum >= partition[penult]);
Where I've written DO SOMETHING WITH "partition" HERE. is where you would actually consume the value. (On the last iteration the code will continue to execute the remainder of the loop but I found this to be better than constantly checking for exit conditions - it's optimised for larger operations)
0,0,10
0,1,9
0,2,8
0,3,7
0,4,6
0,5,5
1,1,8
1,2,7
1,3,6
1,4,5
2,2,6
2,3,5
2,4,4
3,3,4
Oh I've used "unsigned short" because I know my length and integer won't exceed certain limits, change that if it's not suitable for you :) Check the comments; one variable there (cur) had to be signed to handle lengths of 1 or 2 and there's a corresponding if-statement that goes with that, and I've also noted in a comment that if your partition vector has signed ints there is another line that can be simplified.
To get all the compositions, in C++ I would use this simple permutation strategy which thankfully does not produce any duplicates:
do {
// Your code goes here.
} while (next_permutation(partition.begin(), partition.end()));
Nest that in the DO SOMETHING WITH "partition" HERE spot, and you're good to go.
An alternative to finding the compositions (based on the Java code here https://www.nayuki.io/page/next-lexicographical-permutation-algorithm) is as follows. I've found this to perform better than next_permutation().
// Process lexicographic permutations of partition (compositions).
composition = partition;
do {
// Your code goes here.
// Find longest non-increasing suffix
i = last;
while (i > 0 && composition[i - 1] >= composition[i]) {
--i;
}
// Now i is the head index of the suffix
// Are we at the last permutation already?
if (i <= 0) {
break;
}
// Let array[i - 1] be the pivot
// Find rightmost element that exceeds the pivot
j = last;
while (composition[j] <= composition[i - 1])
--j;
// Now the value array[j] will become the new pivot
// Assertion: j >= i
// Swap the pivot with j
temp = composition[i - 1];
composition[i - 1] = composition[j];
composition[j] = temp;
// Reverse the suffix
j = last;
while (i < j) {
temp = composition[i];
composition[i] = composition[j];
composition[j] = temp;
++i;
--j;
}
} while (true);
You'll notice some undeclared variables there, just declare them earlier in the code before all your do-loops: i, j, pos, and temp (unsigned shorts), and composition (same type and length as partition). You can reuse the declaration of i for it's use in a for-loop in the partitions code snippet. Also note variables like last being used which assume this code is nested within the partitions code given earlier.
Again "Your code goes here" is where you consume the composition for your own purposes.
For reference here are my headers.
#include <vector> // for std::vector
#include <numeric> // for std::accumulate
#include <algorithm> // for std::next_permutation and std::max
using namespace std;
Despite the massive increase in speed using these approaches, for any sizeable integers and partition lengths this will still make you mad at your CPU :)
Like I mentioned above, I couldn't get #rlibby's code to work for my needs, and I needed code where n=l, so just a subset of your need. Here's my code below, in C#. I know it's not perfectly an answer to the question above, but I believe you'd only have to modify the first method to make it work for different values of l; basically add the same code #rlibby did, making the array of length l instead of length n.
public static List<int[]> GetPartitionPermutations(int n)
{
int[] l = new int[n];
var results = new List<int[]>();
GeneratePermutations(l, n, n, 0, results);
return results;
}
private static void GeneratePermutations(int[] l, int n, int nMax, int i, List<int[]> results)
{
if (n == 0)
{
for (; i < l.Length; ++i)
{
l[i] = 0;
}
results.Add(l.ToArray());
return;
}
for (int cnt = Math.Min(nMax, n); cnt > 0; --cnt)
{
l[i] = cnt;
GeneratePermutations(l, (n - cnt), cnt, i + 1, results);
}
}
A lot of searching led to this question. Here is an answer that includes the permutations:
#!/usr/bin/python
from itertools import combinations_with_replacement as cr
def all_partitions(n, k):
"""
Return all possible combinations that add up to n
i.e. divide n objects in k DISTINCT boxes in all possible ways
"""
all_part = []
for div in cr(range(n+1), k-1):
counts = [div[0]]
for i in range(1, k-1):
counts.append(div[i] - div[i-1])
counts.append(n-div[-1])
all_part.append(counts)
return all_part
For instance, all_part(4, 3) as asked by OP gives:
[[0, 0, 4],
[0, 1, 3],
[0, 2, 2],
[0, 3, 1],
[0, 4, 0],
[1, 0, 3],
[1, 1, 2],
[1, 2, 1],
[1, 3, 0],
[2, 0, 2],
[2, 1, 1],
[2, 2, 0],
[3, 0, 1],
[3, 1, 0],
[4, 0, 0]]

Resources