- Delphi Cookbook
- Daniele Spinetti Daniele Teti
- 433字
- 2025-04-04 16:22:47
How to do it...
Perform the following steps:
- First, declare an enumerable that returns, by using the GetEnumerator function, an enumerator able to iterate over prime numbers. In addition, we have to declare GetPrimes and IsPrime functions. The first to returns the enumerable (TPrimesEnumerable) over which we can iterate and the second to check if a given number is prime:
unit PrimeEnumU;
interface
uses
System.Classes, System.Generics.Collections;
type
TPrimesEnumerable = record
private
FStart: Integer;
public
constructor Create(AStart: Integer);
function GetEnumerator: TEnumerator<Integer>;
end;
function GetPrimes(const AStart: Integer): TPrimesEnumerable;
function IsPrime(const ANumber: Integer): Boolean;
- In the implementation section we define TPrimesEnumerator. This type, returned by GetEnumerator function of TPrimesEnumerable, implements the two methods GetCurrent, MoveNext, and the Current property to make your container enumerable. In this case we inherit from TEnumerator<Integer>, so to respect the Enumerator interface we have only to override DoGetCurrent and DoMoveNext (take a look at System.Generics.Collections.pas to understand it):
implementation
uses
System.IOUtils;
type
TPrimesEnumerator = class(TEnumerator<Integer>)
private
FCurrent: Integer;
protected
constructor Create(const AStart: Integer);
function DoGetCurrent: Integer; override;
function DoMoveNext: Boolean; override;
end;
- Now we can proceed with implementation:
constructor TPrimesEnumerable.Create(AStart: Integer);
begin
FStart := AStart;
end;
function TPrimesEnumerable.GetEnumerator: TEnumerator<Integer>;
begin
Result := TPrimesEnumerator.Create(FStart);
end;
{ TPrimesEnumerator }
constructor TPrimesEnumerator.Create(const AStart: Integer);
begin
inherited Create;
FCurrent := AStart;
end;
function TPrimesEnumerator.DoGetCurrent: Integer;
begin
Result := FCurrent;
end;
function TPrimesEnumerator.DoMoveNext: Boolean;
begin
// in the while true loop inc FCurrent while FCurrent is not a prime number,
// when it's a prime number, this is only the case you can exit from function
while True do
begin
try
if IsPrime(FCurrent) then
Exit(True);
finally
Inc(FCurrent);
end;
end;
end;
// the function GetPrimes returns directly the Enumerable
function GetPrimes(const AStart: Integer): TPrimesEnumerable;
begin
Result := TPrimesEnumerable.Create(AStart);
end;
// determines if the number passed as a parameter is a prime number
function IsPrime(const ANumber: Integer): Boolean;
var
count: Int64;
I: Integer;
begin
if ANumber <= 1 then
Exit(false);
if ANumber = 2 then
Exit(True);
if (ANumber mod 2) = 0 then
Exit(false);
count := Trunc(Sqrt(ANumber) + 1);
for I := 3 to count do
if (ANumber Mod I) = 0 then
begin
Exit(false)
end
Result := True;
end;
end.
- Then, write the code to iterate over prime numbers and add it to the sum, if it is below 2 million:
procedure Main;
var
LTotal, LNextPrime: Integer;
begin
LTotal := 2;
for LNextPrime in GetPrimes(3) do
if LNextPrime < 2000000 then
LTotal := LTotal + LNextPrime
else
begin
WriteLn(LTotal.ToString);
break;
end;
end;
- Finally, if you run the code, you'll see the Project Euler Problem 10 solved!