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

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]).

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;

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.

Pascal arranging array, with a row number

type
mas = array [1 .. 10000] of real;
var
n: integer;
a: mas;
Rf: text;
Procedure Skaityti;
var
i: integer;
Df: text;
begin
Assign(Df, 'duom1.txt');
Reset(Df);
Readln(Df, n);
for i := 1 to n do
Read(Df, a[i]);
Close(Df);
end;
Procedure MinMax(var min, max, nrmin, nrmax, vid: real);
var
i: integer;
begin
min := a[1];
max := a[1];
nrmin := 1;
nrmax := 1;
for i := 1 to n do
begin
if min > a[i] then
begin
min := a[i];
nrmin := i;
end;
if max < a[i] then
begin
max := a[i];
nrmax := i;
end;
vid := vid + a[i];
end;
vid := vid / n;
end;
var
min, max, nrmin, nrmax, vid: real;
begin
Skaityti;
MinMax(min, max, nrmin, nrmax, vid);
Assign(Rf, 'rez.txt');
Rewrite(Rf);
WriteLn(Rf, 'biggest amount ', max:7:2, ' number ', nrmax:7:0);
WriteLn(Rf, 'smallest amount ', min:7:2, ' number', nrmin:7:0);
WriteLn(Rf, 'average amount ', vid:7:2);
WriteLn(Rf);
WriteLn(Rf, 'number amount');
Close(Rf);
end.
This is the code and it Reads elements from a .txt file to an array, I created procedure to find biggest and smallest value of it. Now I need to create a procedure to write my array from biggest to smallest and a row number next to it. It should look something like this:
Row number value
5 1000000
6 999999
8 888888
and so on.. Any ideas ?
P.S. I can arrange that array to be from biggest to smallest but then the row numbers will mess up :/
Create a record type with two fields, one for the value from the file and the other for the "row" number.
Change the array to be an array of that record type.
When reading the file in the for loop, assign the read value to the value field of the record and the for loop control variable value as the "row" number.
When you sort the array, you sort the records, thus keeping value and row together.

generalized aggregate in vhdl

I have an array / vector and I want to generate a new array by processing the first. A simple example of what I need is that every i-th element from the new array is the sum of the i-1, i, and i+1 elements from the first one.
I know this can be done very easily in a sequential manner by iterating through the array. I was wandering if there any kind of assigning expression that would generalize this and make this a parallel operation.(like in math: new[i] := old[i - 1] + old[i] + old[i + 1], where i ∈ (1, n) ).
As your question is about parallelism, I assume that you are interested in the hardware that will be synthesized from your VHDL description, not by the simulation.
Parallelism is a matter of when all these additions take place? If your design is synchronous - let's say of the rising edge of a clock named clk - then:
subtype word: unsigned(7 downto 0);
type word_array is array(natural range <>) of word;
signal a: word_array(0 to 15);
signal b: word_array(1 to 14);
...
process(clk)
begin
if rising_edge(clk) then
for i in 1 to 14 loop
b(i) <= a(i - 1) + a(i) + a(i + 1);
end loop;
end if;
end process;
will compute in parallel the 14 values in array b at each rising edge of the clock. And it will instantiate as many 8-bits adders as needed to do this. The question is not whether you are using a for loop or something else, it is really when do these operations take place? The answer is in the description: during the very same clock period.
You could overload the "+" operator to work on vectors:
function "+"(a, b: word_array) return word_array is
constant n: positive := a'length;
variable va: word_array(0 to n - 1) := a;
variable vb: word_array(0 to n - 1) := b;
variable sum: word_array(0 to n - 1);
begin
if n = 1 then
sum(0) := va(0) + vb(0);
else
sum := (va(0 to n / 2 - 1) + vb(0 to n / 2 - 1)) &
(va(n / 2 to n - 1) + vb(n / 2 to n - 1));
end if;
return sum;
end function "+";
and use it to apparently write a more parallel description:
process(clk)
begin
if rising_edge(clk) then
b <= a(0 to 13) + a(1 to 14) + a(2 to 15);
end if;
end process;
but it would make no difference and the resulting hardware would be the same.
You could also use a generate statement to do the same:
g: for i in 1 to 14 generate
process(clk)
begin
if rising_edge(clk) then
b(i) <= a(i - 1) + a(i) + a(i + 1);
end if;
end process;
end generate g;
but, again, it would make no difference for the synthesizer.

How to copy on array to another array in different ways - Pascal

I'm solving 3 problems with array.The two of them I've already solved and I 've got 2 questions.
If the codes for the first two are good and how to solve the third problem.
Okay,the third problem is to copy array to another array this way: arrayA=[1,2,3], then arrayB is [1,2,3,3,2,1].
Firstly from start to end and then from end to start.First problem was to copy arrayA to arrayB in this way: arrayA=[1,2,3] ,arrayB=[1,1,2,2,3,3].
I will only post my pseudocodes.
while i<length(a) do begin
b[j]=a[i];
j+=1;
if (j+1) MOD 2 =0 then i+=1;
end;
Another one was to copy arrayA to arrayB twice.arrayA=[1,2,3], arrayB=[1,2,3,1,2,3]. Here I used for loop:
for i=1 to length(a) do arrayB[i]=arrayA[i];
for i=length(a)+1 to 2*length(a) do arrayB[i]=arrayA[i-length(a)]
Avoid while cycles if count is predefined.
Exploit simple index arithmetics (I assume that all arrays are 1-based):
//112233
for i := 1 to length(a) do begin
b[2 * i - 1] := a[i];
b[2 * i] := a[i];
end;
//123123
l := length(a);
for i := 1 to length(a) do begin
b[i] := a[i];
b[i + l] := a[i];
end;
//123321
l := length(a);
for i := 1 to length(a) do begin
b[i] := a[i];
b[2*l - i + 1] := a[i];
end;

Resources