in the Dafny tutorial at rise4fun, s[i := v] is defined for replacing the index i by v in sequence s.
but using this always fails with expected method call, found expression.
for instance in the code below for swapping two indexes
var a:int :=input[j];
var b:int :=input[j-1];
input[j := b]; //expected method call, found expression
input[j-1 := a]; //expected method call, found expression
what is the correct way of using s[i := v] in a case like swapping two indexes.
You could write
var a:int :=input[j];
var b:int :=input[j-1];
input := input[j:=b] ;
input := input[j-i : a];
More succinctly, but perhaps harder to read
input := input[ j := input[j-1] ][ j-1 := input[j] ] ;
Related
I need to check if N values are equals.
var
A, B, C, D : Integer;
begin
...
if(A = B) and (B = C) and (C = D) then
ShowMessage('Same value');
end;
Is there a shorter way to compare N values?
I mean something like:
var
A, B, C, D : Integer;
begin
...
if SameValue([A, B, C, D]) then
ShowMessage('Same value');
end;
Well, the best you can achieve is basically your own suggestion.
You would implement this using an open array parameter:
function AllEqual(const AValues: array of Integer): Boolean;
var
i: Integer;
begin
for i := 1 to High(AValues) do
if AValues[i] <> AValues[0] then
Exit(False);
Result := True;
end;
The correctness of this implementation is obvious:
If the number of values in the array is 0 or 1, it returns True.
Otherwise, and in general, it returns False iff the array contains two non-equal values.
AValues[0] is only accessed if High(AValues) >= 1, in which case the 0th value exists.
A function like this one is straightforward to implement for ordinal types. For real types (floating-point values), it becomes much more subtle, at least if you want to compare the elements with epsilons (like the SameValue function does in the Delphi RTL). Indeed, then you get different behaviour depending on if you compare every element against the first element, or if you compare every element against its predecessor.
Andreas' answer is correct, I'd like to add a different approach though:
uses Math;
function AllEqual(const AValues: array of Integer): Boolean;
begin
Result := (MinIntValue(AValues) = MaxIntValue(AValues));
end;
function AllEqualF(const AValues: array of Double; Epsilon: Double): Boolean;
begin
Result := ((MaxValue(AValues)- MinValue(AValues)) <= Epsilon);
end;
There is quite simple and very fast equality comparison approach for ints without a need of additional method and stuff like this - it's Bitwise Operators
And of course, this could be put in a method with open array or so.
There are even 2 options (or maybe more), with second you also can replace "or" to "+" , OR (not both, it will ruin equality-test logic) you can replace "xor" to "-" (last case)
BUT the resulting condition length is not shorter than original (only the last case is same and all brackets/parenthesis are vital, except first xor/-), here is the testing code:
program Project1;{$APPTYPE CONSOLE}
uses Math; var a, b, c, d, x : Integer; s: string;
begin
Randomize;
repeat
x := Random(10) - 5;
a := x + Sign(Random() - 0.5);
b := x + Sign(Random() - 0.5);
c := x + Sign(Random() - 0.5);
d := x + Sign(Random() - 0.5);
Writeln(a, ' ', b, ' ', c, ' ', d);
Writeln((A = B) and (B = C) and (C = D));
Writeln(a or b or c or d = a and b and c and d);
Writeln(a xor b or (b xor c) or (c xor d) = 0);
Writeln(a - b or (b - c) or (c - d) = 0);
Readln(s);
until s <> '';
end.
I need to make a program that fills an array with Upcase chars and then sort those chars in a second array. It has to change every char in the old array with '*'and then put it in the second array(sorting is from the lowest ASCII code to the highest).
I did the first part and up until this point there's only one problem. My work doesn't function when I fill an array with the first item having the smallest ascii code, ex: 'A','C','E','F','G'. The output for that one is : T2[1] = A and the rest of the T2 array is filled with stars.
Whereas if I don't put the first char as the lowest it works perfectly
like : 'E','A','K'....
program XD;
uses wincrt;
type
tab = array[1..100] of char;
var
t1,t2:tab;
i,n ,k,p,o,v: integer;
begin
repeat
begin
writeln('Donnez la taille T ');
Readln(n);
end;
until(n in [5..20]);
for i := 1 to n do
begin
repeat
begin
writeln('Donnez T1[',i,']');
readln(T1[i]);
end;
until(UPCASE(T1[i]) = T1[i]);
end;
for i := 1 to n do Begin
o := ord(T1[1]);
for k := 2 to n do begin
if (T1[K] <> '*') AND (ord(T1[k]) < o) then
begin
o := ord (T1[k]);
p := k;
End;
end;
T1[p] := '*';
T2[v] := chr(o);
v := v+1;
end;
for i := 1 to n do Begin
writeln('T2[',i,']=', T2[i]);
end;
end.
Lets look at the sorting algorithm. In the loop, you always start with the first item in the T1 array and compare it with the rest.
Whereas if I don't put the first char as the lowest it works perfectly ...
Now, what will happen when the first character is the lowest? Right, it will be replaced with a *, and the rest of the sorting will fail, since you will compare with the Ord('*') value, which is lower than any character value in the alphabet.
To fix the algorithm, compare with the loop index character and swap the lowest character with the loop index value at the end. That will keep the '*' characters out of the loop and the need to compare against them.
for i := 1 to n do begin
o := Ord(T1[i]); // Pick actual loop index value
p := i; // Store index
for k := i+1 to n do begin // Search for lowest character
if (Ord(T1[k]) < o) then begin
o := ord (T1[k]);
p := k;
end;
end;
// Swap the p and i index value, to put the * into the i index position
if (i <> p) then
T1[p] := T1[i];
T1[i] := '*';
T2[i] := Chr(o);
end;
here's the code in Delphi:
function Perfect(x: Integer): Integer;
var
i, a: Integer;
begin
i := 1;
a := 0;
while i <= x div 2 do
begin
if (x mod i = 0) then
a := a + i;
i := i + 1;
end;
if x = a then
Result := x;
end;
Basically, it's a function that shows perfect numbers from given interval. I created a loop for to show these numbers but I have a problem because it also shows some random numbers when it's not a perfect number. So let's say I have [1;7] and then console shows that:
1969410929
1969410929
1969410929
1969410929
1969410929
6
1969410929
What can I do to show only right numbers?
Your code is failing to set the return value if the number is not perfect. In that scenario the returned value is ill defined. You must always set the return value. From the documentation:
If the function exits without assigning a value to Result or the function name, then the function's return value is undefined.
Since a function must return a value, your function is in a bind. What to return in case the value is not perfect? There is no good choice in my view. You do not need to return the number since you already know it. You passed it to the function after all.
So, you should change the design of the function to return a boolean indicating whether or not the number was perfect:
function IsPerfect(x: Integer): Boolean;
var
i, sum: Integer;
begin
sum := 0;
for i := 1 to x div 2 do
if x mod i = 0 then
inc(sum, i);
Result := x = sum;
end;
The code to call the function runs like this:
for i := 1 to 1000 do
if IsPerfect(i) then
Writeln(i);
Output
6
28
496
... "it also shows some random numbers when it's not a perfect number".
The reason for that is that you don't set the Result "variable" when it's not a perfect number. If you create a function that doesn't set the Result variable in all cases, the result of calling it will be undefined in those cases. Random describes it, though it's probably some kind of system, even if the system is just "whatever was left in memory where the Result variable was placed".
You need to determine what to return if it's not a perfect number, and make either of the following code changes:
Result := <what to return if not?>;
if x = a then
Result := x;
or this:
if x = a then
Result := x
else
Result := <what to return if not?>;
I came across the following (conceptually very simple) problem, and want to write code to do it, but am struggling. Let's say we have two rows of equal length, k. Each cell of each row can be either a 0 or a 1.
For e.g., consider the following row-pair, with k = 5: 01011, 00110
Now if the two rows could freely exchange values at each cell, there would be 2^5 possible combinations of row-pairs (some of which may not be unique). For instance, we could have 00010, 01111 as one possible row-pair from the above data. I want to write code in Delphi to list all the possible row-pairs. This is easy enough to do with a set of nested for-loops. However, if the value of k is known only at run-time, I'm not sure how I can use this approach for I don't know how many index variables I would need. I can't see how case statements will help either because I don't know the value of k.
I am hoping that there is an alternative to a nested for-loop, but any thoughts would be appreciated. Thanks.
Given two vectors A and B of length k, we can generate a new pair of vectors A1 and B1 by selectively choosing elements from A or B. Let our decision to choose from A or B be dictated by a bit vector S, also of length k. For i in [0..k), when Si is 0, store Ai in A1i and Bi in B1i. If Si is 1, then vice versa.
We can define that in Delphi with a function like this:
procedure GeneratePair(const A, B: string; S: Cardinal; out A1, B1: string);
var
k: Cardinal;
i: Cardinal;
begin
Assert(Length(A) = Length(B));
k := Length(A);
Assert(k <= 32);
SetLength(A1, k);
SetLength(B1, k);
for i := 1 to k do
if (S and (1 shl Pred(i))) = 0 then begin
A1[i] := A[i];
B1[i] := B[i];
end else begin
A1[i] := B[i];
B1[i] := A[i];
end;
end;
If we count in binary from 0 to 2k−1, that will give us a sequence of bit vectors representing all the possible combinations of exchanging or not-exchanging characters between A and B.
We can write a loop and use the above function to generate all 2k combinations:
A := '01011';
B := '00110';
for S := 0 to Pred(Round(IntPower(2, Length(A)))) do begin
GeneratePair(A, B, S, A1, B1);
writeln(A1, ', ', B1);
end;
That effectively uses one set of nested loops. The outer loop is the one from 0 to 31. The inner loop is the one inside the function from 1 to k. As you can see, we don't need to know the value of k in advance.
Now that, thanks to Rob, I understand the problem, I offer this recursive solution:
{$APPTYPE CONSOLE}
procedure Swap(var A, B: Char);
var
temp: Char;
begin
temp := A;
A := B;
B := temp;
end;
procedure Generate(const A, B: string; Index: Integer);
var
A1, B1: string;
begin
Assert(Length(A)=Length(B));
inc(Index);
if Index>Length(A) then // termination
Writeln(A, ', ', B)
else
begin // recurse
// no swap
Generate(A, B, Index);
//swap
A1 := A;
B1 := B;
Swap(A1[Index], B1[Index]);
Generate(A1, B1, Index);
end;
end;
begin
Generate('01011', '00110', 0);
Readln;
end.
I want to compute a list "intersection". The problem is:
L1 = [1, 0, 2, 3, 1 , 3, 0, 5]
L2 = [3, 5]
Then the result will be
L3 = [0, 0, 0, 1, 0, 1, 0, 1]
Then i will convert this result in a byte. In this case will be 21 in decimal format.
I want to make in delphi and I need this do efficiently. Is there a way to solve this problem better than O(m*n)?
Here's a function that should do what you want. I defined L2 as a set instead of an array since you said all your values will fit in a Byte. Its complexity is O(n); checking set membership runs in constant time. But since the result needs to fit in a byte, the length of L1 must be bound at 8, so the complexity of this function is actually O(1).
function ArrayMembersInSet(const L1: array of Byte; const L2: set of Byte): Byte;
var
i: Integer;
b: Byte;
begin
Assert(Length(L1) <= 8,
'List is to long to fit in result');
Result := 0;
for i := 0 to High(L1) do begin
b := L1[i];
if b in L2 then
Result := Result or (1 shl (7 - i));
end;
end;
Rob's answer will work for this specific case. For a more general case where two lists have to be compared, you can do it in O(m+n) time if both lists are sorted. (Or O(n log n) time if you have to sort them first, but that's still a lot faster than O(m*n).)
The basic List Comparison algorithm looks like this:
procedure ListCompare(list1, list2: TWhateverList; [Add extra params here]);
var
i, j: integer;
begin
i := 0;
j := 0;
while (i < list1.Count) and (j < list2.Count) do
begin
if list1[i] < list2[j] then
begin
//handle this appropriately
inc(i);
end
else if list1[i] > list2[j] then
begin
//handle this appropriately
inc(j);
end
else //both elements are equal
begin
//handle this appropriately
inc(i);
inc(j);
end;
end;
//optional cleanup, if needed:
while (i < list1.Count) do
begin
//handle this appropriately
inc(i);
end;
while (j < list2.Count) do
begin
//handle this appropriately
inc(j);
end;
end;
This can be customized for a whole bunch of tasks, including list intersection, by changing the "handle this appropriately" places, and it's guaranteed to not run for more steps than are in both lists put together. For list intersection, have the equals case add the value to some output and the other two do nothing but advance the counters, and you can leave off the optional cleanup.
One way to use this algorithm is to make the extra params at the top into function pointers and pass in routines that will handle the appropriate cases, or nil to do nothing. (Just make sure you check for nil before invoking them if you go that route!) That way you only have to write the basic code once.
Well no matter what you will need to visit each element in each list comparing the values. A nested loop would accomplish this in O(n^2) and the conversion should just be local work.
EDIT: I noticed that you want a better runtime than O(n*m).