Invaild value of min and max using repeat until loop in pascal - loops

I need use loop from title,but I get incorrect value of result, under my code,please for suggestion, when i use a for everything is ok
const
licz_l = 5;
var
x, suma, min, max: longint;
tab: array [1..5] of longint;
begin
randomize();
suma := 0;
x := 0;
repeat
tab[x] := random(100);
suma := suma + tab[x];
write({'wylosowane liczby : ',}tab[x],';');
min := tab[1];
max := tab[1];
if (tab[x] < min) then
min := tab[x];
// max:=tab[1];
if (max < tab[x]) then
max := tab[x];
x := x + 1;
until x = licz_l;
writeln('');
writeln('srednia : ', suma / licz_l : 4 : 4);
writeln('min : ', min, #9, 'max : ', max);
end.
New code with second loop [for], but like I write, is a posibility to use only one loop[repeat until] to getvthe same effect?
const
licz_l = 5;
var
x, suma, min, max: longint;
tab: array [0..4] of longint;
begin
randomize();
suma := 0;
x := 0;
repeat
tab[x] := random(100);
suma := suma + tab[x];
write({'wylosowane liczby : ',}tab[x],';');
x := x + 1;
until x = licz_l;
min := tab[0];
max := tab[0];
for x := 0 to licz_l-1 do
begin
if (tab[x] < min) then
min := tab[x];
if (max < tab[x]) then
max := tab[x];
end;
writeln('');
writeln('srednia : ',suma/licz_l:4:4);
writeln('min : ',min,#9,'max : ',max);
end.

There are two possible ways to correct your first code (with a single loop).
Remove the lines within the loop: min := tab[1]; and max := tab[1];
Initialize min and max before the loop, with values that are,
on one hand > maximum value that random(100) may return, and
on other hand < minimum value that random(100) may return.
or
Assign min and max unconditionally with the first value, but only the first time your loop runs (if x = 0).

const
licz_l=5;
var
x,suma,min,max: longint;
tab: array [0..4] of longint;
begin
randomize();
suma:=0;
x:=0;
repeat
tab[x]:=random(100);
suma:=suma+tab[x];
write((*'wylosowane liczby : ',*)tab[x],';');
x:=x+1;
until x=licz_l;
min:=tab[0];
max:=tab[0];
for x:=0 to licz_l-1 do
begin
if (tab[x]<min) then
min:=tab[x];
if (max<tab[x]) then
max:=tab[x];
end;
writeln('');
writeln('srednia : ',suma/licz_l:4:4);
writeln('min : ',min,#9,'max : ',max);
end.
Or
const
licz_l = 5;
var
x, suma, min, max: longint;
tab: array [0..4] of longint;
begin
randomize();
suma := 0;
x := 0;
min := 99;
max := 0;
repeat
tab[x] := random(100);
suma := suma + tab[x];
write((*'wylosowane liczby : ',*)tab[x],';');
//min := tab[0];
//max := tab[0];
if (tab[x] < min) then
min := tab[x];
if (max < tab[x]) then
max := tab[x];
x := x + 1;
until x = licz_l;
writeln('');
writeln('srednia : ', suma / licz_l : 4 : 4);
writeln('min : ', min, #9, 'max : ', max);
end.

Related

Array multiplication in codesys

I wanted to multiply 2 matrices in codesys. I have implemented the code in the structured text language. However I am not able to generate the results correctly. Below is the logic which i am trying to implement.
Initialisation in codesys:
PROGRAM POU
VAR
a: ARRAY [1..5,1..2] OF INT:= [1,2,3,4,5,6,7,8,9,1];
b: ARRAY [1..2,1..5] OF INT := [1,2,3,4,5,6,7,8,9,1];
r1: INT:= 5; // no. of rows in a;
c1: INT:=2; // no. of columns in a;
r2: INT:= 2; //no. Of rows in b;
c2: INT:= 5; //no. of columns in b;
i: INT;
j: INT ;
k: INT;
z: INT:=2;
result: ARRAY [1..5,1..5] OF INT:= 0;
END_VAR
Program logic:
FOR i:=1 TO r1 DO
FOR j:=1 TO c2 DO
FOR k:=1 TO z DO
result[i,j]:= result[i,j]+(a[i,k]*b[k,j]);
END_FOR
END_FOR
END_FOR
What may be the reason for not getting the desired output?
The only obvious problem I see is, if you want to initialize an array with a specific value, don't do result: ARRAY [1..5, 1..5] OF INT := 0 as you would should get an error C0032: Cannot convert type 'BIT' to type 'ARRAY [1..5, 1..5] OF INT', instead do this: result: ARRAY [1..5, 1..5] OF INT := [ 25(0) ], although in codesys arrays Elements to which no initialization value is assigned explicitly are initialized internally with the default value of the basic data type, which in case of an INT is 0.
Also, to avoid errors, instad of hardcoding the boundaries I'd recomment to instad use the built in LOWER_BOUND an UPPER_BOUND functions.
Here's an example generic function for Matrix multiplication based on the code in your question:
METHOD IntMatrixProduct : BOOL
VAR_IN_OUT
A: ARRAY [*, *] OF INT;
B: ARRAY [*, *] OF INT;
C: ARRAY [*, *] OF INT;
END_VAR
VAR_INPUT
zero_C: BOOL := TRUE;
END_VAR
VAR
al1: DINT := LOWER_BOUND(A, 1);
au1: DINT := UPPER_BOUND(A, 1);
al2: DINT := LOWER_BOUND(A, 2);
au2: DINT := UPPER_BOUND(A, 2);
bl1: DINT := LOWER_BOUND(B, 1);
bu1: DINT := UPPER_BOUND(B, 1);
bl2: DINT := LOWER_BOUND(B, 2);
bu2: DINT := UPPER_BOUND(B, 2);
cl1: DINT := LOWER_BOUND(C, 1);
cu1: DINT := UPPER_BOUND(C, 1);
cl2: DINT := LOWER_BOUND(C, 2);
cu2: DINT := UPPER_BOUND(C, 2);
height: DINT := au1 - al1;
width: DINT := bu2 - bl2;
common: DINT := au2 - al2;
i, j, k: DINT;
END_VAR
IF (common <> bu1 - bl1 // Width of A != Height of B
OR_ELSE cu1 - cl1 <> height // Height of C != Height of A
OR_ELSE cu2 - cl2 <> width) THEN // Width of C != Width of B
IntMatrixProduct := FALSE; // Error!
RETURN;
END_IF
// Zero C
IF (zero_C) THEN
FOR i := 0 TO height DO
FOR j := 0 TO width DO
result[cl1 + i, cl2 + j] := 0;
END_FOR
END_FOR
END_IF
// Calcutale A*B
FOR i := 0 TO height DO
FOR j := 0 TO width DO
FOR k := 0 TO common DO
result[cl1 + i, cl2 + j] := result[cl1 + i, cl2 + j] + (a[al1 + i, al2 + k] * b[bl1 + k, bl2 + j]);
END_FOR
END_FOR
END_FOR
IntMatrixProduct := TRUE; // Success
You can also try importing the code using PLCOpen from here.
PS. Here's the result I get after running the above function:

Dafny - Fitting digits of a number into an array

I am trying to verify a code that uses simple modulo operation in a while loop to insert the digits of a number into an array.
I recieve a number,
an array with defined size,
and start - an index in the array from which I fit the most significant digit.
i.e if n=123, a = [w,x,y,z], start=0 then I need to create an array [1,2,3] and then fit it into a: [1,2,3,z]
I start by enforcing that the count of number digits (3 in our example) + the starting index do not exceed the bounds of the target array a.
If it doesn't exceed the bounds, I start slicing the number into digits:
var i:nat := (start + nLength - 1);
var n':=n;
while (i>=start && i>0)
decreases i
****invariant *********
{
a[i] := (n' % 10);
i := i - 1;
n' := n' / 10;
}
I am unable to find the right invariant to enfroce the correctness of the loop I made to iterate over the number and split it into digits.
Any suggestions?
Let me help you with a possible invariant. It looks like this invariant holds, but I was not able to prove it. Probably it requires more engineering.
function computeNumber(a: seq<int>, startIncluded: int, endExcluded: int, multiplier: int): int
decreases endExcluded - startIncluded
requires 0 <= startIncluded <= endExcluded <= |a|
requires startIncluded >= endExcluded
{
if startIncluded >= endExcluded then 0
else a[startIncluded]*multiplier + computeNumber(a, startIncluded+1, endExcluded, multiplier/10)
}
...
var endExcluded := start + nLength;
var i:int := endExcluded;
var n':=n;
ghost var tenPower := 1;
ghost var remainder := 0;
while n' > 0 && i > 0
decreases i
invariant n == n' * tenPower + remainder
invariant computeNumber(a[..], i, endExcluded, tenPower) == remainder
{
i := i - 1;
var digit := n' % 10;
a[i] := digit;
n' := n' / 10;
remainder := digit * tenPower + remainder;
tenPower := tenPower * 10;
}
if n' == 0 && i >= 0 {
assert n == remainder;
assert computeNumber(a[..], i, endExcluded, tenPower) == n;
}

How to sort an array

I have problem for sorting my array in Go,
Here is my code :
func main() {
fmt.Print("Masukkan Jumlah Data yang akan dimasukkan: ")
var jumlahdata int
fmt.Scanln(&jumlahdata)
var DataDiagram = make([]int, jumlahdata)
fmt.Print("Masukkan data secara berurutan dengan spasi sebagai pemisah antar angka: ")
for i := 0; i < jumlahdata; i++ {
fmt.Scanf("%d", &DataDiagram[i])
}
fmt.Print("\n")
var max int = DataDiagram[0]
for _, value := range DataDiagram { // Menemukan nilai maximum
if value > max {
max = value
}
}
var mem int
Sorting(DataDiagram, jumlahdata, mem, max)
}
func Grafik(jumlahdata int, max int, DataDiagram []int) {
for i := max; i >= 1; i-- { // membuat Data Diagram
for j := 0; j < jumlahdata; j++ {
if DataDiagram[j] >= i {
fmt.Print(" | ")
} else {
fmt.Print(" ")
}
}
fmt.Print("\n")
}
for i := 0; i < jumlahdata; i++ {
fmt.Print("---")
}
fmt.Print("\n")
fmt.Print(" ")
for i := 0; i < jumlahdata; i++ {
fmt.Print(DataDiagram[i], " ")
}
}
func Sorting(DataDiagram []int, jumlahdata int, mem int, max int) {
for langkah := 0; langkah < (jumlahdata-1) ; langkah++ {
Grafik(jumlahdata, max, DataDiagram)
for i := 0; i < jumlahdata - (langkah-1); i++ {
if DataDiagram[i] > DataDiagram[i + 1] {
mem := DataDiagram[i];
DataDiagram[i] = DataDiagram[i + 1]
DataDiagram[i + 1] = mem;
}
}
}
}
What i expect is look like this:
What I Expect
But the output said otherwise, it give me error : It give me error
Can someone give some guide how to fix this :) i just learn Go yesterday, it similiar to C, but keep giving me index out of range error
I understand your task is to sort an int "array" (slice, in go-speak), showing each step of your work as a graph. Because you must show your work, you can't use go's built-in sorting, e.g. sort.Ints(DataDiagram).
Your problems are with the Sorting function.
Step 1 Your immediate crash-causing problem is that i eventually iterates to a number larger than upper index of DataDiagram. That we fix in the commented line below.
// Step 1: fix the iterator
func Sorting(DataDiagram []int, jumlahdata int, mem int, max int) {
for langkah := 0; langkah < (jumlahdata-1) ; langkah++ {
Grafik(jumlahdata, max, DataDiagram)
for i := 0; i < jumlahdata - 1; i++ { // Was: for i := 0; i < jumlahdata - (langkah-1); i++ {
if DataDiagram[i] > DataDiagram[i + 1] {
mem := DataDiagram[i];
DataDiagram[i] = DataDiagram[i + 1]
DataDiagram[i + 1] = mem;
}
}
}
}
Step 2 The code no longer crashes, but is not guaranteed to sort, because it makes only one pass through the inputs. We need to continue looping until there's no more swapping taking place. That problem is fixed below. The code now produces the expected output on the playground.
// Step 2: loop until sorted
func Sorting(DataDiagram []int, jumlahdata int, mem int, max int) {
swapped := true
for swapped {
Grafik(jumlahdata, max, DataDiagram)
swapped = false
for i := 0; i < jumlahdata - 1; i++ {
if DataDiagram[i] > DataDiagram[i + 1] {
mem := DataDiagram[i];
DataDiagram[i] = DataDiagram[i + 1]
DataDiagram[i + 1] = mem;
swapped = true
}
}
}
}
Step 3 The above code works fine, but perhaps can use some tidying. The end result is unchanged on the playground.
// Step 3: make it prettier
func Sorting(data []int) {
max := data[0]
for _, value := range data { // Menemukan nilai maximum
if value > max {
max = value
}
}
swapped := true
for swapped {
Grafik(len(data), max, data)
swapped = false
for i := 0; i < len(data)-1; i++ {
if data[i] > data[i+1] {
data[i], data[i+1] = data[i+1], data[i]
swapped = true
}
}
}
}
It's much simpler if you would just use
sort.Ints(ints), which you can see here:
https://goplay.space/#i9VIrDG-vL-

Optimizing work with an array of records

I have the following object with an array of a record type:
type
TTimeMark = record
// many fields here
end;
TTimeMarks = array of TTimeMark;
TUserProfile = class(TObject)
TimeLine: TTimeMarks;
....
end;
In this list TUserProfile.TimeLine will be inserted items at run time. I don't know a method of inserting items other than increasing the lenghth of the array with one and then moving all the items a place down until I reach the desired possition. But in this array, the items are records with many fields, so, if I do TimeLine[I]:= TimeLine[I-1], all the data in the memory will be copied from one place to another (am I right ?), and this will take some time. Do you think should I use an array of pointers of that record, instead ? Or is there other fast method to do this ?
This is how I've done.. I used an array of pointers and I make some procedures to easy add, delete and move items:
TPointerArray = array of Pointer;
procedure PArrayInsert(var AArray: TPointerArray; Position: Integer; Count: Integer = 1);
var L, CTail: Integer;
begin
L:= Length(AArray);
if (Count = 0) or (Position > L) then Exit;
SetLength(AArray, L + Count);
CTail:= L - Position;
if CTail > 0 then
Move(AArray[Position], AArray[Position+Count], CTail * SizeOf(Pointer));
end;
procedure PArrayDelete(var AArray: TPointerArray; Position: Integer; Count: Integer = 1);
var L, CTail: Integer;
begin
L:= Length(AArray);
if (L = 0) or (Count = 0) or (Position >= L) or ((Position+Count) > L) then Exit;
CTail:= L - (Position + Count);
if CTail > 0 then
Move(AArray[Position+Count], AArray[Position], CTail * SizeOf(Pointer));
SetLength(AArray, L - Count);
end;
function PArrayMove(var AArray: TPointerArray; FromIndex, ToIndex: Integer; Count: Integer = 1): Boolean;
var L, Size, CT: Integer;
Buff: Pointer;
begin
Result:= False;
L:= High(AArray);
if (FromIndex > L) or (ToIndex > L+1) or
((ToIndex >= FromIndex) and (ToIndex <= (FromIndex+Count))) then Exit;
Size:= Count * SizeOf(Pointer);
GetMem(Buff, Size);
Move(AArray[FromIndex], Buff^, Size);
if FromIndex > ToIndex then begin
CT:= FromIndex - ToIndex;
Move(AArray[ToIndex], AArray[FromIndex+Count-CT], CT * SizeOf(Pointer));
Move(Buff^, AArray[ToIndex], Size);
end
else begin
CT:= ToIndex - FromIndex - Count;
Move(AArray[FromIndex+Count], AArray[FromIndex], CT * SizeOf(Pointer));
Move(Buff^, AArray[FromIndex+CT], Size);
end;
FreeMem(Buff);
Result:= True;
end;

Does Free Pascal have a way to concatenate arrays?

Pascal apparently has string concatenation, but does it have general concatenation for any type of array?
It does not but you can make your own function i coded this in 5 minutes...i am shure there is a better method but i don't have any idea right now.
type
TBArray = array of byte;
function ConcArray(arr1,arr2:TBArray):TBArray;
begin
SetLength(Result,Length(arr1) + Length(arr2));
ZeroMemory(#Result[0],Length(arr1) + Length(arr2));
CopyMemory(#Result[0],#arr1[0],Length(arr1));
CopyMemory(#Result[Length(arr1)],#arr2[0],Length(arr2));
end;
How about this? If you need to concatenate in many places, the + operator looks pretty nice IMHO.
program ConCatTest;
type
SomeRec = record
s: AnsiString;
i: Longint;
end;
SomeArr = array of SomeRec;
operator + (a, b: SomeArr) c: SomeArr;
var
i: Longint;
begin
SetLength(c, Length(a) + Length(b));
for i := 0 to High(a) do
c[i] := a[i];
for i := 0 to High(b) do
c[i + Length(a)] := b[i];
end;
var
a1, a2, a3: SomeArr;
i: Longint;
begin
SetLength(a1, 3);
SetLength(a2, 2);
a1[0].s := 'a';
a1[0].i := 0;
a1[1].s := 'a';
a1[1].i := 1;
a1[2].s := 'a';
a1[2].i := 2;
a2[0].s := 'b';
a2[0].i := 0;
a2[1].s := 'b';
a2[1].i := 1;
a3 := a1 + a2;
for i := 0 to High(a3) do
WriteLn(a3[i].s, a3[i].i);
ReadLn;
end.

Resources