확률을 정확하게 계산


9

이 작업은 확률을 정확하게 계산하기위한 코드 작성에 관한 것입니다. 결과는 가장 축소 된 형태로 분수로 쓰여진 정확한 확률이어야합니다. 즉, 출력 4/8하지 말고 오히려 출력하십시오 1/2.

양의 정수의 경우 n, 길이가 1과 -1 인 균일하게 임의의 문자열을 고려하여 nA라고 부릅니다. 이제 A첫 번째 값으로 연결 합니다. 즉 A[1] = A[n+1](1)에서 색인 경우 A지금 길이 n+1. 이제 n첫 번째 n값이 각각 1 / 4,1 / 2, 1/4 인 -1, 0 또는 1 인 길이 의 두 번째 임의 문자열을 고려하여 B라고 부릅니다.

예를 들어을 고려하십시오 n=3. 가능한 값 ABA = [-1,1,1,-1]B=[0,1,-1]. 이 경우 두 개의 내부 제품은 02입니다.

지금의 내적 생각 A[1,...,n]B와의 내적을 A[2,...,n+1]하고 B.

코드는 두 내부 제품이 모두 0 일 확률을 출력해야합니다.

의 경우 n=1이 확률 분명하다 1/2.

n코드에 지정된 방법 은 신경 쓰지 않지만 변경하는 방법 은 매우 간단하고 분명해야합니다.

언어와 라이브러리

원하는 언어와 라이브러리를 사용할 수 있습니다. 코드를 실행하고 싶습니다. 가능한 경우 리눅스에서 코드를 실행 / 컴파일하는 방법에 대한 자세한 설명을 포함하십시오.


2
처음 몇 개의 테스트 사례 n가 도움이 될 것입니다. 또한 A, B 및 두 가지 내부 제품의 명시 적 예가 도움이 될 수 있습니다.
Martin Ender 2016 년

정수를 하 코딩하기로 선택하면 n=40, 2 또는 3 바이트로 계산됩니까? 출력해야합니까 정확히 a/b 또는 것 [a b], 예, 허용?
Dennis

@ 데니스 그것은 정확해야합니다. 정수를 하드 코딩하면 변경하기 위해 한 곳에서만 변경하면 n됩니까? 그렇지 않으면 허용되지 않는다고 생각합니다.

예, 내 프로그램은 정수를 한 번만 사용하여 데카르트 힘을 계산합니다. 다른 모든 것은 결과 배열에서 파생됩니다.
Dennis

답변:


7

Pyth, 48 47 46 44 바이트

K,smlf!|Fms*Vd.>Tk2^,1_1Q^+0tM3Q^8Qj\//RiFKK

온라인으로 사용해보십시오 : 데모

온라인 버전은 아마 계산하지 않습니다 n=6. 내 랩탑 (오프라인 버전)에서 약 45 초가 걸립니다.

무차별 대입 접근.

설명:

smlf!|Fms*Vd.>Tk2^,1_1Q^+0tM3Q   implicit: Q = input number
                          tM3    the list [-1, 0, 1]
                        +0       add zero, results in [0, -1, 0, 1]
                       ^     Q   all possible lists of length Q using these elements
 m                               map each list d (B in Lembik's notation) to:
                  ,1_1              the list [1, -1]
                 ^    Q             all possible lists of length Q
   f                                filter for lists T (A in Lembik's notation),
                                    which satisfy:
       m        2                      map each k in [0, 1] to:
        s*Vd.>Tk                          scalar-product d*(shifted T by k)
    !|F                                not or (True if both scalar-products are 0)      
  l                                 determine the length                
s                                add all possibilities at the end

K,...^8QQj\//RiFKK   
 ,...^8Q             the list [result of above, 8^Q]
K                    store it in K
              iFK    determine the gcd of the numbers in K
            /R   K   divide the numbers in K by the gcd
         j\/         join the two numbers by "/" and print

dang, gcd를 잊어 버렸습니다. 내가 놓친 것이 있다는 것을 알았습니다
Maltysen

+0r1_2보다 짧습니다 /R2r2_2.
isaacg 2016 년

나는 그것이 당신이 세는 89/512 버전이어야한다고 공평하다고 생각합니다.

@Lembik Ok 변경했습니다.
Jakube

나는 47 자로 할 수있는 일이 결코 일어나지 않았다는 것을 인정해야합니다!

8

매쓰, 159 100 87 86 85 바이트

n=3;1-Mean@Sign[##&@@Norm/@({1,0,0,-1}~t~n.Partition[#,2,1,1])&/@{1,-1}~(t=Tuples)~n]

변경하려면 n처음에 변수 정의를 변경하십시오.

그것은 무차별 적 인 힘이므로 상당히 느리지 만 처음 8 가지 결과는 다음과 같습니다.

n   P(n)
1   1/2
2   3/8
3   7/32
4   89/512
5   269/2048
6   903/8192
7   3035/32768
8   169801/2097152

마지막 것은 이미 231 초가 걸렸으며 런타임은 엄청나게 지수 적입니다.

설명

내가 말했듯이 그것은 무차별적인 힘입니다. 기본적으로, 난 그냥 모든 가능한을 열거하고있어 A하고 B, 가능한 모든 쌍에 대한 두 개의 내적을 계산하고 산출하는 것이 쌍 분율을 찾을 {0, 0}. Mathematica의 조합 및 선형 대수 함수는 골프를 치는 데 매우 도움이되었습니다.

{1,-1}~(t=Tuples)~n

이 포함 된 모든 N-튜플을 생성 1하거나 -1, 모든 가능한 즉 A. 내용은 n = 3즉 :

{{1, 1, 1}, 
 {1, 1, -1}, 
 {1, -1, 1}, 
 {1, -1, -1}, 
 {-1, 1, 1}, 
 {-1, 1, -1}, 
 {-1, -1, 1}, 
 {-1, -1, -1}}

계산하기 위해 B우리는 거의 동일하게 수행합니다.

{1,0,0,-1}~t~n

반복함으로써 0, 우리는 포함 된 각각의 튜플을 복제 0함으로써 또는 0가능성의 두 배 를 만든다 . 다시 예제로 사용 :1-1n = 3

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

이제, 각각의 수에 대한 A, 우리는 가능한 그 각각의 내적 원하는 B, 모두 A[1 .. n]A[2 .. n+1]. 현재이 경우 예는 A있다 {1, 1, -1}, 우리는 모두 내적 원하는 {1, 1, -1}과에를 {1, -1, 1}. 우리 모두 B는 이미 편리한 행렬의 행 이기 때문에 두 행렬의 하위 목록 A을 다른 행렬의 열로 원하므로 그 사이에 간단한 내적을 계산할 수 있습니다. 그러나 조옮김은 {{1, 1, -1}, {1, -1, 1}}단순히 {{1, 1}, {1, -1}, {-1, 1}}2 개의 모든 순환 하위 목록의 목록을 제공합니다 A. 이것이하는 일입니다.

Partition[#,2,1,1]

그래서 우리는 그것을 계산하고 우리의 목록과 함께 내적을 취합니다 B. 우리는 이제 중첩 목록을 얻습니다 (가능한 각 A벡터가 별도의 벡터를 생성하기 때문에 ) ##&@@.

쌍인지 알아 내기 위해 우리 {x, y}는 어디서 제공 {0, 0}하는지 계산 합니다 . 이것은 또는을 제공합니다 .Sign[Norm[{x,y}]]Norm√(x²+y²)01

마지막으로, s와 s의 1목록에서 0s 의 분수를 알고 싶기 때문에 목록의 1산술 평균 만 있으면됩니다. 그러나 이것은 적어도 하나의 내적이 0이 아닌 확률을 산출하므로 1원하는 결과를 얻기 위해 빼기합니다 .


6

Pyth- 65 55 바이트

1 바이트 비용으로 분수가 줄어드는 버그를 수정했습니다.

무차별 대입 방식을 사용하고 엄청나게 골프를 칠 수 있지만 무언가를 얻으려고했습니다. 아주 느린

*F-KP/Jmms*Vked,thdPhd*makhk^,1_1Q^[1ZZ_1)Q,ZZ2/lJ^2/K2

Cartesian 제품을 사용하여 A와를 모두 생성 하고 소스 목록에 두 번 표시 B하여 가변 확률을 수행 0한 다음 내부 제품을 0으로 계산합니다. Vectorization syntactic sugar로 내부 제품을 쉽게 만들 수 있습니다 . 분수를 단순화하는 것이 처음에는 두려웠지만 P림 인수 분해 기능과 2의 거듭 제곱으로 만 줄여야한다는 실현 으로 꽤 쉬웠습니다 .

여기에서 온라인으로 사용해보십시오 .


어떻게 바꾸 n나요?

@Lembik Pyth 프로그램은 두 번째 텍스트 상자에 지정된 사용자 입력을 요청합니다 (온라인 컴파일러를 사용하는 경우).
Jakube

@Jakube 아 감사합니다! 그리고 그것은 실제로 작동하는 것 같습니다 :)

6

CJam, 58 57 54 51 46 바이트

WX]m*Zm*_{~.+2,@fm<\f.*::+0-!},,__~)&:T/'/@,T/

실행하려면 WX]및 사이에 원하는 정수를 삽입하십시오 m*.

비트 매직과 5 바이트 골프를위한 @ jimmy23013 덕분에!

CJam 통역사 에서 온라인으로 사용해보십시오 .

생각

이 답변의 대부분은 간단하지만 두 가지 깔끔한 트릭을 사용합니다.

  • {-1, 1} n의 모든 벡터를 원하는 확률과 {-1, 0, 1} n 의 모든 벡터와 쌍을 이루는 대신 , {-1, 1} n 에서 만족하는 벡터의 삼중 수를 계산합니다. 특정 조건.

    삼중 항의 마지막 두 벡터를 더하면 결과는 {-2, 0, 2} n 의 벡터가 됩니다.

    사람 (-1) = 0 + 1 = 1 + (-1) , 0 의 두 배나 자주 발생되므로 -2 (S) 및 2 (S).

    각 성분을 2로 나누면 원하는 확률 로 {-1, 0, 1} n 의 벡터가 생성 됩니다.

    스칼라 곱이 0 인지 아닌지에 대해서만 관심이 있으므로 나누기를 2로 건너 뛸 수 있습니다 .

  • 질문의 조건과 총 삼중 항 수를 만족시키는 모든 삼중 항을 세고 나면 결과 부분을 줄여야합니다.

    두 숫자의 GCD를 계산하는 대신 분모는 항상 2의 거듭 제곱이므로 두 숫자를 분자를 나누는 2의 최대 거듭 제곱으로 나눌 수 있습니다.

    x 를 나누는 2의 최고 거듭 제곱을 얻기 위해 x~ x + 1 의 비트 AND를 취할 수 있습니다 .

    ~ xx의 모든 비트를 반대로 하므로 모든 후행 01이 됩니다. 추가하여 일을~ X , 그 의가 다시 켜집니다 0 의 마지막 1~ X + 1 마지막 일치 1X .

    다른 모든 비트는 모두 0 의 고유하므로 비트 AND 는 x 의 마지막 1 과 그 뒤에 오는 모든 0 으로 구성된 정수를 반환 합니다. 이것은 x 를 나누는 2의 최대 제곱입니다 .

암호

WX]    e# Push the array [-1 1].
       e# Insert N here.
m*     e# Cartesian product: Push the array of all vectors of {-1,1}^N.
Zm*    e# Cartesian product: Push the array of all triplets of these vectors.
_      e# Copy the array.
{      e# Filter; for each triplet of vectors U, V and W in {-1,1}^N:
  ~    e#   Dump U, V and W on the stack.
  .+   e#   Compute X := V + W, a vector of {-2,0,2}^N, where each component is
       e#   zero with probability 1/2.
  2,@  e#   Push [0 1]. Rotate U on top of it.
  fm<  e#   Push [U U'], where U' is U rotated one dimension to the left.
  \f.* e#   Push [U*X and U'*X], where * denotes the vectorized product.
  ::+  e#   Add the components of both products.
  0-   e#   Remove zeroes.
       e#   Push the logical NOT of the array.
},     e#   If the array was empty, keep the triplet.
,      e# Push X, the length of the filtered array.
__~)&  e# Push X & ~X + 1.
:T     e# Save the result in T and divide X by T.
'/     e# Push a slash.
@,T/   e# Dividet he length of the unfiltered array by T.

WX]m*Zm*_{~.+2,@fm<\f.*::+0-!},,__W*&:T/'/@,T/.
jimmy23013

@ jimmy23013 : 그것은 약간의 인상적인 비트 마법입니다. 감사!
Dennis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.