I am new to Ocaml and I have a problem with this code (below). I am trying to write a program to sort array. I divided array into two halfs, and then I used Array.sort on those two arrays ( I am gonna fix that later, so i wont use Array.sort). And then I wanted to compare elements from those two arrays, but my code is not working.
Can anybody tell me where is the problem?
let a =[|5;4;2;6;1;3|] ;;
let n = Array.length a;;
let l= Array.sub a 0 (n/2);;
Array.sort compare l;;
l;;
let ll= Array.length l;;
let r= Array.sub a (n/2) (n/2);;
Array.sort compare r;;
r;;
let lr=Array.length r;;
let merge l r a =
let k =ref 0 in
let i = ref 0 in
let j =ref 0 in
while( !i<ll && !j< lr) do
if(l.(!i) <= r.(!j)) then
a.(!k) <- l.(!i)
i:= !i+1
else begin
a.(!k) <- r.(!j)
j:= !j+1;
k:= !k+1
end;
while (!i<ll) do
a.(!k)<-l.(!i)
i:= !i+1;
k:=!k+1;
done;
while (!j<ll) do
a.(!k) <-r.(!j)
j:= !j+1;
k:= !k+1
done;
done;;
merge l r a;;
Your problem comes from your misunderstanding of what instructions are. Let's try to explain it in a easy and short way :
If your expression returns a value, it's an expression (a bool, an int, a function ...)
If it doesn't return a value (which means it does a side effect), it's an instruction (and we say it returns unit because actually, that's what it does).
When you have a sequence (this is how multiple instructions executing one after another are called), you separate them with a ;.
So, for example, if I write this
let f x = x := 1; print_int !x; print_newline ()
I have a sequence and I have to separate my instructions with ;.
If I wrote :
let f x = x := 1 print_int !x print_newline ()
You can easily understand that OCaml can't know where the instructions are separated (is it x := 1 print_int; !x? Or anything else?) That's why you need ;.
Now comes the problem with if.
If you write
if cond then instr1; instr2
What is parsed is
(if cond then instr1); instr2
Yes, if cond then instr1 is an instruction because, well, it returns unit, no? So instr2 is not in your then block.
But if you write
if cond then let e1 = e2 in instr1; instr2
Then instr2 is in the then block because the construction let ... in creates a block under which all instructions are nested.
If you're starting with OCaml, my precious advice would be this : always writebegin ... end in your conditionnals. You'll be assured that what you write is what you think is parsed.
I'm too new to comment but will point out that every block needs either parentheses () or begin ... end. Thus, your very first if statement should have then begin at the end of the line. The statements between the begin and else need semi-colons to separate them as in:
if(l.(!i) <= r.(!j)) then begin
a.(!k) <- l.(!i);
i:= !i+1
end else begin
a.(!k) <- r.(!j);
j := !j+1;
k:= !k+1
end;
The first two lines of the while loops also need semi-colons because they are also a block of statements. Note that you do not need a semi-colon for the last statement in a block. They are separators, not end-of-statement. Also, as a shortcut, you can use incr i for i := !i + 1 and similar statements. Also, never use l or ll as variable names. :-)
Related
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
I'm trying to plot 4 data-sets in a single coordinate-system. I can plot every single one of them by themselves. However when I try to plot 2 or more with the same plot function I get an error. I can't use lists since I want to scale the arrays up to 2*10000, which a list can't. I'm using Maple 18.
Can anybody please help me solve this?
This is my code:
Here is a plotted data-set:
Here is the error I get, when trying to plot multiple sets(note I have tried using {} instead of []):
Your problem is that your use of pair and zip is not going to produce Arrays P[i] whose layout is valid for plotting. (Perhaps you cribbed that bit of code from something which was intended to produce a list of lists instead of an Array.)
Instead, you could construct the P[i] as iterator-by-2 Matrices (ie. 2-column Matrices).
One way:
restart;
mu := 2.5:
iterator := 25:
fcn := proc(a)
local F,i;
F := Array(1..iterator);
F[1] := a;
for i from 2 by 1 to iterator do
F[i] := mu*F[i-1]*(1-F[i-1]);
end do;
F;
end proc:
f[1]:=fcn(0.01):
f[2]:=fcn(0.1):
f[3]:=fcn(0.3):
f[4]:=fcn(0.5):
x := Array([seq(i,i=1..iterator)]):
for i from 1 to 4 do
P[i] := <x,f[i]>^%T:
end do:
plot([P[1],P[2],P[3],P[4]]);
Another (similar) way:
restart;
mu := 2.5:
iterator := 25:
fcn := proc(a)
local F,i;
F := Vector(1..iterator);
F[1] := a;
for i from 2 by 1 to iterator do
F[i] := mu*F[i-1]*(1-F[i-1]);
end do;
F;
end proc:
f[1]:=fcn(0.01):
f[2]:=fcn(0.1):
f[3]:=fcn(0.3):
f[4]:=fcn(0.5):
x := Vector([seq(i,i=1..iterator)]):
for i from 1 to 4 do
P[i] := <x|f[i]>:
end do:
plot([P[1],P[2],P[3],P[4]]);
You could alternatively use the command plots:-listplot directly on your f[i], though you'd likely way to also specify different colors for each so that it looked nice when you used plots:-display to render them all together.
I leave aside considerations of performance. There are ways to do all this and get faster computation. I deliberately keep your basic methodology.
I am trying to use the 'Last attribute with a 2D array in Ada, but I can't seem to find the correct syntax to do so.
I know that if I have a 1D array/vector I can use A'last or A'last(n) where n is the nth dimension. But if I do the following
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
end temp;
I get the following compile time error:
Storage_Error stack overflow (or erroneous memory access)
So what am I doing wrong?
I am using GNAT Pro 6.4.1 on Linux.
I'd be very surprised if you got a compile-time Storage_Error on that code.
I've grabbed a copy of your code and modified it as follows; it compiles without error using GNAT (gcc-4.4):
procedure Array_2D is
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
return 42; -- added this
end temp;
begin
null;
end Array_2D;
(Note that I had to add the missing return statement in temp.)
Your syntax for the 'Last attribute (not "command") is correct, but since Ada arrays can have arbitrary lower and upper bounds, it's better to use the 'Range attribute instead:
for i in tempTable'Range(1) loop
for j in tempTable'Range(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
As for the Storage_Error exception, that could easily happen at run time (not compile time) if you call your temp function with a very large value for tempIn. Remember that it has to allocate enough space to hold tempIn**2 Integer objects. Presumably you've also created another UnconstrainedArray_2D object to be passed in as the Table parameter.
It's conceivable that the compiler itself could die with a Storage_Error exception, but I don't see anything in your code that might cause that.
Show us a complete (but small) program that demonstrates the problem you're having, along with the exact (copy-and-pasted) error message. Please distinguish clearly between compile-time and run-time errors.
Your tempTable might have a range of 0..tempIn, but you don't know what range your Table has.. They could be of different length, too.
You would have to check that the length is the same and then use relative indices, like this:
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
if tempTable'Length (1) /= Table'Length (1) or else
tempTable'Length (2) /= Table'Length (2)
then
raise Constraint_Error; -- or something else
end if;
for i in 0 .. tempTable'Length (1) - 1 loop
for j in 0 .. tempTable'Length (2) - 1 loop
tempTable(tempTable'First (1) + i, tempTable'First (2) + j) :=
Table(Table'First (1) + i, Table'First (2) + j);
end loop;
end loop;
end temp;
that way it is ensured that both tables are same length and all indices are valid.
If your tempTable is allowed to be smaller than Table, simply adjust the length check to >. The indices would still be valid.
I don't see an actual value for tempIn set. If the value for tempIn coming into the function temp has not been properly initialized or explicitly set, then the value in tempIn could be anything and probably not something you would like.
I was thinking of a default value. (probably shouldn't post when I am not feeling well :-)
Is there any programming language that has a do-until loop?
Example:
do
{
<statements>
}
until (<condition>);
which is basically equivalent to:
do
{
<statements>
}
while (<negated condition>);
NOTE: I'm looking for post-test loops.
Ruby has until.
i=0
begin
puts i
i += 1
end until i==5
VBA!
Do-Until-Loop
Do-Loop-Until
Although I think quite a number of people here would doubt if it is a real language at all, but well, BASIC is how Microsoft started (quite weak argument for many, I know)...
It is possible in VB.Net
bExitFromLoop = False
Do
'Executes the following Statement
Loop Until bExitFromLoop
It is also possible in SDF-P on BS2000 (Fujitsu/Siemens Operating System)
/ DECLARE-VARIABLE A
/ DECLARE-VARIABLE SWITCH-1(TYPE=*BOOLEAN)
/ SET-VARIABLE A = 5
/ SET-VARIABLE SWITCH-1 = ON
/ REPEAT
/ A = A + 10
/ IF (A > 50)
/ SET-VARIABLE SWITCH-1 = OFF
/ END-IF
/ UNTIL (SWITCH-1 = OFF)
/ SHOW-VARIABLE A
A = 55
Is is also possible is C or C++ using a macro that define until
Example (definition):
#define until(cond) while(!(##cond))
Example (utilisation):
int i = 0;
do {
cout << i << "\n";
i++;
} until(i == 5);
In VB we can find something like:
Reponse = InputBox("Please Enter Pwd")
Do Until Reponse = "Bob-pwr148" ...
Eiffel offers you an until loop.
from
x := 1
until
x > 100
loop
...
end
There is also an "across" loop as well. Both are very powerful and expressive.
The design of this loop has more to offer. There are two more parts to its grammar that will help us resolve two important "correctness" problems.
Endless loop protection.
Iteration failure detection.
Endless Loop Protection
Let's modify our loop code a little by adding a loop variant.
from
x := 1
v := 1_000
until
x > 100
variant
v
loop
...
v := v - 1
end
The loop variant is (essentially) a count-down variable, but not just any old variable. By using the variant keyword, we are telling the compiler to pay attention to v. Specifically, the compiler is going to generate code that watchdogs the v variable for two conditions:
Does v decrease with each iteration of the loop (are we counting down). It does no good to try and use a count-down variable if it is (in fact) not counting down, right? If the loop variant is not counting down (decreasing by any amount), then we throw an exception.
Does v ever reach a condition of less than zero? If so, then we throw an exception.
Both of these work together through the compiler and variant variable to detect when and if our iterating loop fails to iterate or iterates too many times.
In the example above, our code is communicating to us a story that it expects to iterate zero to 1_000 times, but not more. If it is more, then we stop the loop, which leaves us to wonder: Do we really have cases were we iterate more than 1_000 times, or is there something wrong that our condition is failing to become True?
Loop Invariant
Now that we know what a loop variant is, we need to understand what a loop invariant is.
The invariant is a set of one or more Boolean conditions that must hold True after each iteration through the loop. Why do we want these?
Imagine you have 1_000_000 iterations and one of them fails. You don't have time to walk through each iteration, examining it to see it is okay or not. So, you create a set of one or more conditions that are tested upon completion of each iteration. If the one or all of the conditions fail, then you know precisely which iteration (and its deterministic state) is causing the problem!
The loop invariant might look something like:
from
x := 1
y := 0
v := 1_000
invariant
y = x - 1
until
x > 100
variant
v
loop
...
x := x + 1
y := y + 1
v := v - 1
end
In the example above, y is trailing x by 1. We expect that after each iteration, y will always be x - 1. So, we create a loop invariant using the invariant keyword that states our Boolean assertion. If y fails to be x - 1, the loop will immediately throw an exception and let us know precisely which iteration has failed to keep the assertion True.
CONCLUSION
Our loop is now quite tight and secure—well guarded against failure (bugs, errors).
Below is a piece of code shown and doubts are regarding the implementation of loops
C := character'last; --'// SO code colorizer hack
I := 1;
K : loop
Done := C = character'first; --'
Count2 := I;
Exit K when Done;
C := character'pred(c); --'
I := I + 1;
end loop K;
Can anyone please tell me what does 'K' stands for.I guess its not a variable.How does 'K' control the execution of the loop?
K is the name of the loop. The end loop and Exit statements refer to that name, to make it clear what loop is being exited.
The Ada Reference Manual calls it a "loop_statement_identifier".
As noted, K is the loop's label. It allows you to identify a particular loop to aid readability, and also to selectively exit a specific loop from a set of nested enclosing ones (i.e. being a "goto"...shhh! :-)
Here's a contrived example (not compiled checked):
S : Unbounded_String;
F : File_Type;
Done_With_Line : Boolean := False;
All_Done : Boolean := False;
begin
Open(F, In_File, "data_file.dat");
File_Processor:
while not End_Of_File(F) loop
S := Get_Line(F);
Data_Processor:
for I in 1 .. Length(S) loop
Process_A_Character
(Data_Char => Element(S, I), -- Mode in
Line_Done => Done_With_Line, -- Mode out
Finished => All_Done); -- Mode out
-- If completely done, leave the outermost (file processing) loop
exit File_Processor when All_Done;
-- If just done with this line of data, go on to the next one.
exit Data_Processor when Done_With_Line;
end loop;
end loop File_Processor;
Close(F);
end;
K is essentially the name of the loop. The exit k tells the code to stop looping and go to the next statement after loop k ends.
You usually don't need to name loops, as you can just say exit and it will exit the enclosing loop. However, if you have a loop nested inside another loop, and you'd like to exit not the one immediately around the exit statement, but the outermost one, then doing something like this may be required.
K is a label that names the loop. Wow, it has been a long time since I've seen any Ada...