An interview question: About Probability

前端 未结 10 1461
清酒与你
清酒与你 2021-01-29 21:14

An interview question:

Given a function f(x) that 1/4 times returns 0, 3/4 times returns 1. Write a function g(x) using f(x) that 1/2 times returns 0, 1/2 times returns

相关标签:
10条回答
  • 2021-01-29 21:51

    The problem with your algorithm is that it repeats itself with high probability. My code:

    function g(x) = {
        var s = f(x) + f(x) + f(x); 
        // s = 0, probability:  1/64
        // s = 1, probability:  9/64
        // s = 2, probability: 27/64
        // s = 3, probability: 27/64
        if (s == 2) return 0;
        if (s == 3) return 1;
    
        return g(x); // probability to go into recursion = 10/64, with only 1 additional f(x) calculation
    }
    

    I've measured average number of times f(x) was calculated for your algorithm and for mine. For yours f(x) was calculated around 5.3 times per one g(x) calculation. With my algorithm this number reduced to around 3.5. The same is true for other answers so far since they are actually the same algorithm as you said.

    P.S.: your definition doesn't mention 'random' at the moment, but probably it is assumed. See my other answer.

    0 讨论(0)
  • 2021-01-29 21:52

    This is much like the Monty Hall paradox.

    In general.

    Public Class Form1
    
        'the general case
        '
        'twiceThis = 2 is 1 in four chance of 0
        'twiceThis = 3 is 1 in six chance of 0
        '
        'twiceThis = x is 1 in 2x chance of 0
    
        Const twiceThis As Integer = 7
        Const numOf As Integer = twiceThis * 2
    
        Private Sub Button1_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) Handles Button1.Click
    
            Const tries As Integer = 1000
            y = New List(Of Integer)
    
            Dim ct0 As Integer = 0
            Dim ct1 As Integer = 0
            Debug.WriteLine("")
            ''show all possible values of fx
            'For x As Integer = 1 To numOf
            '    Debug.WriteLine(fx)
            'Next
    
            'test that gx returns 50% 0's and 50% 1's
            Dim stpw As New Stopwatch
            stpw.Start()
            For x As Integer = 1 To tries
                Dim g_x As Integer = gx()
                'Debug.WriteLine(g_x.ToString) 'used to verify that gx returns 0 or 1 randomly
                If g_x = 0 Then ct0 += 1 Else ct1 += 1
            Next
            stpw.Stop()
            'the results
            Debug.WriteLine((ct0 / tries).ToString("p1"))
            Debug.WriteLine((ct1 / tries).ToString("p1"))
            Debug.WriteLine((stpw.ElapsedTicks / tries).ToString("n0"))
    
        End Sub
    
        Dim prng As New Random
        Dim y As New List(Of Integer)
    
        Private Function fx() As Integer
    
            '1 in numOf chance of zero being returned
            If y.Count = 0 Then
                'reload y
                y.Add(0) 'fx has only one zero value
                Do
                    y.Add(1) 'the rest are ones
                Loop While y.Count < numOf
            End If
            'return a random value 
            Dim idx As Integer = prng.Next(y.Count)
            Dim rv As Integer = y(idx)
            y.RemoveAt(idx) 'remove the value selected
            Return rv
    
        End Function
    
        Private Function gx() As Integer
    
            'a function g(x) using f(x) that 50% of the time returns 0
            '                           that 50% of the time returns 1
            Dim rv As Integer = 0
            For x As Integer = 1 To twiceThis
                fx()
            Next
            For x As Integer = 1 To twiceThis
                rv += fx()
            Next
            If rv = twiceThis Then Return 1 Else Return 0
    
        End Function
    End Class
    
    0 讨论(0)
  • 2021-01-29 21:54

    Assuming

    P(f[x] == 0) = 1/4
    P(f[x] == 1) = 3/4
    

    and requiring a function g[x] with the following assumptions

    P(g[x] == 0) = 1/2
    P(g[x] == 1) = 1/2
    

    I believe the following definition of g[x] is sufficient (Mathematica)

    g[x_] := If[f[x] + f[x + 1] == 1, 1, 0]
    

    or, alternatively in C

    int g(int x)
    {
        return f(x) + f(x+1) == 1
               ? 1
               : 0;
    }
    

    This is based on the idea that invocations of {f[x], f[x+1]} would produce the following outcomes

    {
      {0, 0},
      {0, 1},
      {1, 0},
      {1, 1}
    }
    

    Summing each of the outcomes we have

    {
      0,
      1,
      1,
      2
    }
    

    where a sum of 1 represents 1/2 of the possible sum outcomes, with any other sum making up the other 1/2.

    Edit. As bdk says - {0,0} is less likely than {1,1} because

    1/4 * 1/4 < 3/4 * 3/4
    

    However, I am confused myself because given the following definition for f[x] (Mathematica)

    f[x_] := Mod[x, 4] > 0 /. {False -> 0, True -> 1}
    

    or alternatively in C

    int f(int x)
    {
        return (x % 4) > 0
               ? 1
               : 0;
    }
    

    then the results obtained from executing f[x] and g[x] seem to have the expected distribution.

    Table[f[x], {x, 0, 20}]
    {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}
    
    Table[g[x], {x, 0, 20}]
    {1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}
    
    0 讨论(0)
  • 2021-01-29 21:55

    If you call f(x) twice in a row, the following outcomes are possible (assuming that successive calls to f(x) are independent, identically distributed trials):

    00 (probability 1/4 * 1/4)
    01 (probability 1/4 * 3/4)  
    10 (probability 3/4 * 1/4)  
    11 (probability 3/4 * 3/4)
    

    01 and 10 occur with equal probability. So iterate until you get one of those cases, then return 0 or 1 appropriately:

    do
      a=f(x); b=f(x);
    while (a == b);
    
    return a;
    

    It might be tempting to call f(x) only once per iteration and keep track of the two most recent values, but that won't work. Suppose the very first roll is 1, with probability 3/4. You'd loop until the first 0, then return 1 (with probability 3/4).

    0 讨论(0)
提交回复
热议问题