mirror of
https://github.com/dlang/phobos.git
synced 2025-05-13 07:39:15 +03:00
issue 5224
This commit is contained in:
parent
82b4f1c901
commit
98b47ad5dd
1 changed files with 58 additions and 93 deletions
145
std/algorithm.d
145
std/algorithm.d
|
@ -7217,120 +7217,72 @@ cases.))
|
||||||
Range remove
|
Range remove
|
||||||
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
|
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
|
||||||
(Range range, Offset offset)
|
(Range range, Offset offset)
|
||||||
if (isBidirectionalRange!Range && hasLength!Range && s != SwapStrategy.stable
|
if (s != SwapStrategy.stable
|
||||||
|
&& isBidirectionalRange!Range && hasLength!Range
|
||||||
&& Offset.length >= 1)
|
&& Offset.length >= 1)
|
||||||
{
|
{
|
||||||
enum bool tupleLeft = is(typeof(offset[0][0]))
|
Tuple!(size_t, size_t)[offset.length] blackouts;
|
||||||
&& is(typeof(offset[0][1]));
|
foreach (i, v; offset)
|
||||||
enum bool tupleRight = is(typeof(offset[$ - 1][0]))
|
|
||||||
&& is(typeof(offset[$ - 1][1]));
|
|
||||||
static if (!tupleLeft)
|
|
||||||
{
|
{
|
||||||
alias offset[0] lStart;
|
static if (is(typeof(v[0]) : size_t) && is(typeof(v[1]) : size_t))
|
||||||
auto lEnd = lStart + 1;
|
{
|
||||||
|
blackouts[i][0] = v[0];
|
||||||
|
blackouts[i][1] = v[1] - v[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto lStart = offset[0][0];
|
static assert(is(typeof(v) : size_t), typeof(v).stringof);
|
||||||
auto lEnd = offset[0][1];
|
blackouts[i][0] = v;
|
||||||
}
|
blackouts[i][1] = 1;
|
||||||
static if (!tupleRight)
|
|
||||||
{
|
|
||||||
alias offset[$ - 1] rStart;
|
|
||||||
auto rEnd = rStart + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto rStart = offset[$ - 1][0];
|
|
||||||
auto rEnd = offset[$ - 1][1];
|
|
||||||
}
|
|
||||||
// Begin. Test first to see if we need to remove the rightmost
|
|
||||||
// element(s) in the range. In that case, life is simple - chop
|
|
||||||
// and recurse.
|
|
||||||
if (rEnd == range.length)
|
|
||||||
{
|
|
||||||
// must remove the last elements of the range
|
|
||||||
range.popBackN(rEnd - rStart);
|
|
||||||
static if (Offset.length > 1)
|
|
||||||
{
|
|
||||||
return .remove!(s, Range, Offset[0 .. $ - 1])
|
|
||||||
(range, offset[0 .. $ - 1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return range;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ok, there are "live" elements at the end of the range
|
size_t left = 0, right = offset.length - 1;
|
||||||
auto t = range;
|
auto tgt = range.save;
|
||||||
auto lDelta = lEnd - lStart, rDelta = rEnd - rStart;
|
size_t steps = 0;
|
||||||
auto rid = min(lDelta, rDelta);
|
|
||||||
foreach (i; 0 .. rid)
|
while (left <= right)
|
||||||
{
|
{
|
||||||
move(range.back, t.front);
|
// Look for a blackout on the right
|
||||||
|
if (blackouts[right][0] + blackouts[right][1] >= range.length)
|
||||||
|
{
|
||||||
|
range.popBackN(blackouts[right][1]);
|
||||||
|
--right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Advance to next blackout on the left
|
||||||
|
assert(blackouts[left][0] >= steps);
|
||||||
|
tgt.popFrontN(blackouts[left][0] - steps);
|
||||||
|
steps = blackouts[left][0];
|
||||||
|
auto toMove = min(blackouts[left][1], blackouts[right][1]);
|
||||||
|
foreach (i; 0 .. toMove)
|
||||||
|
{
|
||||||
|
move(range.back, tgt.front);
|
||||||
range.popBack();
|
range.popBack();
|
||||||
t.popFront();
|
tgt.popFront();
|
||||||
}
|
}
|
||||||
if (rEnd - rStart == lEnd - lStart)
|
steps += toMove;
|
||||||
|
if (toMove == blackouts[left][1])
|
||||||
{
|
{
|
||||||
// We got rid of both left and right
|
// Filled the entire left hole
|
||||||
static if (Offset.length > 2)
|
++left;
|
||||||
{
|
continue;
|
||||||
return .remove!(s, Range, Offset[1 .. $ - 1])
|
|
||||||
(range, offset[1 .. $ - 1]);
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
return range;
|
return range;
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rEnd - rStart < lEnd - lStart)
|
|
||||||
{
|
|
||||||
// We got rid of the entire right subrange
|
|
||||||
static if (Offset.length > 2)
|
|
||||||
{
|
|
||||||
return .remove!(s, Range)
|
|
||||||
(range, tuple(lStart + rid, lEnd),
|
|
||||||
offset[1 .. $ - 1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto tmp = tuple(lStart + rid, lEnd);
|
|
||||||
return .remove!(s, Range, typeof(tmp))
|
|
||||||
(range, tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We got rid of the entire left subrange
|
|
||||||
static if (Offset.length > 2)
|
|
||||||
{
|
|
||||||
return .remove!(s, Range)
|
|
||||||
(range, offset[1 .. $ - 1],
|
|
||||||
tuple(rStart, lEnd - rid));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto tmp = tuple(rStart, lEnd - rid);
|
|
||||||
return .remove!(s, Range, typeof(tmp))
|
|
||||||
(range, tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ditto
|
// Ditto
|
||||||
Range remove
|
Range remove
|
||||||
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
|
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
|
||||||
(Range range, Offset offset)
|
(Range range, Offset offset)
|
||||||
if ((isForwardRange!Range && !isBidirectionalRange!Range
|
if (s == SwapStrategy.stable && isForwardRange!Range && Offset.length >= 1)
|
||||||
|| !hasLength!Range || s == SwapStrategy.stable)
|
|
||||||
&& Offset.length >= 1)
|
|
||||||
{
|
{
|
||||||
auto result = range;
|
auto result = range;
|
||||||
auto src = range, tgt = range;
|
auto src = range, tgt = range;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
foreach (i; offset)
|
foreach (pass, i; offset)
|
||||||
{
|
{
|
||||||
static if (is(typeof(i[0])) && is(typeof(i[1])))
|
static if (is(typeof(i[0])) && is(typeof(i[1])))
|
||||||
{
|
{
|
||||||
|
@ -7342,10 +7294,19 @@ if ((isForwardRange!Range && !isBidirectionalRange!Range
|
||||||
enum delta = 1;
|
enum delta = 1;
|
||||||
}
|
}
|
||||||
assert(pos <= from);
|
assert(pos <= from);
|
||||||
|
if (pass > 0)
|
||||||
|
{
|
||||||
for (; pos < from; ++pos, src.popFront(), tgt.popFront())
|
for (; pos < from; ++pos, src.popFront(), tgt.popFront())
|
||||||
{
|
{
|
||||||
move(src.front, tgt.front);
|
move(src.front, tgt.front);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src.popFrontN(from);
|
||||||
|
tgt.popFrontN(from);
|
||||||
|
pos = from;
|
||||||
|
}
|
||||||
// now skip source to the "to" position
|
// now skip source to the "to" position
|
||||||
src.popFrontN(delta);
|
src.popFrontN(delta);
|
||||||
pos += delta;
|
pos += delta;
|
||||||
|
@ -7373,6 +7334,10 @@ unittest
|
||||||
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
||||||
assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
|
assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
|
||||||
[ 8, 1, 2, 3, 4, 5, 6, 7 ]);
|
[ 8, 1, 2, 3, 4, 5, 6, 7 ]);
|
||||||
|
// http://d.puremagic.com/issues/show_bug.cgi?id=5224
|
||||||
|
a = [ 1, 2, 3, 4 ];
|
||||||
|
assert(remove!(SwapStrategy.unstable)(a, 2) ==
|
||||||
|
[ 1, 2, 4 ]);
|
||||||
|
|
||||||
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
|
||||||
//writeln(remove!(SwapStrategy.stable)(a, 1, 5));
|
//writeln(remove!(SwapStrategy.stable)(a, 1, 5));
|
||||||
|
@ -7415,7 +7380,7 @@ if (isBidirectionalRange!Range)
|
||||||
{
|
{
|
||||||
for (;!range.empty;)
|
for (;!range.empty;)
|
||||||
{
|
{
|
||||||
if (!unaryFun!(pred)(range.front))
|
if (!unaryFun!pred(range.front))
|
||||||
{
|
{
|
||||||
range.popFront();
|
range.popFront();
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue