#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
// The resulting vector contains at index i the sum of 2^-j for j in [i+1, N]
// and is padded with one 0 to get the same length as `v`
static std::vector<double> partialSums(std::vector<double> const& v) {
std::vector<double> result;
// When summing doubles, we need to start with the smaller ones
// because of the precision of representations...
double sum = 0;
for (std::vector<double>::const_reverse_iterator it = v.rbegin(), end = v.rend(); it != end; ++it)
{
sum += *it;
result.push_back(sum);
}
result.pop_back(); // there is a +1 offset in the indexes of the result
std::reverse(result.begin(), result.end());
result.push_back(0); // pad the vector to have the same length as `v`
return result;
}
// The resulting vector contains the indexes elected
static std::vector<size_t> getIndexesImpl(std::vector<double> const& v,
std::vector<double> const& ps,
double r)
{
std::vector<size_t> indexes;
for (size_t i = 0, max = v.size(); i != max; ++i) {
if (r >= v[i]) {
std::cout << ".." << r << ">=" << v[i] << "\n";
r -= v[i];
indexes.push_back(i);
continue;
}
// We favor the closest to 0 in case of equality
if (std::fabs(r - v[i]) < std::fabs(r - ps[i])) {
std::cout << ".." << v[i] - r << " < " << r - ps[i] << "\n";
indexes.push_back(i);
return indexes;
}
}
return indexes;
}
std::vector<size_t> getIndexes(std::vector<double>& v, double r) {
std::vector<double> const ps = partialSums(v);
return getIndexesImpl(v, ps, r);
}
void printIndexes(std::vector<double>& v, double r) {
std::vector<size_t> indexes = getIndexes(v, r);
std::cout << r << ":\n";
for (size_t i = 0, max = indexes.size(); i != max; ++i) {
std::cout << " " << indexes[i] << ": " << v[indexes[i]] << "\n";
}
std::reverse(indexes.begin(), indexes.end());
double sum = 0;
for (size_t i = 0, max = indexes.size(); i != max; ++i) {
sum += v[indexes[i]];
}
std::cout << "=> " << sum << "\n";
}
int main() {
std::vector<double> v;
v.push_back(1.0/2);
v.push_back(1.0/4);
v.push_back(1.0/8);
v.push_back(1.0/16);
v.push_back(1.0/32);
printIndexes(v, 0.3);
printIndexes(v, 0.25665238);
}
ICAgICNpbmNsdWRlIDxjbWF0aD4KCiAgICAjaW5jbHVkZSA8YWxnb3JpdGhtPgogICAgI2luY2x1ZGUgPGlvc3RyZWFtPgogICAgI2luY2x1ZGUgPHZlY3Rvcj4KCiAgICAvLyBUaGUgcmVzdWx0aW5nIHZlY3RvciBjb250YWlucyBhdCBpbmRleCBpIHRoZSBzdW0gb2YgMl4taiBmb3IgaiBpbiBbaSsxLCBOXQogICAgLy8gYW5kIGlzIHBhZGRlZCB3aXRoIG9uZSAwIHRvIGdldCB0aGUgc2FtZSBsZW5ndGggYXMgYHZgCiAgICBzdGF0aWMgc3RkOjp2ZWN0b3I8ZG91YmxlPiBwYXJ0aWFsU3VtcyhzdGQ6OnZlY3Rvcjxkb3VibGU+IGNvbnN0JiB2KSB7CiAgICAgICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiByZXN1bHQ7CgogICAgICAgIC8vIFdoZW4gc3VtbWluZyBkb3VibGVzLCB3ZSBuZWVkIHRvIHN0YXJ0IHdpdGggdGhlIHNtYWxsZXIgb25lcwogICAgICAgIC8vIGJlY2F1c2Ugb2YgdGhlIHByZWNpc2lvbiBvZiByZXByZXNlbnRhdGlvbnMuLi4KCiAgICAgICAgZG91YmxlIHN1bSA9IDA7CiAgICAgICAgZm9yIChzdGQ6OnZlY3Rvcjxkb3VibGU+Ojpjb25zdF9yZXZlcnNlX2l0ZXJhdG9yIGl0ID0gdi5yYmVnaW4oKSwgZW5kID0gdi5yZW5kKCk7IGl0ICE9IGVuZDsgKytpdCkKICAgICAgICB7CiAgICAgICAgICAgIHN1bSArPSAqaXQ7CiAgICAgICAgICAgIHJlc3VsdC5wdXNoX2JhY2soc3VtKTsKICAgICAgICB9CgogICAgICAgIHJlc3VsdC5wb3BfYmFjaygpOyAvLyB0aGVyZSBpcyBhICsxIG9mZnNldCBpbiB0aGUgaW5kZXhlcyBvZiB0aGUgcmVzdWx0CgogICAgICAgIHN0ZDo6cmV2ZXJzZShyZXN1bHQuYmVnaW4oKSwgcmVzdWx0LmVuZCgpKTsKCiAgICAgICAgcmVzdWx0LnB1c2hfYmFjaygwKTsgLy8gcGFkIHRoZSB2ZWN0b3IgdG8gaGF2ZSB0aGUgc2FtZSBsZW5ndGggYXMgYHZgCgogICAgICAgIHJldHVybiByZXN1bHQ7ICAgCiAgICB9CgogICAgLy8gVGhlIHJlc3VsdGluZyB2ZWN0b3IgY29udGFpbnMgdGhlIGluZGV4ZXMgZWxlY3RlZAogICAgc3RhdGljIHN0ZDo6dmVjdG9yPHNpemVfdD4gZ2V0SW5kZXhlc0ltcGwoc3RkOjp2ZWN0b3I8ZG91YmxlPiBjb25zdCYgdiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZDo6dmVjdG9yPGRvdWJsZT4gY29uc3QmIHBzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG91YmxlIHIpCiAgICB7CiAgICAgIHN0ZDo6dmVjdG9yPHNpemVfdD4gaW5kZXhlczsKCiAgICAgIGZvciAoc2l6ZV90IGkgPSAwLCBtYXggPSB2LnNpemUoKTsgaSAhPSBtYXg7ICsraSkgewogICAgICAgICAgaWYgKHIgPj0gdltpXSkgewogICAgICAgICAgICAgIHN0ZDo6Y291dCA8PCAiLi4iIDw8IHIgPDwgIj49IiA8PCB2W2ldIDw8ICJcbiI7CiAgICAgICAgICAgICAgciAtPSB2W2ldOwogICAgICAgICAgICAgIGluZGV4ZXMucHVzaF9iYWNrKGkpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIFdlIGZhdm9yIHRoZSBjbG9zZXN0IHRvIDAgaW4gY2FzZSBvZiBlcXVhbGl0eQogICAgICAgICAgaWYgKHN0ZDo6ZmFicyhyIC0gdltpXSkgPCBzdGQ6OmZhYnMociAtIHBzW2ldKSkgewogICAgICAgICAgICAgIHN0ZDo6Y291dCA8PCAiLi4iIDw8IHZbaV0gLSByIDw8ICIgPCAiIDw8IHIgLSBwc1tpXSA8PCAiXG4iOwogICAgICAgICAgICAgIGluZGV4ZXMucHVzaF9iYWNrKGkpOwogICAgICAgICAgICAgIHJldHVybiBpbmRleGVzOwogICAgICAgICAgfQogICAgICB9CgogICAgICByZXR1cm4gaW5kZXhlczsKICAgIH0KCiAgICBzdGQ6OnZlY3RvcjxzaXplX3Q+IGdldEluZGV4ZXMoc3RkOjp2ZWN0b3I8ZG91YmxlPiYgdiwgZG91YmxlIHIpIHsKICAgICAgICBzdGQ6OnZlY3Rvcjxkb3VibGU+IGNvbnN0IHBzID0gcGFydGlhbFN1bXModik7CiAgICAgICAgcmV0dXJuIGdldEluZGV4ZXNJbXBsKHYsIHBzLCByKTsKICAgIH0KCiAgICB2b2lkIHByaW50SW5kZXhlcyhzdGQ6OnZlY3Rvcjxkb3VibGU+JiB2LCBkb3VibGUgcikgewogICAgICAgIHN0ZDo6dmVjdG9yPHNpemVfdD4gaW5kZXhlcyA9IGdldEluZGV4ZXModiwgcik7CiAgICAgICAgc3RkOjpjb3V0IDw8IHIgPDwgIjpcbiI7CiAgICAgICAgZm9yIChzaXplX3QgaSA9IDAsIG1heCA9IGluZGV4ZXMuc2l6ZSgpOyBpICE9IG1heDsgKytpKSB7CiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCAiICAgIiA8PCBpbmRleGVzW2ldIDw8ICI6ICIgPDwgdltpbmRleGVzW2ldXSA8PCAiXG4iOwogICAgICAgIH0KCiAgICAgICAgc3RkOjpyZXZlcnNlKGluZGV4ZXMuYmVnaW4oKSwgaW5kZXhlcy5lbmQoKSk7CiAgICAgICAgZG91YmxlIHN1bSA9IDA7CiAgICAgICAgZm9yIChzaXplX3QgaSA9IDAsIG1heCA9IGluZGV4ZXMuc2l6ZSgpOyBpICE9IG1heDsgKytpKSB7CiAgICAgICAgICAgIHN1bSArPSB2W2luZGV4ZXNbaV1dOwogICAgICAgIH0KICAgICAgICBzdGQ6OmNvdXQgPDwgIj0+ICIgPDwgc3VtIDw8ICJcbiI7CiAgICB9CgogICAgaW50IG1haW4oKSB7CiAgICAgICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiB2OwogICAgICAgIHYucHVzaF9iYWNrKDEuMC8yKTsKICAgICAgICB2LnB1c2hfYmFjaygxLjAvNCk7CiAgICAgICAgdi5wdXNoX2JhY2soMS4wLzgpOwogICAgICAgIHYucHVzaF9iYWNrKDEuMC8xNik7CiAgICAgICAgdi5wdXNoX2JhY2soMS4wLzMyKTsKCiAgICAgICAgcHJpbnRJbmRleGVzKHYsIDAuMyk7CiAgICAgICAgcHJpbnRJbmRleGVzKHYsIDAuMjU2NjUyMzgpOwogICAgfQ==