Reorder array in pascal, descending - arrays

couldn't find similar posts, so posting my own question.
I got variable array of real:
price = array([58.9],[38.7],[8.95],[28.3])
I need to order it descending, with my code everything works well until last value of the array, I know even why, but can't find solution on my own. Anyway here's the code:
Procedure orderarray;
Var i,dz, j: Integer;
c :real;
v :string[25];
Begin
dz := 1;
For i := 1 to 3 do
Begin
For j:=i+1 to 4 do
if price[j]>price[dz] //searches for highest value in the array
then dz:=j;
c:=price[i]; price[i] := price[dz]; price[dz] := c; //switches current value with highest
End;

I've found solution to my own problem. Posting it just in case anyone will need it. I needed to reset dz to i, not j
Procedure orderarray;
Var i,dz, j: Integer;
c :real;
v :string[25];
Begin
For i := 1 to 3 do
Begin
dz:=i;
For j:=i+1 to 4 do
if price[j]>price[dz] //searches for highest value in the array
then dz:=j;
c:=price[i]; price[i] := price[dz]; price[dz] := c; //switches current value with highest
End;
Thank you everybody for your help, wouldn't get to the solution without you, anyway.

you need to reset dz to j everytime
for j:=i+1 to 4 do
begin
dz := j;
if price[j]>price[dz]
...;
c:=price[i]; ...;
end

In your sample dz will remain always 1, last element will never be moved since it is less then the first.

Related

Special For-Loop in Pascal

I work with a current software for the simulation of power plant processes. Smaller scripts can be written within the software for automation, these scripts are based on Pascal and own function libraries. Was simply retained after the initial release 20 years ago.
My simple script transfers values from one element to another and has this structure:
var f: integer;
S13Be.MXTSTO.data(1,1) := 22;
S12Be.MXTSTO.data(1,S12Be.NFLOW) := 22;
S11Be.MXTSTO.data(1,1) := S12Be.MXTSTO.data(1,S12Be.NFLOW);
S10Be.MXTSTO.data(1,S10Be.NFLOW) := 22;
S9Be.MXTSTO.data(1,1) := S10Be.MXTSTO.data(1,S10Be.NFLOW);
S8Be.MXTSTO.data(1,S8Be.NFLOW) := 22;
S7Be.MXTSTO.data(1,1) := S8Be.MXTSTO.data(1,S8Be.NFLOW);
S5Be.MXTSTO.data(1,S5Be.NFLOW) := 22;
S4Be.MXTSTO.data(1,1) := S5Be.MXTSTO.data(1,S4Be.NFLOW);
S2Be.MXTSTO.data(1,S2Be.NFLOW) := 22;
S1Be.MXTSTO.data(1,1) := S2Be.MXTSTO.data(1,S4Be.NFLOW);
for f := 1 to S13Be.NFLOW+1 do begin
S13Be.MXTSTO.data(1,f) := S13Be.MXTSTO.data(1,1);
end;
for f := 1 to S12Be.NFLOW+1 do begin
S12Be.MXTSTO.data(1,f) := S12Be.MXTSTO.data(1,1);
end;
for f := 1 to S11Be.NFLOW+1 do begin
S11Be.MXTSTO.data(1,f) := S11Be.MXTSTO.data(1,1);
end;
.
.
.
for f := 1 to S2Be.NFLOW+1 do begin
S2Be.MXTSTO.data(1,f) := S2Be.MXTSTO.data(1,1);
end;
for f := 1 to S1Be.NFLOW+1 do begin
S1Be.MXTSTO.data(1,f) := S1Be.MXTSTO.data(1,1);
end;
I would like to put another loop around the outside so that the elements are automatically selected.
The names of the elements are S1Be, S2Be.... S13Be and S1Ent, S2Ent, S3Ent...S13Ent
.MXSTO.data accesses a matrix in the respective element
(1,f) defines the position in the matrix (currently there are only 1x5 and 1x10 matrices; the value .NFLOW specifies which matrix is involved.)
I would be very grateful for a tip, a book recommendation and of course a code.
With best regards
Felix
Translated with www.DeepL.com/Translator (free version)
Names generally no meaning in a compiled program, it doesn't contain them.
If the identifiers are the same type you might be able to define an array of pointers to them, and then iterate using that array.
This can be handled with an enumerated type. The solution will require a little reorganization of your date, but I think it will be worth it. Like most languages variables are independent of each other. If you want to deal with a list of variables they will need to be in a structure of some sort. An array in your case makes sense. However, associating a numeric index with each variable is a bother and requires pointers or some difficult to maintain parsing system.
Nicklaus Wirth created a mechanism to deal with this sort of problem. It is called an enumerated type. For example:
type
BeName = (S1Be, S2Be, S3Be, S4Be);
var
NFLOW: array[BeName] of integer;
MXTSTOdata: array[BeName,1:5,1:10] of integer;
SnBe: BeName;
begin
… Initialization here, the following is how to change your code.
MXTSTOdata(S2Be,1,NFLOW[S2Be]) := 22;
MXTSTOdata(S1Be,1,1) :=MXTSTOdata(S2Be,1,NFLOW[S4Be]);
… Here is just one for loop:
for f := 1 to NFLOW[S1Be]+1 do
MXTSTOdata[S1Be,1,f] := MXTSTOdata[S1Be,1,1];
… Here is a loop of for loops:
for SnBe := S1Be to S4Be do
for f := 1 to NFLOW[SnBe]+1 do
MXTSTOdata[SnBe,1,f] := MXTSTOdata[SnBe,1,1];
Note how the for loop doesn’t need a start and end index. But that depends on which Pascal you are using. Delphi, FreePascal, and standard Pascal differ. You might have to use the first and last element like I showed. You might have a Low and High function available.
var
NFLOW: array[BeName] of integer;
SnBe: BeName;
for SnBe := Low(BeName) to High(BeName) do
for f := 1 to NFLOW[SnBe]+1 do
MXTSTOdata[SnBe,1,f] := MXTSTOdata[SnBe,1,1];
And I might have the syntax for the array declaration wrong. I’ve seen var NFLOW: array of [BeName] of integer; documented on the web, built I haven’t fired up my pascal compiler to check this fragment. However, the enumeration type would help you a lot. Also, there is a for-in construct in FreePascal
for SnBe in BeName do
for f := 1 to NFLOW[SnBe]+1 do
MXTSTOdata[SnBe,1,f] := MXTSTOdata[SnBe,1,1];
The enumeration type is useful in preventing bothersome minor spelling errors from messing up the program, has nice for loop options, and can change the ordering of the values in the enumeration. Changing the ordering may be needed for handling what order assignments are made in, at the cost of program fragility, as you might imagine.
The pred and succ operators are implemented. If you ever wondered what the need were for pred and succ you have now found out. A while loop:
SnBe := S1Be;
repeat
… something
SnBe := succ(SnBe)
until SnBe = S4Be;
Of course that doesn’t get easily to the last value in the enumeration. You could add guard values, but that adds some confusion and messes up the for-in loop.
SnBe := S1Be;
repeat
SomefunctionF(SnBe);
SnBe := succ(SnBe)
until SnBe = S4Be;
SomefunctionF(S4Be);
Is probably the cleanest way to deal with the problem of running in a repeat loop. The reason for adding these examples is you may have two enumerations running in parallel:
type
ToBeName = (S1Be, S2Be, S3Be, S4Be);
NotToBeName = (Bob, Carol, Ted, Alice);
var
NFLOW: array[BeName] of integer;
MXTSTOdata: array[BeName,1:5,1:10] of integer;
Romeo: NotToBeName;
SnBe: BeName;
begin
SnBe:=S1Be;
Romeo:=Bob;
Repeat
ActionFunction(SnBe,Romeo);
SnBe := succ(SnBe);
Romeo := succ(Romeo)
until SnBe = Alice;
Also, this idea might be helpful for your program:
type
EType = (S1Be, S2Be, S3Be, S4Be, Bob, Carol, Ted, Alice);
var
Romeo: EType;
SnBe: EType;
begin
Romeo:= Bob;
SnBe:=S1Be;
repeat
SomeFn(Romeo,SnBe);
SnBe:=succ(SnBe);
until SnBe>S4Be;
The range check applies to pred and succ. For example, the statement
succ(Alice)
would produce an error because there is no element after Alice in the enumerations above.
Lastly, if you need to do things in reverse order you can do:
for SnBe := S4Be downto S1Be do

Can't see contents of array

I'm trying to scan through the contents of my array for a 3x3 tictactoe game. The below procedure is called when the user has had their go and it's now time for the computer to move.
The gameBoard array should be full of '?' at this point, except for the 'X' that the human player just placed. I just wanted to check how many '?' are in the array, these would be the available spaces for the computer to choose. I wanted to place the result in label2 just so I could check that it is working, but it's not. At this point it should show '8' in the label.
Thanks in advance
var
i, iCount, j: Integer;
begin
label1.Caption := 'Computer''s turn';
// scan through gameboard to check available spaces
for i := 1 to 3 do
for j := 1 to 3 do
if (gameBoard[i, j] = '?') then
begin
iCount := iCount + 1;
end;
Label2.Caption := inttostr(iCount);
end;```
Local variables in Delphi are not initialized, so iCount could have any value when the procedure runs. Set iCount to zero before starting the loops.

Arrays in Delphi (object Pascal) using variables?

I have these 10 numbers (one in each line) in a Text File and I need them to be sorted in a chronological order starting with the highest number. I wrote a code which works just fine, but the problem is that the code isn't flexible, because once I add another number to the Text File it won't work since the code is set to sort 10 numbers only...this is due to my array of integers which is supposed to read the values before the sorting process starts, but won't allow me to add a variable to the array's properties so it will be able to read and sort any-size text file...I know there has to be a way of making a program which can sort any-size file of this structure, just please tell me how I could improve my code. (If you think my way isn't too efficient, it's because that's my homework from high school and I need to use these arrays to implement a bubblesort).
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
numbers, sortednumbers : TextFile;
count : integer=0;
number : array[1..10] of integer;
I : integer;
Procedure Swap(var X, Y : Integer);
var
Temp : integer;
begin
Temp := X;
X := Y;
Y := Temp;
end;
procedure Assign;
var I : Integer;
begin
reset(numbers);
for I := 1 to count do ReadLn(numbers, number[I]);
end;
procedure BubbleSort;
var I, J : integer;
begin
for I := 2 to count do
begin
for J := count downto I do
if (number[J] > number[J - 1]) then
Swap(number[J - 1], number[J]);
end;
end;
begin
AssignFile(numbers, 'Numbers.txt');
AssignFile(sortednumbers, 'Sorted-Numbers.txt');
Reset(numbers);
While not EoF(numbers) do
begin
ReadLn(numbers);
Inc(count);
end;
Reset(numbers);
ReWrite(sortednumbers);
Assign;
BubbleSort;
For I := 1 to count do writeln(sortednumbers, number[I]);
CloseFile(numbers);
CloseFile(sortednumbers);
end.
Use a dynamic array. This is an array that can change the number of elements it holds.
Instead of declaring:
number : array[1..10] of integer;
instead skip the bounds declaration:
Number : array of integer;
Then, before you start using it, set its length:
SetLength(Number, 10);
Once you are done, free the memory by setting it to have length 0:
SetLength(Number, 0);
Note that:
Indexes of a dynamic array start from 0, not 1. That is, Number[0] is the first element and Number[9] is the tenth. This is quite common in programming but can be confusing if it's not something you've come across before.
There are other 'quality' changes you can make to your code too. As commenter David Heffernan said, stop using global variables. I would also suggest using try/finally for resource allocation and cleanup, and using streams (and another link, wrap this over TFileStream) instead of the old-style file IO you're currently doing. Also, consider your variable names - Number for an array of numbers is odd - why not add the S and call it Numbers, for example?
That might be a bit much all at once, so go slowly in small steps, save and backup often (preferably into source control), and have fun!
And if it had not been a school project:
function Comparer(List: TStringList; index1, index2: integer): integer;
begin
try
Result:= StrToInt(List[index1]) - StrToInt(List[Index2]);
except
raise Exception.Create('Your file does not contain numbers');
end;
end;
function SortNumbers
var
lStringList: TStringlist;
begin
lStringList := TStringlist.create;
try
lStringList.LoadFromFile('Numbers.txt');
lStringList.CustomSort(Comparer);
lStringList.SaveToFile('Sorted-Numbers.txt');
finally
lStringList.Free;
end;
end;
However the Delphi RTL uses Quicksort, not Bubblesort.

pl/sql remove element from array

I need to remove element from array. I have tried to use array.delete(n) function, but it deletes all elements from identifier n. How to just delete exact element n ?
For example if array is 1 2 3 4 5, and n = 3, after delete it should look like following 1 2 4 5.
My code so far :
DECLARE
/* declare type array */
TYPE number_index_by_number IS TABLE OF number INDEX BY binary_integer;
v_n NUMBER := &sv_n;
v_m NUMBER := &sv_m;
v_min Number;
v_tmp Number;
v_array number_index_by_number;
v_sorted_array number_index_by_number;
begin
for i in 1..v_n
loop
v_array(i) := dbms_random.value(1,1000);
end loop;
for j in v_array.first..v_array.last
loop
DBMS_OUTPUT.put_line('v_array('||j||') :'||v_array(j));
end loop;
<<i_loop>> for i in 1..v_m
loop
/*set first array value to variable min*/
v_min := v_array(1);
v_tmp := 1;
<<j_loop>> for j in v_array.first..v_array.last
loop
DBMS_OUTPUT.put_line('v_array('||j||') :'||v_array(j));
if (v_min > v_array(j)) THEN
begin
v_min := v_array(j);
v_tmp := j;
DBMS_OUTPUT.put_line(j);
end;
end if;
end loop;
/*problem is in at this line*/
v_array.delete(v_tmp);
v_sorted_array(i) := v_min;
end loop;
for i in v_sorted_array.first..v_sorted_array.last
loop
DBMS_OUTPUT.put_line('v_sorted_array('||i||') :'||v_sorted_array(i));
end loop;
end;
I cannot reproduce any of the behaviour you describe. I could not get the delete collection method to do anything other than what it is documented to do.
However, there are a few errors in your code that could do with being tidied up.
Firstly, I should point out if you delete an element with key 3 from a PL/SQL associative array, there is then nothing with key 3 in the array. The remaining values don't 'shuffle' down to fill the gap. If there was an element with key 4 before the delete, the same element will still have key 4 afterwards. As a result, if you delete element j from a PL/SQL associative array v_array and then attempt to get v_array(j), you will get a 'no data found' error. You should check to see whether the element exists, using v_array.exists(j), before attempting to get a nonexistent element.
Secondly, the element with index 1 may get deleted before the last iteration of the outer loop. If this happens, v_array(1) will fail with a 'no data found' error. It would be better to assign NULL to v_min and v_tmp at the start of the loop, and assign to them during the loop if v_min is NULL or greater than v_array(j).
Finally, it seems your code returns the v_m smallest numbers from v_n. It would be worth verifying that v_m is less than or equal to v_n, as otherwise this doesn't make sense.
I'm affraid you cannot use a built-in method like this.
Instead of you shoud create a temp array to collect the elements prior to and afterwards the selected one from the original array, and return the temp array.

Pascal insert user input to an array

I am trying to get better at functional programming. As a start I am planning on trying out with couple of languages like Pascal, Scheme, ML etc. First I started with Pascal. I am trying to insert user input into a integer array in pascal and then get them reverse.
1 program ReverseList;
2
3 var
4 i: Integer;
5 k: Integer;
6 a: array[1..100] of Integer;
7 begin
8 i := 0;
9 repeat
10 writeln('Enter a number');
11 readln(k);
12 if k > -1 then
13 i := i + 1;
14 a[i] := k;
15 until(k < 0);
16 for i := 1 to i do
17 writeln(a[i]);
18 end.
In past I have mostly been a java developer so I was so custom to using all the lists thats available. Also ideally I was wondering if I can build a list where I can iterate over the list based on the number of elements in that list.
It would be great if anyone could point me on the direction of good tutorials in functional programming as well as syntax on above mentioned programming languages.
There are several problems with your program:
The array is not initialized.
There is no input checking, both i=0 and i>100 result in an illegal array index.
The array index and the value are the same, is that correct?
You only write the first 10 numbers (but you use a different index, which is certain to be out of range).
The output is not in reverse.
There are also several pascal tutorials.
By the way, Pascal isn't a functional language. So if you really want to learn a functional language, you better try another one (like Lisp, Ml or probably F#).
It was a good practice and I managed to figure a solution for this. I am sure there are better ways to do, and also this doesn't look like I am using the functionalities of functional programming. But if anyone wants to provide a better solution please do so,
{author: Null-Hypothesis}
program ReverseList;
var
i: Integer; {integer to keep the array length}
k: Integer; {user input value}
a: array[1..100] of Integer; {array to store the user inputs}
begin
i := 0;
repeat {iterate until user input is negative or number of inputs exceed array size}
writeln('Enter a number or enter negative value to exit the program.');
readln(k);
if(k > -1) and (i < 100) then {check for negative value and size of the array}
begin
i := i + 1; {increase array index}
a[i] := k {assign value to array}
end
else
break; {exit if array size exceed the limit of array}
until(k < 0);
writeln;
{Printing the user input before the reversing the list}
writeln('Original order of the list');
for i := 1 to i do
writeln(a[i]);
writeln;
{Printing the reverse list}
writeln('Reversed List');
for i := i downto 1 do {decrement array index}
writeln(a[i]);
writeln('Bye!!!');
end.
Happy Coding, off to the next language...

Resources