The rfind challenge
Timon Gehr
timon.gehr at gmx.ch
Tue Jan 15 05:30:42 PST 2013
On 01/15/2013 12:53 PM, FG wrote:
> On 2013-01-15 06:51, Andrei Alexandrescu wrote:
>> If r is a forward range but not better, this is rather simple:
>>
>> R rfind(R, E)(R range, E element)
>> {
>> for (;;)
>> {
>> auto ahead = range.save.find(element);
>> if (ahead.empty) return range;
>> range = ahead;
>> }
>> }
>
> That example creates an infinite loop. Needs a popFront:
>
> R rfind(R, E)(R range, E element)
> {
> if (range.empty) return range;
> for (;;)
> {
> auto ahead = range.save;
> ahead.popFront();
> ahead = ahead.find(element);
> if (ahead.empty) return range;
> range = ahead;
> }
> }
>
That is buggy too.
> Another thing: if the element is not found, I think an empty range
> should be returned and not the whole range.
Yup.
R rfind(R, E)(R range,E element){
auto r=range.find(element);
if(r.empty) return r;
for(;;){
auto ahead=r.save;
ahead.popFront();
ahead=ahead.find(element);
if(ahead.empty) return r;
r=ahead;
}
}
Full proof (assuming purity of the range primitives):
/+pure+/ R tail(R)(R r)out(result){
assert(result=={
auto a=r;
a.popFront();
return a;
}());
}body{
auto a=r;
a.popFront();
return a;
}
/+pure+/ R rfind(R, E)(R range,E element)out(result){
assert(range.find(element).empty&&result.empty||!range.find(element).empty&&!result.empty&&result.front==element&&result.tail.find(element).empty);
}body{
auto r=range.find(element);
assert(r==range.find(element)&&(r.empty||r.front==element));
if(r.empty){
assert(r==range.find(element)&&r.empty);
return r;
/+assert(result==range.find(element)&&result.empty);
assert(range.find(element).empty&&result.empty);+/
}
assert(r==range.find(element)&&!r.empty&&r.front==element);
assert(!range.find(element).empty&&!r.empty&&r.front==element);
for(;;){
assert(true&&!range.find(element).empty&&!r.empty&&r.front==element);
assert(!range.find(element).empty&&!r.empty&&r.front==element&&!r.empty);
auto ahead=r.save;
assert(!range.find(element).empty&&!r.empty&&r.front==element&&!ahead.empty&&ahead==r.save);
ahead.popFront();
assert(!range.find(element).empty&&!r.empty&&r.front==element&&ahead=={
auto ahead=r.save;
ahead.popFront();
return ahead;
}());
assert(!range.find(element).empty&&!r.empty&&r.front==element&&ahead==r.tail);
ahead=ahead.find(element);
assert(!range.find(element).empty&&!r.empty&&r.front==element&&(ahead.empty||ahead.front==element)&&ahead==r.tail.find(element));
if(ahead.empty){
assert(!range.find(element).empty&&ahead.empty&&!r.empty&&r.front==element&&ahead==r.tail.find(element));
return r;
/+assert(!range.find(element).empty&&ahead.empty&&!result.empty&&result.front==element&&ahead==result.tail.find(element));
assert(!range.find(element).empty&&!result.empty&&result.front==element&&result.tail.find(element).empty);+/
}
assert(!range.find(element).empty&&!ahead.empty&&ahead.front==element);
r=ahead;
assert(!range.find(element).empty&&!r.empty&&r.front==element);
}
assert(false);
}
More information about the Digitalmars-d
mailing list