How to scale down the values so they could fit inside the min and max values - algorithm

I have 6 graph bars with the prices.
Each price number will represent its graphbar's height by respecting min and max heights.
What i want is that graph bar's height wouldn't go below or above the min and the max value.
So i have values of min = 55 and max = 110.
And price numbers are:
49
212
717
1081
93
By which mathematical algorithm I could achieve expected results ?
It's some sort of dynamic scalable bar graphs.
Modified
So the min and max values from the price list will be: 49(min price) => 55(min) and 1081 (max price) => 110(max)

The solution is simple:
Pick the smallest, and largest item and find the difference.
(largest_item - smallest_item) maps to (max-min).
Compute ratio = (max-min)/(largest_item-smallest_item)
final_value = min_value + ratio*(value-smallest_item)
As a mathematical function:
f(x,max,min,largest,smallest) = min + (max-min)/(largest-smallest)*(x-smallest)
where:
x : Input item's price
max: Maximum value (here, 110)
min: Minimum value (here, 55)
largest: Largest item in input (Here, 1081)
smallest: Smallest item in input (Here, 49)
One check, as #amit correctly points out: Ensure largest and smallest item are distinct.
So let x = 93. We have other 4 values with us.
f(x,max,min,largest,smallest) = min + (max-min)/(largest-smallest)*(x-smallest)
value = 55 + ((110-55)/(1081-49)) * (93-49)
value = 57.344961
Further,
f(93,110,55,1081,49) = 57.344961
f(49,110,55,1081,49) = 55
f(1081,110,55,1081,49) = 110

The function:
[(x - min ) / (max-min)*55] + 55
ensures the boundaries you are after - but you should also consider - what should the graph show? What do you want the reader to understand from it?
Why?
(x-min) / (max-min) gives a number in range [0,1] - 0 for min,
1 for max.
Multiplying it with 55 ensures a number in range [0,55].
Adding 55 ensures a number in range [55,110] - as expected.
(*) Note: for max = min - the above fails because of division with 0, take care for these cases manually.

Related

How can I find a permutation of all the digits of a given number such that it is closest to the target number

I just come across this interesting question from a book and I am unable to find the answer.
I have a given number X and a target number Y, task is to find such permutation of all the digits of X such that it is closest to Y.
Numbers are in form of array. No array size limit is given there.
Example
Given number X = 1212
Target number Y = 1500
Answer = 1221
Here, abs(1500-1221) is smallest among all permutations of X.
Given number X = 1212
Target number Y = 1900
Answer = 2112
Here, abs(1900-2112) is smallest among all permutations of X.
Given number X = 1029
Target number Y = 2000
Answer = 2019
Here, abs(2000-2019) is smallest among all permutations of X.
One of the solution I can find is to generate all permutations of the given number and at each stage calculates the difference. But this is very slow.
I tried to find the greedy approach, where I will iterate through all the indices of the target number Y and at each index I will put that digit of the given number X such that abs(Y[i] - X[i]) is minimum. But this fails for many cases.
I am trying to think of a DP approach, but unable to come up with any.
Any lead to the answer will be helpful.
Edit -
Adding pseudo code for my greedy approach
for each index i in [0,Y]:
min_index = 0;
for each index j in [1, X.length]:
if abs(X[j] - Y[i]) < abs(X[min_index] - Y[i]):
min_val = j
print X[min_index]
remove min_index from X
Example X = 1212 and Y = 1900.
step 1 - output 1 and remove index 0 from X.
step 2 - output 2 and remove index 1 from X.
step 3 - output 1 and remove index 2 from X.
step 2 - output 1 and remove index 3 from X.
answer = 1212 which is wrong (correct answer is 2112).
So fails for this test case and lots more.
So, the problem can be seen as follow:
Starting from the largest significant digits, for each of these index, there are three cases:
The current digit will be less than the desired digit, so for the rest of the digits, we try to create the largest number possible => for the rest of the digits, we sorted them in descending order , i.e if we have 0, 2, 7, 5 left -> we will create 7520
The current digit will be larger than the desired digit, so for the rest of the digits, we try to create the smallest number possible => for the rest of the digits, we sorted them in ascending order , i.e if we have 0, 2, 7, 5 left -> we will create 0275
If the current digit is equal to the desired digit, we will append it to the prefix and try to find better match in next iteration.
Pseudo-code:
int prefix, result;
for each index i from 0 to Y.length() {
int larger = prefix + smallestDigitLargerThan(Y(i)) + OtherDigitInAscendingOrder;
int smaller = prefix + largestDigitSmallerThan(Y(i)) + OtherDigitInDescendingOrder;
update result based on larger and smaller;
if there is no digit equals to Y(i)
break;
else {
remove Y(i) in X
prefix = prefix*10 + Y(i)
}
}
}
if prefix == Y {
//We have a full match
return prefix;
}
return result;
For example
X = 1029
Y = 2000
At index 0 -> Y(0) = 2,
int smaller = 0 (prefix) + 1(largest digit that is less than 2) + 920 (other digit in descending order) = 1920
int larger = 0 (prefix) + 9(smallest digit that is greater than 2) + 012 (other digit in ascending order) = 9012
int result = 1920
int prefix = 2
At index 1 -> Y(1) = 0,
int smaller = //Not exist
int larger = 2 + 1 + 09 = 2109
int result = 1920
int prefix = 20
At index 2 -> Y(2) = 0,
int smaller = //Not exist
int larger = 20 + 1 + 9 = 2019
int result = 2019
//Break as there is no digit match Y(2) = 0 from X
Other example:
X = 1212
Y = 1500
At index 0 -> Y(0) = 1,
int smaller = //Not exist
int larger = 0 + 2 + 112 = 2112
int result = 2112
int prefix = 1
At index 1 -> Y(1) = 5,
int smaller = 1 + 2 + 21 = 1221
int larger = //Not exist
int result = 1221
//Break from here as there is no digit match Y(1) = 5 in X
Beam search with width of 3 could be an approach. The idea is to construct the numbers from the largest to the smallest digit, and filling the rest with zeros. You construct the nearest and the second nearest numbers at each step for each number in the beam, and discarding all numbers which are worse than the top three. (In fact you're needing a beam size of two at most. The case of three is only needed, if the distance of two entries in the beams are equal.) During computation the constructed numbers Aand B should never be equal (except for the special case that X only contains the same digit.)
Here are the beams for the second example. The * denotes the best beam, and no * means that both are equally good:
2000* -> 2100* -> 2112*
2200 -> 2211
1000 -> 1200
1100
This is for the first example:
1000 -> 1200* -> 1221*
1100 -> 1122
2000 -> 2100
2200
Third example needs a beam size of 3 for second step, because the distance of second best beams 1900 and 2100 to 2000 is 100:
1000 -> 1900 -> 1901
1100
2000* -> 2000* -> 2019*
2100 2109
Note: I've joined the 3. and the 4. step in all examples.
The numbers X = 1992and Y = 2000 are an interesting example
1000 -> 1900 -> 1992*
1200
2000* -> 2100 -> 2199
2900
because the best beam is changing during computation.
I wrote a small python program for demonstration:
import sys
X = sys.argv[1]
Y = int(sys.argv[2])
def remove(s, i):
return s[:i] + s[i+1:]
def expand(t):
result = set()
val = t[0]
chars = t[1]
index = len(val) - len(chars)
for i in range(len(chars)):
s = val[:index] + chars[i]
r = remove(chars, i)
if index < len(val):
s += val[index + 1:]
result.add((s, r))
return result
beams = [("0" * len(X), X)]
for i in range(len(X)):
newBeams = set()
for t in beams:
newBeams.update(expand(t))
beams = sorted(newBeams, key = lambda t: abs(Y - int(t[0])))[:3]
print beams
print "Result:", beams[0][0]
The code is not optimal but this algorithm has polynomial running time, O(n² ln n) at most, and this estimate is very generous.

The 1000th element which is product of 2, 3, 5

There is a sequence S.
All the elements in S is product of 2, 3, 5.
S = {2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24 ...}
How to get the 1000th element in this sequence efficiently?
I check each number from 1, but this method is too slow.
A geometric approach:
Let s = 2^i . 3^j . 5^k, where the triple (i, j, k) belongs to the first octant of a 3D state space.
Taking the logarithm,
ln(s) = i.ln(2) + j.ln(3) + k.ln(5)
so that in the state space the iso-s surfaces are planes, which intersect the first octant along a triangle. On the other hand, the feasible solutions are the nodes of a square grid.
If one wants to produce the s-values in increasing order, one can keep a list of the grid nodes closest to the current s-plane*, on its "greater than" side.
If I am right, to move from one s-value to the next, it suffices to discard the current (i, j, k) and replace it by the three triples (i+1, j, k), (i, j+1, k) and (i, j, k+1), unless they are already there, and pick the next smallest s.
An efficient implementation will be by storing the list as a binary tree with the log(s)-value as the key.
If you are asking for the first N values, you will explore a pyramidal volume of state-space of height O(³√N), and base area O(³√N²), which is the number of tree nodes, hence the spatial complexity. Every query in the tree will take O(log(N)) comparisons (and O(1) operations to fetch the minimum), for a total of O(N.log(N)).
*More precisely, the list will contain all triples on the "greater than" side and such that no index can be decreased without getting on the other side of the plane.
Here is Python code that implements these ideas.
You will notice that the logarithms are converted to fixed point (7 decimals) to avoid floating-point inaccuracies that could result in the log(s)-values not being found equal. This causes the s values being inexact in the last digits, but this does not matter as long as the ordering of the values is preserved. Recomputing the s-values from the indexes yields exact values.
import math
import bintrees
# Constants
ln2= round(10000000 * math.log(2))
ln3= round(10000000 * math.log(3))
ln5= round(10000000 * math.log(5))
# Initial list
t= bintrees.FastAVLTree()
t.insert(0, (0, 0, 0))
# Find the N first products
N= 100
for i in range(N):
# Current s
s= t.pop_min()
print math.pow(2, s[1][0]) * math.pow(3, s[1][1]) * math.pow(5, s[1][2])
# Update the list
if not s[0] + ln2 in t:
t.insert(s[0] + ln2, (s[1][0]+1, s[1][1], s[1][2]))
if not s[0] + ln3 in t:
t.insert(s[0] + ln3, (s[1][0], s[1][1]+1, s[1][2]))
if not s[0] + ln5 in t:
t.insert(s[0] + ln5, (s[1][0], s[1][1], s[1][2]+1))
The 100 first values are
1 2 3 4 5 6 8 9 10 12
15 16 18 20 24 25 27 30 32 36
40 45 48 50 54 60 64 72 75 80
81 90 96 100 108 120 125 128 135 144
150 160 162 180 192 200 216 225 240 243
250 256 270 288 300 320 324 360 375 384
400 405 432 450 480 486 500 512 540 576
600 625 640 648 675 720 729 750 768 800
810 864 900 960 972 1000 1024 1080 1125 1152
1200 1215 1250 1280 1296 1350 1440 1458 1500 1536
The plot of the number of tree nodes confirms the O(³√N²) spatial behavior.
Update:
When there is no risk of overflow, a much simpler version (not using logarithms) is possible:
import math
import bintrees
# Initial list
t= bintrees.FastAVLTree()
t[1]= None
# Find the N first products
N= 100
for i in range(N):
# Current s
(s, r)= t.pop_min()
print s
# Update the list
t[2 * s]= None
t[3 * s]= None
t[5 * s]= None
Simply put, you just have to generate each ith number consecutively. Let's call the set {2, 3, 5} to be Z. At ith iteration, assume you have all (i-1) of the values generated in the previous iteration. While generating the next one, what you basically have to do is trying all the elements in Z and for each of them generating **the least element they can form that is larger than the element generated at (i-1)th iteration. Then, you simply consider the smallest one among them as the ith value. A simple and not so efficient implementation is given below.
def generate_simple(N, Z):
generated = [1]
for i in range(1, N+1):
minFound = -1
minElem = -1
for j in range(0, len(Z)):
for k in range(0, len(generated)):
candidateVal = Z[j] * generated[k]
if candidateVal > generated[-1]:
if minFound == -1 or minFound > candidateVal:
minFound = candidateVal
minElem = j
break
generated.append(minFound)
return generated[-1]
As you may observe, this approach has a time complexity of O(N2 * |Z|). An improvement in terms of efficiency would be to store where we left off scanning in the array of generated values for each element in a second array, indicesToStart. Then, for each element we would only scan all N values of the array generated for once(i.e. all through the algorithm), which means the time complexity after such an improvement would be O(N * |Z|).
A simple implementation of the improvement based on the simple version provided above, is given below.
def generate_improved(N, Z):
generated = [1]
indicesToStart = [0] * len(Z)
for i in range(1, N+1):
minFound = -1
minElem = -1
for j in range(0, len(Z)):
for k in range(indicesToStart[j], len(generated)):
candidateVal = Z[j] * generated[k]
if candidateVal > generated[-1]:
if minFound == -1 or minFound > candidateVal:
minFound = candidateVal
minElem = j
break
indicesToStart[j] += 1
generated.append(minFound)
indicesToStart[minElem] += 1
return generated[-1]
If you have a hard time understanding how complexity decreases with this algorithm, try looking into the difference in time complexity of any graph traversal algorithm when an adjacency list is used, and when an adjacency matrix is used. The improvement adjacency lists help achieve is almost exactly the same kind of improvement we get here. In a nutshell, you have an index for each element and instead of starting to scan from the beginning you continue from wherever you left the last time you scanned the generated array for that element. Consequently, even though there are N iterations in the algorithm(i.e. the outermost loop) the overall number of operations you make is O(N * |Z|).
Important Note: All the code above is a simple implementation for demonstration purposes, and you should consider it just as a pseudocode you can test. While implementing this in real life, based on the programming language you choose to use, you will have to consider issues like integer overflow when computing candidateVal.

Two values from range having maximum xor

We are given two constraint L and R(L<=R) and we have to find two values i and j(l<=i<=j<=R) such that Xor of them is maximum.
I already tried O(n^2) so want anything better.
Here is the solution that you can use (This gives you answer in log(R))
Let me explain it with an example:
Let L=34, R=45. Represent them as bit-arrays:
L = 100010 R = 101101
You start from the left till you find the first mismatch of the form:
L[i] = 0 and R[i] = 1
You will always find this because L < R. (If L==R, this is trivial case and answer is 0)
From here on, change every bit of L to 1 and every bit of R to 0.
The numbers you get will be your i and j and their XOR will be the max you can get.
eg. 34 and 45
100010 and 101101
1st mismatch at index 2 [0-based]
From there, change all L[i] to 1 and all R[i] to 0
=> i = 100111 and j = 101000
=> i = 39 and j = 40
and i^j = 15
If this is a one time request, with no preprocessing:
Given a range [L, R] you just need to be able to find a number that has 1 at a particular bit position among the numbers in this range. This can easily be done with bit operations.
suppose you have L = 0, R = 7, in binary your numbers are:
000, 001, 010, ..., 111
the current number is 000, to maximize xor you need to find the number which has 1 at the most significant bit position. The first such number is 4 = 100. Now you are dealing with range 100, 101, ..., 111 and bit at the second highest position. The bit at the second highest position is 0, so to maximize xor you again need a number with a 1 on that position. The first such number is 6 = 110. You can apply the very same pattern again. Now that you are done with 000 you can do the same for 001 and so on.
The number of iterations for one number is the maximum number of bits you have in numbers from L to R. Hence the total number of operations is O((R-L+1)*log(R-L+1))

Algorithm to find the 'possible' combinations of variables with constraints in Matlab?

Say I have 7 items in A and 4 items in B
A=[10;40;90;130;200;260;320]
B=[100;300;500;1000]
I want to have the list of possible combinations where :
All sub-components of A MUST be included
sub-components of B can be added until the the SUM of all sub-componenets added is greater than 2000
Anyone has an idea how to do this in Matlab ?
My try :
X=sum(A);
y=1;
for Y=1:((length(A))-1);
X=X+B(y);
if(X>2000)
disp('Following is unacceptable')
end
y=y+1
end
However this code is not correct. It just adding the first element of B then adding it with the second element and so on. It isn't providing me with possible combinations.
Example :
sum(A) + B(1) = OK
sum(A) + B(4) = NOT OK
sum(A) + B(1) + B(2) = OK
sum(A) + B(2) + B(3) = OK
etc...
I want this to be automated if values of A or B change in the future. I am not sure if this is a case of probability as well.
Just use nchoosek and a double for-loop to go through all possible combinations of elements in B:
SA = sum(A);
for k = 1:numel(B)
for idx = nchoosek(1:numel(B), k)'
B_subset = B(idx);
if (SA + sum(B_subset) <= 2000)
disp([A(:)', B_subset(:)'])
end
end
end
This prints all combinations with a sum less than (or equal to) 2000. For your example we get:
10 40 90 130 200 260 320 100
10 40 90 130 200 260 320 300
10 40 90 130 200 260 320 500
10 40 90 130 200 260 320 100 300
10 40 90 130 200 260 320 100 500
10 40 90 130 200 260 320 300 500
10 40 90 130 200 260 320 100 300 500
Explanation:
The inner for-loop:
The inner for-loop uses nchoosek(1:numel(B), k), which generates all k-length combinations out of 1...length(B) (I'm using numel instead of length out of habit; in this case it has the same effect). For example, in our case B has 4 elements, so for k = 3 we get nchoosek(1:4, 3):
1 2 3
1 2 4
1 3 4
2 3 4
What we get from this is all the possible k-length combinations of indices of elements in B. In each iteration, this for-loop assigns a different combination of indices to idx. How do we convert the indices of B to real elements? We simply write B(idx).
Inside loop the combination is tested: if the total sum(A) + sum(B(idx)) is less than (or equal to) 2000, that combination is displayed.
The outer for-loop:
The outer for-loop simply iterates over all possible lengths of combinations (that is, over all possible values of k).
Hope that helps!
P.S:
Some MATLAB programming tips for the future:
1. Variable names are case-sensitive.
2. You don't need to increment the loop variable. The for loop does that automatically for you.
The best approach would involve some recursion, like this:
sumA=sum(A);
find_CombinationsOfB(B,sumA,[])
function ret=findCombinationsOfB(in_vals,total_sum,already_contained)
if total_sum>2000
ret=false;
else
for y=1:length(in_vals);
if (~findCombinationsOfB(in_vals([1:(y-1);(y+1):length(in_vals)],total_sum+in_vals(y),[already_contained in_vals(y))
display([already_contained in_vals])
end
end
ret=true;
end
Essentially what this does is tries each combination of B. It will print any that don't add up to 2000, including the sum from A.
Step by step, here's what it does:
Initially, the full array of B is passed, along with the sum of A. An empty array is passed to store which elements of B have been used so far.
Each element added in turn to the function, and called again with a new sum, and with a value missing from the array.
If at any point the array sum is over 2000, it stops that chain of reasoning.
If you want to know more about how this works, print in_vals, total_sum, and already_contained in the start of the function, like this:
fprintf("in_vals=%s total_sum=%i already_contained=%s",mat2str(in_vals),total_sum,mat2str(already_contained));
It should show you at each iteration what is happening.
Assuming B is not very long (around 10 elements), an exhaustive search through all combinations will work just fine. You can carry out this exhaustive search with a recursive function, but the code below uses a trick that's particularly concise in MATLAB: it sweeps through all combinations of the elements of B by representing each combination as a binary bit string.
% examine each of 2^length(B) combinations
for i=0:2^length(B)-1
% converts the binary string into an array of 0 and 1 used to select elements in B
combo = dec2bin(i, length(B))-'0';
% print the combination of elements if their sum is large
if combo * B + sum(A) > 2000
disp(find(combo));
end
end
There are 2^length(B) possible combinations. This examines them in turn, representing the combination as a binary string of length length(B), and evaluating the sum of these elements (with a dot product between the bit string and B).

How to optimize the layout of rectangles

I have a dynamic number of equally proportioned and sized rectangular objects that I want to optimally display on the screen. I can resize the objects but need to maintain proportion.
I know what the screen dimensions are.
How can I calculate the optimal number of rows and columns that I will need to divide the screen in to and what size I will need to scale the objects to?
Thanks,
Jamie.
Assuming that all rectangles have the same dimensions and orientation and that such should not be changed.
Let's play!
// Proportion of the screen
// w,h width and height of your rectangles
// W,H width and height of the screen
// N number of your rectangles that you would like to fit in
// ratio
r = (w*H) / (h*W)
// This ratio is important since we can define the following relationship
// nbRows and nbColumns are what you are looking for
// nbColumns = nbRows * r (there will be problems of integers)
// we are looking for the minimum values of nbRows and nbColumns such that
// N <= nbRows * nbColumns = (nbRows ^ 2) * r
nbRows = ceil ( sqrt ( N / r ) ) // r is positive...
nbColumns = ceil ( N / nbRows )
I hope I got my maths right, but that cannot be far from what you are looking for ;)
EDIT:
there is not much difference between having a ratio and the width and height...
// If ratio = w/h
r = ratio * (H/W)
// If ratio = h/w
r = H / (W * ratio)
And then you're back using 'r' to find out how much rows and columns use.
Jamie, I interpreted "optimal number of rows and columns" to mean "how many rows and columns will provide the largest rectangles, consistent with the required proportions and screen size". Here's a simple approach for that interpretation.
Each possible choice (number of rows and columns of rectangles) results in a maximum possible size of rectangle for the specified proportions. Looping over the possible choices and computing the resulting size implements a simple linear search over the space of possible solutions. Here's a bit of code that does that, using an example screen of 480 x 640 and rectangles in a 3 x 5 proportion.
def min (a, b)
a < b ? a : b
end
screenh, screenw = 480, 640
recth, rectw = 3.0, 5.0
ratio = recth / rectw
puts ratio
nrect = 14
(1..nrect).each do |nhigh|
nwide = ((nrect + nhigh - 1) / nhigh).truncate
maxh, maxw = (screenh / nhigh).truncate, (screenw / nwide).truncate
relh, relw = (maxw * ratio).truncate, (maxh / ratio).truncate
acth, actw = min(maxh, relh), min(maxw, relw)
area = acth * actw
puts ([nhigh, nwide, maxh, maxw, relh, relw, acth, actw, area].join("\t"))
end
Running that code provides the following trace:
1 14 480 45 27 800 27 45 1215
2 7 240 91 54 400 54 91 4914
3 5 160 128 76 266 76 128 9728
4 4 120 160 96 200 96 160 15360
5 3 96 213 127 160 96 160 15360
6 3 80 213 127 133 80 133 10640
7 2 68 320 192 113 68 113 7684
8 2 60 320 192 100 60 100 6000
9 2 53 320 192 88 53 88 4664
10 2 48 320 192 80 48 80 3840
11 2 43 320 192 71 43 71 3053
12 2 40 320 192 66 40 66 2640
13 2 36 320 192 60 36 60 2160
14 1 34 640 384 56 34 56 1904
From this, it's clear that either a 4x4 or 5x3 layout will produce the largest rectangles. It's also clear that the rectangle size (as a function of row count) is worst (smallest) at the extremes and best (largest) at an intermediate point. Assuming that the number of rectangles is modest, you could simply code the calculation above in your language of choice, but bail out as soon as the resulting area starts to decrease after rising to a maximum.
That's a quick and dirty (but, I hope, fairly obvious) solution. If the number of rectangles became large enough to bother, you could tweak for performance in a variety of ways:
use a more sophisticated search algorithm (partition the space and recursively search the best segment),
if the number of rectangles is growing during the program, keep the previous result and only search nearby solutions,
apply a bit of calculus to get a faster, precise, but less obvious formula.
This is almost exactly like kenneth's question here on SO. He also wrote it up on his blog.
If you scale the proportions in one dimension so that you are packing squares, it becomes the same problem.
One way I like to do that is to use the square root of the area:
Let
r = number of rectangles
w = width of display
h = height of display
Then,
A = (w * h) / r is the area per rectangle
and
L = sqrt(A) is the base length of each rectangle.
If they are not square, then just multiply accordingly to keep the same ratio.
Another way to do a similar thing is to just take the square root of the number of rectangles. That'll give you one dimension of your grid (i.e. the number of columns):
C = sqrt(n) is the number of columns in your grid
and
R = n / C is the number of rows.
Note that one of these will have to ceiling and the other floor otherwise you will truncate numbers and might miss a row.
Your mention of rows and columns suggests that you envisaged arranging the rectangles in a grid, possibly with a few spaces (e.g. some of the bottom row) unfilled. Assuming this is the case:
Suppose you scale the objects such that (an as-yet unknown number) n of them fit across the screen. Then
objectScale=screenWidth/(n*objectWidth)
Now suppose there are N objects, so there will be
nRows = ceil(N/n)
rows of objects (where ceil is the Ceiling function), which will take up
nRows*objectScale*objectHeight
of vertical height. We need to find n, and want to choose the smallest n such that this distance is smaller than screenHeight.
A simple mathematical expression for n is made trickier by the presence of the ceiling function. If the number of columns is going to be fairly small, probably the easiest way to find n is just to loop through increasing n until the inequality is satisfied.
Edit: We can start the loop with the upper bound of
floor(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))
for n, and work down: the solution is then found in O(sqrt(N)). An O(1) solution is to assume that
nRows = N/n + 1
or to take
n=ceil(sqrt(N*objectHeight*screenWidth/(screenHeight*objectWidth)))
(the solution of Matthieu M.) but these have the disadvantage that the value of n may not be optimal.
Border cases occur when N=0, and when N=1 and the aspect ratio of the objects is such that objectHeight/objectWidth > screenHeight/screenWidth - both of these are easy to deal with.

Resources