Make a Matrix class that can be initialized without declaring matrix size first - matrix

I am new to Smalltalk and am taking a class init currently. One of the problems we were assigned requires creating a new Class "HeavyMatrix", which is called like this —
aMatrix := HeavyMatrix new.
Notice that there is no initial size assignment. The size is supposed to be undetermined upon creation. Then, the class adds values to the matrix with the following method —
aMatrix setRow:1 column:2 value:7.
All the values in the matrix which have not been declared in this way default to 0. The new Class HeavyMatrix is not supposed to subclass anything other than Object (i.e. not Matrix or Array). Can any Smalltalkers help me out? There are some other methods the class must contain but I think I can figure everything else once I am able to initialize the class. Thanks!

What can I suggest you… First of all you can just used ordered collections and inside setRow:column:value: if current column size is smaller that required than add what is missing an OrderedCollection instances. The same with desired row size (add 0s). The implementation will be something like this:
initialize
rows := OrderedCollection new
setRow: aRow column: aColumn value: aValue
| row |
rows size < aRow ifTrue: [
(aRow - rows size) timesRepeat: [rows add: OrderedCollection new]].
row := rows at: aRow.
row size < aColumn ifTrue: [
(aColumn - row size) timesRepeat: [row add: 0]].
row at: aColumn put: aValue
getRow: aRow column: aColumn
aRow <= rows size ifTrue: [
|row|
row := rows at: aRow.
aColumn <= rows size ifTrue: [^ row at: aColumn]].
^ 0
But more efficient way to do that is to implement a sparse matrix I think. You have a lot of structures described at wiki. Please note, that this matrices are only efficient when you have a low amount of elements compering to the size of the matrix itself. But if you'll check even the easiest implementation, like storing a coords-value data in dictionary, than it will suite you a lot:
initialize
dict := Dictionary new
setRow: aRow column: aColumn value: aValue
dict at: aRow#aColumn put: aValue
getRow: aRow column: aColumn
dict at: aRow#aColumn ifAbsent: [0]

Related

QTP/UFT - Storing Multiple Arrays In An Array

I have a function that imports a sheet to the global sheet and then loops through the columns and rows to create an array.
Code
Public Function importArray()
DataTable.ImportSheet "location","Lists", "Global"
rowCount = DataTable.GetSheet(dtGlobalSheet).GetRowCount -1
columnCount = DataTable.GetSheet(dtGlobalSheet).GetParameterCount
ReDim myArray(-1)
For x = 1 to columnCount Step 1
For i = 0 to rowCount Step 1
ReDim Preserve myArray(UBound(myArray) + 1)
myArray(i) = Datatable.Value(x, dtGlobalSheet)
Datatable.SetNextRow
Next
MsgBox Join(myArray, vbNewLine)
Next
End Function
So now that I know I can get the columns into an array, I need to store each array individually.
For example:
Main array = myArray(i)
Call importArray() to get array
Column count = 2
Column names = Name, Surname
Store array into array variable with name as column name
Populate myArray() with stored arrays
myArray(Name(), Surname())
The reason I want to do this is because I have a function that will need to reference these arrays to look for a value in the array then do some logic. While I know that I can just create arrays one by one, the problem is that I might have 20 arrays to use, in which case the code will become really bulky.
Perhaps there is a better way to do what I am thinking of doing, but otherwise, help on this would be really appreciated.
Use multidimensional arrays
'Declare a Dynamic Array
Dim arrData()
' Make it a multidimensional array
ReDim Preserve arrData(rowCount, colCount)
For Loop row
For Loop col
arrData(row, col) = ...
Next
Next
column names as array indexes is not okay - that is a dictionary (Map) already

how to ARRAY specific cells based on rules?

is there a (maybe a one (?) formula)-way how to pick all green cells (but only those which has numbers and excluding 0) in a row and put/list them in an array to that coresponding row ??
example: in cell AO1 there will be formula that will list these results:
AO1 = 647
AP1 = 2806
AQ1 = 15490
AR1 = 32105
AS1 = 33808
something like array of constants but constant will be a cell reference... I can only think of a hard way to doing it like make a table/grid of all green cells and then array them, but not sure how could I exlude things from arraying (things like: skip empty cell and skip cell that is "<1" )
edit: in another words: cell AO1: =arrayformula({$p$1;$r$1;$t$1;$v$1;$x$1;$z$1;$ab$1;$ad$1;$af$1;$ah$1;$aj$1;$al$1};and dont array empty and "<1" cells)
If the row are fixed could simply use filter on all the rows
like this : (I used the range you give in your question)
=FILTER(
{$p$1;$r$1;$t$1;$v$1;$x$1;$z$1;$ab$1;$ad$1;$af$1;$ah$1;$aj$1;$al$1};
{$p$1;$r$1;$t$1;$v$1;$x$1;$z$1;$ab$1;$ad$1;$af$1;$ah$1;$aj$1;$al$1}>0)
And for the K and the unique you can add them like this:
=ARRAYFORMULA(UNIQUE(FILTER(
{$p$1;$r$1;$t$1;$v$1;$x$1;$z$1;$ab$1;$ad$1;$af$1;$ah$1;$aj$1;$al$1};
{$p$1;$r$1;$t$1;$v$1;$x$1;$z$1;$ab$1;$ad$1;$af$1;$ah$1;$aj$1;$al$1}>0))&" K")

Reading a text file and constructing a matrix from it

I need to construct a matrix; a number of columns and rows are also in the first row of the matrix, I'll make an example so its more clearer.
4 3
1 2 3
5 6 7
9 10 8
1 11 13
Where m=4 (number of rows) and n=3 (number of columns)
This is an example of a text file. Is something like this even possible?
Program Feb;
const
max=100;
type
Matrix=array[1..max,1..max] of integer;
var datoteka:text;
m,n:integer;
counter:integer;
begin
assign(datoteka,'datoteka.txt');
reset(datoteka);
while not eoln(datoteka) do
begin
read(datoteka, m);
read(datoteka, n);
end;
repeat
read eoln(n)
until eof(datoteka)
write (m,n);
end.
My code isn't a big help, cause I don't know how to write it.
First, have a look at the code I wrote to do the task, and then look at my explanation below.
program Matrixtest;
uses
sysutils;
var
NoOfCols,
NoOfRows : Integer;
Source : TextFile;
Matrix : array of array of integer;
FileName : String;
Row,
Col : Integer; // for-loop iterators to access a single cell of the matrix
Value : Integer;
begin
// First, construct the name of the file defining the matrix
// This assumes that the file is in the same folder as this app
FileName := ExtractFilePath(ParamStr(0)) + 'MatrixDef.Txt';
writeln(FileName); // echo it back to the screen so we can see it
// Next, open the file
Assign(Source, FileName);
Reset(Source);
read(Source, NoOfRows, NoOfCols);
writeln('Cols: ', NoOfCols, 'Rows: ', NoOfRows);
SetLength(Matrix, NoOfCols, NoOfRows);
readln(source); // move to next line in file
// Next, read the array data
for Row := 1 to NoOfRows do begin
for Col := 1 to NoOfCols do begin
read(Source, Value);
Matrix[Col - 1, Row - 1] := Value;
end;
end;
// Display the array contents
for Row := 1 to NoOfRows do begin
for Col := 1 to NoOfCols do begin
writeln('Row: ', Row, ' contents', Matrix[Col - 1, Row - 1]);
end;
end;
Close(Source); // We're done with the file, so close it to release OS resources
readln; // this waits until you press a key, so you can read what's been displayed
end.
In your program, you can use a two-dimensional array to represent your matrix. Free Pascal supports multi-dimensional arrays; see https://wiki.lazarus.freepascal.org/Multidimensional_arrays for more information.
This is a complex task, so it helps to know how to do more basic things like reading an array of a size known at compile-time from a text file.
The wrinkle in this task is that you are supposed to read the dimensions (numbers of rows and columns) of the matrix at run-time from the file which contains the matrix's contents.
One inefficient way to do this would be to declare the matrix array with huge dimensions, larger than anything you would expect in practice, using the type of array declaration in the Wiki page linked above.
A better way is to use dynamic arrays, whose dimensions you can set at run-time. To use this, you need to know:
How to declare a dynamic array in Free Pascal
How to set the dimensions of the array at run-time, once you've picked them up from your matrix-definition file (hint: SetLength is the way to do this)
The fact that a Free Pascal dynamic array is zero-based
The easiest way of managing zero-based arrays is to write your code (in terms of Row and Column variables) as if the matrix were declared as array[1..NoOfRows, 1..NoOfColumns] and subtract one from the array indexes only when you actually access the array, as in:
Row := 3;
Column := 4;
Value := Matrix[Row - 1, Column - 1];

Get Capped Maximum Value From List

I have a list of values that range anywhere from 500-1000. I have a second list of values that denote relevant breakpoints in the 500-1000 range (500, 520, 540, 600, etc). I need to return the highest value in the second list that is less than the value in a given number from the first list. I noticed the "N" functions let you set a conditional on them, so for example if I do:
List.Max(List.FirstN(SomeTable[Breakpoints], each _ < 530))
It correctly returns 520 to me. However if I put this inside an AddColumn function and change the 530 to a local field reference:
Table.AddColumn(MyTable, "MinValue", each List.Max(List.FirstN(SomeTable[Breakpoints], each _ < [SomeNumbers])))
Then I get a "We cannot apply field access to the type Number" error. Is what I'm trying to do possible and I'm just formatting it wrong? I always get confused with scope and references in PQ, so it may just be that.
After each, [SomeNumbers] by itself is short for _[SomeNumbers] (which is what you see when filtering a column). In the List.FirstN call, _ refers to a number in the list instead of a row in a table: the value of _ is tied to the closest each, where closeness is measured by the number of layers of nesting between _ and the appearance of each . Therefore, in your code [SomeNumbers] is trying to find the column SomeNumbers on a number, which doesn't exist.
There are a couple ways to fix this:
You can use a let...in statement to store the current value of the SomeNumbers column to use it for later, like so:
each
let
currentNumber = [SomeNumbers],
result = List.Max(List.FirstN(SomeTable[Breakpoints], each _ < currentNumber))
in
result
You can explicitly define a function with the (x) => ... syntax instead of using each twice, like so:
each List.Max(List.FirstN(SomeTable[Breakpoints], (point) => point < [SomeNumbers]))

Are Oracle PL/SQL arrays indexed from 0 or from 1?

I have in front of me a piece of code like this:
FOR row IN 1..l_RowSet(1).count
LOOP
l_a_variable := l_RowSet(1)(row);
END LOOP;
l_RowSet is an ApEx type -- apex_plugin_util.t_column_value_list -- defined thus:
type t_column_value_list is table of wwv_flow_global.vc_arr2 index by pls_integer;
where wwv_flow_global.vc_arr2 is defined as
type vc_arr2 is table of varchar2(32767) index by binary_integer;
The vc_arr2 is passed back to my code from the apex_plugin_util.get_data function. The vc_arr2 is indexed by column number, not by row.
As best I can make out this means that the data is effectively stored in a 2D array, indexed by column and then by row.
When using the LOOP statement, would this be indexed from zero or from one? Because it seems to me that I ought to be able to make that LOOP redundant, ie:
l_a_variable := l_RowSet(1)(1);
But I'd need to know in advance whether to give 0 or 1 as the initial row.
I can't find a clear answer in the Oracle docs (unsurprisingly, "index" is a fairly widely-used term) and a look through SO doesn't show anybody else with the same question either.
An associative array isn't necessarily dense. There may be an element at index 0, there may be an element at index -1, there may be an element at index 1. Or you might have elements at indexes 17, 42, and 127. The code you posted implies that the associative array is dense and that the indexes start at 1.
In the specific case of apex_plugin_util.get_data the collection should be dense and should start at 1. If the loop is actually not doing anything other than what you posted, you could replace it by fetching the last element of l_RowSet(1), i.e.
l_a_variable := l_RowSet(1)(l_RowSet(1).count);

Resources