Programming a function parameterized by a Domain in Maple - symbolic-math

I want to implement the Extended Euclidean Algorithm for arbitrary Euclidean Domains in Maple.
I tried passing the domain as an argument to the procedure, but it does not seem to work.
EEA:=proc(ED,a,b)
description
"Extended Euclidean Algorithm"
"INPUT: an Euclidean Domain ED and two elements from said domain"
"Computes the GCD as a R-linear combination";
local r_0, r_1, r_aux, s_0, s_1, s_aux, t_0, t_1, t_aux, q;
# Initialization
r_0 := a; r_1 := b;
s_0 := 1; s_1 := 0;
t_0 := 0; t_1 := 1;
while r_1 <> 0 do;
q := ED[quo](r_0, r_1);
r_aux := r_0 - q * r_1;
r_0 := r_1; r_1 := r_aux;
s_aux := s_0 - q * s_1;
s_0 := s_1; s_1 := s_aux;
t_aux := t_0 - q * t_1;
t_0 := t_1; t_1 := t_aux;
od;
return r_0, s_0, t_0;
end proc:
When I execute:
with(Domains):
a := 30; b := 42;
r, s, t := EEA(Z, a, b);
The program gets stuck in a loop.
What is going on?

Nevermind, I needed to capitalize Z[Quo].

Related

Delphi create letters with for loop

As you know in Excel column names are letters. When it reaches Z it continues with AA-AB-AC. Is it possible to make a similar function in Delphi XE7 + for loop?
I've tried:
var
i:integer;
str:string;
begin
str:='a';
for i := 0 to 26-1 do
begin
inc (str,1);
memo1.Lines.Add(str);
end;
but it returned:
[dcc32 Error] FBarkodsuzIndesignVerisiOlustur.pas(249): E2064 Left side cannot be assigned to
I assume that's because str is not an integer.
I can convert numbers to letters with this function:
function numberToString(number: Integer): String;
begin
Result := '';
if (number < 1) or (number > 26) then
Exit;
Result := 'abcdefghijklmnopqrstuvwxyz'[number];
end;
But I have no idea how we can create letters like AA when it exceeds 26.
Also with below approach, it creates 26 letters just fine but when it exceeds 26 it starts to use characters like brackets:
for i := 0 to 27-1 do
begin
memo1.Lines.Add(Char(Ord('a') + i));
end;
Output of it:
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
when it reach to Z it'll continue as "AA" "BB" "CC" and so on like Excel creates column names.
This is the function that I use for the task.
function SpreadSheetColName(const Col: Integer): string;
var
c: Char;
begin
Assert(Col >= 0);
if Col<26 then begin
c := 'A';
Inc(c, Col);
Result := c;
end else begin
Result := SpreadSheetColName(Col div 26 - 1) + SpreadSheetColName(Col mod 26);
end;
end;
Note that it uses zero based indices. I would suggest that you also use zero based indices as a general rule throughout your programming.
If you can't bring yourself to do that, then a one based version would look like this:
function SpreadSheetColName(const Col: Integer): string;
function SpreadSheetColNameZeroBased(const Col: Integer): string;
var
c: Char;
begin
Assert(Col >= 0);
if Col<26 then begin
c := 'A';
Inc(c, Col);
Result := c;
end else begin
Result := SpreadSheetColNameZeroBased(Col div 26 - 1) + SpreadSheetColNameZeroBased(Col mod 26);
end;
end;
begin
Result := SpreadSheetColNameZeroBased(Col - 1);
end;

Can´t undertand 10th line instruction after inner FOR loop

I've been studying "Algorithms and Data Structures" by N.Wirth. He codes his algorithms in a language he created: Oberon. I finished the book but I have one doubt about this algorithim of page 19 coded in Oberon:
PROCEDURE Power (VAR W: Texts.Writer; N: INTEGER);
VAR i, k, r: INTEGER;
d: ARRAY N OF INTEGER;
BEGIN
FOR k := 0 TO N-1 DO
Texts.Write(W, "."); r := 0;
FOR i := 0 TO k-1 DO
r := 10*r + d[i]; d[i] := r DIV 2; r := r MOD 2;
Texts.Write(W, CHR(d[i] + ORD("0")))
END;
d[k] := 5; Texts.Write(W, "5"); Texts.WriteLn(W)
END
END Power
The resulting output text for N = 10 is
.5
.25
.125
.0625
.03125
.015625
.0078125
.00390625
.001953125
.0009765625
I don´t understand what the instructions in line 10 d[k] := 5; Texts.Write(W, "5"); Texts.WriteLn(W) does:
1) Why you would you d[k] := 5? the program already printed all the output required (d[0] to d[k-1]).
2) why would you print a 5 after that? (Texts.Write(W, "5"))
The computation utilizes the fact that the last digit will always be five.
Unless the execution has finished, the variable d[k] is read in the next turn of the outer loop when r becomes 10*r + d[i] in the last turn of the inner loop
The statement Texts.Write(W, "5") requires (marginally) less computation than Texts.Write(W, d[i]).

Pascal an array of records

program R3cord;
type rekord = record
end;
var i,d,j,c,x,y,a : integer;
mas : array[1..5] of rekord;
begin
x := 4;
y := 5;
for i := 1 to y do
Read(mas[i]);
for i := 1 to x do
begin
d := i;
for j := i + 1 to y do
if mas[j] > mas[d] then
d := j;
c := mas[i]; mas[i] := mas[d]; mas[d] := c;
end;
for i := 1 to 5 do
Write(mas[i],' ');
end.
I'm having a trouble here, as you can see this program will read user's input and will sort it in descending order. I need to have a row number near number which was before the sorting. I've read that record is good for it, but I can't find any tutorials how to do it.
First, your record doesn't have anything in it. I think you want:
type
rekord = record
value: Integer;
row: Integer;
end;
And when you read it in:
for i := 1 to 5 do
begin
Read(mas[i].value);
mas[i].row = i;
end
The above will number the rows 1, 2, 3, ...
And in your sort:
if mas[j].value > mas[d].value
When you swap, be sure to swap the whole record as you're currently doing. Don't just swap the values.

Sort arrays by multiple fields

I have multiple arrays and they all start with integer fields, from 1 up to 5 fields, and these are like indexes that need to be sorted, from min to max:
TArrayA = record
Field1:integer;
Field2:integer;
Field3:integer;
Field4:integer;
Field5:integer;
... //other fields, strings, integers... up to 50 fields
end;
ArrayA:=array of TArrrayA;
Currently I use this approach to sort:
// sort by Field1
top:=Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if ArrayA[look].Field1 < ArrayA[min].Field1 then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
// now sort by Field2
top:=Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if (ArrayA[look].Field1 = ArrayA[min].Field1) And
(ArrayA[look].Field2 < ArrayA[min].Field2) then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
This does the job. Although is a bit slow when I need to sort all 5 fields,
and this is how I do it, field by field, so I sort the array 5 times. Is there any better, faster way?
Here is example:
procedure TForm1.Button8Click(Sender: TObject);
type
TArrayA = record
Field1: integer;
Field2: integer;
Field3: integer;
Field4: integer;
Field5: integer;
end;
var
ArrayA: array of TArrayA;
vTmpRecord: TArrayA;
top, counter, min, max, look: integer;
i,t1,t2:integer;
begin
SetLength(ArrayA,100000);
for i := 0 to 99999 do
begin
ArrayA[i].Field1:=1+Random(100);
ArrayA[i].Field2:=1+Random(100);
ArrayA[i].Field3:=1+Random(100);
ArrayA[i].Field4:=1+Random(100);
ArrayA[i].Field5:=1+Random(100);
end;
t1:=GetTickCount;
// sort by Field1
top := Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if ArrayA[look].Field1 < ArrayA[min].Field1 then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
// sort by Field2
top := Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if (ArrayA[look].Field1 = ArrayA[min].Field1) and
(ArrayA[look].Field2 < ArrayA[min].Field2) then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
// sort by Field3
top := Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if (ArrayA[look].Field1 = ArrayA[min].Field1) and (ArrayA[look].Field2 = ArrayA[min].Field2) and
(ArrayA[look].Field3 < ArrayA[min].Field3) then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
// sort by Field4
top := Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if (ArrayA[look].Field1 = ArrayA[min].Field1) and (ArrayA[look].Field2 = ArrayA[min].Field2) and (ArrayA[look].Field3 = ArrayA[min].Field3) and
(ArrayA[look].Field4 < ArrayA[min].Field4) then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
// sort by Field5
top := Length(ArrayA);
for counter := 0 to top do
begin
min := counter;
for look := counter + 1 to top do
if (ArrayA[look].Field1 = ArrayA[min].Field1) and (ArrayA[look].Field2 = ArrayA[min].Field2) and (ArrayA[look].Field3 = ArrayA[min].Field3) and (ArrayA[look].Field4 = ArrayA[min].Field4) and
(ArrayA[look].Field5 < ArrayA[min].Field5) then
min := look;
vTmpRecord := ArrayA[min];
ArrayA[min] := ArrayA[counter];
ArrayA[counter] := vTmpRecord;
end;
t2:=GetTickCount;
Button8.Caption:=IntToStr(t2-t1);
end;
You can use built in Quick sort method for sorting arrays with your custom comparer:
uses
System.Math,
System.Generics.Defaults,
System.Generics.Collections;
TArray.Sort<TArrayA>(ArrayA, TComparer<TArrayA>.Construct( function(const Left, Right: TArrayA): Integer
begin
if Left.Field1 = Right.Field1 then
begin
if Left.Field2 = Right.Field2 then
begin
Result := CompareValue(Left.Field3, Right.Field3);
end
else Result := CompareValue(Left.Field2, Right.Field2);
end
else Result := CompareValue(Left.Field1, Right.Field1);
end
));
I added code only for first three fields, but you will get the picture how to build your own comparer for more fields.
The most important thing for you to do is to separate the sort algorithm from the data. That way you can write, or use, a single sort algorithm again and again with different data
The classic way to do that is to use a comparison sort. They are sort algorithms that require a compare function that compares two items and returns a negative integer for less than, a positive integer for greater than, and zero when equal.
So, let's start by demonstrating such a compare function for your data. Storing multiple fields as you have makes it hard to write a general purpose comparer. Better to put the fields in an array. Once you have done so you can do the compare lexicographically using iteration like this:
function CompareIntegerArray(const lhs, rhs: array of Integer): Integer;
var
i: Integer;
begin
Assert(Length(lhs) = Length(rhs));
for i := low(lhs) to high(lhs) do
if lhs[i] < rhs[i] then
exit(-1)
else if lhs[i] > rhs[i] then
exit(1);
exit(0);
end;
With a lexicographic order we first compare the primary field. If they differ we have our answer, otherwise we move on to the secondary field. And so on. Such an algorithm is well suited to iteration as demonstrated above.
This overcomes a significant weakness in your approach, by sorting the array once only.
Once you have this compare function you need to wrap it in an outer compare function that extracts data from the record fields and populates arrays. Perhaps along these lines:
type
TMyArray = array [1..5] of Integer;
function GetMyArray(const Value: TArrayA): TMyArray;
begin
Result[1] := Value.Field1;
Result[2] := Value.Field2;
....
end;
function MyCompare(const lhs, rhs: TArrayA): Integer;
begin
Result := CompareIntegerArray(
GetMyArray(lhs),
GetMyArray(rhs)
);
end;
Now, as promised, you can use this compare function with a general purpose sort like TArray.Sort<T> from Generics.Collections. This is an implementation of Quicksort, a comparison sort with average complexity of O(n log n). That will typically yield a huge benefit over your O(n2) bubble sort.
Life would be simpler if you could replace the record with an actual array. Another option that might be useful would be to add a method to the record that returned an array of integer ready for use in the lexicographic compare function.
To recap:
Separate data, comparison and sorting to facilitate re-use and clarity.
Use arrays to enable lexicographic compare to be implemented with a loop.
Use an efficient sort algorithm such as Quicksort.

Pascal strings & records [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Here is my code so far, incase you cannot tell I am trying to write a dictionary, maybe with 1 thing with every letter of the alphabet, maybe just 15 or so random entries. Here is what I have so far
program Dictionary;
uses crt;
Type
Asdf = String[26];
Definition = Record
First, Full, NorV, Class : Asdf;
End;
Var
A, B, C, D, E, F, g, h, i, j, k, l, m, n, o, p, q, r,
s, t, u, v, w, x, y, z : Definition;
BEGIN
a.First := 'a';
a.Full := 'apple';
a.NorV := 'noun';
a.Class := 'fruit';
b.First := 'b';
b.full := 'bee';
b.NorV := 'noun';
b.Class := 'insect';
c.first := 'c';
c.full := 'cat';
c.NorV := 'noun';
c.class := 'animal';
d.first := 'd';
d.full := 'dunk';
d.Norv := 'verb';
d.class := 'action';
e.first := 'e';
e.full := 'egg';
e.norv := 'noun';
e.class := 'food';
f.first := 'f';
f.full := 'forget';
f.norv := 'verb';
f.class := 'action';
g.First := 'g';
g.Full := 'grape';
g.NorV := 'noun';
g.Class := 'fruit';
h.First := 'h';
h.Full := 'horse';
h.NorV := 'noun';
h.class := 'animal';
i.First := 'i';
i.Full := 'invent';
i.NorV := 'verb';
i.class := 'action';
j.First := 'j';
j.Full := 'jump';
j.NorV := 'noun';
j.class := 'action';
k.First := 'k';
k.Full := 'kangaroo';
k.NorV := 'noun';
k.class := 'animal';
l.First := 'l';
l.Full := 'look';
l.NorV := 'verb';
l.class := 'action';
m.First := 'm';
m.Full := 'mango';
m.NorV := 'noun';
m.Class := 'fruit';
n.First := 'n';
n.Full := 'noose';
n.NorV := 'noun';
n.class := 'object';
o.First := 'o';
o.Full := 'orangutan';
o.NorV := 'noun';
o.class := 'animal';
p.First := 'p';
p.Full := 'prod';
p.NorV := 'verb';
p.class := 'action';
q.First := 'q';
q.Full := 'queen';
q.NorV := 'noun';
q.class := 'royalty';
r.First := 'r';
r.Full := 'run';
r.NorV := 'verb';
r.class := 'action';
s.First := 's';
s.Full := 'shoot';
s.NorV := 'verb';
s.class := 'action';
t.First := 't';
t.Full := 'train';
t.NorV := 'noun';
t.class := 'transport';
u.First := 'u';
u.Full := 'umbrella';
u.NorV := 'noun';
u.class := 'object';
v.First := 'v';
v.Full := 'vegetable';
v.NorV := 'noun';
v.class := 'vegetable';
w.First := 'w';
w.Full := 'walk';
w.NorV := 'verb';
w.class := 'action';
x.First := 'x';
x.Full := 'xylophone';
x.NorV := 'noun';
x.class := 'object';
y.First := 'y';
y.Full := 'yank';
y.NorV := 'verb';
y.class := 'action';
z.First := 'z';
z.Full := 'zoo';
z.NorV := 'noun';
z.class := 'area';
Writeln ('Type the first letter of the word you want to view');
Readln (
END.
what should i put at the end so that when it is typed, it can be searched? I can add more variables if i have to. Help please!
As you found out it is hard to enumerate multiple variables.
The standard solution is to put them in an array
var
myarray: array['A'..'Z'] of Definition;
and then enumerate with
var
myloopvar: Char;
for myloopvar := 'A' to 'Z' do
if myarray[myloopvar].firstletter = 'X' then
DoSomething;
You are try to set the character at position 1 of the string. The reason why the first one works is because the 'a' string can be type casted to a character by the compiler. The other strings can not be type casted. Drop the index and things should work (untested).
BEGIN
Def.FirstLetter := 'a';
Def.FullName := 'apple';
Def.NounorVerb := 'noun'
END.

Resources