xiaowuc1's blog

By xiaowuc1, 18 months ago, In English

I was motivated to write this blog post after reading this blog post about possible precision issues in output and requiring printing a rounded answer exactly instead of printing an answer within a tolerance. This blog post feels somewhat related insofar as that it has an issue with floating point numbers, and also a doubt as to the correctness of the underlying data. Alternatively, someone can find the mistake in my logic.

The problem in question is Rationalization which asks to find a positive rational $$$\frac{A}{B}$$$ that is within a range $$$[C-F, C+F]$$$. Among all such fractions, minimize $$$A$$$, and among all such with minimal $$$A$$$, minimize $$$B$$$. The judge data guarantee that $$$1 \le A, B < 10^6$$$.

My solution path is as follows: If $$$C-F \le \frac{A}{B} \le C+F$$$, then $$$B(C-F) \le A \le B(C+F)$$$. Therefore, we can just check all $$$B$$$ in increasing order and find the smallest $$$B$$$ where $$$[B(C-F), B(C+F)]$$$ contains some integer, and the smallest such integer should be our $$$A$$$.

Now, $$$C$$$ and $$$F$$$ are floating-point numbers, so in order to make sure that we can represent $$$C-F$$$ and $$$C+F$$$ exactly, we scale them up by powers of 10 until they are exactly integers. Fortunately, we're guaranteed that these numbers are written in decimal form.

Some poorly written Python code

This gets 60 points on Kattis with a WA verdict on the final subtask, so it does print something which is deemed incorrect (as opposed to printing nothing or printing a value of $$$A$$$ that is too large and getting RTE). Since the solution does pass the first two subtasks, I am reasonably confident that it is not completely wrong. I presume that the second subtask is meant to admit solutions that have precision issues by representing values using floating point values (perhaps by scaling each of the floating point values directly by $$$B$$$), though I haven't bothered to experiment much there.

I do have a weak prior that some Kattis problems with floating point numbers do something incorrect — for example, for this problem, all reference solutions say that three points are collinear if and only if the turn would be at most $$$10^{-9}$$$ degrees, as opposed to checking collinearity exactly.

Because of this prior, I'd like to identify the test case to see where I went wrong. Sadly, I can't find the input data for this problem, so I'm stuck trying to find a bug in my solution/logic or conclude the test data are wrong. I'd just like to ask the author for test case 77 to verify it by hand. In the interim, I might be able to get the test case in a few hours if I can find a way to AC the first 76 cases and differentiate that I'm in test case 77. (Kattis only allows 10 submissions within a 10 minute window.)

Alternatively, did I go wrong somewhere?

Update 1: Test case 77 has c = 7.80212 and f = 0.0000000684. I wrote a slow program that seems to generate the same output as what my program prints.

More Python code

This fraction is not equal to either of $$$C-F$$$ and $$$C+F$$$.

Update 2: jeroenodb was able to AC the problem and with his solution we were able to prove that the test data are indeed incorrect. I have contacted Kattis to try to get this rectified.

  • Vote: I like it
  • +108
  • Vote: I do not like it

»
18 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

My solution, based on continued fractions also gets WA on test 77:

Code

And it also gives $$$\frac{133229}{17076}$$$ on your test case, so something seems weird...

UPD: I also tried few other solutions, including basically brute force. Still WA77 with the same output. Looks like an error in test data?

»
18 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Paging esr6vqa.

»
18 months ago, # |
Rev. 2   Vote: I like it +55 Vote: I do not like it

I got accepted with this very bad, float code with an epsilon of $$$10^{-9}$$$, but only on the left edge of the interval. Possibly the author did something similar, so this is recreating the same bug.

#include "bits/stdc++.h"
using namespace std;
const int oo = 1e9;
int main() {
    double c,f; cin >> c >> f;
    pair<int,int> ans = {oo,oo};
    for(int b=1;b<int(1e6);++b) {
        auto lo = max(c-f-1e-9,0.);
        double a = llround(ceil(lo*b));
        if(a==0) a=1;
        if(a/b<=(c+f)) {
            ans=min(ans,{a,b});
        }
    }
    cout << ans.first << '\n' << ans.second << '\n';
}

On this test

7.80212 0.0000000684

It prints:

131021 16793

  • »
    »
    18 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Thanks! It would seem that this is the only test case among the judge data that is incorrect (my Python code gets AC if I patch exactly that test case).

»
18 months ago, # |
  Vote: I like it +11 Vote: I do not like it

The Kattis problem Dice and Ladders seems to have the same issue. This code, which is based on one of the original contest's official solutions, passes:

Спойлер

However, increasing the precision by changing T to long double causes it to WA on test case 16/17.

  • »
    »
    18 months ago, # ^ |
      Vote: I like it +8 Vote: I do not like it

    I also contacted Kattis about this in February of 2022. However, it does not seem to have been fixed.

»
18 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Thanks for making this blog post! I had previously made a blog post asking for help on this question and unfortunately it went nowhere.

»
18 months ago, # |
  Vote: I like it +50 Vote: I do not like it

Hello! Thanks for this post!

You are indeed correct that there is an error with the testdata.

While implementing the solution to this problem we accidentally used an error margin in the solution. As only one programmer wrote judge solutions to this problem, the error margin was the same in all of them, which caused the test case to have a wrong answer.

None of us checking the problem caught this issue, and it was only found during the Doris competition in which it was originally used.

The issue was promptly fixed in the Github repository. But we did not mention it to Kattis, as we thought they would reinstall from the repository when adding it to open.kattis.com, an error from our part.

We later noticed it having an unusually high difficulty rating, and that that the old problem was used, and have since contacted Kattis hoping to have it corrected.

The extra error margin is 10^-9, that is, add 10^-9 to F to have the correct solution.

We are sorry for the inconvenience, and will make sure to have multiple different people write solutions as well as to be more clear with Kattis when these errors happen in the future.