1

this is in regards to the problem Sherlock And Counting. https://www.hackerrank.com/challenges/sherlock-and-counting

I've used diffchecker to compare thousands of results that my code has produced vs the results that I've bought using my hackos. They are the same! My code is returning faulty in spite of my results being the same as the results bought using the hackos.

I've removed the diffchecker link because it's too large and freezes the tab but I've tested the first 2000 results and my results are the same as the results bought using the hackos. Simply put, I cannot understand why Hackerrank does not accept my code? You can try inputting this code and noticing that you do indeed get the same results as the test cases (bought using the hackos) but somehow it doesn't accept it?

import java.io.*;
import java.util.*;
import java.math.*;

public class Solution {

    public static void main(String[] args) {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT.
        Your class should be named Solution. */
        Scanner in = new Scanner(System.in);
        int testcases = in.nextInt();
        /* Each individual test case */
        for(int index = 0; index < testcases; ++index)
        {
            long N = in.nextLong();
            long K = in.nextLong();
            /* Notice that we require i < N and i to be a positive integer.
            This is impossible if N == 1. Therefore, a simple test solves
            a big issue. */
            if(N <= 1){
                System.out.println(0);
            }
            /* Test if discriminant is negative. If it is, the number of
            integers is N - 1 because every number fits under the graph. */
            else if(N*N - 4*N*K < 0) 
            {
                System.out.println(N - 1);
            }
            /* Notice if the discriminant is zero, then necessarily
            N = 4 * K. In an alternate form, the quadratic will be
            written as i^2 - Ni + N^2/4, also recognized as (i - N/2)^2.
            Therefore, the answer is N - 2. */
            else if (N*N - 4*N*K == 0)
            {
                System.out.println(N - 1);
            }
            /* Test if discriminant is positive. If it is, the number of
            integers depends on the locus of solutions. */
            else if(N*N - 4*N*K > 0)
            {
                long solnOne = (long) (N + Math.sqrt(N*N - 4*N*K))/2;
                long solnTwo = (long) (N - Math.sqrt(N*N - 4*N*K))/2;
                if(solnOne > solnTwo){
                    long temp = solnOne;
                    solnOne = solnTwo;
                    solnTwo = temp;
                }
                long LeftBound = (long) solnOne;
                long RightBound = (long) solnTwo + 1;

                /* Now there may be possibilities such that the left solution
                is less than one and/or the right solution is greater than or equal
                to the bound. We must account for these possibilities. */

                /* Here, both bounds are unacceptable. Therefore, there is no
                solution. */
                if(LeftBound < 1 && RightBound >= N)
                {
                    System.out.println(0);
                }
                /* Here, only the right bound is acceptable. */
                else if(LeftBound < 1)
                {
                    System.out.println(N - RightBound);
                }
                /* Here, only the left bound is acceptable. */
                else if(RightBound >= N)
                {
                    System.out.println(LeftBound);
                }
                /* Both bounds are allowed! */
                else
                {
                    System.out.println(N - RightBound + LeftBound);
                }
            }
        }

    }
}

1 Answers1

0

Try N=9, K=2. Your answer is 5.
Valid values are i = [1, 2, 3, 6, 7, 8], so real answer is 6.

First, your solnOne is always >= solnTwo. Flip them and your if(solnOne > solnTwo) will never be true.

Second, the cast to long truncates the values. That is why you do solnTwo + 1, but when solnTwo is exactly equals to 6, the + 1 will miss that as a valid value. Also, you cast to long before dividing by 2. Oops!

Instead, don't cast to long:

double solnOne = (N - Math.sqrt(N*N - 4*N*K))/2;
double solnTwo = (N + Math.sqrt(N*N - 4*N*K))/2;
long LeftBound = (long) Math.floor(solnOne);
long RightBound = (long) Math.ceil(solnTwo);

Also, since HackerRank may time you out, performance matters, so to help JIT, calculate N*N - 4*N*K only once and store in a variable. Same for Math.sqrt(N*N - 4*N*K), since sqrt() is relatively slow.

For your own testing, you should move everything, starting from if(N <= 1){, into a static long calc(long N, long K) method. Then you could write unit tests against it.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • You're correct. For the `rightBound` I did not check that it could actually intersect with the x-axis. –  Jun 04 '16 at 06:56
  • I did everything you suggested and now I do get 6 for my answer. However, my test cases still fail. Do I post a new snippet in this comment, do I update the OP's code content, or do I replace the OP's code content? –  Jun 04 '16 at 07:16
  • @MathApprentice *You* are the OP (Original Poster) of the question. I am the OP of *this* answer. So you see, your comment is a bit weird. ;-) If my answer helped you, you should click the up-arrow (tooltip: This answer is useful). If my answer solved your problem, you should simply accept it by click the checkmark, thereby showing others that your question has been answered to your satisfaction. If you have a clarification to the question, edit it. If you have a different question, create a new one. If you don't think this question will benefit others, just delete it. – Andreas Jun 04 '16 at 07:23
  • I can't upvote yet, but when I acquire enough reputation points (15), I will upvote this answer. –  Jun 04 '16 at 07:25
  • @MathApprentice You should be able to accept, though, assuming you want to, of course. – Andreas Jun 04 '16 at 07:28
  • We need to find something more precise than the `Math.sqrt` function. –  Jun 04 '16 at 23:44
  • @MathApprentice See [Square root of BigDecimal in Java](http://stackoverflow.com/a/19743026/5221149). – Andreas Jun 05 '16 at 00:02
  • What are some tests I should try? –  Jun 05 '16 at 02:21
  • I just noticed that I was trying to add my discriminant, a double, to a long. That's not going to work out. –  Jun 05 '16 at 02:27
  • sorry bro, but being indirect wont help you. –  Aug 17 '16 at 09:04