From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: project euler 26
Date: Wed, 6 Sep 2023 09:06:31 +0200 [thread overview]
Message-ID: <ud98do$2dbqr$1@dont-email.me> (raw)
In-Reply-To: <87a5u0rts0.fsf@bsb.me.uk>
On 2023-09-06 03:10, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2023-09-05 17:18, Ben Bacarisse wrote:
>>
>>> There was
>>> boiler plate code in my program that could be abstracted out into a
>>> generic function (or package?) so that any function can be maximised
>>> over some range or, better yet, any iterable type (if that's how Ada
>>> does things).
>>
>>> Can someone here show me how?
>>
>> You define some classes. Either generic or tagged. E.g. a generic class of
>> functions that uses two generic classes of the argument and the value:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type)
>> return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> with function "=" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
>> -- Function type
>> with function Func (Argument : Argument_Type) return Value_Type;
>> function Generic_Maximum_At (Left, Right : Argument_Type)
>> return Value_Type;
>>
>> and the implementation
>>
>> function Generic_Maximum_At (Left, Right : Argument_Type)
>> return Value_Type is
>> Argument : Argument_Type := Left;
>> Max : Value_Type;
>> Value : Value_Type;
>> begin
>> if Right < Left then
>> raise Constraint_Error with "Empty interval";
>> end if;
>> Max := Func (Argument);
>> while not (Argument = Right) loop
>> Argument := Next (Argument);
>> Value := Func (Argument);
>> if Max < Value then
>> Max := Value;
>> end if;
>> end loop;
>> return Max;
>> end Generic_Maximum_At;
>>
>> or you can choose to pass the function as an argument:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type)
>> return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type) return Boolean is <>;
>> function Generic_Maximum_At
>> ( Left, Right : Argument_Type;
>> Func : access function (Argument : Argument_Type)
>> return Value_Type
>> ) return Value_Type;
>>
>> Or you can make it a package which is usually a better choice as one can
>> pack into it several entities sharing the same generic interface:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type)
>> return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type )
>> return Boolean is <>;
>> with function "=" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type) return Boolean is <>;
>> package Generic_Discrete_Comparable_Valued is
>> function Maximum_At
>> ( Left, Right : Argument_Type;
>> Func : access function (Argument : Argument_Type)
>> return Value_Type
>> ) return Value_Type;
>> -- Other useless functions
>> end Generic_Discrete_Comparable_Valued;
>>
>> The generic classes of arguments/values can be in turn factored out into
>> reusable generic packages:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type) return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type) return Boolean is <>;
>> with function "=" (Left, Right : Argument_Type) return Boolean is <>;
>> package Generic_Arguments is
>> end Generic_Arguments;
>>
>> generic
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
>> package Generic_Values is
>> end Generic_Values;
>>
>> generic
>> with package Arguments is new Generic_Arguments (<>);
>> with package Values is new Generic_Values (<>);
>> package Generic_Discrete_Comparable_Valued is
>> use Arguments, Values;
>> function Maximum_At
>> ( Left, Right : Argument_Type;
>> Func : access function (Argument : Argument_Type)
>> return Value_Type
>> ) return Value_Type;
>> -- Other useless functions
>> end Generic_Discrete_Comparable_Valued;
>
> Thank you. I can't yet see how to use any of these alternatives, but
> that's my problem.
It is pretty much straightforward. E.g. the last one:
package Arguments is new Generic_Arguments (Integer, Integer'Succ);
package Values is new Generic_Values (Integer);
package Functions is
new Generic_Discrete_Comparable_Valued (Arguments, Values);
Now you can print the maximum of your Period function:
Put_Line
( "Max at"
& Integer'Image (Functions.Maximum_At (2, 999, Period'Access))
);
> Are there any good online sources on Ada generic
> programming so I can find out how to implement and use this short of
> package?
Actually I provided an implementation above. Here it is again:
package body Generic_Discrete_Comparable_Valued is
function Maximum_At
( Left, Right : Argument_Type;
Func : access function (Argument : Argument_Type)
return Value_Type
) return Value_Type is
Argument : Argument_Type := Left;
Max : Value_Type;
Value : Value_Type;
begin
if Right < Left then
raise Constraint_Error with "Empty interval";
end if;
Max := Func (Argument);
while not (Argument = Right) loop
Argument := Next (Argument);
Value := Func (Argument);
if Max < Value then
Max := Value;
end if;
end loop;
return Max;
end Maximum_At;
end Generic_Discrete_Comparable_Valued;
(The packages Generic_Arguments and Generic_Values have no bodies)
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
next prev parent reply other threads:[~2023-09-06 7:06 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-04 9:19 project euler 26 CSYH (QAQ)
2023-09-04 11:06 ` Niklas Holsti
2023-09-04 12:39 ` Dmitry A. Kazakov
2023-09-04 16:01 ` Ben Bacarisse
2023-09-04 19:20 ` Dmitry A. Kazakov
2023-09-04 20:18 ` Ben Bacarisse
2023-09-04 21:00 ` Dmitry A. Kazakov
2023-09-04 23:16 ` Ben Bacarisse
2023-09-05 7:23 ` Dmitry A. Kazakov
2023-09-05 15:18 ` Ben Bacarisse
2023-09-05 17:08 ` Dmitry A. Kazakov
2023-09-06 1:10 ` Ben Bacarisse
2023-09-06 7:06 ` Dmitry A. Kazakov [this message]
2023-09-06 15:16 ` Ben Bacarisse
2023-09-06 15:54 ` Dmitry A. Kazakov
2023-09-06 23:32 ` Ben Bacarisse
2023-09-07 9:02 ` Dmitry A. Kazakov
2023-09-08 1:32 ` Ben Bacarisse
2023-09-08 7:23 ` Dmitry A. Kazakov
2023-09-09 0:25 ` Ben Bacarisse
2023-09-09 9:32 ` Dmitry A. Kazakov
2023-09-10 1:20 ` Ben Bacarisse
2023-09-10 8:46 ` Dmitry A. Kazakov
2023-09-10 19:22 ` Ben Bacarisse
2023-09-11 6:53 ` Dmitry A. Kazakov
2023-09-11 16:13 ` Ben Bacarisse
2023-09-12 7:17 ` Dmitry A. Kazakov
2023-09-13 12:24 ` Ben Bacarisse
2023-09-14 6:33 ` Dmitry A. Kazakov
2023-09-14 14:30 ` Ben Bacarisse
2023-09-08 6:09 ` G.B.
2023-09-08 21:02 ` Ben Bacarisse
2023-09-09 8:13 ` G.B.
2023-09-09 21:04 ` Ben Bacarisse
2023-09-10 9:11 ` Dmitry A. Kazakov
2023-09-05 17:35 ` moi
2023-09-04 14:23 ` Dmitry A. Kazakov
2023-09-07 7:31 ` Francesc Rocher
2023-09-15 9:07 ` CSYH (QAQ)
2023-09-19 7:59 ` comp.lang.ada
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox