Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Grid Formatting Demo
#11
(Yesterday, 08:07 PM)SMcNeill Wrote: Again, you're not maintaining your set ratios.  

Yes, a 7x3 grid is going to hold 21 items, but it's not going to be able to match your 16:9 ratio.
7x3 is going to scale to a 21:9 ratio, which doesn't match what you started with originally at all.

If that ratio is something that doesn't have to be maintained, then why's it even there to start with?  What's the point for it?

1x1 is square.
1x2 is... not square.
2x1 is... not square.

If I have 2 items, I can put them in a 1x2 grid, or a 2x1 grid, but those grids aren't going to be SQUARE -- which was the whole initial requirement for things.

It's only at:
1x1 that we have a square.
2x2 that we have a square.
3x3 that we have a square.
4x4 that we have a square.

Your description sets the ratio that you want to find a solution for, but then the solutions you are finding doesn't match that ratio.

Let's say you want to sort out how large a SQUARE grid you need to hold 12 items.
3x3 IS square, but it can only hold 9 items.
4x3 isn't square, but it can hold 12 items.
4x4 IS square, but it holds 16 items.  You have 4 empty spaces left over on your grid.

Is the 4x3 a better answer?  Sure, it might be -- but it's NOT a SQUARE grid like the ratio demanded it to be.



If you don't need to maintain the ratio, all you need to do is simple math and look for values that multiply to the closest number for you.  The best answer would always just be a simple 1xnumber grid.  It'd never have any spaces left over.

(Yesterday, 08:15 PM)Pete Wrote: 4:3 = 8x6 so 48 cells available, only 20 used would be 28 empty.

The math is certainly correct, so the question would be will it work in practice.

Maybe the problem is you are wanting more of a collage effect for uneven distribution like fitting jigsaw pieces together. This cell approach, using mixed photo sizes, is a grid, meaning smaller photos get placed in the center of the grid sized to the largest photo.

Pete

Thanks so much you guys, for taking the time to explain... I am going to have to digest this over the weekend, just don't have time right now.

What I did do was take Steve's ratios and put them into my program, and then had both programs output their results to a tab-delimited file, and ran tests on various counts (20, 555, 1014, 1200, 2000, 12900, 15400, 14400, 87500, 1414000 items) and brought that into Excel to compare them side by side, and output some table ML with a simple formula. Below is the test data. I'm going to read through what you guys said and make sense of it. Thanks again for listening and explaining...

Program Items H-Ratio V-Ratio Columns Rows Total Cells Empty Cells Layout
Steve 20 2 3 4 6 24 4 Classic 35mm (4x6; 6x9; etc.)
madsci 20 2 3 3 7 21 1 Classic 35mm (4x6, 6x9, etc.)
Steve 555 2 3 20 30 600 45 Classic 35mm (4x6; 6x9; etc.)
madsci 555 2 3 19 30 570 15 Classic 35mm (4x6, 6x9, etc.)
Steve 1014 2 3 28 42 1176 162 Classic 35mm (4x6; 6x9; etc.)
madsci 1014 2 3 26 39 1014 0 Classic 35mm (4x6, 6x9, etc.)
Steve 1200 2 3 30 45 1350 150 Classic 35mm (4x6; 6x9; etc.)
madsci 1200 2 3 28 43 1204 4 Classic 35mm (4x6, 6x9, etc.)
Steve 2000 2 3 38 57 2166 166 Classic 35mm (4x6; 6x9; etc.)
madsci 2000 2 3 36 56 2016 16 Classic 35mm (4x6, 6x9, etc.)
Steve 12900 2 3 94 141 13254 354 Classic 35mm (4x6; 6x9; etc.)
madsci 12900 2 3 92 141 12972 72 Classic 35mm (4x6, 6x9, etc.)
Steve 14400 2 3 98 147 14406 6 Classic 35mm (4x6; 6x9; etc.)
madsci 14400 2 3 97 149 14453 53 Classic 35mm (4x6, 6x9, etc.)
Steve 15400 2 3 102 153 15606 206 Classic 35mm (4x6; 6x9; etc.)
madsci 15400 2 3 101 153 15453 53 Classic 35mm (4x6, 6x9, etc.)
Steve 87500 2 3 242 363 87846 346 Classic 35mm (4x6; 6x9; etc.)
madsci 87500 2 3 241 364 87724 224 Classic 35mm (4x6, 6x9, etc.)
Steve 1414000 2 3 972 1458 1417176 3176 Classic 35mm (4x6; 6x9; etc.)
madsci 1414000 2 3 970 1458 1414260 260 Classic 35mm (4x6, 6x9, etc.)
Steve 20 1 1 5 5 25 5 Square (profile pictures; social media)
madsci 20 1 1 5 5 25 5 Square (profile pictures, social media)
Steve 555 1 1 24 24 576 21 Square (profile pictures; social media)
madsci 555 1 1 24 24 576 21 Square (profile pictures, social media)
Steve 1014 1 1 32 32 1024 10 Square (profile pictures; social media)
madsci 1014 1 1 32 32 1024 10 Square (profile pictures, social media)
Steve 1200 1 1 35 35 1225 25 Square (profile pictures; social media)
madsci 1200 1 1 35 35 1225 25 Square (profile pictures, social media)
Steve 2000 1 1 45 45 2025 25 Square (profile pictures; social media)
madsci 2000 1 1 45 45 2025 25 Square (profile pictures, social media)
Steve 12900 1 1 114 114 12996 96 Square (profile pictures; social media)
madsci 12900 1 1 114 114 12996 96 Square (profile pictures, social media)
Steve 14400 1 1 121 121 14641 241 Square (profile pictures; social media)
madsci 14400 1 1 120 120 14400 0 Square (profile pictures, social media)
Steve 15400 1 1 125 125 15625 225 Square (profile pictures; social media)
madsci 15400 1 1 125 125 15625 225 Square (profile pictures, social media)
Steve 87500 1 1 296 296 87616 116 Square (profile pictures; social media)
madsci 87500 1 1 296 296 87616 116 Square (profile pictures, social media)
Steve 1414000 1 1 1190 1190 1416100 2100 Square (profile pictures; social media)
madsci 1414000 1 1 1190 1190 1416100 2100 Square (profile pictures, social media)
Steve 20 5 7 5 7 35 15 5 x 7 photo
madsci 20 5 7 3 7 21 1 5 x 7 photo
Steve 555 5 7 20 28 560 5 5 x 7 photo
madsci 555 5 7 19 30 570 15 5 x 7 photo
Steve 1014 5 7 30 42 1260 246 5 x 7 photo
madsci 1014 5 7 26 39 1014 0 5 x 7 photo
Steve 1200 5 7 30 42 1260 60 5 x 7 photo
madsci 1200 5 7 29 42 1218 18 5 x 7 photo
Steve 2000 5 7 40 56 2240 240 5 x 7 photo
madsci 2000 5 7 37 55 2035 35 5 x 7 photo
Steve 12900 5 7 100 140 14000 1100 5 x 7 photo
madsci 12900 5 7 95 136 12920 20 5 x 7 photo
Steve 14400 5 7 105 147 15435 1035 5 x 7 photo
madsci 14400 5 7 101 143 14443 43 5 x 7 photo
Steve 15400 5 7 105 147 15435 35 5 x 7 photo
madsci 15400 5 7 104 149 15496 96 5 x 7 photo
Steve 87500 5 7 255 357 91035 3535 5 x 7 photo
madsci 87500 5 7 250 350 87500 0 5 x 7 photo
Steve 1414000 5 7 1005 1407 1414035 35 5 x 7 photo
madsci 1414000 5 7 1004 1409 1414636 636 5 x 7 photo
Steve 20 4 3 8 6 48 28 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 20 4 3 7 3 21 1 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 555 4 3 28 21 588 33 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 555 4 3 28 20 560 5 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 1014 4 3 40 30 1200 186 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 1014 4 3 38 27 1026 12 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 1200 4 3 44 33 1452 252 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 1200 4 3 40 30 1200 0 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 2000 4 3 52 39 2028 28 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 2000 4 3 53 38 2014 14 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 12900 4 3 132 99 13068 168 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 12900 4 3 132 98 12936 36 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 14400 4 3 140 105 14700 300 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 14400 4 3 140 103 14420 20 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 15400 4 3 144 108 15552 152 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 15400 4 3 144 107 15408 8 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 87500 4 3 344 258 88752 1252 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 87500 4 3 342 256 87552 52 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 1414000 4 3 1376 1032 1420032 6032 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 1414000 4 3 1375 1029 1414875 875 Older PC monitor + analog TV (640x480, 1024x768, etc.)
Steve 20 4 5 8 10 80 60 Art prints + medium format (8x10; 16x20)
madsci 20 4 5 4 5 20 0 Art prints + medium format (8x10, 16x20)
Steve 555 4 5 24 30 720 165 Art prints + medium format (8x10; 16x20)
madsci 555 4 5 21 27 567 12 Art prints + medium format (8x10, 16x20)
Steve 1014 4 5 32 40 1280 266 Art prints + medium format (8x10; 16x20)
madsci 1014 4 5 28 37 1036 22 Art prints + medium format (8x10, 16x20)
Steve 1200 4 5 32 40 1280 80 Art prints + medium format (8x10; 16x20)
madsci 1200 4 5 30 40 1200 0 Art prints + medium format (8x10, 16x20)
Steve 2000 4 5 44 55 2420 420 Art prints + medium format (8x10; 16x20)
madsci 2000 4 5 40 50 2000 0 Art prints + medium format (8x10, 16x20)
Steve 12900 4 5 104 130 13520 620 Art prints + medium format (8x10; 16x20)
madsci 12900 4 5 101 128 12928 28 Art prints + medium format (8x10, 16x20)
Steve 14400 4 5 108 135 14580 180 Art prints + medium format (8x10; 16x20)
madsci 14400 4 5 107 135 14445 45 Art prints + medium format (8x10, 16x20)
Steve 15400 4 5 112 140 15680 280 Art prints + medium format (8x10; 16x20)
madsci 15400 4 5 110 140 15400 0 Art prints + medium format (8x10, 16x20)
Steve 87500 4 5 268 335 89780 2280 Art prints + medium format (8x10; 16x20)
madsci 87500 4 5 264 332 87648 148 Art prints + medium format (8x10, 16x20)
Steve 1414000 4 5 1064 1330 1415120 1120 Art prints + medium format (8x10; 16x20)
madsci 1414000 4 5 1063 1331 1414853 853 Art prints + medium format (8x10, 16x20)
Steve 20 16 9 16 9 144 124 Standard HD display (1920x1080; 1280x720; etc.)
madsci 20 16 9 7 3 21 1 Standard HD display (1920x1080, 1280x720, etc.)
Steve 555 16 9 32 18 576 21 Standard HD display (1920x1080; 1280x720; etc.)
madsci 555 16 9 33 17 561 6 Standard HD display (1920x1080, 1280x720, etc.)
Steve 1014 16 9 48 27 1296 282 Standard HD display (1920x1080; 1280x720; etc.)
madsci 1014 16 9 45 23 1035 21 Standard HD display (1920x1080, 1280x720, etc.)
Steve 1200 16 9 48 27 1296 96 Standard HD display (1920x1080; 1280x720; etc.)
madsci 1200 16 9 48 25 1200 0 Standard HD display (1920x1080, 1280x720, etc.)
Steve 2000 16 9 64 36 2304 304 Standard HD display (1920x1080; 1280x720; etc.)
madsci 2000 16 9 61 33 2013 13 Standard HD display (1920x1080, 1280x720, etc.)
Steve 12900 16 9 160 90 14400 1500 Standard HD display (1920x1080; 1280x720; etc.)
madsci 12900 16 9 152 85 12920 20 Standard HD display (1920x1080, 1280x720, etc.)
Steve 14400 16 9 176 99 17424 3024 Standard HD display (1920x1080; 1280x720; etc.)
madsci 14400 16 9 160 90 14400 0 Standard HD display (1920x1080, 1280x720, etc.)
Steve 15400 16 9 176 99 17424 2024 Standard HD display (1920x1080; 1280x720; etc.)
madsci 15400 16 9 166 93 15438 38 Standard HD display (1920x1080, 1280x720, etc.)
Steve 87500 16 9 400 225 90000 2500 Standard HD display (1920x1080; 1280x720; etc.)
madsci 87500 16 9 396 221 87516 16 Standard HD display (1920x1080, 1280x720, etc.)
Steve 1414000 16 9 1600 900 1440000 26000 Standard HD display (1920x1080; 1280x720; etc.)
madsci 1414000 16 9 1587 891 1414017 17 Standard HD display (1920x1080, 1280x720, etc.)
Steve 20 11 14 11 14 154 134 legal paper (11x14)
madsci 20 11 14 3 7 21 1 legal paper (11x14)
Steve 555 11 14 22 28 616 61 legal paper (11x14)
madsci 555 11 14 20 28 560 5 legal paper (11x14)
Steve 1014 11 14 33 42 1386 372 legal paper (11x14)
madsci 1014 11 14 28 37 1036 22 legal paper (11x14)
Steve 1200 11 14 33 42 1386 186 legal paper (11x14)
madsci 1200 11 14 30 40 1200 0 legal paper (11x14)
Steve 2000 11 14 44 56 2464 464 legal paper (11x14)
madsci 2000 11 14 39 52 2028 28 legal paper (11x14)
Steve 12900 11 14 110 140 15400 2500 legal paper (11x14)
madsci 12900 11 14 100 129 12900 0 legal paper (11x14)
Steve 14400 11 14 110 140 15400 1000 legal paper (11x14)
madsci 14400 11 14 106 136 14416 16 legal paper (11x14)
Steve 15400 11 14 121 154 18634 3234 legal paper (11x14)
madsci 15400 11 14 110 140 15400 0 legal paper (11x14)
Steve 87500 11 14 264 336 88704 1204 legal paper (11x14)
madsci 87500 11 14 262 334 87508 8 legal paper (11x14)
Steve 1414000 11 14 1056 1344 1419264 5264 legal paper (11x14)
madsci 1414000 11 14 1054 1342 1414468 468 legal paper (11x14)
Steve 20 17 22 17 22 374 354 Standard letter size (8.5x11)
madsci 20 17 22 3 7 21 1 Standard letter size (8.5x11)
Steve 555 17 22 34 44 1496 941 Standard letter size (8.5x11)
madsci 555 17 22 20 28 560 5 Standard letter size (8.5x11)
Steve 1014 17 22 34 44 1496 482 Standard letter size (8.5x11)
madsci 1014 17 22 27 38 1026 12 Standard letter size (8.5x11)
Steve 1200 17 22 34 44 1496 296 Standard letter size (8.5x11)
madsci 1200 17 22 30 40 1200 0 Standard letter size (8.5x11)
Steve 2000 17 22 51 66 3366 1366 Standard letter size (8.5x11)
madsci 2000 17 22 39 52 2028 28 Standard letter size (8.5x11)
Steve 12900 17 22 102 132 13464 564 Standard letter size (8.5x11)
madsci 12900 17 22 99 131 12969 69 Standard letter size (8.5x11)
Steve 14400 17 22 119 154 18326 3926 Standard letter size (8.5x11)
madsci 14400 17 22 105 138 14490 90 Standard letter size (8.5x11)
Steve 15400 17 22 119 154 18326 2926 Standard letter size (8.5x11)
madsci 15400 17 22 109 142 15478 78 Standard letter size (8.5x11)
Steve 87500 17 22 272 352 95744 8244 Standard letter size (8.5x11)
madsci 87500 17 22 260 337 87620 120 Standard letter size (8.5x11)
Steve 1414000 17 22 1054 1364 1437656 23656 Standard letter size (8.5x11)
madsci 1414000 17 22 1045 1354 1414930 930 Standard letter size (8.5x11)
Reply
#12
For now I'll call attention to one simple case - a 4:3 ratio.
Say 100 columns to 75 rows, that's 4:3 right?
100x75 = 7500 items.
Here is what the 2 programs output for 7500 items:

Program Items H-Ratio V-Ratio Columns Rows Total Cells Empty Cells Layout
steve 7500 4 3 104 78 8112 612 Older PC monitor + analog TV (640x480; 1024x768; etc.)
madsci 7500 4 3 100 75 7500 0 Older PC monitor + analog TV (640x480, 1024x768, etc.)

Is my program's output not correct? 
Code for both programs is below. 
Anyway, thanks again for your patience and time with this...
I will follow up later!

Madscijr:
Code: (Select All)
Option _Explicit

Type LayoutType
    HRatio As Single
    VRatio As Single
    Name As String

    ColumnCount As Integer
    RowCount As Integer

    TargetCount As Long
    CellCount As Long
    EmptyCells As Long

    Error As String
End Type ' LayoutType

' BASIC PROGRAM METADATA
Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)

Dim iLoop1 As Integer
Dim iLoop2 As Integer
Dim iCount As Integer
Dim iItemCount As Long
Dim iEvenCount As Long
Dim iSquareCount As Long
Dim iLayoutCount As Integer
Dim sNextName As String
Dim RatioSum As Single
Dim sngColumnCount As Single
Dim sngRowCount As Single
Dim sngRowCol As Single
Dim sRatio As String
Dim sColsRows As String
Dim sCount As String
Dim sLine As String
Dim iMaxEmpty As Long
Dim iMinEmpty As Long
Dim iNextMinEmpty As Long
Dim iIndex As Integer
Dim iSortIndex As Integer
Dim bFinished As Integer
Dim in$

' LAYOUTS
ReDim arrLayout(1 To 32) As LayoutType
ReDim arrSorted(1 To 32) As LayoutType

' SHOW USER DEBUG FILE/PATH SO THEY CAN COPY TO CLIPBOARD:
in$ = _INPUTBOX$(m_ProgramName$, "Current debug filename is:", m_ProgramPath$ + m_ProgramName$ + ".txt")

' INIT SCREEN
Screen _NewImage(1280, 900, 32)
_ScreenMove 0, 0
Cls , cBlack

' =============================================================================
' INITIALIZE LAYOUT OPTIONS
For iLoop1 = LBound(arrLayout) To UBound(arrLayout)
    arrLayout(iLoop1).Name = ""
    arrLayout(iLoop1).HRatio = 0
    arrLayout(iLoop1).VRatio = 0
    arrLayout(iLoop1).Error = ""
Next iLoop1

iLayoutCount = 0
Restore RatioData
Do
    iLayoutCount = iLayoutCount + 1
    Read arrLayout(iLayoutCount).HRatio
    Read arrLayout(iLayoutCount).VRatio
    Read sNextName: arrLayout(iLayoutCount).Name = Replace$(sNextName, ";", ",")
    If arrLayout(iLayoutCount).HRatio = 0 Then Exit Do
Loop

RatioData:
Data 1,1,Square (profile pictures; social media)
Data 2,3,Classic 35mm (4x6; 6x9; etc.)
Data 5,7,5 x 7 photo
Data 17,22,Standard letter size (8.5x11)
Data 4,3,Older PC monitor + analog TV (640x480; 1024x768; etc.)
Data 4,5,Art prints + medium format (8x10; 16x20)
Data 11,14,legal paper (11x14)
Data 16,9,Standard HD display (1920x1080; 1280x720; etc.)
Data 0,0,Custom (user enters ratio)

' =============================================================================
' PROMPT USER TO ENTER A NUMBER THEN CALCULATE ROWS/COLUMNS BASED ON LAYOUT RATIOS
Do
    Do
        Color cLtGray, cBlack
        Print "-------------------------------------------------------------------------------"
        Print "Grid Layouts"
        Print "-------------------------------------------------------------------------------"
        Input "Number of items? (0 to exit)"; in$
        Print
        _KeyClear: '_DELAY 1
       
        If IsNumber%(in$) = _TRUE Then
            iItemCount = Val(in$)
            Exit Do
        End If
    Loop
    If iItemCount < 1 Then Exit Do
   
    ' -----------------------------------------------------------------------------
    ' Get even # of items
    If IsEven%(iItemCount) = _TRUE Then
        iEvenCount = iItemCount
    Else
        iEvenCount = iItemCount + 1
    End If

    ' -----------------------------------------------------------------------------
    ' Get total # of items we would need for an equal number of rows and columns

    ' DOES COUNT ALLOW FOR A PERFECT SQUARE?
    sngRowCol = Sqr(iItemCount)
    If sngRowCol = Int(sngRowCol) Then
        ' COUNT IS ALREADY RIGHT FOR SQUARE LAYOUT
        iSquareCount = iItemCount
    Else
        ' ADD ITEMS TO ALLOW FOR SQUARE LAYOUT
        iSquareCount = iItemCount
        Do
            iSquareCount = iSquareCount + 1
            sngRowCol = Sqr(iSquareCount)
            If sngRowCol = Int(sngRowCol) Then Exit Do
        Loop
    End If
   
    ' -----------------------------------------------------------------------------
    ' DETERMINE RATIOS WITH CALCULATED NUMBER OF ROWS/COLUMNS FOR EACH
    iMaxEmpty = 0
    'For iLoop1 = 1 To iLayoutCount
    For iLoop1 = LBound(arrLayout) To UBound(arrLayout)
        ' Ignore uninitialized
        If arrLayout(iLoop1).HRatio > 0 And arrLayout(iLoop1).VRatio > 0 Then
            arrLayout(iLoop1).Error = ""
           
            arrLayout(iLoop1).ColumnCount = 0
            arrLayout(iLoop1).RowCount = 0
           
            arrLayout(iLoop1).TargetCount = iItemCount
            arrLayout(iLoop1).CellCount = 0
            arrLayout(iLoop1).EmptyCells = 0
           
            If arrLayout(iLoop1).HRatio <= 0 Then
                arrLayout(iLoop1).Error = arrLayout(iLoop1).Error + _
                    "Illegal value: " + _
                    "arrLayout(" + _TRIM$(Str$(iLoop1)) + ").HRatio = " + _
                    _TRIM$(Str$(arrLayout(iLoop1).HRatio)) + ". "
            End If
           
            If arrLayout(iLoop1).VRatio <= 0 Then
                arrLayout(iLoop1).Error = arrLayout(iLoop1).Error + _
                    "Illegal value: " + _
                    "arrLayout(" + _TRIM$(Str$(iLoop1)) + ").VRatio = " + _
                    _TRIM$(Str$(arrLayout(iLoop1).VRatio)) + ". "
            End If
           
            If Len(arrLayout(iLoop1).Error) = 0 Then
                ' IS RATIO A PERFECT SQUARE?
                If arrLayout(iLoop1).HRatio = arrLayout(iLoop1).VRatio Then
                    ' # OF COLUMS EQUALS # ROWS
                    arrLayout(iLoop1).ColumnCount = Sqr(iSquareCount)
                    arrLayout(iLoop1).RowCount = arrLayout(iLoop1).ColumnCount
                Else
                    ' NOT A PERFECT SQUARE
                    sngColumnCount = Sqr(iEvenCount * (arrLayout(iLoop1).HRatio / arrLayout(iLoop1).VRatio))
                    sngRowCount = Sqr(iEvenCount * (arrLayout(iLoop1).VRatio / arrLayout(iLoop1).HRatio))
                   
                    ' DO THESE DIVIDE EVENLY?
                    If sngColumnCount = Int(sngColumnCount) Then
                        arrLayout(iLoop1).ColumnCount = Int(sngColumnCount)
                    Else
                        arrLayout(iLoop1).ColumnCount = Fix(sngColumnCount)
                    End If
                    If sngRowCount = Int(sngRowCount) Then
                        arrLayout(iLoop1).RowCount = Int(sngRowCount)
                    Else
                        arrLayout(iLoop1).RowCount = Fix(sngRowCount)
                    End If
                   
                    ' ENOUGH COLUMNS & ROWS?
                    If arrLayout(iLoop1).HRatio > arrLayout(iLoop1).VRatio Then
                        Do
                            If arrLayout(iLoop1).ColumnCount * arrLayout(iLoop1).RowCount >= iItemCount Then Exit Do
                            arrLayout(iLoop1).ColumnCount = arrLayout(iLoop1).ColumnCount + 1
                        Loop
                    Else
                        Do
                            If arrLayout(iLoop1).ColumnCount * arrLayout(iLoop1).RowCount >= iItemCount Then Exit Do
                            arrLayout(iLoop1).RowCount = arrLayout(iLoop1).RowCount + 1
                        Loop
                    End If
                   
                End If
               
            End If
           
            ' Calculate total # of cells + empty cells
            If Len(arrLayout(iLoop1).Error) = 0 Then
                arrLayout(iLoop1).CellCount = arrLayout(iLoop1).ColumnCount * arrLayout(iLoop1).RowCount
                arrLayout(iLoop1).EmptyCells = arrLayout(iLoop1).CellCount - arrLayout(iLoop1).TargetCount
               
                ' STORE MAXIMUM # OF EMPTY CELLS
                If arrLayout(iLoop1).EmptyCells > iMaxEmpty Then
                    iMaxEmpty = arrLayout(iLoop1).EmptyCells
                End If
            End If
        End If
    Next iLoop1
   
    ' -----------------------------------------------------------------------------
    ' SORT RATIOS IN ORDER OF EMPTY CELLS
    'arrLayout(iLoop1).EmptyCells = arrLayout(iLoop1).CellCount - arrLayout(iLoop1).TargetCount
   
    ' INITIALIZE SORTED LAYOUTS
    For iLoop1 = LBound(arrSorted) To UBound(arrSorted)
        arrSorted(iLoop1).Name = ""
        arrSorted(iLoop1).HRatio = 0
        arrSorted(iLoop1).VRatio = 0
        arrSorted(iLoop1).Error = ""
    Next iLoop1
   
    ' SORT RATIOS
    bFinished = _FALSE
    iSortIndex = LBound(arrSorted) - 1
    iMinEmpty = iMaxEmpty + 1 ' reset min value to find
   
    Do
        ' Reset compare
        iNextMinEmpty = iMaxEmpty + 1 ' reset temp min value to find
        iIndex = LBound(arrLayout) - 1 ' Set iIndex outside of array bounds, next smallest not found (yet)
       
        ' Find smallest empty
        For iLoop1 = LBound(arrLayout) To UBound(arrLayout)
            ' Ignore unused
            If arrLayout(iLoop1).HRatio > 0 And arrLayout(iLoop1).VRatio > 0 Then
                ' Ignore errors
                If Len(arrLayout(iLoop1).Error) = 0 Then
                    ' Is this the smallest yet?
                    If arrLayout(iLoop1).EmptyCells < iMinEmpty Then
                        iMinEmpty = arrLayout(iLoop1).EmptyCells ' update minimum
                    End If
                   
                    ' Is this the smallest of the ones left so far?
                    If arrLayout(iLoop1).EmptyCells < iNextMinEmpty Then
                        iNextMinEmpty = arrLayout(iLoop1).EmptyCells ' update minimum
                        iIndex = iLoop1 ' remember this layout
                    End If
                End If
            End If
        Next iLoop1

        ' Add smallest to sorted
        ' As long as iIndex is within array bounds, we found next smallest
        If iIndex >= LBound(arrLayout) Then
            iSortIndex = iSortIndex + 1
            If iSortIndex <= UBound(arrSorted) Then
                arrSorted(iSortIndex).HRatio = arrLayout(iIndex).HRatio
                arrSorted(iSortIndex).VRatio = arrLayout(iIndex).VRatio
                arrSorted(iSortIndex).Name = arrLayout(iIndex).Name
                arrSorted(iSortIndex).ColumnCount = arrLayout(iIndex).ColumnCount
                arrSorted(iSortIndex).RowCount = arrLayout(iIndex).RowCount
                arrSorted(iSortIndex).TargetCount = arrLayout(iIndex).TargetCount
                arrSorted(iSortIndex).CellCount = arrLayout(iIndex).CellCount
                arrSorted(iSortIndex).EmptyCells = arrLayout(iIndex).EmptyCells
                arrSorted(iSortIndex).Error = ""

                arrLayout(iIndex).Error = "Sorted" ' remove this from sort pool
            Else
                ' Exceeded sorted array size, quit sorting
                Exit Do
            End If
        Else
            ' Finished sorting
            Exit Do
        End If

    Loop
   
    ' -----------------------------------------------------------------------------
    ' HEADER FOR DISPLAYING SORTED RESULTS TO SCREEN
    Color cLtGray, cBlack
    Print "LAYOUTS FROM MOST OPTIMAL TO LEAST:"
    Print
    Color cWhite~&, cBlack
    Print "   #   H-Ratio    V-Ratio    Columns    Rows       Cells      Empty      Layout"
    Print "----   --------   --------   --------   --------   --------   --------   ------"
    '         1   12345678   12345678   12345678   12345678   12345678   12345678   123456
    
    ' -----------------------------------------------------------------------------
    ' HEADER FOR OUTPUTTING RESULTS TO A TAB-DELIMITED FILE
    PrintDebugFile _
        "Items" + chr$(9) + _
        "H-Ratio" + chr$(9) + _
        "V-Ratio" + chr$(9) + _
        "Columns" + chr$(9) + _
        "Rows" + chr$(9) + _
        "Total Cells" + chr$(9) + _
        "Empty Cells" + chr$(9) + _
        "Layout"
    
    ' -----------------------------------------------------------------------------
    ' OUTPUT RESULTS TO SCREEN AND FILE
    iCount = 0
    For iLoop1 = LBound(arrSorted) To UBound(arrSorted)
        ' Ignore unused
        If arrSorted(iLoop1).HRatio > 0 And arrSorted(iLoop1).VRatio > 0 Then
            iCount = iCount + 1
            
            ' -----------------------------------------------------------------------------
            ' OUTPUT TO SCREEN
            
            ' ASSEMBLE SPACE-DELIMITED LINE
            sLine = _
                Right$(String$(4, " ") + _Trim$(Str$(iItemCount)), 4) + _
                "   " + _
                left$( _Trim$(Str$(arrSorted(iLoop1).HRatio)) + string$(8, " "), 8) + _
                "   " + _
                left$( _Trim$(Str$(arrSorted(iLoop1).VRatio)) + string$(8, " "), 8) + _
                "   " + _
                right$( string$(8, " ") + _Trim$(Str$(arrSorted(iLoop1).ColumnCount)) , 8) + _
                "   " + _
                right$( string$(8, " ") + _Trim$(Str$(arrSorted(iLoop1).RowCount)) , 8) + _
                "   " + _
                right$( string$(8, " ") + _Trim$(Str$(arrSorted(iLoop1).CellCount)) , 8) + _
                "   " + _
                right$( string$(8, " ") + _Trim$(Str$(arrSorted(iLoop1).EmptyCells)) , 8) + _
                "   " + _
                arrSorted(iLoop1).Name
            
            ' SHOW OPTIMAL LAYOUTS IN YELLOW, SQUARE LAYOUTS IN LIME, ALL OTHERS IN CYAN
            If arrSorted(iLoop1).ColumnCount = arrSorted(iLoop1).RowCount Then
                Color cLime~&, cBlack
            ElseIf arrSorted(iLoop1).EmptyCells = iMinEmpty Then
                Color cYellow~&, cBlack
            Else
                Color cCyan~&, cBlack
            End If
            
            ' PRINT NEXT LINE
            Print Left$(sLine, 160)
            
            ' -----------------------------------------------------------------------------
            ' OUTPUT TO FILE
            
            ' ASSEMBLE TAB-DELIMITED LINE
            sLine = _
                _Trim$(Str$(iItemCount)) + _
                chr$(9) + _
                _Trim$(Str$(arrSorted(iLoop1).HRatio)) + _
                chr$(9) + _
                _Trim$(Str$(arrSorted(iLoop1).VRatio)) + _
                chr$(9) + _
                _Trim$(Str$(arrSorted(iLoop1).ColumnCount)) + _
                chr$(9) + _
                _Trim$(Str$(arrSorted(iLoop1).RowCount)) + _
                chr$(9) + _
                _Trim$(Str$(arrSorted(iLoop1).CellCount)) + _
                chr$(9) + _
                _Trim$(Str$(arrSorted(iLoop1).EmptyCells)) + _
                chr$(9) + _
                arrSorted(iLoop1).Name
            
            ' WRITE NEXT LINE TO FILE
            PrintDebugFile sLine
        End If
    Next iLoop1
   
    ' CLEAR KEYBOARD BUFFER AND START OVER
    _KeyClear: '_DELAY 1
    Print
Loop

Cls: Print: Print "Finished"

End

' /////////////////////////////////////////////////////////////////////////////
' Simple timestamp function

Function CurrentDateTime$
    CurrentDateTime$ = Mid$(Date$, 7, 4) + "-" + _
        Mid$(Date$, 1, 5) + " " + _
        Time$
End Function ' CurrentDateTime$

' /////////////////////////////////////////////////////////////////////////////
' Returns TRUE if number n is even
' https://slaystudy.com/qbasic-program-to-check-if-number-is-even-or-odd/
' see also: IsOdd%

Function IsEven% (n)
    If n Mod 2 = 0 Then
        IsEven% = _TRUE
    Else
        IsEven% = _FALSE
    End If
End Function ' IsEven%

' /////////////////////////////////////////////////////////////////////////////
' Returns TRUE if value OriginalString$ is numeric.

' Re: Does a Is Number function exist in QB64?
' https://www.qb64.org/forum/index.php?topic=896.15

' Version 2 by madscijr
' Returns TRUE (-1) if string is an integer, FALSE (0) if not

' Version 1 by MWheatley
' Reply #18 on: January 01, 2019, 11:24:30 AM
' returns 1 if string is an integer, 0 if not

Function IsNumber% (OriginalString$)
    Dim bResult%: bResult% = _FALSE
    Dim iLoop%
    Dim TestString$
    'Dim bNegative%
    Dim iDecimalCount%
    Dim sNextChar$

    'THEY SHOULD TRIM OUTSIDE THE FUNCTION!
    'TestString$ = _TRIM$(OriginalString$)

    If Len(OriginalString$) > 0 Then
        TestString$ = ""
        If Left$(OriginalString$, 1) = "+" Then
            TestString$ = Right$(OriginalString$, Len(OriginalString$) - 1)
            'bNegative% = FALSE
        ElseIf Left$(OriginalString$, 1) = "-" Then
            TestString$ = Right$(OriginalString$, Len(OriginalString$) - 1)
            'bNegative% = TRUE
        Else
            TestString$ = OriginalString$
            'bNegative% = FALSE
        End If
        If Len(TestString$) > 0 Then
            bResult% = _TRUE
            iDecimalCount% = 0
            For iLoop% = 1 To Len(TestString$)
                sNextChar$ = Mid$(TestString$, iLoop%, 1)
                If sNextChar$ = "." Then
                    iDecimalCount% = iDecimalCount% + 1
                    If iDecimalCount% > 1 Then
                        ' TOO MANY DECIMAL POINTS, INVALID!
                        bResult% = _FALSE
                        Exit For
                    End If
                ElseIf Asc(sNextChar$) < 48 Or Asc(sNextChar$) > 57 Then
                    ' NOT A NUMERAL OR A DECIMAL, INVALID!
                    bResult% = _FALSE
                    Exit For
                End If
            Next iLoop%
        End If
    End If
    IsNumber% = bResult%
End Function ' IsNumber%

' /////////////////////////////////////////////////////////////////////////////
' Writes sText to a debug file in the EXE folder.
' Debug file is named the same thing as the program EXE name with ".txt" at the end.
' For example the program "C:\QB64\MyProgram.BAS" running as
' "C:\QB64\MyProgram.EXE" would have an output file "C:\QB64\MyProgram.EXE.txt".
' If the file doesn't exist, it is created, otherwise it is appended to.

' If in debug mode, show the user the debug path that they can copy/paste
' using _INPUTBOX$:
' result$ = _INPUTBOX$(m_ProgramName$, "Current debug filename is:", m_ProgramPath$ + m_ProgramName$ + ".txt")

Sub PrintDebugFile (sText As String)
    Dim sFileName As String
    Dim sError As String
    Dim sOut As String
    Dim sTimestamp as string
    
    sFileName = m_ProgramPath$ + m_ProgramName$ + ".txt"
    sError = ""
    sTimestamp = CurrentDateTime$
    
    If _FileExists(sFileName) = _FALSE Then
        sOut = ""
        'sOut = sOut + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Chr$(13) + Chr$(10)
        'sOut = sOut + "PROGRAM : " + m_ProgramName$ + Chr$(13) + Chr$(10)
        'sOut = sOut + "RUN DATE: " + sTimestamp + Chr$(13) + Chr$(10)
        'sOut = sOut + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Chr$(13) + Chr$(10)
        sError = PrintFile$(sFileName, sOut, _FALSE)
    End If
    If Len(sError) = 0 Then
        sError = PrintFile$(sFileName, sText, _TRUE)
    End If
    If Len(sError) <> 0 Then
        Print sTimestamp + " PrintDebugFile FAILED"
        Print String$( len(sTimestamp) + 1, " ") + "sFileName = " + chr$(34) + sFileName + chr$(34)
        Print String$( len(sTimestamp) + 1, " ") + "ERROR     = " + sError
    End If
End Sub ' PrintDebugFile

' /////////////////////////////////////////////////////////////////////////////
' Writes sText to file sFileName.
' If bAppend=_TRUE appends to file, else overwrites it.

' Returns blank if successful else returns error message.

' Example:
' m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
' m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)
' sFileName = m_ProgramPath$ + m_ProgramName$ + ".OUT.txt"
' sText = "This is a test." + chr$(13) + "Here is line 2." + chr$(13) + "End."
' sError = PrintFile$(sFileName, sText, _FALSE)

Function PrintFile$ (sFileName As String, sText As String, bAppend As Integer)
    Dim sError As String: sError = ""

    If Len(sError) = 0 Then
        If (bAppend = _TRUE) Then
            If _FileExists(sFileName) Then
                Open sFileName For Append As #1 ' opens an existing file for appending
            Else
                sError = "Error in PrintFile$ : File not found. Cannot append."
            End If
        Else
            Open sFileName For Output As #1 ' opens and clears an existing file or creates new empty file
        End If
    End If
    If Len(sError) = 0 Then
        ' NOTE: WRITE places text in quotes in the file
        'WRITE #1, x, y, z$
        'WRITE #1, sText

        ' PRINT does not put text inside quotes
        Print #1, sText

        Close #1
    End If

    PrintFile$ = sError
End Function ' PrintFile$

' /////////////////////////////////////////////////////////////////////////////
' FROM: String Manipulation
' found at abandoned, outdated and now likely malicious qb64 dot net website
' http://www.qb64.[net]/forum/index_topic_5964-0/
'
'SUMMARY:
'   Purpose:  A library of custom functions that transform strings.
'   Author:   Dustinian Camburides (dustinian@gmail.com)
'   Platform: QB64 (www.qb64.org)
'   Revision: 1.6
'   Updated:  5/28/2012

'SUMMARY:
'[Replace$] replaces all instances of the [Find] sub-string with the [Add] sub-string within the [Text] string.
'INPUT:
'Text: The input string; the text that's being manipulated.
'Find: The specified sub-string; the string sought within the [Text] string.
'Add: The sub-string that's being added to the [Text] string.

Function Replace$ (Text1 As String, Find1 As String, Add1 As String)
    ' VARIABLES:
    Dim Text2 As String
    Dim Find2 As String
    Dim Add2 As String
    Dim lngLocation As Long ' The address of the [Find] substring within the [Text] string.
    Dim strBefore As String ' The characters before the string to be replaced.
    Dim strAfter As String ' The characters after the string to be replaced.

    ' INITIALIZE:
    ' MAKE COPIESSO THE ORIGINAL IS NOT MODIFIED (LIKE ByVal IN VBA)
    Text2 = Text1
    Find2 = Find1
    Add2 = Add1

    lngLocation = InStr(1, Text2, Find2)

    ' PROCESSING:
    ' While [Find2] appears in [Text2]...
    While lngLocation
        ' Extract all Text2 before the [Find2] substring:
        strBefore = Left$(Text2, lngLocation - 1)

        ' Extract all text after the [Find2] substring:
        strAfter = Right$(Text2, ((Len(Text2) - (lngLocation + Len(Find2) - 1))))

        ' Return the substring:
        Text2 = strBefore + Add2 + strAfter

        ' Locate the next instance of [Find2]:
        lngLocation = InStr(1, Text2, Find2)

        ' Next instance of [Find2]...
    Wend

    ' OUTPUT:
    Replace$ = Text2
End Function ' Replace$

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN TEXT MODE COLOR CODE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function cBlackT%
    cBlackT% = 0
End Function

Function cBlueT%
    cBlueT% = 1
End Function

Function cGreenT%
    cGreenT% = 2
End Function

Function cLtBlueT%
    cLtBlueT% = 3
End Function

Function cRedT%
    cRedT% = 4
End Function

Function cPurpleT%
    cPurpleT% = 5
End Function

Function cOrangeT%
    cOrangeT% = 6
End Function

Function cWhiteT%
    cWhiteT% = 7
End Function

Function cGrayT%
    cGrayT% = 8
End Function

Function cPeriwinkleT%
    cPeriwinkleT% = 9
End Function

Function cLtGreenT%
    cLtGreenT% = 10
End Function

Function cCyanT%
    cCyanT% = 11
End Function

Function cLtRedT%
    cLtRedT% = 12
End Function

Function cPinkT%
    cPinkT% = 13
End Function

Function cYellowT%
    cYellowT% = 14
End Function

Function cLtGrayT%
    cLtGrayT% = 15
End Function
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END TEXT MODE COLOR CODE FUNCTIONS
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' BEGIN RGB COLOR FUNCTIONS #RGB
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Function cRed~& ()
    cRed = _RGB32(255, 0, 0)
End Function

Function cOrangeRed~& ()
    cOrangeRed = _RGB32(255, 69, 0)
End Function ' cOrangeRed~&

Function cDarkOrange~& ()
    cDarkOrange = _RGB32(255, 140, 0)
End Function ' cDarkOrange~&

Function cOrange~& ()
    cOrange = _RGB32(255, 165, 0)
End Function ' cOrange~&

Function cGold~& ()
    cGold = _RGB32(255, 215, 0)
End Function ' cGold~&

Function cYellow~& ()
    cYellow = _RGB32(255, 255, 0)
End Function ' cYellow~&

' LONG-HAIRED FRIENDS OF JESUS OR NOT,
' THIS IS NOT YELLOW ENOUGH (TOO CLOSE TO LIME)
' TO USE FOR OUR COMPLEX RAINBOW SEQUENCE:
Function cChartreuse~& ()
    cChartreuse = _RGB32(127, 255, 0)
End Function ' cChartreuse~&

' WE SUBSTITUTE THIS CSS3 COLOR FOR INBETWEEN LIME AND YELLOW:
Function cOliveDrab1~& ()
    cOliveDrab1 = _RGB32(192, 255, 62)
End Function ' cOliveDrab1~&

Function cLime~& ()
    cLime = _RGB32(0, 255, 0)
End Function ' cLime~&

Function cMediumSpringGreen~& ()
    cMediumSpringGreen = _RGB32(0, 250, 154)
End Function ' cMediumSpringGreen~&

' ADDED THIS FOR THE GAUGE COLOR:
Function cSpringGreen~& ()
    cSpringGreen = _RGB32(0, 255, 160)
End Function ' cSpringGreen~&

Function cCyan~& ()
    cCyan = _RGB32(0, 255, 255)
End Function ' cCyan~&

Function cDeepSkyBlue~& ()
    cDeepSkyBlue = _RGB32(0, 191, 255)
End Function ' cDeepSkyBlue~&

Function cDodgerBlue~& ()
    cDodgerBlue = _RGB32(30, 144, 255)
End Function ' cDodgerBlue~&

Function cSeaBlue~& ()
    cSeaBlue = _RGB32(0, 64, 255)
End Function ' cSeaBlue~&

Function cBlue~& ()
    cBlue = _RGB32(0, 0, 255)
End Function ' cBlue~&

Function cBluePurple~& ()
    cBluePurple = _RGB32(64, 0, 255)
End Function ' cBluePurple~&

Function cDeepPurple~& ()
    cDeepPurple = _RGB32(96, 0, 255)
End Function ' cDeepPurple~&

Function cPurple~& ()
    cPurple = _RGB32(128, 0, 255)
End Function ' cPurple~&

Function cPurpleRed~& ()
    cPurpleRed = _RGB32(128, 0, 192)
End Function ' cPurpleRed~&

Function cDarkRed~& ()
    cDarkRed = _RGB32(160, 0, 64)
End Function ' cDarkRed~&

Function cBrickRed~& ()
    cBrickRed = _RGB32(192, 0, 32)
End Function ' cBrickRed~&

Function cDarkGreen~& ()
    cDarkGreen = _RGB32(0, 100, 0)
End Function ' cDarkGreen~&

Function cGreen~& ()
    cGreen = _RGB32(0, 128, 0)
End Function ' cGreen~&

Function cOliveDrab~& ()
    cOliveDrab = _RGB32(107, 142, 35)
End Function ' cOliveDrab~&

Function cLightPink~& ()
    cLightPink = _RGB32(255, 182, 193)
End Function ' cLightPink~&

Function cHotPink~& ()
    cHotPink = _RGB32(255, 105, 180)
End Function ' cHotPink~&

Function cDeepPink~& ()
    cDeepPink = _RGB32(255, 20, 147)
End Function ' cDeepPink~&

Function cMagenta~& ()
    cMagenta = _RGB32(255, 0, 255)
End Function ' cMagenta~&

Function cBlack~& ()
    cBlack = _RGB32(0, 0, 0)
End Function ' cBlack~&

Function cDimGray~& ()
    cDimGray = _RGB32(105, 105, 105)
End Function ' cDimGray~&

Function cGray~& ()
    cGray = _RGB32(128, 128, 128)
End Function ' cGray~&

Function cDarkGray~& ()
    cDarkGray = _RGB32(169, 169, 169)
End Function ' cDarkGray~&

Function cSilver~& ()
    cSilver = _RGB32(192, 192, 192)
End Function ' cSilver~&

Function cLtGray~& ()
    cLtGray~& = cLightGray~&
End Function ' cLtGray~&

Function cLightGray~& ()
    cLightGray = _RGB32(211, 211, 211)
End Function ' cLightGray~&

Function cGainsboro~& ()
    cGainsboro = _RGB32(220, 220, 220)
End Function ' cGainsboro~&

Function cWhiteSmoke~& ()
    cWhiteSmoke = _RGB32(245, 245, 245)
End Function ' cWhiteSmoke~&

Function cWhite~& ()
    cWhite = _RGB32(255, 255, 255)
    'cWhite = _RGB32(254, 254, 254)
End Function ' cWhite~&

Function cDarkBrown~& ()
    cDarkBrown = _RGB32(128, 64, 0)
End Function ' cDarkBrown~&

Function cLightBrown~& ()
    cLightBrown = _RGB32(196, 96, 0)
End Function ' cLightBrown~&

Function cKhaki~& ()
    cKhaki = _RGB32(240, 230, 140)
End Function ' cKhaki~&

Function cEmpty~& ()
    'cEmpty~& = -1
    cEmpty = _RGB32(0, 0, 0, 0)
End Function ' cEmpty~&

' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' END RGB COLOR FUNCTIONS @RGB
' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Steve:
Code: (Select All)
' Grid Formatting Demo
' https://qb64phoenix.com/forum/showthread.php?tid=3482&pid=0#pid0

' From: SMcNeill
' Date: 2/21/2025 1:00 PM
' Based off the topic here: https://qb64phoenix.com/forum/showthread.php?tid=3475
' -----------------------------------------------------------------------------
' I tried to break this down as simple as possible, so that one can use this
' to generate a series of grids in a set ratio and choose which layout would
' work best for their number of items. I *think* this basically follows the
' same spirit of what [url=https://qb64phoenix.com/forum/member.php?action=profile&uid=10]@madscijr[/url] was trying to do with his code.
'
' One difference here though -- I removed the inverse values as they're always
' going to be the same result, just turned sideways!
'
' a 4 x 6 grid holds 24 items.
' a 6 x 4 grid holds the same 24 items.
'
' Seems like a waste to list them both. If one really wants that, then just
' swap your X and Y numbers. It won't change how many items the grid would hold.
' 4 x 6 is the same as 6 x 4. Wink
'
' Try it out. See if this does what you were trying to do, and see if it's a
' little bit simpler and easier to understand. Big Grin

Type Ratio_Type
    x As _Integer64
    y As _Integer64
    description As String
    size As _Integer64
    scale As _Integer64
    total As _Integer64
    empty As _Integer64
End Type

' BASIC PROGRAM METADATA
Dim Shared m_ProgramPath$: m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
Dim Shared m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)

Dim Shared Ratio(8) As Ratio_Type
Dim shared items As Long

' SHOW USER DEBUG FILE/PATH SO THEY CAN COPY TO CLIPBOARD:
Dim in$ : in$ = _INPUTBOX$(m_ProgramName$, "Current debug filename is:", m_ProgramPath$ + m_ProgramName$ + ".txt")

Screen _NewImage(1280, 720, 32)
InitRatios
Cls
Do
    Input "Enter the number of items =>"; items
    If items <= 0 Then System
    CalculateGrids items
    SortGrids
    DisplayGrids
Loop

Sub DisplayGrids
    dim sLine as string
    
    Print
    Color &HFF00FF00&&
    
    ' HEADER FOR DISPLAYING SORTED RESULTS TO SCREEN
    Print "   #   H-Ratio    V-Ratio    Columns    Rows       Cells      Empty      Layout"
    Print "----   --------   --------   --------   --------   --------   --------   ------"
    
    ' HEADER FOR OUTPUTTING RESULTS TO A TAB-DELIMITED FILE
    PrintDebugFile _
        "Items" + chr$(9) + _
        "H-Ratio" + chr$(9) + _
        "V-Ratio" + chr$(9) + _
        "Columns" + chr$(9) + _
        "Rows" + chr$(9) + _
        "Total Cells" + chr$(9) + _
        "Empty Cells" + chr$(9) + _
        "Layout"
    
    Color &HFFFFFFFF&&
    
    For i = 1 To UBound(Ratio)
        
        ' -----------------------------------------------------------------------------
        ' OUTPUT TO SCREEN
        
        ' ASSEMBLE SPACE-DELIMITED LINE
        sLine = _
            Right$(String$(4, " ") + _Trim$(Str$(items)), 4) + _
            "   " + _
            left$( _Trim$(Str$(ratio(i).x)) + string$(8, " "), 8) + _
            "   " + _
            left$( _Trim$(Str$(ratio(i).y)) + string$(8, " "), 8) + _
            "   " + _            
            right$( string$(8, " ") + _Trim$(Str$(ratio(i).x * ratio(i).scale)) , 8) + _
            "   " + _
            right$( string$(8, " ") + _Trim$(Str$(ratio(i).y * ratio(i).scale)) , 8) + _
            "   " + _
            right$( string$(8, " ") + _Trim$(Str$(ratio(i).x * ratio(i).scale * ratio(i).y * ratio(i).scale)) , 8) + _
            "   " + _
            right$( string$(8, " ") + _Trim$(Str$(ratio(i).empty)) , 8) + _
            "   " + _
            ratio(i).description
            'ratio(i).scale
            
        ' PRINT NEXT LINE
        print left$(sLine, 160)
            
        ' -----------------------------------------------------------------------------
        ' OUTPUT TO FILE
        
        ' ASSEMBLE TAB-DELIMITED LINE
        sLine = _
            _Trim$(Str$(items)) + _
            chr$(9) + _
            _Trim$(Str$(ratio(i).x)) + _
            chr$(9) + _
            _Trim$(Str$(ratio(i).y)) + _
            chr$(9) + _
            _Trim$(Str$(ratio(i).x * ratio(i).scale)) + _
            chr$(9) + _
            _Trim$(Str$(ratio(i).y * ratio(i).scale)) + _
            chr$(9) + _
            _Trim$(Str$(ratio(i).x * ratio(i).scale * ratio(i).y * ratio(i).scale)) + _
            chr$(9) + _
            _Trim$(Str$(ratio(i).empty)) + _
            chr$(9) + _
            ratio(i).description
        
        ' WRITE NEXT LINE TO FILE
        PrintDebugFile sLine

    Next i
End Sub ' DisplayGrids

Sub SortGrids
    For i = 1 To UBound(Ratio)
        For j = i + 1 To UBound(Ratio)
            If Ratio(i).empty > Ratio(j).empty Then Swap Ratio(i), Ratio(j)
    Next j, i
End Sub ' SortGrids

Sub CalculateGrids (items)
    For i = 1 To UBound(Ratio)
        n = 1
        Do Until Ratio(i).size * n ^ 2 > items
            n = n + 1
        Loop
        Ratio(i).scale = n ' this is the scaler
        Ratio(i).total = Ratio(i).size * n ^ 2 ' this is the total number of cells
        Ratio(i).empty = Ratio(i).total - items
    Next i
End Sub ' CalculateGrids

Sub InitRatios
    RatioData:
    Data 1,1,Square (profile pictures; social media)
    Data 2,3,Classic 35mm (4x6; 6x9; etc.)
    Data 5,7,5 x 7 photo
    Data 17,22,Standard letter size (8.5x11)
    Data 4,3,Older PC monitor + analog TV (640x480; 1024x768; etc.)
    Data 4,5,Art prints + medium format (8x10; 16x20)
    Data 11,14,legal paper (11x14)
    Data 16,9,Standard HD display (1920x1080; 1280x720; etc.)
    For i = 1 To UBound(Ratio)
        Read Ratio(i).x, Ratio(i).y, Ratio(i).description
        Ratio(i).size = Ratio(i).x * Ratio(i).y
    Next i
End Sub ' InitRatios

' /////////////////////////////////////////////////////////////////////////////
' Simple timestamp function

Function CurrentDateTime$
    CurrentDateTime$ = Mid$(Date$, 7, 4) + "-" + _
        Mid$(Date$, 1, 5) + " " + _
        Time$
End Function ' CurrentDateTime$

' /////////////////////////////////////////////////////////////////////////////
' Writes sText to a debug file in the EXE folder.
' Debug file is named the same thing as the program EXE name with ".txt" at the end.
' For example the program "C:\QB64\MyProgram.BAS" running as
' "C:\QB64\MyProgram.EXE" would have an output file "C:\QB64\MyProgram.EXE.txt".
' If the file doesn't exist, it is created, otherwise it is appended to.

' If in debug mode, show the user the debug path that they can copy/paste
' using _INPUTBOX$:
' result$ = _INPUTBOX$(m_ProgramName$, "Current debug filename is:", m_ProgramPath$ + m_ProgramName$ + ".txt")

Sub PrintDebugFile (sText As String)
    Dim sFileName As String
    Dim sError As String
    Dim sOut As String
    Dim sTimestamp as string
    
    sFileName = m_ProgramPath$ + m_ProgramName$ + ".txt"
    sError = ""
    sTimestamp = CurrentDateTime$
    
    If _FileExists(sFileName) = _FALSE Then
        sOut = ""
        'sOut = sOut + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Chr$(13) + Chr$(10)
        'sOut = sOut + "PROGRAM : " + m_ProgramName$ + Chr$(13) + Chr$(10)
        'sOut = sOut + "RUN DATE: " + sTimestamp + Chr$(13) + Chr$(10)
        'sOut = sOut + "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + Chr$(13) + Chr$(10)
        sError = PrintFile$(sFileName, sOut, _FALSE)
    End If
    If Len(sError) = 0 Then
        sError = PrintFile$(sFileName, sText, _TRUE)
    End If
    If Len(sError) <> 0 Then
        Print sTimestamp + " PrintDebugFile FAILED"
        Print String$( len(sTimestamp) + 1, " ") + "sFileName = " + chr$(34) + sFileName + chr$(34)
        Print String$( len(sTimestamp) + 1, " ") + "ERROR     = " + sError
    End If
End Sub ' PrintDebugFile

' /////////////////////////////////////////////////////////////////////////////
' Writes sText to file sFileName.
' If bAppend=_TRUE appends to file, else overwrites it.

' Returns blank if successful else returns error message.

' Example:
' m_ProgramPath$ = Left$(Command$(0), _InStrRev(Command$(0), "\"))
' m_ProgramName$: m_ProgramName$ = Mid$(Command$(0), _InStrRev(Command$(0), "\") + 1)
' sFileName = m_ProgramPath$ + m_ProgramName$ + ".OUT.txt"
' sText = "This is a test." + chr$(13) + "Here is line 2." + chr$(13) + "End."
' sError = PrintFile$(sFileName, sText, _FALSE)

Function PrintFile$ (sFileName As String, sText As String, bAppend As Integer)
    Dim sError As String: sError = ""

    If Len(sError) = 0 Then
        If (bAppend = _TRUE) Then
            If _FileExists(sFileName) Then
                Open sFileName For Append As #1 ' opens an existing file for appending
            Else
                sError = "Error in PrintFile$ : File not found. Cannot append."
            End If
        Else
            Open sFileName For Output As #1 ' opens and clears an existing file or creates new empty file
        End If
    End If
    If Len(sError) = 0 Then
        ' NOTE: WRITE places text in quotes in the file
        'WRITE #1, x, y, z$
        'WRITE #1, sText

        ' PRINT does not put text inside quotes
        Print #1, sText

        Close #1
    End If

    PrintFile$ = sError
End Function ' PrintFile$
Reply
#13
(Yesterday, 09:58 PM)madscijr Wrote: Is my program's output not correct? 
Anyway, thanks again for your patience and time with this...
I will follow up later!

Actually, in this case, you have found the simplest of goofs in my code. In fact, it's such a simple thing, that it's BLEEPING embarrassing that nobody caught it sooner.

Look at this snippet of the old code:

Code: (Select All)
Sub CalculateGrids (items)
    For i = 1 To UBound(Ratio)
        n = 1
        Do Until Ratio(i).size * n ^ 2 > items
            n = n + 1
        Loop
        Ratio(i).scale = n 'this is the scaler
        Ratio(i).total = Ratio(i).size * n ^ 2 'this is the total number of cells
        Ratio(i).empty = Ratio(i).total - items
    Next
End Sub

Let's zoom in one one line in specific:

Do Until Ratio(i).size * n ^ 2 > items

What's that line basically say for us to do?

Expand the grid until it has more spaces than our desired number of items.

Let's reiterate and stress the main point: *more spaces*

NOTE that we don't really need MORE spaces. We need at least THE NUMBER of spaces, or MORE....

Change that single line to the following excessive alteration:

Do Until Ratio(i).size * n ^ 2 >= items

Now you'll get back 0 spaces left over for perfect fit solutions.

7500 items, in a 4:3 ratio results in a 25x scaler for 100x75 grid layout with 0 spaces left over.

You don't need MORE spaces; just ENOUGH spaces and by skipping that equal sign there, we missed this very common use case. Code has been edited and fixed in the original post (that was haaard work editing that, LOL!), and you shouldn't see this glitch any longer.
Reply
#14
(Today, 12:16 AM)SMcNeill Wrote: ...
Code has been edited and fixed in the original post (that was haaard work editing that, LOL!), and you shouldn't see this glitch any longer.

Aha - thanks for clearing that up, I was seriously doubting my sanity, wondering if you guys were messing with me, LoL! I'll try the new code tomorra, it's been a loooong day and I'm done with the computer for a bit. Thanks again and have a pleasant evening!
Reply




Users browsing this thread: 9 Guest(s)