Evenly distribute values into array - c++
I have a fixed size boolean array of size 8. The default value of all elements in the array is false. There will be a number of truth values to fill between 1-8.
I want to distribute the truth values as far away from one another as possible. I also wish to be able to randomize the configuration. In this scenario the array wraps around so position 7 is "next to" position 0 in the array.
here are some examples for fill values. I didn't include all possibilities, but hopefully it gets my point across.
1: [1, 0, 0, 0, 0, 0, 0, 0] or [0, 1, 0, 0, 0, 0, 0, 0]
2: [1, 0, 0, 0, 1, 0, 0, 0] or [0, 1, 0, 0, 0, 1, 0, 0]
3: [1, 0, 0, 1, 0, 0, 1, 0] or [0, 1, 0, 0, 1, 0, 0, 1]
4: [1, 0, 1, 0, 1, 0, 1, 0] or [0, 1, 0, 1, 0, 1, 0, 1]
5: [1, 1, 0, 1, 1, 0, 1, 0]
6: [1, 1, 0, 1, 1, 1, 0, 1]
7: [1, 1, 1, 1, 1, 1, 1, 0]
8: [1, 1, 1, 1, 1, 1, 1, 1]
The closest solution I have come up with so far hasn't quite produced the results I'm looking for...
I seek to write it in c++ but here is a little pseudo-code of my algorithm so far...
not quite working out how I wanted
truths = randBetween(1, 8)
values = [0,0,0,0,0,0,0,0]
startPosition = randBetween(0, 7) //starting index
distance = 4
for(i = 0; i < truths; i++) {
pos = i + startPosition + (i * distance)
values[pos % 8] = 1
}
this is an example output from my current code. those marked with a star are incorrect.
[0, 0, 0, 0, 1, 0, 0, 0]
[0, 1, 0, 0, 1, 0, 0, 0]*
[0, 1, 0, 0, 1, 0, 1, 0]
[0, 1, 0, 1, 1, 0, 1, 0]*
[1, 1, 0, 1, 1, 0, 1, 0]
[1, 1, 0, 1, 1, 1, 1, 0]*
[1, 1, 1, 1, 1, 1, 1, 0]
[1, 1, 1, 1, 1, 1, 1, 1]
I'm looking for a simple way to distribute the truth values evenly throughout the array without having to code for special cases.
Check this out:
#include <cassert>
#include <vector>
#include <iostream>
#include <iomanip>
/**
* Generate an even spaced pattern of ones
* #param arr destination vector of ints
* #param onescnt the requested number of ones
*/
static inline
void gen(std::vector<int>& arr, size_t onescnt) {
const size_t len = arr.size();
const size_t zeroscnt = len - onescnt;
size_t ones = 1;
size_t zeros = 1;
for (size_t i = 0; i < len; ++i) {
if (ones * zeroscnt < zeros * onescnt) {
ones++;
arr[i] = 1;
} else {
zeros++;
arr[i] = 0;
}
}
}
static inline
size_t count(const std::vector<int>& arr, int el) {
size_t cnt = 0;
for (size_t i = 0; i < arr.size(); ++i) {
cnt += arr[i] == el;
}
return cnt;
}
static inline
void gen_print(size_t len, size_t onescnt) {
std::vector<int> arr(len);
gen(arr, onescnt);
std::cout << "gen_printf(" << std::setw(2) << len << ", " << std::setw(2) << onescnt << ") = {";
for (size_t i = 0; i < len; ++i) {
std::cout << arr[i] << ",";
}
std::cout << "}\n";
assert(count(arr, 1) == onescnt);
}
int main() {
for (int i = 0; i <= 8; ++i) {
gen_print(8, i);
}
for (int i = 0; i <= 30; ++i) {
gen_print(30, i);
}
return 0;
}
Generates:
gen_printf( 8, 0) = {0,0,0,0,0,0,0,0,}
gen_printf( 8, 1) = {0,0,0,0,0,0,0,1,}
gen_printf( 8, 2) = {0,0,0,1,0,0,0,1,}
gen_printf( 8, 3) = {0,1,0,0,1,0,0,1,}
gen_printf( 8, 4) = {0,1,0,1,0,1,0,1,}
gen_printf( 8, 5) = {1,0,1,1,0,1,0,1,}
gen_printf( 8, 6) = {1,1,0,1,1,1,0,1,}
gen_printf( 8, 7) = {1,1,1,1,1,1,0,1,}
gen_printf( 8, 8) = {1,1,1,1,1,1,1,1,}
gen_printf(30, 0) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}
gen_printf(30, 1) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,}
gen_printf(30, 2) = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,}
gen_printf(30, 3) = {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,}
gen_printf(30, 4) = {0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,}
gen_printf(30, 5) = {0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,}
gen_printf(30, 6) = {0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,}
gen_printf(30, 7) = {0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,}
gen_printf(30, 8) = {0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,}
gen_printf(30, 9) = {0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,}
gen_printf(30, 10) = {0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,}
gen_printf(30, 11) = {0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,}
gen_printf(30, 12) = {0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,}
gen_printf(30, 13) = {0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,}
gen_printf(30, 14) = {0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,}
gen_printf(30, 15) = {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,}
gen_printf(30, 16) = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,}
gen_printf(30, 17) = {1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,}
gen_printf(30, 18) = {1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,}
gen_printf(30, 19) = {1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,0,1,}
gen_printf(30, 20) = {1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,}
gen_printf(30, 21) = {1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,0,1,}
gen_printf(30, 22) = {1,1,0,1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,0,1,}
gen_printf(30, 23) = {1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,}
gen_printf(30, 24) = {1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,}
gen_printf(30, 25) = {1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,}
gen_printf(30, 26) = {1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,}
gen_printf(30, 27) = {1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,}
gen_printf(30, 28) = {1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,}
gen_printf(30, 29) = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,}
gen_printf(30, 30) = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,}
#edit - better evenly spaced pattern.
Explanation:
So let's take an array of 8 ints and we want to have 5 ones. The ideal ratio of (ones / zeros) in a sequence with 8 elements and 5 ones, well would be (5 / 3). We will never approach such ratio, but we can try.
The idea is to loop through the array and remember the number of ones and zeros we have written in the array. If the ratio of (written ones / written zeros) is lower then the destination ratio (ones / zeros) we want to achieve, we need to put a one to the sequence. Otherwise we put zero in the sequence. The ratio changes and we make the decision next time. The idea is to pursue the ideal ratio of ones per zeros in each slice of the array.
A simple way to do this would be to round the ideal fractional positions.
truths = randBetween(1, 8)
values = [0,0,0,0,0,0,0,0]
offset = randBetween(0, 8 * truths - 1)
for(i = 0; i < truths; i++) {
pos = (offset + (i * 8)) / truths
values[pos % 8] = 1
}
This is an application of Bresenham's line-drawing algorithm. I use it not because it's fast on old hardware, but it places true values exactly.
#include <iostream>
#include <stdexcept>
#include <string>
#include <random>
int main(int argc, char **argv) {
try {
// Read the argument.
if(argc != 2) throw std::invalid_argument("one argument");
int dy = std::stoi(argv[1]);
if(dy < 0 || dy > 8) throw std::out_of_range("[0..8]");
int values[8] = {0};
// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
int dx = 8;
int delta = 2 * dy - dx; // Balance the line. Permute it up later.
for(int x = 0; x < dx; x++) {
if(delta > 0) {
values[x] = 1;
delta -= 2 * dx;
}
delta += 2 * dy;
}
for(int x = 0; x < dx; x++)
std::cout << (x ? ", " : "") << values[x];
std::cout << std::endl;
// Rotate the number by a random amount.
// I'm sure there is an easier way to do this.
// https://stackoverflow.com/questions/7560114/random-number-c-in-some-range
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, dx - 1);
int rotate = distr(eng);
bool first = true;
int x = rotate;
do {
std::cout << (first ? "" : ", ") << values[x];
first = false;
x = (x + 1) % dx;
} while(x != rotate);
std::cout << std::endl;
} catch(const std::exception &e) {
std::cerr << "Something went wrong: " << e.what() << std::endl;
return 1;
}
return 0;
}
Once you have an exact solution, rotate it by a random amount.
0, 1, 0, 0, 1, 0, 1, 0
1, 0, 0, 1, 0, 0, 1, 0
You need to calculate distance dynamically. One element is clear, that can reside at arbitrary location
2 elements is clear, too, distance needs to be 4.
4 elements need a distance of 2
8 elements a distance of 1
More difficult are numbers that don't divide the array:
3 requires a distance of 2.66.
5 requires a distance of 1.6
7 requires a distance of 0.875
Errm... In general, if you have a distance of X.Y, you will have to place some of the elements at distances of X and some at distances of X + 1. X is simple, it will be the result of an integer division: 8 / numberOfElements. The remainder will determine how often you will have to switch to X + 1: 8 % numberOfElements. For 3, this will result in 2, too, so you will have 1x distance of 2 and 2x distance of 3:
[ 1 0 1 0 0 1 0 0 ]
2 3 3 (distance to very first 1)
For 5, you'll get: 8/5 = 1, 8%5 = 3, so: 2x distance of 1, 3x distance of 2
[ 1 1 1 0 1 0 1 0 ]
1 1 2 2 2
For 7 you'll get: 8/7 = 1, 8%7 = 1, so: 7x distance of 1, 1x distance of 2
[ 1 1 1 1 1 1 1 0 ]
1 1 1 1 1 1 2
That will work for arbitrary array length L:
L/n = minimum distance
L%n = number of times to apply minimum distance
L-L%n = number of times to apply minimum distance + 1
Mathematical metrics won't reveal any difference between first applying all smaller distances then all larger ones, human sense for aesthetics, though, might prefer if you alternate between larger and smaller as often as possible – or you apply the algorithm recursively (for larger array length), to get something like 2x2, 3x3, 2x2, 3x3 instead of 4x2 and 6x3.
Related
Hand executing a C++ vector
I'm new to programming and C++, in my course I need to hand execute a program and show how the elements change and which ones. I'm a bit stuck on this but I think I'm on the right track. Any assistance would be really appreciated. void data(vector<double> &data, int idx, double value) { data.push_back(value); if (idx >= data.size() - 1) return; if (idx < 0) idx = 0; for(int i = data.size() - 1; i > idx; i--) { data[i] = data[i -1]; data[i - 1] = value; } } The data set I'm using is: [4, -6, 0, 8, -7] idx: 2 value: -7 So the -7 value is what is push_back onto the end of the vector I think I've figured out some of it, data.size() - 1 means the last element in the array and if the idx is greater or equal to the last element return that value? The for loop seems to iterate backwards to me.
If your problem is to figure out the purpose of this algorithm, read this answer. Let's first take your example: std::vector<double> a{ 4, -6, 0, 8, -7 }; data(a, 2, -7); The result is: 4, -6, -7, 0, 8, -7 It should be clear that data(vec, idx, val) inserts val into the vec so that it is the idxth element and the vec increased its size by 1. If idx is out of range, it is adjusted to 0 (if < 0) or vec.size() (if >= vec.size().) Edit: Visualization: Initially: 4, -6, 0, 8, -7, -7 First iteration I = data.size() - 1 = 5: 4, -6, 0, 8, -7, -7 (data[5] = data[4]) 4, -6, 0, 8, -7, -7 (data[4] = value) (Note: here -7 = -7 so nothing changes) Second iteration I = 4: 4, -6, 0, 8, 8, -7 (data[4] = data[3]) 4, -6, 0, -7, 8, -7 (data[3] = value) Third iteration I = 3: 4, -6, 0, 0, 8, -7 (data[3] = data[2]) 4, -6, -7, 0, 8, -7 (data[2] = value) Now I = 2, over.
if (idx >= data.size() - 1) return; Actually you check that the index isn't outside of the array. data.size() - 1 is the last element, so idx can be the second last element at most. We will see why this. if (idx < 0) idx = 0; If the index is lower than 0, just set it to 0 to access the first element for(int i = data.size() - 1; i > idx; i--) You start with the index of the last element, and as long as it is greater than idx you continue with another iteration (and decrement it). So in your example you would have two iterations with i = 4 and i = 3. idx is like a lower exclusive bound data[i] = data[i -1]; data[i - 1] = value; You first copy the previous element to the current one, and then the value (-7 in your case) to the previous element. So in the last iteration i-1 will be the same as idx. And because of that idx cannot be the last element, because then the loop won't enter. So what this actually does, is inserting value step-by-step from the end of the vector to the position idx. The last element is lost and the others slide one position up. Every iteration it gets one position more to the left and what was there before steps up.
Largest Area Axis-Aligned Rectangle Inside Convex Polygon [duplicate]
Given an NxN binary matrix (containing only 0's or 1's), how can we go about finding largest rectangle containing all 0's? Example: I 0 0 0 0 1 0 0 0 1 0 0 1 II->0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 <--IV 0 0 1 0 0 0 IV For the above example, it is a 6×6 binary matrix. the return value in this case will be Cell 1:(2, 1) and Cell 2:(4, 4). The resulting sub-matrix can be square or rectangular. The return value can also be the size of the largest sub-matrix of all 0's, in this example 3 × 4.
Here's a solution based on the "Largest Rectangle in a Histogram" problem suggested by #j_random_hacker in the comments: [Algorithm] works by iterating through rows from top to bottom, for each row solving this problem, where the "bars" in the "histogram" consist of all unbroken upward trails of zeros that start at the current row (a column has height 0 if it has a 1 in the current row). The input matrix mat may be an arbitrary iterable e.g., a file or a network stream. Only one row is required to be available at a time. #!/usr/bin/env python from collections import namedtuple from operator import mul Info = namedtuple('Info', 'start height') def max_size(mat, value=0): """Find height, width of the largest rectangle containing all `value`'s.""" it = iter(mat) hist = [(el==value) for el in next(it, [])] max_size = max_rectangle_size(hist) for row in it: hist = [(1+h) if el == value else 0 for h, el in zip(hist, row)] max_size = max(max_size, max_rectangle_size(hist), key=area) return max_size def max_rectangle_size(histogram): """Find height, width of the largest rectangle that fits entirely under the histogram. """ stack = [] top = lambda: stack[-1] max_size = (0, 0) # height, width of the largest rectangle pos = 0 # current position in the histogram for pos, height in enumerate(histogram): start = pos # position where rectangle starts while True: if not stack or height > top().height: stack.append(Info(start, height)) # push elif stack and height < top().height: max_size = max(max_size, (top().height, (pos - top().start)), key=area) start, _ = stack.pop() continue break # height == top().height goes here pos += 1 for start, height in stack: max_size = max(max_size, (height, (pos - start)), key=area) return max_size def area(size): return reduce(mul, size) The solution is O(N), where N is the number of elements in a matrix. It requires O(ncols) additional memory, where ncols is the number of columns in a matrix. Latest version with tests is at https://gist.github.com/776423
Please take a look at Maximize the rectangular area under Histogram and then continue reading the solution below. Traverse the matrix once and store the following; For x=1 to N and y=1 to N F[x][y] = 1 + F[x][y-1] if A[x][y] is 0 , else 0 Then for each row for x=N to 1 We have F[x] -> array with heights of the histograms with base at x. Use O(N) algorithm to find the largest area of rectangle in this histogram = H[x] From all areas computed, report the largest. Time complexity is O(N*N) = O(N²) (for an NxN binary matrix) Example: Initial array F[x][y] array 0 0 0 0 1 0 1 1 1 1 0 1 0 0 1 0 0 1 2 2 0 2 1 0 0 0 0 0 0 0 3 3 1 3 2 1 1 0 0 0 0 0 0 4 2 4 3 2 0 0 0 0 0 1 1 5 3 5 4 0 0 0 1 0 0 0 2 6 0 6 5 1 For x = N to 1 H[6] = 2 6 0 6 5 1 -> 10 (5*2) H[5] = 1 5 3 5 4 0 -> 12 (3*4) H[4] = 0 4 2 4 3 2 -> 10 (2*5) H[3] = 3 3 1 3 2 1 -> 6 (3*2) H[2] = 2 2 0 2 1 0 -> 4 (2*2) H[1] = 1 1 1 1 0 1 -> 4 (1*4) The largest area is thus H[5] = 12
Here is a Python3 solution, which returns the position in addition to the area of the largest rectangle: #!/usr/bin/env python3 import numpy s = '''0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0''' nrows = 6 ncols = 6 skip = 1 area_max = (0, []) a = numpy.fromstring(s, dtype=int, sep=' ').reshape(nrows, ncols) w = numpy.zeros(dtype=int, shape=a.shape) h = numpy.zeros(dtype=int, shape=a.shape) for r in range(nrows): for c in range(ncols): if a[r][c] == skip: continue if r == 0: h[r][c] = 1 else: h[r][c] = h[r-1][c]+1 if c == 0: w[r][c] = 1 else: w[r][c] = w[r][c-1]+1 minw = w[r][c] for dh in range(h[r][c]): minw = min(minw, w[r-dh][c]) area = (dh+1)*minw if area > area_max[0]: area_max = (area, [(r-dh, c-minw+1, r, c)]) print('area', area_max[0]) for t in area_max[1]: print('Cell 1:({}, {}) and Cell 2:({}, {})'.format(*t)) Output: area 12 Cell 1:(2, 1) and Cell 2:(4, 4)
Here is J.F. Sebastians method translated into C#: private Vector2 MaxRectSize(int[] histogram) { Vector2 maxSize = Vector2.zero; int maxArea = 0; Stack<Vector2> stack = new Stack<Vector2>(); int x = 0; for (x = 0; x < histogram.Length; x++) { int start = x; int height = histogram[x]; while (true) { if (stack.Count == 0 || height > stack.Peek().y) { stack.Push(new Vector2(start, height)); } else if(height < stack.Peek().y) { int tempArea = (int)(stack.Peek().y * (x - stack.Peek().x)); if(tempArea > maxArea) { maxSize = new Vector2(stack.Peek().y, (x - stack.Peek().x)); maxArea = tempArea; } Vector2 popped = stack.Pop(); start = (int)popped.x; continue; } break; } } foreach (Vector2 data in stack) { int tempArea = (int)(data.y * (x - data.x)); if(tempArea > maxArea) { maxSize = new Vector2(data.y, (x - data.x)); maxArea = tempArea; } } return maxSize; } public Vector2 GetMaximumFreeSpace() { // STEP 1: // build a seed histogram using the first row of grid points // example: [true, true, false, true] = [1,1,0,1] int[] hist = new int[gridSizeY]; for (int y = 0; y < gridSizeY; y++) { if(!invalidPoints[0, y]) { hist[y] = 1; } } // STEP 2: // get a starting max area from the seed histogram we created above. // using the example from above, this value would be [1, 1], as the only valid area is a single point. // another example for [0,0,0,1,0,0] would be [1, 3], because the largest area of contiguous free space is 3. // Note that at this step, the heigh fo the found rectangle will always be 1 because we are operating on // a single row of data. Vector2 maxSize = MaxRectSize(hist); int maxArea = (int)(maxSize.x * maxSize.y); // STEP 3: // build histograms for each additional row, re-testing for new possible max rectangluar areas for (int x = 1; x < gridSizeX; x++) { // build a new histogram for this row. the values of this row are // 0 if the current grid point is occupied; otherwise, it is 1 + the value // of the previously found historgram value for the previous position. // What this does is effectly keep track of the height of continous avilable spaces. // EXAMPLE: // Given the following grid data (where 1 means occupied, and 0 means free; for clairty): // INPUT: OUTPUT: // 1.) [0,0,1,0] = [1,1,0,1] // 2.) [0,0,1,0] = [2,2,0,2] // 3.) [1,1,0,1] = [0,0,1,0] // // As such, you'll notice position 1,0 (row 1, column 0) is 2, because this is the height of contiguous // free space. for (int y = 0; y < gridSizeY; y++) { if(!invalidPoints[x, y]) { hist[y] = 1 + hist[y]; } else { hist[y] = 0; } } // find the maximum size of the current histogram. If it happens to be larger // that the currently recorded max size, then it is the new max size. Vector2 maxSizeTemp = MaxRectSize(hist); int tempArea = (int)(maxSizeTemp.x * maxSizeTemp.y); if (tempArea > maxArea) { maxSize = maxSizeTemp; maxArea = tempArea; } } // at this point, we know the max size return maxSize; } A few things to note about this: This version is meant for use with the Unity API. You can easily make this more generic by replacing instances of Vector2 with KeyValuePair. Vector2 is only used for a convenient way to store two values. invalidPoints[] is an array of bool, where true means the grid point is "in use", and false means it is not.
Solution with space complexity O(columns) [Can be modified to O(rows) also] and time complexity O(rows*columns) public int maximalRectangle(char[][] matrix) { int m = matrix.length; if (m == 0) return 0; int n = matrix[0].length; int maxArea = 0; int[] aux = new int[n]; for (int i = 0; i < n; i++) { aux[i] = 0; } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { aux[j] = matrix[i][j] - '0' + aux[j]; maxArea = Math.max(maxArea, maxAreaHist(aux)); } } return maxArea; } public int maxAreaHist(int[] heights) { int n = heights.length; Stack<Integer> stack = new Stack<Integer>(); stack.push(0); int maxRect = heights[0]; int top = 0; int leftSideArea = 0; int rightSideArea = heights[0]; for (int i = 1; i < n; i++) { if (stack.isEmpty() || heights[i] >= heights[stack.peek()]) { stack.push(i); } else { while (!stack.isEmpty() && heights[stack.peek()] > heights[i]) { top = stack.pop(); rightSideArea = heights[top] * (i - top); leftSideArea = 0; if (!stack.isEmpty()) { leftSideArea = heights[top] * (top - stack.peek() - 1); } else { leftSideArea = heights[top] * top; } maxRect = Math.max(maxRect, leftSideArea + rightSideArea); } stack.push(i); } } while (!stack.isEmpty()) { top = stack.pop(); rightSideArea = heights[top] * (n - top); leftSideArea = 0; if (!stack.isEmpty()) { leftSideArea = heights[top] * (top - stack.peek() - 1); } else { leftSideArea = heights[top] * top; } maxRect = Math.max(maxRect, leftSideArea + rightSideArea); } return maxRect; } But I get Time Limite exceeded excpetion when I try this on LeetCode. Is there any less complex solution?
I propose a O(nxn) method. First, you can list all the maximum empty rectangles. Empty means that it covers only 0s. A maximum empty rectangle is such that it cannot be extended in a direction without covering (at least) one 1. A paper presenting a O(nxn) algorithm to create such a list can be found at www.ulg.ac.be/telecom/rectangles as well as source code (not optimized). There is no need to store the list, it is sufficient to call a callback function each time a rectangle is found by the algorithm, and to store only the largest one (or choose another criterion if you want). Note that a proof exists (see the paper) that the number of largest empty rectangles is bounded by the number of pixels of the image (nxn in this case). Therefore, selecting the optimal rectangle can be done in O(nxn), and the overall method is also O(nxn). In practice, this method is very fast, and is used for realtime video stream analysis.
Here is a version of jfs' solution, which also delivers the position of the largest rectangle: from collections import namedtuple from operator import mul Info = namedtuple('Info', 'start height') def max_rect(mat, value=0): """returns (height, width, left_column, bottom_row) of the largest rectangle containing all `value`'s. Example: [[0, 0, 0, 0, 0, 0, 0, 0, 3, 2], [0, 4, 0, 2, 4, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 0, 3, 0, 0, 4], [0, 0, 0, 0, 4, 2, 0, 0, 0, 0], [0, 0, 0, 2, 0, 0, 0, 0, 0, 0], [4, 3, 0, 0, 1, 2, 0, 0, 0, 0], [3, 0, 0, 0, 2, 0, 0, 0, 0, 4], [0, 0, 0, 1, 0, 3, 2, 4, 3, 2], [0, 3, 0, 0, 0, 2, 0, 1, 0, 0]] gives: (3, 4, 6, 5) """ it = iter(mat) hist = [(el==value) for el in next(it, [])] max_rect = max_rectangle_size(hist) + (0,) for irow,row in enumerate(it): hist = [(1+h) if el == value else 0 for h, el in zip(hist, row)] max_rect = max(max_rect, max_rectangle_size(hist) + (irow+1,), key=area) # irow+1, because we already used one row for initializing max_rect return max_rect def max_rectangle_size(histogram): stack = [] top = lambda: stack[-1] max_size = (0, 0, 0) # height, width and start position of the largest rectangle pos = 0 # current position in the histogram for pos, height in enumerate(histogram): start = pos # position where rectangle starts while True: if not stack or height > top().height: stack.append(Info(start, height)) # push elif stack and height < top().height: max_size = max(max_size, (top().height, (pos - top().start), top().start), key=area) start, _ = stack.pop() continue break # height == top().height goes here pos += 1 for start, height in stack: max_size = max(max_size, (height, (pos - start), start), key=area) return max_size def area(size): return size[0] * size[1]
To be complete, here's the C# version which outputs the rectangle coordinates. It's based on dmarra's answer but without any other dependencies. There's only the function bool GetPixel(int x, int y), which returns true when a pixel is set at the coordinates x,y. public struct INTRECT { public int Left, Right, Top, Bottom; public INTRECT(int aLeft, int aTop, int aRight, int aBottom) { Left = aLeft; Top = aTop; Right = aRight; Bottom = aBottom; } public int Width { get { return (Right - Left + 1); } } public int Height { get { return (Bottom - Top + 1); } } public bool IsEmpty { get { return Left == 0 && Right == 0 && Top == 0 && Bottom == 0; } } public static bool operator ==(INTRECT lhs, INTRECT rhs) { return lhs.Left == rhs.Left && lhs.Top == rhs.Top && lhs.Right == rhs.Right && lhs.Bottom == rhs.Bottom; } public static bool operator !=(INTRECT lhs, INTRECT rhs) { return !(lhs == rhs); } public override bool Equals(Object obj) { return obj is INTRECT && this == (INTRECT)obj; } public bool Equals(INTRECT obj) { return this == obj; } public override int GetHashCode() { return Left.GetHashCode() ^ Right.GetHashCode() ^ Top.GetHashCode() ^ Bottom.GetHashCode(); } } public INTRECT GetMaximumFreeRectangle() { int XEnd = 0; int YStart = 0; int MaxRectTop = 0; INTRECT MaxRect = new INTRECT(); // STEP 1: // build a seed histogram using the first row of grid points // example: [true, true, false, true] = [1,1,0,1] int[] hist = new int[Height]; for (int y = 0; y < Height; y++) { if (!GetPixel(0, y)) { hist[y] = 1; } } // STEP 2: // get a starting max area from the seed histogram we created above. // using the example from above, this value would be [1, 1], as the only valid area is a single point. // another example for [0,0,0,1,0,0] would be [1, 3], because the largest area of contiguous free space is 3. // Note that at this step, the heigh fo the found rectangle will always be 1 because we are operating on // a single row of data. Tuple<int, int> maxSize = MaxRectSize(hist, out YStart); int maxArea = (int)(maxSize.Item1 * maxSize.Item2); MaxRectTop = YStart; // STEP 3: // build histograms for each additional row, re-testing for new possible max rectangluar areas for (int x = 1; x < Width; x++) { // build a new histogram for this row. the values of this row are // 0 if the current grid point is occupied; otherwise, it is 1 + the value // of the previously found historgram value for the previous position. // What this does is effectly keep track of the height of continous avilable spaces. // EXAMPLE: // Given the following grid data (where 1 means occupied, and 0 means free; for clairty): // INPUT: OUTPUT: // 1.) [0,0,1,0] = [1,1,0,1] // 2.) [0,0,1,0] = [2,2,0,2] // 3.) [1,1,0,1] = [0,0,1,0] // // As such, you'll notice position 1,0 (row 1, column 0) is 2, because this is the height of contiguous // free space. for (int y = 0; y < Height; y++) { if (!GetPixel(x, y)) { hist[y]++; } else { hist[y] = 0; } } // find the maximum size of the current histogram. If it happens to be larger // that the currently recorded max size, then it is the new max size. Tuple<int, int> maxSizeTemp = MaxRectSize(hist, out YStart); int tempArea = (int)(maxSizeTemp.Item1 * maxSizeTemp.Item2); if (tempArea > maxArea) { maxSize = maxSizeTemp; maxArea = tempArea; MaxRectTop = YStart; XEnd = x; } } MaxRect.Left = XEnd - maxSize.Item1 + 1; MaxRect.Top = MaxRectTop; MaxRect.Right = XEnd; MaxRect.Bottom = MaxRectTop + maxSize.Item2 - 1; // at this point, we know the max size return MaxRect; } private Tuple<int, int> MaxRectSize(int[] histogram, out int YStart) { Tuple<int, int> maxSize = new Tuple<int, int>(0, 0); int maxArea = 0; Stack<Tuple<int, int>> stack = new Stack<Tuple<int, int>>(); int x = 0; YStart = 0; for (x = 0; x < histogram.Length; x++) { int start = x; int height = histogram[x]; while (true) { if (stack.Count == 0 || height > stack.Peek().Item2) { stack.Push(new Tuple<int, int>(start, height)); } else if (height < stack.Peek().Item2) { int tempArea = (int)(stack.Peek().Item2 * (x - stack.Peek().Item1)); if (tempArea > maxArea) { YStart = stack.Peek().Item1; maxSize = new Tuple<int, int>(stack.Peek().Item2, (x - stack.Peek().Item1)); maxArea = tempArea; } Tuple<int, int> popped = stack.Pop(); start = (int)popped.Item1; continue; } break; } } foreach (Tuple<int, int> data in stack) { int tempArea = (int)(data.Item2 * (x - data.Item1)); if (tempArea > maxArea) { YStart = data.Item1; maxSize = new Tuple<int, int>(data.Item2, (x - data.Item1)); maxArea = tempArea; } } return maxSize; }
An appropriate algorithm can be found within Algorithm for finding the largest inscribed rectangle in polygon (2019). I implemented it in python: import largestinteriorrectangle as lir import numpy as np grid = np.array([[0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 1], [0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0]], "bool") grid = ~grid lir.lir(grid) # [1, 2, 4, 3] the result comes as x, y, width, height
calculate gradient directions
I want calculate angles of gradients from depth map and group it for some directions (8 sectors) But my function calculates only first 3 directions cv::Mat calcAngles(cv::Mat dimg)//dimg is depth map { const int directions_num = 8;//number of directions const int degree_grade = 360; int range_coeff = 255 / (directions_num + 1);//just for visualize cv::Mat x_edge, y_edge, full_edge, angles; dimg.copyTo(x_edge); dimg.copyTo(y_edge); dimg.copyTo(full_edge); //compute gradients Sobel( dimg, x_edge, CV_8U, 1, 0, 5, 1, 19, 4 ); Sobel( dimg, y_edge, CV_8U, 0, 1, 5, 1, 19, 4 ); Sobel( dimg, full_edge, CV_8U, 1, 1, 5, 1, 19, 4 ); float freq[directions_num + 1];//for collect direction's frequency memset(freq, 0, sizeof(freq)); angles = cv::Mat::zeros(dimg.rows, dimg.cols, CV_8U);//store directions here for(int i = 0; i < angles.rows; i++) { for(int j = 0; j < angles.cols; j++) { angles.at<uchar>(i, j) = (((int)cv::fastAtan2(y_edge.at<uchar>(i, j), x_edge.at<uchar>(i, j))) / (degree_grade/directions_num) + 1 ) * (dimg.at<uchar>(i, j) ? 1 : 0);//fastatan returns values from 0 to 360, if i not mistaken. I want group angles by directions_num sectors. I use first 'direction' (zero value) for zero values from depth map (zero value at my depth map suggest that it is bad pixel) freq[angles.at<uchar>(i, j)] += 1; } } for(int i = 0; i < directions_num + 1; i++) { printf("%2.2f\t", freq[i]); } printf("\n"); angles *= range_coeff;//for visualization return angles; } Out from one of the frames: 47359.00 15018.00 8199.00 6224.00 0.00 0.00 0.00 0.00 0.00 (first value is "zero pixel", next is number of gradients in n-place but only 3 are not zero) Visualization Is there way out? Or these result is OK? PS Sorry for my writing mistakes. English in not my native language.
You used CV_8U type for Sobel output. It is unsigned integer 8 bit. So it can store only positive values. That's why fastAtan2 returns less or equal than 90. Change type to CV_16S and use short type for accessing the elements: cv::Sobel(dimg, x_edge, CV_16S, 1, 0, 5, 1, 19, 4); cv::Sobel(dimg, y_edge, CV_16S, 0, 1, 5, 1, 19, 4); cv::fastAtan2(y_edge.at<short>(i, j), x_edge.at<short>(i, j))
Elegant way the find the Vertices of a Cube
Nearly every OpenGL tutorial lets you implement drawing a cube. Therefore the vertices of the cube are needed. In the example code I saw a long list defining every vertex. But I would like to compute the vertices of a cube rather that using a overlong list of precomputed coordinates. A cube is made of eight vertices and twelve triangles. Vertices are defined by x, y, and z. Triangles are defined each by the indexes of three vertices. Is there an elegant way to compute the vertices and the element indexes of a cube?
When i was "porting" the csg.js project to Java I've found some cute code which generated cube with selected center point and radius. (I know it's JS, but anyway) // Construct an axis-aligned solid cuboid. Optional parameters are `center` and // `radius`, which default to `[0, 0, 0]` and `[1, 1, 1]`. The radius can be // specified using a single number or a list of three numbers, one for each axis. // // Example code: // // var cube = CSG.cube({ // center: [0, 0, 0], // radius: 1 // }); CSG.cube = function(options) { options = options || {}; var c = new CSG.Vector(options.center || [0, 0, 0]); var r = !options.radius ? [1, 1, 1] : options.radius.length ? options.radius : [options.radius, options.radius, options.radius]; return CSG.fromPolygons([ [[0, 4, 6, 2], [-1, 0, 0]], [[1, 3, 7, 5], [+1, 0, 0]], [[0, 1, 5, 4], [0, -1, 0]], [[2, 6, 7, 3], [0, +1, 0]], [[0, 2, 3, 1], [0, 0, -1]], [[4, 5, 7, 6], [0, 0, +1]] ].map(function(info) { return new CSG.Polygon(info[0].map(function(i) { var pos = new CSG.Vector( c.x + r[0] * (2 * !!(i & 1) - 1), c.y + r[1] * (2 * !!(i & 2) - 1), c.z + r[2] * (2 * !!(i & 4) - 1) ); return new CSG.Vertex(pos, new CSG.Vector(info[1])); })); })); };
I solved this problem with this piece code (C#): public CubeShape(Coord3 startPos, int size) { int l = size / 2; verts = new Coord3[8]; for (int i = 0; i < 8; i++) { verts[i] = new Coord3( (i & 4) != 0 ? l : -l, (i & 2) != 0 ? l : -l, (i & 1) != 0 ? l : -l) + startPos; } tris = new Tris[12]; int vertCount = 0; void AddVert(int one, int two, int three) => tris[vertCount++] = new Tris(verts[one], verts[two], verts[three]); for (int i = 0; i < 3; i++) { int v1 = 1 << i; int v2 = v1 == 4 ? 1 : v1 << 1; AddVert(0, v1, v2); AddVert(v1 + v2, v2, v1); AddVert(7, 7 - v2, 7 - v1); AddVert(7 - (v1 + v2), 7 - v1, 7 - v2); } } If you want to understand more of what is going on, you can check out the github page I wrote that explains it.
Getting the number of trailing 1 bits
Are there any efficient bitwise operations I can do to get the number of set bits that an integer ends with? For example 1110 = 10112 would be two trailing 1 bits. 810 = 10002 would be 0 trailing 1 bits. Is there a better algorithm for this than a linear search? I'm implementing a randomized skip list and using random numbers to determine the maximum level of an element when inserting it. I am dealing with 32 bit integers in C++. Edit: assembler is out of the question, I'm interested in a pure C++ solution.
Calculate ~i & (i + 1) and use the result as a lookup in a table with 32 entries. 1 means zero 1s, 2 means one 1, 4 means two 1s, and so on, except that 0 means 32 1s.
Taking the answer from Ignacio Vazquez-Abrams and completing it with the count rather than a table: b = ~i & (i+1); // this gives a 1 to the left of the trailing 1's b--; // this gets us just the trailing 1's that need counting b = (b & 0x55555555) + ((b>>1) & 0x55555555); // 2 bit sums of 1 bit numbers b = (b & 0x33333333) + ((b>>2) & 0x33333333); // 4 bit sums of 2 bit numbers b = (b & 0x0f0f0f0f) + ((b>>4) & 0x0f0f0f0f); // 8 bit sums of 4 bit numbers b = (b & 0x00ff00ff) + ((b>>8) & 0x00ff00ff); // 16 bit sums of 8 bit numbers b = (b & 0x0000ffff) + ((b>>16) & 0x0000ffff); // sum of 16 bit numbers at the end b will contain the count of 1's (the masks, adding and shifting count the 1's). Unless I goofed of course. Test before use.
The Bit Twiddling Hacks page has a number of algorithms for counting trailing zeros. Any of them can be adapted by simply inverting your number first, and there are probably clever ways to alter the algorithms in place without doing that as well. On a modern CPU with cheap floating point operations the best is probably thus: unsigned int v=~input; // find the number of trailing ones in input int r; // the result goes here float f = (float)(v & -v); // cast the least significant bit in v to a float r = (*(uint32_t *)&f >> 23) - 0x7f; if(r==-127) r=32;
GCC has __builtin_ctz and other compilers have their own intrinsics. Just protect it with an #ifdef: #ifdef __GNUC__ int trailingones( uint32_t in ) { return ~ in == 0? 32 : __builtin_ctz( ~ in ); } #else // portable implementation #endif On x86, this builtin will compile to one very fast instruction. Other platforms might be somewhat slower, but most have some kind of bit-counting functionality that will beat what you can do with pure C operators.
There may be better answers available, particularly if assembler isn't out of the question, but one viable solution would be to use a lookup table. It would have 256 entries, each returning the number of contiguous trailing 1 bits. Apply it to the lowest byte. If it's 8, apply to the next and keep count.
Implementing Steven Sudit's idea... uint32_t n; // input value uint8_t o; // number of trailing one bits in n uint8_t trailing_ones[256] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 8}; uint8_t t; do { t=trailing_ones[n&255]; o+=t; } while(t==8 && (n>>=8)) 1 (best) to 4 (worst) (average 1.004) times (1 lookup + 1 comparison + 3 arithmetic operations) minus one arithmetic operation.
This code counts the number of trailing zero bits, taken from here (there's also a version that depends on the IEEE 32 bit floating point representation, but I wouldn't trust it, and the modulus/division approaches look really slick - also worth a try): int CountTrailingZeroBits(unsigned int v) // 32 bit { unsigned int c = 32; // c will be the number of zero bits on the right static const unsigned int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF}; static const unsigned int S[] = {1, 2, 4, 8, 16}; // Our Magic Binary Numbers for (int i = 4; i >= 0; --i) // unroll for more speed { if (v & B[i]) { v <<= S[i]; c -= S[i]; } } if (v) { c--; } return c; } and then to count trailing ones: int CountTrailingOneBits(unsigned int v) { return CountTrailingZeroBits(~v); }
http://graphics.stanford.edu/~seander/bithacks.html might give you some inspiration.
Implementation based on Ignacio Vazquez-Abrams's answer uint8_t trailing_ones(uint32_t i) { return log2(~i & (i + 1)); } Implementation of log2() is left as an exercise for the reader (see here)
Taking #phkahler's answer you can define the following preprocessor statement: #define trailing_ones(x) __builtin_ctz(~x & (x + 1)) As you get a one left to all the prior ones, you can simply count the trailing zeros.
Blazingly fast ways to find the number of trailing 0's are given in Hacker's Delight. You could complement your integer (or more generally, word) to find the number of trailing 1's.
I have this sample for you : #include <stdio.h> int trailbits ( unsigned int bits, bool zero ) { int bitsize = sizeof(int) * 8; int len = 0; int trail = 0; unsigned int compbits = bits; if ( zero ) compbits = ~bits; for ( ; bitsize; bitsize-- ) { if ( compbits & 0x01 ) trail++; else { if ( trail > 1 ) len++; trail = 0; } compbits = compbits >> 1; } if ( trail > 1 ) len++; return len; } void PrintBits ( unsigned int bits ) { unsigned int pbit = 0x80000000; for ( int len=0 ; len<32; len++ ) { printf ( "%c ", pbit & bits ? '1' : '0' ); pbit = pbit >> 1; } printf ( "\n" ); } void main(void) { unsigned int forbyte = 0x0CC00990; PrintBits ( forbyte ); printf ( "Trailing ones is %d\n", trailbits ( forbyte, false )); printf ( "Trailing zeros is %d\n", trailbits ( forbyte, true )); }