Page 1 of 1
Calculating optimal matrix size to fit N elements
Posted: Thu Oct 27, 2016 5:43 pm
by Lunasole
Hi once more. Yesterday I needed such code and remembered I've already wrote it many years ago, so here it is reanimated and ported to PB ^^
Rarely but might be useful. Also I don't know how exactly such algorithm is called (nor exists it or not).
Code: Select all
EnableExplicit
; (c) Lunasole 2000x-don't-remember-exactly
; Value a number to fit, can be >= 0
; RETURN: none, the X and Y sizes of matrix returned byref
Procedure AmountToMatrix (Value, *OutX.Integer, *OutY.Integer)
Protected.d SamplesDiff ; can use integer instead, result will be "more square" but less optimal
*OutY\i = Int(Sqr(Value))
*OutX\i = *OutY\i
If Pow(*OutY\i, 2) < Value
SamplesDiff = 0.4 + (Value - Pow(*OutY\i, 2)) / *OutY\i
If Mod(SamplesDiff, 2) = 0
*OutX\i = *OutY\i + SamplesDiff / 2
*OutY\i = *OutY\i + SamplesDiff / 2
Else
*OutX\i = *OutY\i + SamplesDiff
EndIf
EndIf
EndProcedure
; Example
; assume you have 5000 files
Define inFilesCnt = 5000
; and need to place them using box-like order for some reason ^^
Define SamplesX, SamplesY
; that thing does something like that
AmountToMatrix(inFilesCnt, @SamplesX, @SamplesY)
Debug Str(inFilesCnt) + " files may be ordered using " + Str(SamplesX) + "x" + Str(SamplesY) + " matrix"
Re: Calculating optimal matrix size to fit N elements
Posted: Thu Oct 27, 2016 9:20 pm
by Lunasole
Here is slightly extended version, it allows to define one of sizes manually, also optional UseInt switch changes auto-calculation behavior:
Code: Select all
EnableExplicit
; Value a number to fit, can be >= 0
; *OutX, OutY in/out values. input must be zero to be calculated
; UseInt if true, use rounding to estimate diff (this affects results on auto-calculation)
; RETURN: none, the X and Y sizes of matrix returned byref
Procedure AmountToMatrix (Value, *OutX.Integer, *OutY.Integer, UseInt = #False)
Protected.d SamplesDiff
If *OutX\i = 0 And *OutY\i = 0 ; both X and Y are 0
*OutY\i = Int(Sqr(Value))
*OutX\i = *OutY\i
If Pow(*OutY\i, 2) < Value
If UseInt
SamplesDiff = Round(0.4 + (Value - Pow(*OutY\i, 2)) / *OutY\i, #PB_Round_Nearest)
Else
SamplesDiff = 0.4 + (Value - Pow(*OutY\i, 2)) / *OutY\i
EndIf
If Mod(SamplesDiff, 2) = 0
*OutX\i = *OutY\i + SamplesDiff / 2
*OutY\i = *OutY\i + SamplesDiff / 2
Else
*OutX\i = *OutY\i + SamplesDiff
EndIf
EndIf
ElseIf *OutX\i And Not *OutY\i ; user defined X size, but not Y
*OutY\i = Round(Value / *OutX\i, #PB_Round_Up)
ElseIf *OutY\i And Not *OutX\i ; user defined Y size, but not X
*OutX\i = Round(Value / *OutY\i, #PB_Round_Up)
EndIf
EndProcedure
; Example
; assume you have 5000 files
Define inFilesCnt = 5000
; and need to place them using box-like order for some reason ^^
Define SamplesX = 0, SamplesY = 0
; that thing does something like that
AmountToMatrix(inFilesCnt, @SamplesX, @SamplesY, #False)
Debug Str(inFilesCnt) + " files may be ordered using " + Str(SamplesX) + "x" + Str(SamplesY) + " matrix"
Re: Calculating optimal matrix size to fit N elements
Posted: Fri Oct 28, 2016 1:16 pm
by blueb
Not exactly elegant, but would't this work?...
Code: Select all
; ... and need to place them using box-like order for some reason.
FileNumber = 5000
result.i = Round(Sqr(FileNumber), #PB_Round_Up)
; test
Debug result
Debug result * result
Re: Calculating optimal matrix size to fit N elements
Posted: Fri Oct 28, 2016 5:18 pm
by Lunasole
blueb wrote:Not exactly elegant, but would't this work?...
That simplified variant works too, but shows wrong results for some values.
For example if filenumber = 5 it will return 3x3 matrix, while my code 3x2
Re: Calculating optimal matrix size to fit N elements
Posted: Fri Oct 28, 2016 8:20 pm
by #NULL
using the code by blueb with an additional step to reduce height by 1 if possible:
Code: Select all
For FileNumber = 1 To 100
resultX = Round(Sqr(FileNumber), #PB_Round_Up)
resultY = resultX
If (resultX * resultY) > FileNumber
If (resultX * (resultY-1)) >= FileNumber
resultY = resultY - 1
EndIf
EndIf
Debug "-----------------------"
Debug "" + FileNumber + " : " + resultX + " x " + resultY + " = " + Str(resultX * resultY)
For n=1 To FileNumber
s.s + "#"
If n % resultX = 0 Or n = FileNumber
Debug s
s = ""
EndIf
Next
Debug ""
Next
Re: Calculating optimal matrix size to fit N elements
Posted: Sun Oct 30, 2016 8:31 pm
by #NULL
i just realized that you can do it also without the IFs
if the decimal part of Sqr(n) is > 0.5 then x and y need to be the same (rounded up) and if the decimal part is > 0.0 and <= 0.5 then you can reduce one of the dimensions.
you can achive this easily by using round-up for one dimension and round-nearest for the other one.
Code: Select all
For FileNumber = 1 To 100
sqr.f = Sqr(FileNumber)
resultX = Round(sqr, #PB_Round_Up)
resultY = Round(sqr, #PB_Round_Nearest)
Debug "-----------------------"
Debug "" + FileNumber + " : " + resultX + " x " + resultY + " = " + Str(resultX * resultY)
For n=1 To FileNumber
s.s + "#"
If n % resultX = 0 Or n = FileNumber
Debug s
s = ""
EndIf
Next
Debug ""
Next
i can't prove this mathematically but it seems to work
