Coding a recursive function for highest possible input

5

2

Challenge

You are given the following function:- enter image description here which is the same as:-

enter image description here

with the base cases q(r, b, L) = 1 whenever r ≤ L, q(r, 0, L) = 0, if r > L and q(r, 0, L) = 1, if r ≤ L.

Your task is to code a program that takes r as input, and outputs the value of q(r, r - L, L) for all L taking integer values from 1 to (r-1), where r is any nonnegative integer.

Example 1

Input

Enter the value of r: 2

Output

q(2,1,1) = 0.3333333333

Example 2

Input

Enter the value of r: 3

Output

q(3,2,1) = 0.1

q(3,1,2) = 0.5

Winning criterion

The code that can correctly output q(r, r-L, L) for all L taking integer values from 1 to (r-1), for the highest value of r, in less than 300 seconds. In case of a tie, the code with lesser runtime will be considered. As this is a runtime-based challenge, I shall test all submissions on my machine.

Train Heartnet

Posted 2014-12-07T14:28:11.360

Reputation: 153

1Your sum/product notations both use the letter k as their variable. I think this is technically valid, but it might be easier to read if you used two different letters. – stokastic – 2014-12-07T19:03:19.423

@stokastic: Edited, thanks. – Train Heartnet – 2014-12-07T19:19:39.293

2Which of the two base cases takes priority when r < L and b = 0? And what value of b will be used in the winning criterion? – Peter Taylor – 2014-12-07T23:21:46.980

@PeterTaylor: Thanks for pointing this out. The first case (r ≤ L) takes priority. Edited accordingly. Also, the highest input value of b for which the code produces a correct output in less than 300 seconds, will be used. – Train Heartnet – 2014-12-08T04:00:44.507

1@PeterTaylor let me guess: are you working on a closed-form? – Soham Chowdhury – 2014-12-08T07:42:00.657

That doesn't really answer my second question. The current statement of the winning criterion says that it's the highest value of r with tie-breaking on the highest value of b, but since the program always takes both values it doesn't make any sense to talk about the highest value of r unless you define a function from the input value of r in the non-tiebreak case to the value of b. In other words, you need to specify a sequence of (r, b) pairs for the winning criterion to make any sense. – Peter Taylor – 2014-12-08T08:10:23.650

I'm sorry, but I don't understand what you're trying to say. Why doesn't it make sense to talk about the highest value of r? To compare two submissions, first the highest values of r that can be evaluated by both the codes are looked at, regardless of the value of b. In the case of a tie-breaker, the highest value of b that can be evaluated by both codes, for that tied value of r, is looked at. Could you provide an example in terms of two submissions to show how this current winning criterion breaks down? – Train Heartnet – 2014-12-08T08:52:25.337

One way of looking at it is that the recursion is in b as well as r, so for every r there will be a different b for which a submission can meet the time constraint. If that function from r to b has different asymptotics for two submissions, they're incomparable. Another way is that if we take b = 0, the limit on how far a submission can go is I/O-bound; if we take b = 1000, it's CPU-bound. – Peter Taylor – 2014-12-08T09:28:18.367

Oh, I think I somewhat understand the problem now. I can't think of a way to get around it though. Do you have suggestions for an alternate winning criterion? – Train Heartnet – 2014-12-08T09:44:07.377

I presume you came across the function in some context which gives you more intuition for how it should behave than I have, but the easiest fix would be to say the highest value of x such that input r=x, b=x completes within the time constraint. – Peter Taylor – 2014-12-08T09:48:02.477

Yes, I do know the context behind the function, but sadly, it doesn't give me much insight into how the function behaves, other than the fact that the number of recursions increases quite rapidly with increasing values of r and b. It's one of the reasons I started this challenge; to see if others could come up with better, possibly less recursive approaches to understand this function. – Train Heartnet – 2014-12-08T10:14:58.207

That fix sounds good enough. Let's go with it. – Train Heartnet – 2014-12-08T10:16:04.307

1

@JobinIdiculla One problem with using r = b is that the values tend towards 1 very quickly: http://codepad.org/RT33DjpB

– primo – 2014-12-08T10:54:20.080

@primo: Thank you, working on a fix. – Train Heartnet – 2014-12-08T11:09:49.647

@primo: Could you run your code for r = 50, b = 22 please? – Train Heartnet – 2014-12-08T11:35:06.127

@JobinIdiculla slightly more interesting values: http://codepad.org/2IWYwqSj Although I think something like b = r-L might be better: http://codepad.org/5ZbrN1ai

– primo – 2014-12-08T11:44:24.820

@primo: Hmm, I see. Could you try the code for r = 50 and b = 25 as well, please? It's just that my code isn't efficient enough, for values beyond r = 24. – Train Heartnet – 2014-12-08T11:53:06.550

@JobinIdiculla Also including r = 100; b = 50: http://codepad.org/QWb9v2uz

– primo – 2014-12-08T11:58:36.810

@primo: Thank you! I think your idea of b = r - L works much better. I think it'll be better to go with that. :) – Train Heartnet – 2014-12-08T12:58:32.523

Though this would mean the challenge statement would change (r becomes the only input). Is it alright if I change the challenge statement, given that other coders might already be working on the original statement? – Train Heartnet – 2014-12-08T13:05:26.237

@JobinIdiculla I don't think it would be a problem, because it only affects the input, rather than the function definition. It does affect the winning criterion, but they're aren't any submissions yet anyway. – primo – 2014-12-08T13:58:49.153

@primo: I see. It's done. – Train Heartnet – 2014-12-08T14:12:44.007

3q(r, r-1, 1) == 2(r!)^2/(2r)! (http://oeis.org/A001700) and r(r, 1, r-1) == (r-1)/(r+1) (trivial). Haven't checked the others yet. – kennytm – 2014-12-08T17:23:16.023

3In the interests of clarity, q(r,r-1,1) is the reciprocal of A001700. – Peter Taylor – 2014-12-10T10:12:20.037

Answers

7

Java

I've applied some algebraic transformation and dynamic programming.

public class CodeGolf42234 {
    public static void main(String[] args) {
        int r = Integer.parseInt(args[0]);
        for (int L = 1; L < r; L++) System.out.println(qDouble5(r, r-L, L));
    }

    private static double qDouble5(int _r, int _b, int L) {
        double[][] q = new double[_r+1][_b+1];
        for (int r = 0; r <= L; r++) {
            for (int b = 0; b < q[r].length; b++) q[r][b] = 1;
        }
        for (int r = L + 1; r < q.length; r++) {
            for (int b = 1 + (r - L - 1)/L; b < q[r].length; b++) {
                double sum = 0, m = 1;
                for (int k = 0; k <= L; k++) {
                    sum += m * q[r-k][b-1];
                    m = m * (r - k) / (r + b - 1 - k);
                }
                q[r][b] = sum * b / (r + b);
            }
        }
        return q[_r][_b];
    }
}

Peter Taylor

Posted 2014-12-07T14:28:11.360

Reputation: 41 901

Thank you for the submission. On my system (Windows, Netbeans IDE), the highest value of r that can be evaluated using this code, in under 300 seconds (297 seconds) is 731. Good job, Peter! :) – Train Heartnet – 2014-12-10T10:36:42.120

1

Java

Here's a recursive solution. Just like you wanted. You can always uncomment the output and display it if you want.

import java.util.ArrayList;
import java.util.Scanner;


public class HeaderFinder
{
static ArrayList<Double> answers = new ArrayList<Double>();
public static void main(String[]args)
{
    Scanner scanner = new Scanner(System.in);
    int r = scanner.nextInt();
    for(int b=r-1; b!=0; b--)
        for(int L=r-1; L!=0; L--)
            answers.add(formulate(r,b,L));

//  int i=-1;
//      for(int b=r-1; b!=0; b--)
//          for(int L=r-1; L!=0; L--)
//              System.out.println("q("+r+", "+b+", "+L+") = "+answers.get(++i));

}

public static double formulate(double r, double b, double L)
{
    if(b==0)
        if(r>L)
            return 0.0;
        else
            return 1;
    if(r<=L)
        return 1;
    double partone = (b/(r+b));
    double result = 0.0;
    for(int k=1; k<=L; k++)
    {
        result+=summation(r, b, k) * (b/(r+b-k)) * formulate(r-k, b-1, L);
    }
    return (partone * formulate(r, b-1, L)) + result;
}

public static double summation(double r, double b, int k)
{
    double rb = r+b;
    double mul=r/rb;
    for(int i=1; i<k; i++)
    {
        mul*=(r-i)/(rb-i);
    }
    return mul;
}
}

Luminous

Posted 2014-12-07T14:28:11.360

Reputation: 309