Gargoyle
(MM club member)
2005-10-13 09:16 PM
Knowledge request

While I have written several scripts I still need enlightment on how a couple of things work, and I come to you great gurus here to help me understand.

First is multi-dimensional array's. How do use them, and where are they appropriate?

Second is seeding of a RND, when would be the appropriate time to use them, and why would you seed a RND.

Thanks.


Bryce
(KiX Supporter)
2005-10-13 10:45 PM
Re: Knowledge request

Multidimensional arrays, the simplest multi-dim arrays are.

a 5x5 grid

Code:

0 1 2 3 4 5
a 3 s 5 y h d
b e 4 5 6 7 9
c 3 e w 8 9 0
d 2 e e 4 5 6
e 2 3 1 9 9 3
f 3 4 d 7 q s



Take the values 3,C and you get 8 this is a 2 dimensional array, and the most common used.

You can represent this type of an array two ways inside of KiXtart.

Code:

;example 1
dim $array[5,5]
? $array[2,3]


or

Code:

;example 2
DIM $array[5]
for $i = 0 to ubound($array)
$array[$i] = $array
next
? $array[2][3]



both ways have their advantages / disadvantages.

The major disadvantage of example one, is that kix can only redim the last multi-dim value. But in example 2 you do not have that limitation.

Example 2 on the other hand take a good deal bit more code to build the array, but i feel it is a good trade off for a more flexible setup.


Bryce
(KiX Supporter)
2005-10-13 10:51 PM
Re: Knowledge request

and example using a multidimensional array.

you have a text file with the following data in it.
Code:

3 s 5 y h d
e 4 5 6 7 9
3 e w 8 9 0
2 e e 4 5 6
2 3 1 9 9 3
3 4 d 7 q s




Code:

$data = loadfile("data.txt")
for $i = 0 to ubound($data)
$data[$i] = split($data[$i])
next

? $data[2][3]

;this Function will load the contents of a text file into an array
Function loadfile($file)
DIM $fso,$f,$fs
$fso = CreateObject("Scripting.FileSystemObject")
$f = $fso.GetFile($file)
If @ERROR Exit(2) EndIf
$fs = $f.OpenAsTextStream(1)
$loadfile = Split($fs.Read($f.size),@CRLF)
Exit(@ERROR)
EndFunction



when you print 2,3 you should get "8"


Bryce
(KiX Supporter)
2005-10-13 10:59 PM
Re: Knowledge request

Quote:


Second is seeding of a RND, when would be the appropriate time to use them, and why would you seed a RND.

Thanks.




you will always want to seed a RND, because you see... RND is not realt all that random.

run the following code.

Code:

for $i = 1 to 10
? RND(10)
next



you get this....?
Code:

G:\kix\sandbox>kix32 test

0
6
2
8
6
5
3
9
9
8



and... you get it everytime that you will run it too.

now, run this.

Code:
SRND(@msecs)
for $i = 1 to 10
? RND(10)
next



that should shake things up enough to get... "random numbers". but if you always use the same seed, you will always get the same random numbers.


Gargoyle
(MM club member)
2005-10-14 01:02 AM
Re: Knowledge request

Re: RND

so if I am using RND to generate a number in an UDF, will it generate the same RND each time I call the UDF, or will it generate the same RND each time I run the script?


Richard H.Administrator
(KiX Supporter)
2005-10-14 10:10 AM
Re: Knowledge request

Quote:

and why would you seed a RND



You need to seed it because it is a pseudo-random number generator, not a random number generator.

The RNG (random number generator) works by taking a start value, pushing it through a complex calculation and ending up with another number. The problem is that first number. There is absolutely no random event that your PC can get to to establish that first number.

This means that it is up to you to find a random-ish number.

The other reason for having a seed is that a predictable stream of "random" number might be desirable. You might want to get the same numbers every time you run the program.

I use this for password generation. The BIOS on our PCs is locked down with a password. Unfortunately somtimes we need to divulge this password to employees or third party engineers so we cannot use a common password.

We could allocate random passwords and record them on a spreadsheet, but that would be an administrative nightmare.

Instead we generate random passwords using a hash of the PC serial number as a seed. This means we can always regenerate the password by typing the PC serial number into the password program.

The local administrator password is managed in the same way.

Quote:

Re: RND

so if I am using RND to generate a number in an UDF, will it generate the same RND each time I call the UDF, or will it generate the same RND each time I run the script?




The RNG state is in the KiXtart session scope. This means that you only need to seed the RNG once per kix32.exe execution.

Even if you run a number of scripts e.g. "kix32.exe script1.kix script2.kix script3.kix" you will only need to seed the RNG in script1.kix

The RNG is pretty basic, and one of it's flaws is that the first number returned is not very random at all. It is good practice to discard the first number after seeding the RNG.

Also, don't seed the RNG in the UDF as that will restart the pseudo-RNG sequence making it even less random!

Finally, don't used @MSECS alone to seed the RNG. Choose something else. @MSECS has a range of 0-999 which means that your "random" numbers will only be from a selection of a thousand possible results. We are moving from random numbers towards predictable!

@TICKS is a better option for a simple seed. A reasonable (if not perfect) simple seed might be:
Code:
SRND(@TICKS*1000+@MSECS)



Gargoyle
(MM club member)
2005-10-14 05:09 PM
Re: Knowledge request

Ok, so now I understand seeding. I am still absorbing the info on multi-dimensional arrays. Have not figured out where I would use them yet, but that could be just because I have not tried to use a script that would have use of them.

I appreciate your explanations, it is making me a better scripter ever so slowly.


Gargoyle
(MM club member)
2005-10-27 05:47 PM
Re: Knowledge request

Back to multi dim arrays.

I now have a need for one of these, but need to verify my logic thought with you before I really get lost.

With an array that is already populated with values can I add the second dimenstion to it?

Assuming I have an array of 6 values, and I want to associate 6 other values to that value (a 6x6 array) would I write it something like this...
Code:

;This would assign a value to the second dimension correct?
$array[0][0] = $value
;This would get a value associated to a particular location?
$value = $array[1][5]



What about 3 dimensional arrays? Can they be done? and how would you visualize it. I am thinking of an array that might be 6x6x3 so that you now have x,y,x axis to work with. Or is it easier to make two seperate 2 dimensional arrays that reference the other?


Last question would be, which is read first down or across (x or y axis)

Thanks.


Glenn BarnasAdministrator
(KiX Supporter)
2005-10-27 07:35 PM
Re: Knowledge request

A simple way to picture a multi-dimensional array might be:
$X[0,0,0] = Row, Col, Page
$X[0,0,0,0] = Row, Col, Page, Book
$X[0,0,0,0,0] = Row, Col, Page, Book, Shelf

and so on..

Since you are desining the code, the row/col association can be anything you like - whatever makes sense to you.
$X[0,0,0,0,0] = Shelf, Book, Page, Col, Row is NOT the SAME as above, but is equivelent, as long as you maintain the same references throughout your program.

Glenn


Gargoyle
(MM club member)
2005-10-27 07:42 PM
Re: Knowledge request

Thanks Glenn I get the dimensional aspect now.
However when building array, can I take an already defined array and make it multidimensional? If so how do you add the second dimension? I assume (hopefully I understand it correctly) that Kix only will allow you to change the last dimension.

So if I was to have 3 dimension array I could only change the 3rd dimension.


Glenn BarnasAdministrator
(KiX Supporter)
2005-10-27 08:17 PM
Re: Knowledge request

Um, not exactly..

The ReDim function changes the array size declaration, optionally preserving the existing data. I don't think it allows you to add a dimension - it changes the size of an array. If your array already has 2 or more dimensions, you've reached the Twilight Zone and can only change the size of the last dimension. Arrays of Arrays, as was noted, are much more flexible in terms of resizing, but require a bit more skill and coding to manipulate.

So, if your array was 10 rows of 3 columns, you could add columns (the last dimension) but not rows. If you structured it as 3 columns with 10 rows, you could add rows, but not columns.

Very often, we create the array with the maximum number of cells we thnik we will need, and then use ReDim to resize it down to the actual number of required cells. For example, if I DIM $X[100] and then populate only 37 elements, if I later scan the array, I have to reference each element (using another counter variable) and constantly test for valid data. However, if I know that I only added 37 elements (0-36, remember - it's 0-based), I can resize my array - (assuming the counter var $Ctr post-incremented and is at 37)

ReDim Preserve $X[$Ctr - 1]

Then I could us a For Each loop to enumerate the elements of the array:

For Each $Element in $X ; note the array is $X, not $X[]
$Element ?
Next


Glenn


Gargoyle
(MM club member)
2005-10-27 08:34 PM
Re: Knowledge request

So can I do this...
Code:

Dim $Array[6]
For $Count = 0 to 5
$array[$count] = $SomeVar
Next
Redim Preserve $Array[6][6]
For $Count = 0 to 5
For $Count2 = 0 to 5
$array[$count][$count2] = $AnotherVar
Next
Next



Glenn BarnasAdministrator
(KiX Supporter)
2005-10-27 10:05 PM
Re: Knowledge request

No - wrong on 2 counts.. once you define an array with a spcific number of dimensions, you can't add or remove dimensions, you can only change the size of the array. So, your ReDim could increase or decrease the number of ELEMENTS (cells) in the array, but not the number of dimensions. A one-dimensional array is a collection of rows with 1 column. You can only change the number of rows, not columns.

Secondly, [x][y] isn't a two-dimensional array, it's an array of arrays. Think of this:

$X = "a", "b", "c"
This creates and populates an array, with element 0 containing "a" and element 2 containing "c"

So

Dim $X[3]
$X[0] = "a", "b", "c"
$X[1] = "d", "e", "f"
$X[2] = "g", "h", "i"


Each element of the array "$X" contains yet another array, so you can specify

$V = $X[1][1]
'v=' $V ?


and $V will contain "e" - the second element of the $X array, and the second element of the array in that element. As you can see, it can get confusing.

Copy the above into a test script.. Then add:

$SubArray = $X[2]
For Each $Element in $SubArray
'SubElement=' $Element ?
Next


That should make it clear.

Then, you could actually re-dim $SubArray, and reassign it to your parent array.

ReDim Preserve $SubArray[3]
$SubArray[3] = "z"
$X[2] = $SubArray

'1: ' UBound($X[1]) ?
'2: ' UBound($X[2]) ?


You can see that the sub-arrays in element 1 and 2 of the parent array have different values now.

Glenn


Gargoyle
(MM club member)
2005-10-27 10:51 PM
Re: Knowledge request

Think I am getting it now.

My goal with this is to get some user input ex: Your Name
Then present them with a set of options that will be associated to each person that entered their name.

The that I am reading it now is to build an array with each of the "names" as my columns, and then assign the options to a new row. So that it would look something like this

$Array[0] = "Name1","Name2","Name3" etc...
$Array[1] = 0, 3, 4 etc...
$Array[2] = "C","F","J" etc...

Then when I need to find what option Name3 picked I would

$ = $Array[2][2][1]

and would get Name3 4 F

So in closing (I hope) My First DIM statement is the number Rows that I need.

After that Each [] that I add to the end of $ARRAY[] references the Row that I am reading from. I.E.

$Array[0][1][2][3][4][5] =
Row 0 1 2 3 4 5 etc...

The Columns will be defined by the data that is entered into each row.

Then as I gather the options selected by the user I would do a
$Array[2] = $Array[2] + $Option
to add another column to this array element

If this is all correct my last question would be can you have unequal columns in each row?


Sealeopard
(KiX Master)
2005-10-27 11:12 PM
Re: Knowledge request

You still don't seem to understand the difference between a multi-dimensinal array and an array of arrays. These are two distinct beasts.
An Excel spreadsheet for exampel is a two-dimensional array, consisting of rows and columns.You'd reference it in KiXtart like this:
Code:

dim $a[3,3]
? $a[2,3]


A three-dimensional array is like a cube or multiple layers of two-dimensional arrays, like the tabs in Excel, where each tab references one dimension. Thus
Code:

dim $a[2,3,4]
? $a[2,2,2]


In an array of arrays, each element in an array is an array by itself, not a single value.
Code:

dim $a[2], $b[2]
$a[1]=$b

? $a[1][2]


$a[1] now references variable $b, which is an array. $a[1][2] references the second element in variable $b which is in $a[1].


Gargoyle
(MM club member)
2005-10-27 11:29 PM
Re: Knowledge request

Okay so I am showing the use of an array of arrays.
Was the logic process correct?

Can you show me using my example how to do it correctly, as there seems to be something that I am missing completly.

Sealeopard, normally I understand exactly what you are saying, but you completly lost me that time. Maybe it is the way that I am describing what I am doing. I would post code, but I haven't done any yet. This is the very beginning of coding.

Thanks.


Glenn BarnasAdministrator
(KiX Supporter)
2005-10-28 12:19 AM
Re: Knowledge request

Paste the sample code snippets into a file and run them.. then play with them and see what changes. Experiment for a while, and don't be afraid to break the toys.

Glenn

PS - I probably have more "x.kix" and similar files in my Misc folder than all my scripts and UDFs combined, just examples to see how code works...


Gargoyle
(MM club member)
2005-10-28 12:41 AM
Re: Knowledge request

I think I get the array of array deal (THINK).

This Code:
Then as I gather the options selected by the user I would do a 
$Array[2] = $Array[2] + $Option
to add another column to this array element


Should be Code:

$Subarray[4] = $Array[2]
Redim Preserve $Subarray[5]
$Subarray[5] = $OptionToAdd
$Array[2] = $Subarray



Is that correct? And what about the rest of my logic, as far as I can tell from what you are saying here it is correct.


Sealeopard
(KiX Master)
2005-10-28 02:36 PM
Re: Knowledge request

You're now introducing circular references of arrays. Please get your understanding of a simple array straight first.

To add a column to an array, you use REDIM.

For example, an array with three rows and three columns is defined as DIM $a[2,2]. To add another columns to it, you'd do a REDIM $a[2,3], if you want to preserve the existing array element contents you'd use PRESERVE, thus REDIM PRESERVE $a[2,3]. Please experiment with this first to fully understand it. You now have a total of three rows and four columns. Arrays beyond two dimensions work the same way. Imagine an array as a collections ofindividual data elements, e.g. wooden cubes. A variable is a single wooden cube. A row or column of wooden cubes would represent a one-dimensional array, with each cube being a single data element. Now add a second ropw of wooden cubes to the first one, you now have a two-dimensional array of wooden cubes.

Then, put another two rows of cubes onto the existing ones, you now have a structure resembling a cube by itself, e.g. two cubes long, two cubes high, and two cubes in depth.

Now comes the tricky, or easy part. Instead of considering a single cube as a data element assume that the cube itself is made of a number of red wooden cubes, e.g. a 3x3x3 cube of red wooden cubes. This is an array-of-arrays.

I'm giving up now, I have no idea how to simplify it even more, maybe start with a drawing?

You MUST understand the basics of arrays before you can start using them effectively.


Richard H.Administrator
(KiX Supporter)
2005-10-28 02:45 PM
Re: Knowledge request

Quote:

Is that correct? And what about the rest of my logic, as far as I can tell from what you are saying here it is correct.




You might be correct, but it's hard to tell

I think that you are over-complicating the process because you are new to arrays and how to use them.

Take a step back, and describe for us exactly what it is you are trying to do. We can suggest a solution which might include arrays. Or it might not!

For example, after understanding what you want to do we may well suggest that you would be better off writing the data directly to an INI file rather than storing it in an array.


Gargoyle
(MM club member)
2005-10-28 03:23 PM
Re: Knowledge request

Quote:

describe for us exactly what it is you are trying to do



I have form that asks the user to enter a series of names from 2 - 6, the number of names is random and could change everytime the script is used.
After that form information is submitted I am storing the names in an array $Names[5]
I then present another form that has options on it. On the options page there are 4 sets of radio buttons where each will represent a single value to be stored. One set of checkboxes that will result in a single value to be stored.

The options that are checked will be individual to each of the users set in the first form.

My thought was that an array that is 6x5 would be perfect for this as I would have a single array that would hold the user name and the options selected per user.

Hope that helps.

The cube analogy is helping. I will be drawing it out on paper to make sure that I am getting it. To this point in all of my scripts I have alway's used a flat array (1 dimension).


Sealeopard
(KiX Master)
2005-10-28 05:07 PM
Re: Knowledge request

You have a 5x4 array like this:
Code:

Name1 Option1 Option2 Option3 Option4
Name2 Option1 Option2 Option3 Option4
Name3 Option1 Option2 Option3 Option4
Name4 Option1 Option2 Option3 Option4
Name5 Option1 Option2 Option3 Option4
Name6 Option1 Option2 Option3 Option4


If you'd like to solve this as an array of arrays, then you have a options array $op[3] and a names array $nm[6,1] similar to this:
Code:

Name1 $op
Name2 $op
Name3 $op
Name4 $op
Name5 $op
Name6 $op


The code would look like this:
Code:

dim $nm[5],$op[3]
; firts name
$nm[0,0]='Name1'
$op[0]=1
$op[1]=2
$op[2]=3
$op[3]=4
$nm[0,1]=$op

$nm[1,0]='Name2'
$op[0]=1
$op[1]=2
$op[2]=3
$op[3]=4
$nm[1,1]=$op
; pull first name
? 'First Name = '+$nm[0,0]
? 'Options:'
$options=$nm[0,1] ;pull the options array into it's own new variable
for $optnr=0 to 3
? 'Option '+$optnr+': '+$options[$optnr]
? 'Option '+$optnr+': '+$nm[0,1][$optnr] ;alternative way to reference the element
next


Some people consider the array-of-arrays more elegant, however, it requres more care in pulling data.

Please be advised that this code is a figment of my imagination and has not undergone any testing whatsoever and might therefore not work. It is for illustration purposes only.


Gargoyle
(MM club member)
2005-10-28 06:11 PM
Re: Knowledge request

Quote:

understand the basics of arrays



I agree and hence why I have most here shaking their head at me.

If I am understanding the explanation that Jens provided earlier..

For a 2 Dimension array...

Dim the array as follows Dim $Array[Rows,Columns]
Once you declare the array you can not change the number of Rows but with a Redim you can change the number of columns.

In my particular use I would Code:
Dim $Array[$index,5]
;Where $index is the # of names that need to be tracked starting from 0



I would then be able to assign to $array[0,0] the name of the first user, $array[0,1] would be the first option, $array[0,2] ... $array[0,5] for the remaining options.
Then I would repeat the process for each user moving to the next row $array[1,0] ....

So my data would end up looking like this....
Name1 Opt1 Opt2 Opt3 Opt4 Opt5
Name2 Opt1 Opt2 Opt3 Opt4 Opt5

This would then provide a 2 dimensional array instead of using an array of array's.

If this is a correct understanding of how it works, then I have at least moved a bit forward. Now 3 dimensions.... Well lets just wait for awhile, I don't see a need for them at this point in my script.


Sealeopard
(KiX Master)
2005-10-28 08:48 PM
Re: Knowledge request

Yes, that's exactly whay I tried to convey. Now, a 3-D array is just like a 2D-array, but younow add yet another layer/dimension to it. For exampel, space coordinates are 3-D, you need length, width, height, to descirbe a location/point. In case of a 4-D array, you could consider the fourth dimension beigntime, you now need to also describe the time from when you want toe element. Anyway, hope you get the gist of it.

Gargoyle
(MM club member)
2005-10-28 08:57 PM
Re: Knowledge request

Thank you. I think the problem was my mixing up Array of Array's and MultiDim.

Once I looked at MultiDim like a database record it all made sense.

I really appreciate everyones understanding in this.


Sealeopard
(KiX Master)
2005-10-29 09:19 PM
Re: Knowledge request

A database table is still two-dimensional, In my book, multi-dimensional starts when you go boyond two dimensions.

Now, an OLAP cube in the data warehouse world, that's where the fun starts


LonkeroAdministrator
(KiX Master Guru)
2005-10-29 11:38 PM
Re: Knowledge request

two dimensional is a multi-dimensional as in my book multi counts for everything else than single.

Mart
(KiX Supporter)
2005-10-30 01:06 PM
Re: Knowledge request

Quote from http://www.yourdictionary.com/ahd/m/m0473300.html

Quote:


mul·ti·di·men·sion·al

Of, relating to, or having several dimensions.





Two is several so imho two dimensions is also multidimensional.


Les
(KiX Master)
2005-10-30 02:24 PM
Re: Knowledge request

You obviously did not look up "several".
Quote:

Being of a number more than two or three but not many




http://www.yourdictionary.com/ahd/s/s0296200.html


Gargoyle
(MM club member)
2005-10-30 05:36 PM
Re: Knowledge request

And to go back to the topic for just a second....

When using an array ex: [3,5], if you do a Ubound($array) What value would be returned.


LonkeroAdministrator
(KiX Master Guru)
2005-10-30 07:52 PM
Re: Knowledge request

hmm...
I think manual says it...
it was the right most, or was it left most... hard to remember.


Gargoyle
(MM club member)
2005-10-30 11:02 PM
Re: Knowledge request

Again you are correct

Quote:

UBOUND(array,dimension)
....
Dimesion
Optional parameter indicating the dimension of the array you want to know the upper boundray of. The default is 1.




So I geuss I would need to ask is it 0 based? With the default being 1 I would say not, but never hurts to ask.


LonkeroAdministrator
(KiX Master Guru)
2005-10-30 11:59 PM
Re: Knowledge request

try it out

logic indeed dictates that it would be from 1 up.
first dimension and so on, right?

on the other hand, with that logic array element 0 wouldn't exist.


Gargoyle
(MM club member)
2005-10-31 04:26 AM
Re: Knowledge request

I have coded it that way (with a 1 for the first dimension) but have not completed enough code to test it really.

Maybe by tomorrow.