Dynamic Resizing

BlitzMax Forums/BlitzMax Beginners Area/Dynamic Resizing

PaulJG(Posted 2005) [#1]
Bit tricky to explain this.. plenty of head scratching involved !.

I need to indirectly reference an array, so I need something like index[10]

But with those 10 array places I need to reference a number of sub references..

kinda like, index[10,5]

But the problem is.. although I know the lefthand number ("10") - which is fixed, I dont know how big the sub part is.. ("5")

Although I could run though the list, make a note of the total number of arrays needed - it wont be the same for every array.. so there could be alot of wasted space.

(lost yet ?)

Here's an example of what I'm trying to do:

index[1]=1
index[2]=1,2,3,4
index[3]=1,2,3,4,5,6

so although I could use "int index[2,6]"

theres alot of wasted space in index[0]. (since it will have room for 6 sub arrays)

As I've said though I cant just have them seperate.. int index1[3],int index2[6]..etc

Any help please chaps !.


marksibly(Posted 2005) [#2]
Try an array of arrays...

Local index[][3]

index[0]=[1]
index[1]=[1,2,3,4]
index[2]=[1,2,3,4,5,6]


PaulJG(Posted 2005) [#3]
Thanks Mark.

This has to go in a type, to be used in a function though - how do I 'new' the array ?

I've got this in my type: field index:int[][]

then this in the function: index=new int[][3]

But it brings up the error,"Compile Error:Unable to convert from 'Int Array Array' to 'Int'"


PaulJG(Posted 2005) [#4]
Tried to do it a slighty different way, I've got a:
Type indices
	Field indices:Int[]
End Type

In my main type this:
Type obj_data
       Field indexdata:indices[]
end type

Finally, I'm using this in my function..
	obj_ptr.indexdata=New indices[10]
	obj_ptr.indexdata[0].indices=New Int[4]

Which results in a Unhandled Memory error !???


PowerPC603(Posted 2005) [#5]
This may be the thing you are looking for:
Type ObjectData
	Field indexdata:indices[0]
End Type

Type Indices
	Field indices:Int[0]
End Type

' Create a new object of type ObjectData
Local objectpointer:ObjectData = New ObjectData

' Resize the array "indexdata" to let it have 10 indexes (0..9)
objectpointer.indexdata = objectpointer.indexdata[..10]

' Create a new "indices" object at index 1 of the array "indexdata"
objectpointer.indexdata[1] = New indices
' Resize the array "indices" inside the indices type-instance, inside "indexdata" array index 1
objectpointer.indexdata[1].indices = objectpointer.indexdata[1].indices[..5]
' Set a random value from 1 to 100 inside the indices array at index 2, which resides inside the "indexdata"
' array at index 1
objectpointer.indexdata[1].indices[2] = Rand(1, 100)

' Now at index 1 of array "indexdata", there's an array with 5 indexes (0..4)



' Create a new "indices" object at index 2 of the array "indexdata"
objectpointer.indexdata[2] = New indices
' Resize the array "indices" inside the indices type-instance, inside "indexdata" array index 1
objectpointer.indexdata[2].indices = objectpointer.indexdata[1].indices[..20]
' Set a random value from 1 to 100 inside the indices array at index 12, which resides inside the "indexdata"
' array at index 1
objectpointer.indexdata[2].indices[12] = Rand(1, 100)

' Now at index 2 of array "indexdata", there's an array with 20 indexes (0.19)



PrintData(objectpointer, 1, 2)
PrintData(objectpointer, 2, 12)

Function PrintData(a:ObjectData, x, y)
	Print a.indexdata[x].indices[y]
End Function



Extron(Posted 2005) [#6]
And with this :
Type toto
	Field index:Int[][]

	Method Init(val:Int, val1:Int)
		index=index[..val+1]
		index[val]=index[val][..val1]
	End Method
End Type

' We create a new type toto
ex:toto=New toto
' We initialize first array to 0 (1 index) and second array to 0-2 (3 index)
ex.Init(0,3)
' We assign the 3 values to array [0] because there is space for 3 values in the second array
ex.index[0]=[1,2,3]  ' Assign 3 values to the first array index 0
' Print result
Print ex.index[0][0]
Print ex.index[0][1]
Print ex.index[0][2]
Print

' Now we need 5 values in the second array.
' We resize this array.
ex.Init(0,5)
' We assign value 4 and 5 (you need to assign new value one by one)
ex.index[0][3]=4 ; ex.index[0][4]=5
' Print result
Print ex.index[0][0]
Print ex.index[0][1]
Print ex.index[0][2]
Print ex.index[0][3]
Print ex.index[0][4]


You need to index the first array before init the second array.
Array[][] indicate array is created but not sized, return an error.
You can do this :
First assign an array [0][] or
First assign an array [2][] or
First assign an array [0][10] or First assign an array [2][10]
No importance since the first array is initialized.

More compact, no pointer.


PowerPC603(Posted 2005) [#7]
A complete example (expanding on my previous code):
Type ObjectData
	Field indexdata:indices[]
End Type

Type Indices
	Field indices:Int[]
End Type

SeedRnd(MilliSecs())

' Create a new object of type ObjectData
Local objectpointer:ObjectData = New ObjectData
' Resize the array "indexdata" to let it have 10 indexes (0..9)
objectpointer.indexdata = objectpointer.indexdata[..10]



' Create new "indices" objects at all indexes of the array "indexdata"
For i = 0 To 9
	objectpointer.indexdata[i] = New indices
Next



' Resize array "indices" for all "indices"-type-instances and set a random number for all of them
For i = 0 To (objectpointer.indexdata.length - 1)
	' Resize the array "indices" at each index of array "indexdata" to a random size between 1 and 10
	objectpointer.indexdata[i].indices = objectpointer.indexdata[i].indices[..Rand(1, 10)]
	' Set a random value from 1 to 100 inside the indices array at each index,
	' which resides inside the "indexdata" array at each index
	For j = 0 To (objectpointer.indexdata[i].indices.length - 1)
		objectpointer.indexdata[i].indices[j] = Rand(1, 100)
	Next
Next



' Print all data
For i = 0 To (objectpointer.indexdata.length - 1)
	For j = 0 To (objectpointer.indexdata[i].indices.length - 1)
		PrintData(objectpointer, i, j)
	Next

	Print
Next



Function PrintData(a:ObjectData, x, y)
	Print "objectpointer.indexdata[" + x + "].indices[" + y + "]: " + a.indexdata[x].indices[y]
End Function



PowerPC603(Posted 2005) [#8]
@ extron:

I've expanded your code too to this:
Type toto
	Field index:Int[][]

	Method Init(val:Int, val1:Int)
		index=index[..val+1]
		index[val]=index[val][..val1]
	End Method
End Type

SeedRnd(MilliSecs())

' We create a new type toto
ex:toto=New toto

' We initialize first array to 10 (indexes 0..9) and second array to a random size (from 1 to 10)
For i = 0 To 9
	ex.init(i, Rand(1, 10))
Next

' Fill each index with a random number
For i = 0 To (ex.index.length - 1)
	For j = 0 To (ex.index[i].length - 1)
		ex.index[i][j] = Rand(1, 100)
	Next
Next

' Print all numbers
For i = 0 To (ex.index.length - 1)
	For j = 0 To (ex.index[i].length - 1)
		Print "ex.index[" + i + "][" + j + "]: " + ex.index[i][j]
	Next

	Print
Next


Now you have two fully working examples which you can use, PaulJG.

But I have to admit, Extron's code is easier to understand and follow.


PowerPC603(Posted 2005) [#9]
And I want also to thank PaulJG for supplying this problem, because I was actually looking for some similar code.

I want to create a spacesim, where a datafile stated how many space-sectors there are, how many stations each sector has, and how many commodities each station has.
Each station can have a different number of commodities, and each sector can have a different number of stations.

I was creating code with types, which have arrays, where each index points at another type, which also had arrays (like my first expanded code at this thread).
Now I'm using Extron's approach and reduced my code significantly.

Now I can do: "Universe.NewStation", which automatically adds a new station to the last added sector.
When I do "Universe.NewCommodity", this adds a new commodity to the last added station, which was last added to a sector.

Type TUniverse
	Field NumSec%
	Field ASectors:TSector[]

	Field NumStat%
	Field AStations:TStation[][]

	Field NumComm%
	Field AComm:TCommodity[][][]

	Method NewSector()
		' Set variables (increase sectornumber and reset all others)
		NumSec% = NumSec% + 1
		NumStat% = 0
		NumComm% = 0

		' Resize the "ASectors"-array to include a new sector
		ASectors = ASectors[..NumSec%]
		' Also preset first index of AStations to have the same number of indexes as there are sectors
		AStations = AStations[..NumSec%]

		' Create a new "TSector"-type-instance at this new "ASectors"-index
		ASectors[NumSec% - 1] = New TSector
		' Load data into this new type-instance from the "Universe.txt" datafile
		LoadSectorData(ASectors[NumSec% - 1])
	End Method
	Method LoadSectorData(SectorPointer:TSector)
		' Temporary loadroutine (sets a name for the sector)
		SectorPointer.Name$ = "Sector " + NumSec%
	End Method



	Method NewStation()
		' This method creates a new station inside the last sector

		' Set variables (increase stationnumber and reset others)
		NumStat% = NumStat% + 1
		NumComm% = 0

		' Resize the "AStations"-array to include a new station
		AStations[NumSec% - 1] = AStations[NumSec% - 1][..NumStat%]
		' Also preset first and second indexes of Acomm to have the same number of indexes as there
		' are sectors and stations
		AComm = AComm[..NumSec%]
		AComm[NumSec% - 1] = AComm[NumSec% - 1][..NumStat%]

		' Create a new "TStation"-type-instance at this new "AStations"-index
		AStations[NumSec% - 1][NumStat% - 1] = New TStation
		' Load data into this new type-instance from the "Universe.txt" datafile
		LoadStationData(AStations[NumSec% - 1][NumStat% - 1])
	End Method
	Method LoadStationData(StationPointer:TStation)
		' Temporary loadroutine (sets a name for the station)
		StationPointer.Name$ = "Station " + NumStat%
	End Method



	Method NewCommodity()
		' This method creates a new commodity inside the last station, which is inside the last sector

		' Set variables (increase commoditynumber)
		NumComm% = NumComm% + 1

		' Resize the "AComm"-array to include a new commodity
		AComm[NumSec% - 1][NumStat% - 1] = AComm[NumSec% - 1][NumStat% - 1][..NumComm%]

		' Create a new "TCommodity"-type-instance at this new "AComm"-index
		AComm[NumSec% - 1][NumStat% - 1][NumComm% - 1] = New TCommodity
		' Load data into this new type-instance from the "Universe.txt" datafile
		LoadCommodityData(AComm[NumSec% - 1][NumStat% - 1][NumComm% - 1])
	End Method
	Method LoadCommodityData(CommodityPointer:TCommodity)
		' Temporary loadroutine (sets a name for the commodity)
		CommodityPointer.Name$ = "Commodity " + NumComm%
	End Method
End Type

Type TSector
	Field Name$
End Type

Type TStation
	Field Name$
End Type

Type TCommodity
	Field Name$
End Type



SeedRnd(MilliSecs())

' Add a random number of sectors, which all have a random number
' of stations, which in turn all have a random number of commodities
Universe:TUniverse = New TUniverse
For i = 0 To Rand(1, 10)
	Universe.NewSector()
	For j = 0 To Rand(1, 10)
		Universe.NewStation()
		For k = 0 To Rand(1, 10)
			Universe.NewCommodity()
		Next
	Next
Next

' Print all names of all sectors, stations and commodities inside the universe
For i = 0 To (Universe.ASectors.length - 1)
	Print Universe.ASectors[i].Name$

	For j = 0 To (Universe.AStations[i].length - 1)
		Print "    " + Universe.AStations[i][j].Name$

		For k = 0 To (Universe.AComm[i][j].length - 1)
			Print "        " + Universe.AComm[i][j][k].Name$
		Next

		Print
	Next

	Print
Next


Now all code is inside the TUniverse type.
Previously all code existed in separate types.
The loading routines must be included next, but I don't expect any problems here.

I was searching for the same thing, a multidimensional array with a dynamically secondary index (or how would you call it).

So you see, helping others can help yourself too.
This thread certainly helped my own project.


Extron(Posted 2005) [#10]
Good if it can help.

I also give a solution in this thread :
http://www.blitzbasic.com/Community/posts.php?topic=42327

Good luck in your project. ;)


PaulJG(Posted 2005) [#11]
Big thanks to you both ! :)