Ймовірність усіх комбінацій даних подій


18

Враховуючи послідовність подій з ймовірністю від 0,0 до 1,0, генеруйте та виводите ймовірність виникнення кожної комбінації. Ви можете припустити, що послідовність чисел надається будь-якою конструкцією, яку надає обрана вами мова.

Ось приклад; Ви можете припустити, що довжина комбінацій послідовностей вписується в пам'ять:

{ 0.55, 0.67, 0.13 }

Програма друкує кожну комбінацію та пов'язану з цим ймовірність виникнення цієї послідовності. A 1 позначає, що подія в цьому індексі вхідної послідовності сталася, а 0 позначає, що ця подія не сталася. Бажаний вихід нижче (мені не важливо друкувати твір, це лише в інформаційних цілях алгоритму):

[0,0,0] = (1 - 0.55) * (1-0.67) * (1-0.13) = 0.129195
[0,0,1] = (1 - 0.55) * (1-0.67) * (0.13)   = 0.019305
[0,1,0] = (1 - 0.55) * (0.67)   * (1-0.13) = 0.262305
[0,1,1] = (1 - 0.55) * (0.67)   * (0.13)   = 0.039195
[1,0,0] = (0.55)     * (1-0.67) * (1-0.13) = 0.157905
[1,0,1] = (0.55)     * (1-0.67) * (0.13)   = 0.023595
[1,1,0] = (0.55)     * (0.67)   * (1-0.13) = 0.320595
[1,1,1] = (0.55)     * (0.67)   * (0.13)   = 0.047905

Ця проблема дотично пов'язана з розрахунком "декартового продукту".

Пам'ятайте, що це код-гольф, тому код з найменшою кількістю байтів виграє.


3
Ласкаво просимо до програмування головоломок та коду для гольфу та приємного першого виклику!
Дверна ручка

Було [0.129195, 0.019305, 0.262305, ..., 0.047905]б достатньо як вихід або [0,0,0], [0,0,1], ...необхідні?
Лайконі

@Laikoni Це результат добре. Вихідна частина не є проблемою.
Марк Джонсон

Чи може бути вихід у зворотному порядку?
Луїс Мендо

@LuisMendo Звичайно, чому б ні.
Марк Джонсон

Відповіді:


8

Haskell, 86 байт

unlines.map(\p->show(fst<$>p)++" = "++show(product$snd<$>p)).mapM(\x->[(0,1-x),(1,x)])

Приклад використання:

Prelude> putStrLn $ unlines.map(\p->show(fst<$>p)++" = "++show(product$snd<$>p)).mapM(\x->[(0,1-x),(1,x)]) $ [0.55, 0.67, 0.13]
[0,0,0] = 0.12919499999999998
[0,0,1] = 1.9304999999999996e-2
[0,1,0] = 0.262305
[0,1,1] = 3.9195e-2
[1,0,0] = 0.157905
[1,0,1] = 2.3595e-2
[1,1,0] = 0.320595
[1,1,1] = 4.790500000000001e-2

Більшість байтів витрачається на форматування виводу. Якщо вас цікавить лише вектор вірогідності, це лише 29 байт:

map product.mapM(\x->[1-x,x])

Як це працює:

                    mapM(\x->[(0,1-x),(1,x)])   -- for each number x in the input
                                                -- list make either the pair (0,1-x)
                                                -- or (1,x). Build a list with
                                                -- all combinations

    map(\p->                    )               -- for each such combination p
          show(fst<$>p)                         -- print the first elements
          ++" = "++                             -- then the string " = "
          show(product$snd<$>p)                 -- then the product of the second
                                                -- elements

unlines                                         -- joins with newlines

Це акуратно; Мені було цікаво, чи буде дійсно короткий чисто функціональний спосіб зробити це. Ви випадково знаєте C # або F #? Мені цікаво, як виглядатиме той самий алгоритм у цих мовах, оскільки я абсолютно не знайомий із синтаксисом Haskell.
Марк Джонсон

@MarkJohnson: ні, вибачте, що я не знаю ні C #, ні F #.
німі

5

Математика, 46 45 байт

(s=#;1##&@@Abs[#-s]&/@{1,0}~Tuples~Length@s)&

Бере список. Навіть працює для порожнього списку {}, для якого є вихід {1}.

Тестовий випадок:

%[{0.55, 0.67, 0.13}]
{0.129195, 0.019305, 0.262305, 0.039195, 0.157905, 0.023595, 0.320595, 0.047905}

Пояснення

Дано список імовірностей sта список бітівb із 0позначенням "не відбулося" та із 1позначенням "відбулося", список ймовірностей, які потрібно помножити, задається на

1 - b - s

до підпису. Якщо замість цього0 позначає "відбулося" та 1"не сталося", це спрощує до

b - s

тож ми:

                      {1,0}~Tuples~Length@s   (* Generate all possible bit combinations *)
              (#-s)&/@{1,0}~Tuples~Length@s   (* Generate probabilities to be multiplied
                                                  up to sign *)
     1##&@@Abs[#-s]&/@{1,0}~Tuples~Length@s   (* Correct sign and multiply;
                                                 1##& is short for Times *)
(s=#;1##&@@Abs[#-s]&/@{1,0}~Tuples~Length@s)& (* Assign s to first argument of function,
                                                 done separately to avoid clash
                                                 with inner function *)

4

Perl, 42 40 байт

Включає +1 для -a

Наведіть числа на STDIN:

perl -M5.010 combi.pl <<< "0.55 0.67 0.13"

виходи

0.129195
0.019305
0.262305
0.039195
0.157905
0.023595
0.320595
0.047905

combi.pl:

#!/usr/bin/perl -a
$"=")\\*({1-,}";say eval for<({1-,}@F)>

4

MATL , 12 11 байт

TF-|Z}&Z*!p

Вхід - вектор стовпця з форматом [0.55; 0.67; 0.13]

Спробуйте в Інтернеті!

TF    % Push [1, 0]
-     % Subtract from implicit input (column array), with broadcast. Gives a 2-col
      % matrix where the first column is the input minus 1 and the second is the input
|     % Absolute value
Z}    % Split the matrix into its rows
&Z*   % Cartesian product of all resulting. This gives a matrix as result, with each
      % "combination" on a different row
!p    % Product of each row. Implicitly display

3

Perl, 116 байт

for(glob"{0,1}"x(@a=split/ /,<>)){@c=split//;$d=1;$d*=@c[$_]?$a[$_]:1-$a[$_]for 0..$#a;say"[".join(",",@c)."] = $d"}

Читає:

for(glob"{0,1}"x(@a=split/ /,<>)){
    @c=split//;
    $d=1;$d*=@c[$_]?$a[$_]:1-$a[$_]for 0..$#a;
    say"[".join(",",@c)."] = $d"
}

Створює список усіх можливих комбінацій довжини 0s та 1s, що дорівнює кількості вхідних параметрів (наприклад, для прикладу вище, це було б довжиною 3), потім обчислює кожну ймовірність.

Дякую @Dada, що показав мені, що може виконувати globфункція , хоча я не на 100% впевнений, що розумію як це робиться.

Вибірка зразка:

[0,0,0] = 0.129195
[0,0,1] = 0.019305
[0,1,0] = 0.262305
[0,1,1] = 0.039195
[1,0,0] = 0.157905
[1,0,1] = 0.023595
[1,1,0] = 0.320595
[1,1,1] = 0.047905

1
-aзамість (@a=split/ /,<>)...
Дада

3

R, 72 69 байт

Бере вхід з stdin і повертає R-вектор вірогідностей.

apply(abs(t(expand.grid(rep(list(1:0),length(x<-scan())))-x)),1,prod)

Редагувати: Видалено один непотрібний перенос, перестановочна матриця тепер є перекладеною версією наведеної нижче, імовірності обчислюються як продукт, що відповідає стовпцю, а не рядковий. Приклад виводу:

[1] 0.129195 0.157905 0.262305 0.320595 0.019305 0.023595 0.039195 0.047905

Зауважте, що ймовірності в іншому порядку пояснюються тим, що матриця перестановки, що генерується, expand.gridстворює наступне (генерація цієї матриці, ймовірно, може бути гольф за допомогою зовнішніх пакетів):

1    1    1    1
2    0    1    1
3    1    0    1
4    0    0    1
5    1    1    0
6    0    1    0
7    1    0    0
8    0    0    0

Перша ймовірність відповідає перевернутому результату першого рядка у вищевказаній матриці, а друга - перевернутому другому рядку і т. Д. Форматування виводу, щоб побачити це ще більш чітко, збільшує програму довше (164 байти):

m=expand.grid(rep(list(1:0),length(x<-scan())))
cat(paste0("[",apply(abs(m-1),1,function(x)paste0(x,collapse=",")),"] = ",apply(abs(t(t(m)-x)),1,prod),"\n"),sep="")

який натомість виробляє:

[0,0,0] = 0.129195
[1,0,0] = 0.157905
[0,1,0] = 0.262305
[1,1,0] = 0.320595
[0,0,1] = 0.019305
[1,0,1] = 0.023595
[0,1,1] = 0.039195
[1,1,1] = 0.047905

Я працював над власною відповіддю на це, але не зміг придумати акуратне рішення. Прекрасне використання expand.grid! Я думаю, що applyможе працювати як на фреймах даних, так і на матрицях, тому ваш код повинен працювати без знака t(t(...)), що заощадить 6 байт.
rturnbull

@rturnbull Зауважте, що tне пов'язано з жодним фреймом даних, але дозволяє дозволити віднімання вектора ймовірності з матриці перестановки (з різними розмірами). Принаймні одна з них потрібна завдяки тому, як R обробляє ці векторизовані операції, але, ймовірно, я міг би видалити зовнішній транспозит і застосувати продукт замість стовпців.
Оновиться


2

J, 14 байт

-.([:,*/)/@,.]

Використання

   f =: -.([:,*/)/@,.]
   f 0.55 0.67 0.13
0.129195 0.019305 0.262305 0.039195 0.157905 0.023595 0.320595 0.047905

Пояснення

-.([:,*/)/@,.]  Input: array P
-.              Complement (1-x) for each x in P
             ]  Identity, get P
           ,.   Interleave to make pairs [(1-x), x]
  (     )/@     Reduce from right-to-left by
      */          Forming the multiplication table
   [:,            Flattening the result

Ви можете перейти |*//0.55 0.67 0.13-/0 1на поїзд?
Adám

2

Pyth, 10 байт

*MaVLQ^U2l

Спробуйте в Інтернеті: Демонстрація

Пояснення:

*MaVLQ^U2lQ   implicit Q at the end (Q = input list)
      ^U2lQ   repeated Cartesian product of [0, 1] with itself length(Q)-times
              this gives all combinations of 0s and 1s
  aVLQ        absolute difference between these 0-1-vectors with Q
*M            fold the vectors by multiplication

1

C, 110 байт

i,k;f(float* a,int n){for(k=0;k<1<<n;++k){float p=1;for(i=0;i<n;++i)p*=k&(1<<i)?a[i]:1-a[i];printf("%f,",p);}}

Безумовно:

i,k;f(float* a,int n){ 
 for(k=0; k<1<<n; ++k){
  float p=1;
  for (i=0; i<n; ++i)
   p*=k&(1<<i)?a[i]:1-a[i];
  printf("%f,",p);
 }
}

Працює до 32 елементів, + 5 + 1 байт для 64 елементів (оголосити long k;та додати Lв першому циклі, щоб так k<1L<<N).


1
Для> 32 предметів, чи вимагає C буква "L" у прямому значенні *1*<<nабо це лише C ++?
Марк Джонсон

@MarkJohnson так, я думаю, це зажадає.
Карл Напф

1

05AB1E , 8 байт

<Äæ¹æR+P

Спробуйте в Інтернеті!

 <Äæ¹æR+P  # Main link (Input is [.1,.2])
 ###########
 <Ä        # Invert input, take the abs value.
           # Stack is [.9,.8]
   æ¹æ     # Powerset of both inverted and original arrays.
           # Stack is [[],[.1],[.2],[.1,.2]],[[],[.9],[.8],[.9,.8]]
      R+   # Reverse original array, add arrays together.
           # Stack is [.9,.8],[.1,.8],[.2,.9],[.1,.2]
        P  # For each sub array, push product.
           # Final Result: [0.02, 0.18, 0.08, 0.72]
           # E.G.          [  11,   10,   01,   00]

1

JavaScript (Firefox 30-57), 57 байт

f=([p,...a])=>1/p?[for(q of[1-p,p])for(b of f(a))q*b]:[1]

Повертає масив усіх ймовірностей. Якщо ви також хочете масив подій, то для 86 байт:

f=([p,...a])=>1/p?[for(e of'01')for(b of f(a))[[+e,...b[0]],(+e?p:1-p)*b[1]]]:[[[],1]]

Якщо вам дозволено події як рядок, то це лише 80 байт:

f=([p,...a])=>1/p?[for(e of'01')for(b of f(a))[e+b[0],(+e?p:1-p)*b[1]]]:[['',1]]

Віднімайте два байти для 1/кожного рішення, якщо ймовірність ніколи не буде нульовою.


Як би ти це запустив у <script></script>блоці? У мене виникають проблеми з тим, що перший "за" несподіваний?
Марк Джонсон

@MarkJohnson Поки ви користуєтеся Firefox 30 або пізнішої версії, він повинен просто працювати.
Ніл

0

Perl 6, 24 19 байт латиниці-1

{[*] 1 «-»@_ «|»@_}

Старіший код:

{[*] map {1-$^a|$^a},@_}

Це функція. Використовуйте його так:

{[*] 1 «-»@_ «|»@_}(0.55, 0.67, 0.13)

отримати:

any(any(any(0.129195, 0.019305), any(0.262305, 0.039195)), any(any(0.157905, 0.023595), any(0.320595, 0.047905)))

Пояснення старого коду:

[*]          multiply together all array elements
map          but first transform each element via
{1-$^a|$^a}  considering both 1 minus the value and the value
,@_          of the function input

Новий код в основному той самий, просто використовуючи терзарний синтаксис:

[*]          multiply together all array elements
1 «-»@_      of the array formed by subtracting the argument from 1
«|»@_        pointwise considering both that and the original array

Карта генерує масив, повний anyконструкцій, які множиться на більшіany конструкції, акуратно вирішуючи проблему, навіть не потребуючи циклу.

Не найкоротша мова для програми, але це дуже прямий переклад проблеми.


0

Діалог APL , 10 байт

Нове рішення

Походження індексу незалежне. Анонімна функція. В якості аргументу береться список ймовірностей.

∘.×/⊢,¨1-⊢

∘.×/ Декартовий скорочення продукту закінчилося

значення аргументу

кожен в парі з

1-⊢ значення аргументу доповнення (літ. один мінус значення аргументу)

СпробуйтеAPL онлайн!


Старе рішення

Потрібно, ⎕IO←0що для багатьох систем за замовчуванням. Підказки до списку ймовірностей

|⎕∘.×.-⊂⍳2

Пояснення

| абсолютне значення

вхід, ɑ = [ ɑ ₁  ɑ ₂  ɑ ₃]

∘.×.-модифікований внутрішній тензор, помножений, ( ɑ ₁ - b ₁) ⊗ ( ɑ ₂ - b ₂) ⊗ ( ɑ ₃ - b ₃), з

⊂⍳2доданий список b = [[0 1]]

Математичне визначення

Оскільки b укладено, воно скалярне, а тому розширене на довжину ɑ , а саме 3, тому весь вираз

A = │ ( ɑ ₁ - b ) ⊗ ( ɑ ₂ - b ) ⊗ ( ɑ ₃ - b ) │ =

 │ ( ɑ ₁ - [0,1]) ⊗ ( ɑ ₂ - [0,1]) ⊗ ( ɑ ₃ - [0,1]) │ =

 │ [ ɑ ₁, ɑ ₁ - 1] ⊗ [ ɑ ₂ , ɑ ₂ - 1] ⊗ [ ɑ ₃, ɑ ₃ - 1] │ =

 ⎢ ⎡ ⎡   ɑɑ ₂ ⎤ ɑ⎡  ɑ ɑ ₂ ( ɑ ₃-1) ⎤ ⎤ ⎥
 ⎢ ⎢ ⎣  ɑ ₁ ( ɑ ₂-1) ɑ ₃ ⎦ ⎣  ɑ ₁ ( ɑ ₂-1) ( ɑ ₃-1) ⎦ ⎥ ⎥
 ⎢ ⎢ ⎡ ( ɑ ₁-1) ɑ ɑ ₃ ⎤ ⎡ ( ɑ ₁-1) ɑ ₂ ( ɑ ₃-1) ⎤ ⎥ ⎥
 ⎢ ⎣ ⎣ ( ɑ ₁-1) ( ɑ ₂-1) ɑ ₃⎦ ⎣ ( ɑ ₁- 1) ( ɑ ₂-1) ( ɑ ₃-1) ⎦ ⎦ ⎥

СпробуйтеAPL онлайн!

Примітки (стосується як старого, так і нового рішення)

Програма і формула працює для будь-якого числа ( n ) змінних і повертає n -вимірний масив довжиною 2 у кожному вимірі. З трьома змінними ймовірність конкретного результату
Р ( p , q , r ) = A p , q , r,
яку зручно вибирати з масиву з (⊃A)[p;q;r]вилученимp q r⌷⊃A

Наприклад , 1 1 0⌷⊃|0.55 0.67 0.13∘.×.-⊂⍳2дає P (55%, 67%, ¬13%) = 1.9305%


0

PHP, 105 97 94 93 87 байт

for(;$i<2**$c=count($a=$argv)-$p=1;$i+=print-abs($p))for(;$c;)$p*=$a[$c--]-!($i>>$c&1);

Бігайте так:

php -r 'for(;$i<2**$c=count($a=$argv)-$p=1;$i+=print-abs($p))for(;$c;)$p*=$a[$c--]-!($i>>$c&1);' -- .55 .67 .13 2>/dev/null;echo
> -0.129195-0.157905-0.262305-0.320595-0.019305-0.023595-0.039195-0.047905

Зауважте, що вихід є мало ендіанським:

[0,0,0]
[1,0,0]
[0,1,0]
[1,1,0]
[0,0,1]
[1,0,1]
[0,1,1]
[1,1,1]

Пояснення

for(
  ;
  $i<2**$c=                 # Iterate over possible combinations: 2^c,
    count($a=$argv)-$p=1;   #   where c is input length -p (set p to 1)
  $i+=print-abs($p)         # Increment i and print product after each
)                           #   iteration, dash separated
  for(
     ;
     $c;                    # Iterate over input ($c..0)
  )
    $p*=                    # Multiply the product by difference between:
      $a[$c--]-             # - The $c-th item of the input.
      !($i>>$c&1);          # - The $c-th bit of `$i`, negated (1 or 0)

Налаштування

  • Збережено 8 байт, використовуючи двійкову логіку, щоб отримати біт замість перетворення в рядок
  • Збережено байт, поєднавши скидання $p до 1 з обчисленням$c
  • Збережено байт, додавши результат print (1) до $i замість збільшення
  • Збережено байт, використовуючи підкреслення як роздільник виводу
  • Збережено байт, використовуючи знак мінус як роздільник (негативних шансів немає).
  • Збережено 6 байт за допомогою, $cа не$$i

0

C ++ 17, 137 131 129 байт

Збереження 6 байт шляхом оголошення #define A auto , що такий короткий макрос економить що-небудь. -2 байти для використання #importта видалення пробілу раніше<

#import<iostream>
#define A auto
A g(A r){std::cout<<r<<",";}A g(A r,A x,A...p){g(x*r,p...);g(r-x*r,p...);}A f(A...p){g(1,p...);}

Породжує всі можливі комбінації.

Безумовно:

//base case to print the result
int g(auto r){std::cout << r << ",";}

//extract item from parameter pack
int g(auto r, auto x, auto... p) {
 g(x*r,p...);    //multiply with temp result and call with tail
 g(r-x*r,p...);  //same as above for (1-x)
}

//start of recursion, setting temp result to 1
int f(auto...p){g(1,p...);}

Використання:

f(0.55, 0.67, 0.13);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.