class Smooth {
public static void main
(String[] args
) { testar(0.05, 10, 40, 50, 20, 35);
testar(0.34, 22, 18);
testar(0.25, 260, 350, 430, 280, 640, 650, 240, 430, 320, 585, 385, 450, 760, 690, 400);
testar(null, 128, 180, 96, 108, 130, 150, 165, 139, 140, 165, 290, 190, 210, 240, 235);
testar(null, 36, 48, 26, 31, 57, 42, 26, 23, 18, 25, 18, 36, 41, 18, 22);
}
private static void testar
(Double a,
double...
d) { System.
out.
println("Valores: " + java.
util.
Arrays.
toString(d
)); if (a != null) {
double r = smooth(a, d);
System.
out.
println("Taxa: " + a
+ " - resultado: " + r
); double b = smoothRatio(r, d);
System.
out.
println("Taxa (prova real): " + b
); }
double p = bestSmooth(d);
System.
out.
println("Melhor taxa: " + p
+ " - resultado: " + smooth
(p, d
)); }
public static double smooth(double a, double... d) {
double soma = 0.0;
double potencia = 1.0;
for (int i = d.length - 1; i >= 0; i--) {
soma += a * potencia * d[i];
potencia *= 1.0 - a;
}
return soma;
}
public static double bestSmooth(double... d) {
double v1 = 0.0;
double v5 = 1.0;
while (true) {
double v3 = (v1 + v5) / 2;
if (v3 == v1 || v3 == v5) return v3;
double s1 = smooth(v1, d);
double s3 = smooth(v3, d);
double s5 = smooth(v5, d);
if (s5 >= s3 && s5 >= s1) {
v1 = v3;
} else if (s1 >= s3 && s1 >= s5) {
v5 = v3;
} else {
double v2 = (v1 + v3) / 2;
double v4 = (v3 + v5) / 2;
double s2 = smooth(v2, d);
double s4 = smooth(v4, d);
if (s4 >= s3 && s4 >= s5) {
v1 = v3;
v3 = v4;
} else if (s2 >= s3 && s2 >= s1) {
v5 = v3;
v3 = v2;
} else if (s3 >= s2 && s3 >= s4) {
v1 = v2;
v5 = v4;
}
}
}
}
private static boolean ordered(double a, double b, double c) {
return (a <= b && b <= c) || (c <= b && b <= a);
}
public static double smoothRatio(double total, double... d) {
double minA = 0.0;
double maxA = bestSmooth(d);
double smoothMin = smooth(minA, d);
double smoothMax = smooth(maxA, d);
if (!ordered(smoothMin, total, smoothMax)) {
}
while (true) {
if (total == smoothMin) return minA;
if (total == smoothMax) return maxA;
double mid = minA + (maxA - minA) / 2;
if (mid == minA) return smoothMin;
if (mid == maxA) return smoothMax;
double smoothMid = smooth(mid, d);
if (ordered(smoothMid, total, smoothMax)) {
minA = mid;
smoothMin = smoothMid;
} else if (ordered(smoothMid, total, smoothMin)) {
maxA = mid;
smoothMax = smoothMid;
}
}
}
}
Y2xhc3MgU21vb3RoIHsKICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKICAgICAgICB0ZXN0YXIoMC4wNSwgMTAsIDQwLCA1MCwgMjAsIDM1KTsKICAgICAgICB0ZXN0YXIoMC4zNCwgMjIsIDE4KTsKICAgICAgICB0ZXN0YXIoMC4yNSwgMjYwLCAzNTAsIDQzMCwgMjgwLCA2NDAsIDY1MCwgMjQwLCA0MzAsIDMyMCwgNTg1LCAzODUsIDQ1MCwgNzYwLCA2OTAsIDQwMCk7CiAgICAgICAgdGVzdGFyKG51bGwsIDEyOCwgMTgwLCA5NiwgMTA4LCAxMzAsIDE1MCwgMTY1LCAxMzksIDE0MCwgMTY1LCAyOTAsIDE5MCwgMjEwLCAyNDAsIDIzNSk7CiAgICAgICAgdGVzdGFyKG51bGwsIDM2LCA0OCwgMjYsIDMxLCA1NywgNDIsIDI2LCAyMywgMTgsIDI1LCAxOCwgMzYsIDQxLCAxOCwgMjIpOwogICAgfQoKICAgIHByaXZhdGUgc3RhdGljIHZvaWQgdGVzdGFyKERvdWJsZSBhLCBkb3VibGUuLi4gZCkgewogICAgCVN5c3RlbS5vdXQucHJpbnRsbigiVmFsb3JlczogIiArIGphdmEudXRpbC5BcnJheXMudG9TdHJpbmcoZCkpOwogICAgCWlmIChhICE9IG51bGwpIHsKICAgICAgICAgICAgZG91YmxlIHIgPSBzbW9vdGgoYSwgZCk7CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiVGF4YTogIiArIGEgKyAiIC0gcmVzdWx0YWRvOiAiICsgcik7CiAgICAgICAgICAgIGRvdWJsZSBiID0gc21vb3RoUmF0aW8ociwgZCk7CiAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiVGF4YSAocHJvdmEgcmVhbCk6ICIgKyBiKTsKICAgIAl9CiAgICAgICAgZG91YmxlIHAgPSBiZXN0U21vb3RoKGQpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiTWVsaG9yIHRheGE6ICIgKyBwICsgIiAtIHJlc3VsdGFkbzogIiArIHNtb290aChwLCBkKSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCk7CiAgICB9CgogICAgcHVibGljIHN0YXRpYyBkb3VibGUgc21vb3RoKGRvdWJsZSBhLCBkb3VibGUuLi4gZCkgewogICAgICAgIGRvdWJsZSBzb21hID0gMC4wOwogICAgICAgIGRvdWJsZSBwb3RlbmNpYSA9IDEuMDsKICAgICAgICBmb3IgKGludCBpID0gZC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgICAgICBzb21hICs9IGEgKiBwb3RlbmNpYSAqIGRbaV07CiAgICAgICAgICAgIHBvdGVuY2lhICo9IDEuMCAtIGE7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzb21hOwogICAgfQoKICAgIHB1YmxpYyBzdGF0aWMgZG91YmxlIGJlc3RTbW9vdGgoZG91YmxlLi4uIGQpIHsKICAgICAgICBkb3VibGUgdjEgPSAwLjA7CiAgICAgICAgZG91YmxlIHY1ID0gMS4wOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIGRvdWJsZSB2MyA9ICh2MSArIHY1KSAvIDI7CiAgICAgICAgICAgIGlmICh2MyA9PSB2MSB8fCB2MyA9PSB2NSkgcmV0dXJuIHYzOwogICAgICAgICAgICBkb3VibGUgczEgPSBzbW9vdGgodjEsIGQpOwogICAgICAgICAgICBkb3VibGUgczMgPSBzbW9vdGgodjMsIGQpOwogICAgICAgICAgICBkb3VibGUgczUgPSBzbW9vdGgodjUsIGQpOwogICAgICAgICAgICBpZiAoczUgPj0gczMgJiYgczUgPj0gczEpIHsKICAgICAgICAgICAgICAgIHYxID0gdjM7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoczEgPj0gczMgJiYgczEgPj0gczUpIHsKICAgICAgICAgICAgICAgIHY1ID0gdjM7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBkb3VibGUgdjIgPSAodjEgKyB2MykgLyAyOwogICAgICAgICAgICAgICAgZG91YmxlIHY0ID0gKHYzICsgdjUpIC8gMjsKICAgICAgICAgICAgICAgIGRvdWJsZSBzMiA9IHNtb290aCh2MiwgZCk7CiAgICAgICAgICAgICAgICBkb3VibGUgczQgPSBzbW9vdGgodjQsIGQpOwogICAgICAgICAgICAgICAgaWYgKHM0ID49IHMzICYmIHM0ID49IHM1KSB7CiAgICAgICAgICAgICAgICAgICAgdjEgPSB2MzsKICAgICAgICAgICAgICAgICAgICB2MyA9IHY0OwogICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzMiA+PSBzMyAmJiBzMiA+PSBzMSkgewogICAgICAgICAgICAgICAgICAgIHY1ID0gdjM7CiAgICAgICAgICAgICAgICAgICAgdjMgPSB2MjsKICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoczMgPj0gczIgJiYgczMgPj0gczQpIHsKICAgICAgICAgICAgICAgICAgICB2MSA9IHYyOwogICAgICAgICAgICAgICAgICAgIHY1ID0gdjQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBvcmRlcmVkKGRvdWJsZSBhLCBkb3VibGUgYiwgZG91YmxlIGMpIHsKICAgICAgICByZXR1cm4gKGEgPD0gYiAmJiBiIDw9IGMpIHx8IChjIDw9IGIgJiYgYiA8PSBhKTsKICAgIH0KCiAgICBwdWJsaWMgc3RhdGljIGRvdWJsZSBzbW9vdGhSYXRpbyhkb3VibGUgdG90YWwsIGRvdWJsZS4uLiBkKSB7CiAgICAgICAgZG91YmxlIG1pbkEgPSAwLjA7CiAgICAgICAgZG91YmxlIG1heEEgPSBiZXN0U21vb3RoKGQpOwogICAgICAgIGRvdWJsZSBzbW9vdGhNaW4gPSBzbW9vdGgobWluQSwgZCk7CiAgICAgICAgZG91YmxlIHNtb290aE1heCA9IHNtb290aChtYXhBLCBkKTsKICAgICAgICBpZiAoIW9yZGVyZWQoc21vb3RoTWluLCB0b3RhbCwgc21vb3RoTWF4KSkgewogICAgICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKHRvdGFsICsgIiAiICsgc21vb3RoTWluICsgIiAiICsgc21vb3RoTWF4ICsgIiAiICsgbWluQSArICIgIiArIG1heEEpOwogICAgICAgIH0KCiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgaWYgKHRvdGFsID09IHNtb290aE1pbikgcmV0dXJuIG1pbkE7CiAgICAgICAgICAgIGlmICh0b3RhbCA9PSBzbW9vdGhNYXgpIHJldHVybiBtYXhBOwogICAgICAgICAgICBkb3VibGUgbWlkID0gbWluQSArIChtYXhBIC0gbWluQSkgLyAyOwogICAgICAgICAgICBpZiAobWlkID09IG1pbkEpIHJldHVybiBzbW9vdGhNaW47CiAgICAgICAgICAgIGlmIChtaWQgPT0gbWF4QSkgcmV0dXJuIHNtb290aE1heDsKICAgICAgICAgICAgZG91YmxlIHNtb290aE1pZCA9IHNtb290aChtaWQsIGQpOwogICAgICAgICAgICBpZiAob3JkZXJlZChzbW9vdGhNaWQsIHRvdGFsLCBzbW9vdGhNYXgpKSB7CiAgICAgICAgICAgICAgICBtaW5BID0gbWlkOwogICAgICAgICAgICAgICAgc21vb3RoTWluID0gc21vb3RoTWlkOwogICAgICAgICAgICB9IGVsc2UgaWYgKG9yZGVyZWQoc21vb3RoTWlkLCB0b3RhbCwgc21vb3RoTWluKSkgewogICAgICAgICAgICAgICAgbWF4QSA9IG1pZDsKICAgICAgICAgICAgICAgIHNtb290aE1heCA9IHNtb290aE1pZDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQ==
Valores: [10.0, 40.0, 50.0, 20.0, 35.0]
Taxa: 0.05 - resultado: 7.078253125000002
Taxa (prova real): 0.05
Melhor taxa: 1.0 - resultado: 35.0
Valores: [22.0, 18.0]
Taxa: 0.34 - resultado: 11.056799999999999
Taxa (prova real): 0.33999999999999997
Melhor taxa: 0.9090909212827682 - resultado: 18.18181818181818
Valores: [260.0, 350.0, 430.0, 280.0, 640.0, 650.0, 240.0, 430.0, 320.0, 585.0, 385.0, 450.0, 760.0, 690.0, 400.0]
Taxa: 0.25 - resultado: 514.275442045182
Taxa (prova real): 0.24999999999999967
Melhor taxa: 0.3844731971623787 - resultado: 529.8357007856109
Valores: [128.0, 180.0, 96.0, 108.0, 130.0, 150.0, 165.0, 139.0, 140.0, 165.0, 290.0, 190.0, 210.0, 240.0, 235.0]
Melhor taxa: 0.9200836578384042 - resultado: 235.20144008802336
Valores: [36.0, 48.0, 26.0, 31.0, 57.0, 42.0, 26.0, 23.0, 18.0, 25.0, 18.0, 36.0, 41.0, 18.0, 22.0]
Melhor taxa: 0.21615071594715118 - resultado: 26.222890515272397