#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <vector>
#include <algorithm>
namespace
{
class SomeBigObj
{
private:
double m_fVal;
public:
SomeBigObj() : m_fVal(0.0) { }
SomeBigObj(const double x) : m_fVal(x) { }
bool operator<(const SomeBigObj& rhs) const { return (m_fVal < rhs.m_fVal); }
double get() const { return m_fVal; }
};
} // namespace
const SomeBigObj srcArr[] = {
3.1, 4.1, 5.9, 2.6, 5.3, 5.8, 9.7, 9.3, 2.3, 8.4, 4.6, 2.6, 4.3, 3.8, 3.2, 7.9, 5.0, 2.8, 8.4, 1.9
};
/// 配列内容表示
void printarr(const std::vector<SomeBigObj>& arr, std::vector<int>& indices)
{
assert(arr.size() == indices.size());
const size_t arrsz = arr.size();
printf("arr[] : (");
for (size_t i = 0; i < arrsz; i++) {
printf(" %3.1f", arr[indices[i]].get());
}
printf(" )\n");
printf("idx[] : (");
for (size_t i = 0; i < arrsz; i++) {
printf(" %3d", indices[i]);
}
printf(" )\n");
}
/// lower_bound結果検証
bool chk_lb(const std::vector<SomeBigObj>& arr, std::vector<int>& indices, const SomeBigObj& x, const int lb)
{
assert(arr.size() == indices.size());
const size_t arrsz = arr.size();
assert(0 <= lb && (size_t)lb < arrsz);
for (size_t i = 0; i < (size_t)lb; i++) {
if (!(arr[indices[i]] < x)) {
printf("ERROR: Illegal LB (1) (i=%zu)\n", i);
return false;
}
}
for (size_t i = (size_t)lb; i < arrsz; i++) {
if (arr[indices[i]] < x) {
printf("ERROR: Illegal LB (2) (i=%zu)\n", i);
return false;
}
}
return true;
}
/// 間接ソート版lower_bound
int custom_lower_bound(const std::vector<SomeBigObj>& arr, std::vector<int>& indices, const SomeBigObj& x)
{
// SomeBigObjの間接ソート用比較関数
// xのコピーを避けるため[&](a, b)とする。
auto cmpFunc = [&](const int idx, const SomeBigObj& xx)->bool {
return arr[idx] < xx;
};
auto found_it = std::lower_bound(indices.begin(), indices.end(), x, cmpFunc);
// Indexに変換
return (int)std::distance(indices.begin(), found_it);
}
int main()
{
// 間接ソート対象データ作成
std::vector<SomeBigObj> arr;
{
const size_t sz = sizeof(srcArr) / sizeof(srcArr[0]);
for (size_t i = 0; i < sz; i++) {
arr.push_back(srcArr[i]);
}
}
const size_t arrsz = arr.size();
// 間接ソート用配列作成
std::vector<int> indices(arrsz);
for (size_t i = 0; i < arrsz; i++) {
indices[i] = i;
}
// 間接ソート
auto cmpFunc = [=](const int a, const int b)->bool { return (arr[a] < arr[b]); };
std::sort(indices.begin(), indices.end(), cmpFunc);
// 配列内容ダンプ
printarr(arr, indices);
// lower_boundテスト
bool bFailed = false;
for (double val = 0.0; val < 10.0; val += 1.0) {
// Lower bound取得
const SomeBigObj x(val);
const int lb = custom_lower_bound(arr, indices, x);
// 表示
printf("x=%.2f: lb=%d\n", x.get(), lb);
// チェック
if (!chk_lb(arr, indices, x, lb)) {
bFailed = true;
}
}
if (!bFailed) {
printf("OK\n");
}
else {
printf("NG\n");
}
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPGFzc2VydC5oPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgoKbmFtZXNwYWNlCnsKCWNsYXNzIFNvbWVCaWdPYmoKCXsKCXByaXZhdGU6CgkJZG91YmxlIG1fZlZhbDsKCXB1YmxpYzoKCQlTb21lQmlnT2JqKCkgOiBtX2ZWYWwoMC4wKSB7IH0KCQlTb21lQmlnT2JqKGNvbnN0IGRvdWJsZSB4KSA6IG1fZlZhbCh4KSB7IH0KCQlib29sIG9wZXJhdG9yPChjb25zdCBTb21lQmlnT2JqJiByaHMpIGNvbnN0IHsgcmV0dXJuIChtX2ZWYWwgPCByaHMubV9mVmFsKTsgfQoJCWRvdWJsZSBnZXQoKSBjb25zdCB7IHJldHVybiBtX2ZWYWw7IH0KCX07Cgp9ICAgLy8gbmFtZXNwYWNlCgpjb25zdCBTb21lQmlnT2JqIHNyY0FycltdID0gewoJMy4xLCA0LjEsIDUuOSwgMi42LCA1LjMsIDUuOCwgOS43LCA5LjMsIDIuMywgOC40LCA0LjYsIDIuNiwgNC4zLCAzLjgsIDMuMiwgNy45LCA1LjAsIDIuOCwgOC40LCAxLjkKfTsKCi8vLyDphY3liJflhoXlrrnooajnpLoKdm9pZCBwcmludGFycihjb25zdCBzdGQ6OnZlY3RvcjxTb21lQmlnT2JqPiYgYXJyLCBzdGQ6OnZlY3RvcjxpbnQ+JiBpbmRpY2VzKQp7Cglhc3NlcnQoYXJyLnNpemUoKSA9PSBpbmRpY2VzLnNpemUoKSk7CgoJY29uc3Qgc2l6ZV90IGFycnN6ID0gYXJyLnNpemUoKTsKCglwcmludGYoImFycltdIDogKCIpOwoJZm9yIChzaXplX3QgaSA9IDA7IGkgPCBhcnJzejsgaSsrKSB7CgkJcHJpbnRmKCIgJTMuMWYiLCBhcnJbaW5kaWNlc1tpXV0uZ2V0KCkpOwoJfQoJcHJpbnRmKCIgKVxuIik7CgoJcHJpbnRmKCJpZHhbXSA6ICgiKTsKCWZvciAoc2l6ZV90IGkgPSAwOyBpIDwgYXJyc3o7IGkrKykgewoJCXByaW50ZigiICUzZCIsIGluZGljZXNbaV0pOwoJfQoJcHJpbnRmKCIgKVxuIik7Cn0KCi8vLyBsb3dlcl9ib3VuZOe1kOaenOaknOiovApib29sIGNoa19sYihjb25zdCBzdGQ6OnZlY3RvcjxTb21lQmlnT2JqPiYgYXJyLCBzdGQ6OnZlY3RvcjxpbnQ+JiBpbmRpY2VzLCBjb25zdCBTb21lQmlnT2JqJiB4LCBjb25zdCBpbnQgbGIpCnsKCWFzc2VydChhcnIuc2l6ZSgpID09IGluZGljZXMuc2l6ZSgpKTsKCgljb25zdCBzaXplX3QgYXJyc3ogPSBhcnIuc2l6ZSgpOwoKCWFzc2VydCgwIDw9IGxiICYmIChzaXplX3QpbGIgPCBhcnJzeik7CgoJZm9yIChzaXplX3QgaSA9IDA7IGkgPCAoc2l6ZV90KWxiOyBpKyspIHsKCQlpZiAoIShhcnJbaW5kaWNlc1tpXV0gPCB4KSkgewoJCQlwcmludGYoIkVSUk9SOiBJbGxlZ2FsIExCICgxKSAoaT0lenUpXG4iLCBpKTsKCQkJcmV0dXJuIGZhbHNlOwoJCX0KCX0KCWZvciAoc2l6ZV90IGkgPSAoc2l6ZV90KWxiOyBpIDwgYXJyc3o7IGkrKykgewoJCWlmIChhcnJbaW5kaWNlc1tpXV0gPCB4KSB7CgkJCXByaW50ZigiRVJST1I6IElsbGVnYWwgTEIgKDIpIChpPSV6dSlcbiIsIGkpOwoJCQlyZXR1cm4gZmFsc2U7CgkJfQoJfQoKCXJldHVybiB0cnVlOwp9CgovLy8g6ZaT5o6l44K944O844OI54mIbG93ZXJfYm91bmQKaW50IGN1c3RvbV9sb3dlcl9ib3VuZChjb25zdCBzdGQ6OnZlY3RvcjxTb21lQmlnT2JqPiYgYXJyLCBzdGQ6OnZlY3RvcjxpbnQ+JiBpbmRpY2VzLCBjb25zdCBTb21lQmlnT2JqJiB4KQp7CgkvLyBTb21lQmlnT2Jq44Gu6ZaT5o6l44K944O844OI55So5q+U6LyD6Zai5pWwCgkvLyB444Gu44Kz44OU44O844KS6YG/44GR44KL44Gf44KBWyZdKGEsIGIp44Go44GZ44KL44CCCglhdXRvIGNtcEZ1bmMgPSBbJl0oY29uc3QgaW50IGlkeCwgY29uc3QgU29tZUJpZ09iaiYgeHgpLT5ib29sIHsKCQlyZXR1cm4gYXJyW2lkeF0gPCB4eDsKCQkKCX07CglhdXRvIGZvdW5kX2l0ID0gc3RkOjpsb3dlcl9ib3VuZChpbmRpY2VzLmJlZ2luKCksIGluZGljZXMuZW5kKCksIHgsIGNtcEZ1bmMpOwoJLy8gSW5kZXjjgavlpInmj5sKCXJldHVybiAoaW50KXN0ZDo6ZGlzdGFuY2UoaW5kaWNlcy5iZWdpbigpLCBmb3VuZF9pdCk7Cn0KCmludCBtYWluKCkKewoJLy8g6ZaT5o6l44K944O844OI5a++6LGh44OH44O844K/5L2c5oiQCglzdGQ6OnZlY3RvcjxTb21lQmlnT2JqPiBhcnI7Cgl7CgkJY29uc3Qgc2l6ZV90IHN6ID0gc2l6ZW9mKHNyY0FycikgLyBzaXplb2Yoc3JjQXJyWzBdKTsKCQlmb3IgKHNpemVfdCBpID0gMDsgaSA8IHN6OyBpKyspIHsKCQkJYXJyLnB1c2hfYmFjayhzcmNBcnJbaV0pOwoJCX0KCX0KCWNvbnN0IHNpemVfdCBhcnJzeiA9IGFyci5zaXplKCk7CgoJLy8g6ZaT5o6l44K944O844OI55So6YWN5YiX5L2c5oiQCglzdGQ6OnZlY3RvcjxpbnQ+IGluZGljZXMoYXJyc3opOwoJZm9yIChzaXplX3QgaSA9IDA7IGkgPCBhcnJzejsgaSsrKSB7CgkJaW5kaWNlc1tpXSA9IGk7Cgl9CgoJLy8g6ZaT5o6l44K944O844OICglhdXRvIGNtcEZ1bmMgPSBbPV0oY29uc3QgaW50IGEsIGNvbnN0IGludCBiKS0+Ym9vbCB7IHJldHVybiAoYXJyW2FdIDwgYXJyW2JdKTsgfTsKCXN0ZDo6c29ydChpbmRpY2VzLmJlZ2luKCksIGluZGljZXMuZW5kKCksIGNtcEZ1bmMpOwoKCS8vIOmFjeWIl+WGheWuueODgOODs+ODlwoJcHJpbnRhcnIoYXJyLCBpbmRpY2VzKTsKCgkvLyBsb3dlcl9ib3VuZOODhuOCueODiAoJYm9vbCBiRmFpbGVkID0gZmFsc2U7Cglmb3IgKGRvdWJsZSB2YWwgPSAwLjA7IHZhbCA8IDEwLjA7IHZhbCArPSAxLjApIHsKCQkvLyBMb3dlciBib3VuZOWPluW+lwoJCWNvbnN0IFNvbWVCaWdPYmogeCh2YWwpOwoJCWNvbnN0IGludCBsYiA9IGN1c3RvbV9sb3dlcl9ib3VuZChhcnIsIGluZGljZXMsIHgpOwoJCS8vIOihqOekugoJCXByaW50ZigieD0lLjJmOiBsYj0lZFxuIiwgeC5nZXQoKSwgbGIpOwoJCS8vIOODgeOCp+ODg+OCrwoJCWlmICghY2hrX2xiKGFyciwgaW5kaWNlcywgeCwgbGIpKSB7CgkJCWJGYWlsZWQgPSB0cnVlOwoJCX0KCX0KCWlmICghYkZhaWxlZCkgewoJCXByaW50ZigiT0tcbiIpOwoJfQoJZWxzZSB7CgkJcHJpbnRmKCJOR1xuIik7Cgl9Cn0K