Jump to content

2D array problem (repeat index, wrap-around)


Recommended Posts

I have a little stepstone in a project I just can't seem to get my head around. So, after 5-10 hours of hair-pulling, I throw the towell and call for help here. The first to provide a solution will be duly credited in the software I create ;) This goes into a printing house.

Task: i have a series of numbers in a 2D array. Typically defined by length of series, start, step etc. The generation is no problem.

I need to write these to a file. This is where I have problems.

An example illustrates:

Number series. This is held in a 2D array

1,2,3,4,5,6,7,8,9
11,12,13,14,15,16,17,18,19
21,22,23,24,25,26,27,28,29

Now, I define a value "numbers per line". This is a value less than how many numbers I have on each line. Example 3

Futher I can define a start index value, example 5.

Now I would like to take values of index 5,6,7 from line 1, 5,6,7 from line 2, 5,6,7 from line 3. And after that 8,9,1 from line 1 etc. The index wraps around if I reach the end. This continues until index 4 is at position 3. The part about how many lines to do is easy.

What I can't figure out is how to "reset" the index value so that I cound 4,5,6,4,5,6,4,5,6,7,8,9,7,89,7,8,9,1,2,3,1,2,3  etc.

Desired output here from example

5,6,7,15,16,17,25,26,27
8,9,1,18,19,11,28,29,21
2,3,4,12,13,14,22,23,24

Any suggestions open, take it as a challenge.

What  I have so far:

I can' t figure out the repeating of the index, but I can do the wrap-around (checking the ubound). So, I get index 1,2,3,4,5,6,7,8,9,1,2,3.. which is of course wrong.

(actual production number series is much more, just simple example here).

 

 

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

can you explain the second part a little better, I got everything up to taking the number that ends in 5 and the two next indexes and pushing them to the front, but i dont understand the 8,9,1 stuff after that

#include<array.au3>

; mess with a 1D

$aData= stringsplit("1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,21,22,23,24,25,26,27,28,29" , "," , 2)

$x = 0

    For $i = 0 to ubound($aData) - 1
        If stringright($aData[$i] , 1) = 5 Then
        _ArrayInsert($aData , $x , $aData[$i])
        _ArrayDelete($aData , $i + 1)
            $i+=1
            $x+=1
            _ArrayInsert($aData , $x , $aData[$i])
            _ArrayDelete($aData , $i + 1)
                $i+=1
                $x+=1
            _ArrayInsert($aData , $x , $aData[$i])
            _ArrayDelete($aData , $i + 1)
        $x+=1
        EndIf
    Next

;display as a 2D

$r = 0
$x = 0
Local $aOut[3][9]

For $i = 0 to UBound($aData) - 1
    $aOut[$r][$x] = $aData[$i]
    $x+=1
    If $x = 9 Then
    $x = 0
    $r += 1
    If $r = 3 then exitloop
    EndIf
Next

_ArrayDisplay($aOut)

 

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Link to comment
Share on other sites

Strange requests get strange responses. :unsure:

#include <Array.au3>
#include 'ArrayWorkshop.au3'

Local $aArray = _
[[1,2,3,4,5,6,7,8,9], _
[11,12,13,14,15,16,17,18,19], _
[21,22,23,24,25,26,27,28,29]]
_ArrayDisplay($aArray)

Local $iRows = UBound($aArray), $iCols = UBound($aArray, 2), $iStep = 3
If Int($iCols / $iRows) <> $iStep Then
    MsgBox(0, "Error", "Bounds are incomensurable with step value.") ; doesn't add up
    Exit
EndIf

; column modulation [method = divide and conquer]
Local $aModCols, $iStart = 4
If $iStart >= $iCols Or $iStart < 0 Then Exit ; out of range

If $iStart > 0 Then
    $aModCols = _ExtractRegion($aArray, 2, $iStart, $iCols)
    _ArrayAttach($aModCols, _ExtractRegion($aArray, 2, 0, $iStart), 2)
Else
    $aModCols = $aArray ; start is 0
EndIf
;_ArrayDisplay($aModCols, "ModCols")

Local $aGrid, $iColCount, $iRowCount = 0
For $c = 0 To $iCols - $iStep Step $iStep
    $aGrid = _ExtractRegion($aModCols, 2, $c, $iStep)
    $iColCount = 0
    For $i = 0 To $iRows -1
        For $j = 0 To $iStep -1
            $aArray[$iRowCount][$iColCount] = $aGrid[$i][$j]
            $iColCount += 1
        Next
    Next
    $iRowCount += 1
Next
_ArrayDisplay($aArray)

Using ArrayWorkshop may be overkill right now, but I'm working on a script to generate a stripped and compressed version of the UDF to meet individual requirements. Also the code above is sub-optimal, but serves to demonstrate a plausible method. If it does what you want then it can be optimized.

Edited by czardas
Link to comment
Share on other sites

  • Moderators

Myicq,

My contribution:

#include <Array.au3>

Global $aData[][] = [[1,2,3,4,5,6,7,8,9], _
                    [11,12,13,14,15,16,17,18,19], _
                    [21,22,23,24,25,26,27,28,29]]

$iItemsPerLine = UBound($aData, 2)

$iReqPerLine = 3

$iStartIndex = 7 ; <<<<<<<<<<<<<<<<< Alter this to test

; For each row
For $iRow = 0 To UBound($aData) - 1

    ConsoleWrite(@CRLF & "Row " & $iRow & ":")

    ; Extract these elements
    For $j = 1 To $iReqPerLine
        ; Calculate index
        $iColumn = $iStartIndex + $j - 1
        ; Correct if required
        $iColumn = Mod($iColumn, $iItemsPerLine)

        ConsoleWrite(" " & $aData[$iRow][$iColumn])

    Next

Next
ConsoleWrite(@CRLF)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

This might give you some ideas.

#include <Array.au3>

Local $icount = 0, $iNum = 0
Local $aArray = _
        [[1, 2, 3, 4, 5, 6, 7, 8, 9], _
         [11, 12, 13, 14, 15, 16, 17, 18, 19], _
         [21, 22, 23, 24, 25, 26, 27, 28, 29]] ;, _
         ;[31, 32, 33, 34, 35, 36, 37, 38, 39]]

Local $iRowDim = UBound($aArray), $iColDim = UBound($aArray, 2)
Local $aArray2[$iRowDim][$iColDim]
Local $icount
Local $iStartIndex = 4, $iStep = 3
;ConsoleWrite($iRowDim & "  " & $iColDim & @LF)

For $k = 0 To $iRowDim - 1
    $icount = 0
    For $i = 0 To $iRowDim - 1
        For $j = $iStartIndex + ($k * $iStep) To $iStartIndex + $iStep + ($k * $iStep) - 1
            ;ConsoleWrite($k & @TAB & $i & @TAB & $j & @TAB & Mod($j, $iColDim) & @TAB & $icount & @LF)
            if $icount < $iColDim Then
            $aArray2[$k][$icount] = $aArray[$i][Mod($j, $iColDim)]
            $icount += 1
            EndIf
        Next
    Next
Next

_ArrayDisplay($aArray2)

#cs Returns:-
    5,6,7,15,16,17,25,26,27
    8,9,1,18,19,11,28,29,21
    2,3,4,12,13,14,22,23,24
#ce

 

Link to comment
Share on other sites

Thanks all for your answers ! Especially because it was more a puzzle / algorithm question, more than autoit stuff.

I have learned from the examples, but maybe I did not explain well enough that the 2D initial array can be of different size.

I will try to give another example and what I think could provide correct solution.

1) take a number of 1D arrays (or a single 2D array). This could be as simple as 1,2,3,4,5,6,7,8,9,10

2) now print this array so that it matches with example 3 columns. (10 placed in column 3).

This is not always possible, but will at _maximum_ take 3 * 10 (lines * elements) lines.

Spoiler
1,2,3       < line 1
4,5,6
7,8,9
10,1,2      < 10 is not in last column, so loops around here.
3,4,5
6,7,8
9,10,1      < and loops again here.
2,3,4
5,6,7
8,9,10      < line 10. Last number in last position. We are done.

 

Now, if I had a second 1d array, I would also have to use 10 lines (same length).  Hopefully it's clear now what I mean by "looping around."

My proposed solution now. (for 2d arrays)

The solution I am going to program soon will be:

1) treat the 2D array like 1D arrays, and create separately results as above. That part is simple.

2) now I have as many 2D arrays as I had lines in the original 2D array.

3) now I can take rows 1 and concatenate, rows 2 and concatenate etc. For final result .

Example:

Spoiler
First lines of resulting 2D arrays.
/array 1           /array 2             /array 3
1 2 3              11 12 13             21 22 23
4 5 6              14 15 16             24 25 26
7 8 9              17 18 19             27 28 29


Now concatenate the lines:
1 2 3 11 12 13 21 22 23
4 5 6 14 15 16 24 25 26
etc

With different start values (index) the arrays would just be shifted around:
8 9 10 18 19 20 28 29 30
1 2 3  11 12 13 21 22 23
...
5 6 7  15 16 17 25 26 27

 

Not sure if this is the fasted way, but it's the only one I can overview right now.

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

Forgot to add (and can't edit):

Reason to loop around: Image you print the lines from this array on a continous paper running right-to-left. If you reach the end of the array, you restart. The numbers must now be an ever-continous string of 1,2,3 | ,4,5,6 | ,7,8,9 | ,10,1,2 | ,3,4,5 | ,6,7,8 | ,9,10,.... The can't be lines with only 2 or 1 digit. The bars should clarify.

 

Spoiler
1,2,3       < line 1
4,5,6
7,8,9
10,1,2      < 10 is not in last column, so loops around here.
3,4,5
6,7,8
9,10,1      < and loops again here.
2,3,4
5,6,7
8,9,10      < line 10. Last number in last position. We are done.

 

 

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

That didn't make sense to me. Sure arrays can be different sizes, but in order to satisfy the conditions in the first example, the rows and columns must be commensurable. You have not given an example of how to handle incommensurable array bounds. What is meant to happen with an array containing 13 columns and 5 rows? I don't think you have thought this through properly. I also fail to see any practical application.

Edit I just looked again and I see the error in your thinking. Recursion is a tricky business. Your proposed solution is a time bomb. Don't replicate data: use Mod().

Edited by czardas
Link to comment
Share on other sites

  • Moderators

Myicq,

Rather than asking us to solve "puzzle / algorithm" questions, how about explaining clearly what it is you are trying to achieve by all this - because I for one will not put in any more effort until you do so. I could produce various algorithms to parse arrays all day long, but unless I understand what the end result is supposed to be I have no idea whether they are relevant to the real world problem you are trying to solve.

M23

 

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

@Melba23 of course, and I understand. Will try to detail here, sorry if being too verbose.

Application is to create datafile for a print application (think endless webs, ticket printers, newspapers etc). This print application prints tickets / papers etc with numbers. Typically the paper is cut into smaller rolls, each roll then containing numbers from X-Y.

So, the press must print f.ex  1..5900 1..5900  or reversed.

The catch here is that the particular printing machine prints a certain width every print. Each "width" can contain from 1 to, say, 10 ticket. That is why the datafile must have several numbers in each line. Further, the print application may have several lanes, which each may use a different numbering series.

I calculate the no. of tickets per print based on this width and ticket size.

So, in the printout, a very simple numbering series could be  (prints separated by bar)

1  2  3 | 4  5  6 |  7  8  9 | 1  2  3 | 4  5  6 |  7  8  9 | ...
                                  ^ restart of DB

That adds up. But if it does not add up, the database file must be (I can't see other solution) added to until it matches a complete width, otherwise there will be holes in the print. The fields are statically linked, and the length of a print is constant.
 

1 2 3 | 4 5 6 | 7 8 9 | 10     | 
                            ^can't end here, or there would be unwanted blanks.

 

The length of the finished database is not going to be infinite, typically number series are less than 10.000, and the maximum no. of repeats is never more than no. of tickets per print * amount of numbers. So for 3 tickets, and 3000 numbers, maximum 9000. Often less though.  With 4 and 18 numbers, criteria is fulfilled after 9 lines, not 36.

Below a screenshot of a typical print, this one has counting right-to-left (position of objects is indefferent and handled). Each print like this is one record. This example has 6 identical lanes, but could be different.

Spoiler

 

printscreen-numbers.jpg.8ea8172a92e7dfae


 

I understand this is very specific, and I have already recieved some good input and ideas. I think I have an idea of the solution.

 

Once complete, this part makes AU3 a very critical part of an every day application helping millions of labels and tickets have numbers.

 

Edited by Myicq

I am just a hobby programmer, and nothing great to publish right now.

Link to comment
Share on other sites

I still don't get it. Let's imagine you had a machine with 9 lanes and you want to print 10 tickets numbered 1 to 10. Do you intend to print 90 tickets instead of the 10 you actually need in order to fill up all the blanks? Then what happens to the 80 extra tickets you don't need? Couldn't you just print 5 x 2 lanes instead?

Edited by czardas
Link to comment
Share on other sites

I did not even understand the question very well, anyway, here is my 2 cent
(Just a wild guess)

Local $aInput[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ; an 1d array
Local $iBase = 7 ; tickets for each line
Local $iTiketLen = 8 ; wanted length for each ticket
Local $iCounter = 0 ; if you want start from another index just set it here instead of 0

Local $iBound = UBound($aInput)
Local $iStep = 1

Do
    Do
        $iIndex = Mod($iCounter, $iBound) ; Index stays within bound (it loops around)
        ConsoleWrite(StringFormat('%0' & $iTiketLen & 's', $aInput[$iIndex]) & @TAB) ;

        $iCounter += 1
        $iStep += 1

    Until $iStep > $iBase

    ConsoleWrite(@CR)
    $iStep = 1

    ; when to end the loop?
    ; here for example will end when last element of the array corresponds
    ; with the last column (it will form a rectangular sheet of tickets)
Until ($aInput[$iBound - 1] = $aInput[$iIndex]) And ($iIndex >= $iBound - 1)

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

  • Moderators

Myicq,

I am with czardas here - why on earth do you need to keep printing the tickets until you have a full line ending with the final number? Why can you not just stop when you first reach the highest value and leave a few blank spaces?

And these "lanes" - are these where the "cuts" occur, so that in your screenshot example you would end up with 6 separate "rolls" running from 0001 to 0007? If so, then how do you determine the starting position for each "lane"?

M23

Edit: This does your basic "full" listing, iterating as many times as necessary to get the final number at the end of a row:

$iMaxNumber = Random(10, 50, 1)
ConsoleWrite("Max: " & $iMaxNumber & @CRLF)

$iReqPerLine = Random(3, 9, 1)

$iIndex = 1

While 1

    For $j = 1 To $iReqPerLine
        ConsoleWrite(StringFormat("%04i", $iIndex) & " | ")

        If $j = $iReqPerLine And $iIndex = $iMaxNumber Then
            ConsoleWrite(@CRLF)
            ExitLoop 2
        EndIf

        $iIndex += 1
        $iIndex = Mod($iIndex - 1, $iMaxNumber) + 1

    Next

    ConsoleWrite(@CRLF)

WEnd

 

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...