mirror of
https://github.com/dlang/phobos.git
synced 2025-05-13 15:52:41 +03:00
fix issue 155421
This commit is contained in:
parent
e93695e902
commit
682536d586
3 changed files with 121 additions and 4 deletions
|
@ -3384,17 +3384,20 @@ auto topN(alias less = "a < b",
|
|||
SwapStrategy ss = SwapStrategy.unstable,
|
||||
Range1, Range2)(Range1 r1, Range2 r2)
|
||||
if (isRandomAccessRange!(Range1) && hasLength!Range1 &&
|
||||
isInputRange!Range2 && is(ElementType!Range1 == ElementType!Range2))
|
||||
isInputRange!Range2 && is(ElementType!Range1 == ElementType!Range2) &&
|
||||
hasLvalueElements!Range1 && hasLvalueElements!Range2)
|
||||
{
|
||||
import std.container : BinaryHeap;
|
||||
|
||||
static assert(ss == SwapStrategy.unstable,
|
||||
"Stable topN not yet implemented");
|
||||
|
||||
auto heap = BinaryHeap!(Range1, less)(r1);
|
||||
for (; !r2.empty; r2.popFront())
|
||||
foreach (ref e; r2)
|
||||
{
|
||||
heap.conditionalInsert(r2.front);
|
||||
heap.conditionalSwap(e);
|
||||
}
|
||||
|
||||
return r1;
|
||||
}
|
||||
|
||||
|
@ -3408,6 +3411,69 @@ unittest
|
|||
assert(a == [0, 1, 2, 2, 3]);
|
||||
}
|
||||
|
||||
// bug 15421
|
||||
unittest
|
||||
{
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.internal.test.dummyrange;
|
||||
import std.meta : AliasSeq;
|
||||
|
||||
alias RandomRanges = AliasSeq!(
|
||||
DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random)
|
||||
);
|
||||
|
||||
alias ReferenceRanges = AliasSeq!(
|
||||
DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Forward),
|
||||
DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Bidirectional),
|
||||
DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random),
|
||||
DummyRange!(ReturnBy.Reference, Length.No, RangeType.Forward),
|
||||
DummyRange!(ReturnBy.Reference, Length.No, RangeType.Bidirectional));
|
||||
|
||||
foreach (T1; RandomRanges)
|
||||
{
|
||||
foreach (T2; ReferenceRanges)
|
||||
{
|
||||
import std.array;
|
||||
|
||||
T1 A;
|
||||
T2 B;
|
||||
|
||||
A.reinit();
|
||||
B.reinit();
|
||||
|
||||
topN(A, B);
|
||||
|
||||
// BUG(?): sort doesn't accept DummyRanges (needs Slicing and Length)
|
||||
auto a = array(A);
|
||||
auto b = array(B);
|
||||
sort(a);
|
||||
sort(b);
|
||||
|
||||
assert(equal(a, [ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 ]));
|
||||
assert(equal(b, [ 6, 6, 7, 7, 8, 8, 9, 9, 10, 10 ]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bug 15421
|
||||
unittest
|
||||
{
|
||||
auto a = [ 9, 8, 0, 3, 5, 25, 43, 4, 2, 0, 7 ];
|
||||
auto b = [ 9, 8, 0, 3, 5, 25, 43, 4, 2, 0, 7 ];
|
||||
|
||||
topN(a, 4);
|
||||
topN(b[0 .. 4], b[4 .. $]);
|
||||
|
||||
sort(a[0 .. 4]);
|
||||
sort(a[4 .. $]);
|
||||
sort(b[0 .. 4]);
|
||||
sort(b[4 .. $]);
|
||||
|
||||
assert(a[0 .. 4] == b[0 .. 4]);
|
||||
assert(a[4 .. $] == b[4 .. $]);
|
||||
assert(a == b);
|
||||
}
|
||||
|
||||
// bug 12987
|
||||
unittest
|
||||
{
|
||||
|
|
|
@ -369,14 +369,37 @@ must be collected.
|
|||
insert(value);
|
||||
return true;
|
||||
}
|
||||
// must replace the top
|
||||
|
||||
assert(!_store.empty, "Cannot replace front of an empty heap.");
|
||||
if (!comp(value, _store.front)) return false; // value >= largest
|
||||
_store.front = value;
|
||||
|
||||
percolate(_store[], 0, _length);
|
||||
debug(BinaryHeap) assertValid();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Swapping is allowed if the heap is full. If $(D less(value, front)), the
|
||||
method exchanges store.front and value and returns $(D true). Otherwise, it
|
||||
leaves the heap unaffected and returns $(D false).
|
||||
*/
|
||||
bool conditionalSwap(ref ElementType!Store value)
|
||||
{
|
||||
_payload.refCountedStore.ensureInitialized();
|
||||
assert(_length == _store.length);
|
||||
assert(!_store.empty, "Cannot swap front of an empty heap.");
|
||||
|
||||
if (!comp(value, _store.front)) return false; // value >= largest
|
||||
|
||||
import std.algorithm.mutation : swap;
|
||||
swap(_store.front, value);
|
||||
|
||||
percolate(_store[], 0, _length);
|
||||
debug(BinaryHeap) assertValid();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Example from "Introduction to Algorithms" Cormen et al, p 146
|
||||
|
@ -409,6 +432,7 @@ initialized with $(D s) and $(D initialSize).
|
|||
BinaryHeap!(Store, less) heapify(alias less = "a < b", Store)(Store s,
|
||||
size_t initialSize = size_t.max)
|
||||
{
|
||||
|
||||
return BinaryHeap!(Store, less)(s, initialSize);
|
||||
}
|
||||
|
||||
|
@ -537,3 +561,25 @@ unittest
|
|||
h.dup();
|
||||
}));
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
import std.internal.test.dummyrange;
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
alias RefRange = DummyRange!(ReturnBy.Reference, Length.Yes, RangeType.Random);
|
||||
|
||||
RefRange a;
|
||||
RefRange b;
|
||||
a.reinit();
|
||||
b.reinit();
|
||||
|
||||
auto heap = heapify(a);
|
||||
foreach (ref elem; b)
|
||||
{
|
||||
heap.conditionalSwap(elem);
|
||||
}
|
||||
|
||||
assert(equal(heap, [ 5, 5, 4, 4, 3, 3, 2, 2, 1, 1]));
|
||||
assert(equal(b, [10, 9, 8, 7, 6, 6, 7, 8, 9, 10]));
|
||||
}
|
||||
|
|
|
@ -169,6 +169,11 @@ struct DummyRange(ReturnBy _r, Length _l, RangeType _rt, T = uint[])
|
|||
ret.arr = arr[lower..upper];
|
||||
return ret;
|
||||
}
|
||||
|
||||
typeof(this) opSlice()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
static if (l == Length.Yes)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue