# Find the probability of getting k (the sum of the dropped values) when rolling n dice (part 2 of 2)

``````Option Explicit

Sub main()
Const c_int_side_dice = 6  'сколько граней у кубика
Const c_int_dice_number = 100  'кол-во кубиков
Const c_int_number_to_find = 200  'число, вероятность выпадения которого хотим найти
Dim probability
probability = dice_probability(c_int_dice_number, c_int_number_to_find, c_int_side_dice)
MsgBox probability
End Sub

' собственно поиск вероятности определённого значения
Function dice_probability(int_dice_number, int_number_to_find, c_int_side_dice)
If int_number_to_find >= int_dice_number And int_number_to_find <= c_int_side_dice * int_dice_number Then
ReDim list_values(int_dice_number * (c_int_side_dice - 1))
Dim i, j
i = 0
For j = int_dice_number To c_int_side_dice * int_dice_number
list_values(i) = j
i = i + 1
Next
Dim list_interm_probability()
interm_probabilities c_int_side_dice, int_dice_number, list_interm_probability
For i = 0 To int_dice_number * (c_int_side_dice - 1)
If list_values(i) = int_number_to_find Then
Exit For
End If
Next
dice_probability = list_interm_probability(i) / (c_int_side_dice ^ int_dice_number)
Else
'задаваемое число выходит за рамки реально возможного диапазона значений
dice_probability = 0.0
End If
End Function

'возвращает список/массив: сколько раз встречается значение
Sub interm_probabilities(int_side_dice, int_pow, list_out)
'На примере int_side_dice = 6, int_pow = 5
'{
'  1: [1, 1, 1, 1, 1, 1],
'  2: [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1],
'  4: [1, 4, 10, 20, 35, 56, 80, 104, 125, 140, 146, 140, 125, 104, 80, 56, 35, 20, 10, 4, 1]
'  5: [1, 5, 15, 35, 70, 126, 205, 305, 420, 540, 651, 735, 780, 780, 735, 651, 540, 420, 305, 205, 126, 70, 35, 15, 5, 1]
'}
Dim j
Dim list_interm_probability()
ReDim list_interm_probability(int_side_dice - 1)
For j = 0 To int_side_dice - 1
list_interm_probability(j) = 1
Next
Dim dict_interm_probability
Set dict_interm_probability = CreateObject("Scripting.Dictionary")

If int_pow = 0 Then
MsgBox "Не поддерживается"
Quit
ElseIf int_pow <> 1 Then
Dim list_to_do()
map_todo list_to_do, int_pow
For j = 0 To UBound(list_to_do, 2)
'MsgBox list_to_do(0, j) & vbTab & list_to_do(1, j) & vbTab & list_to_do(2, j)
multiply_cins_orig _
dict_interm_probability.Item(list_to_do(0, j)), _
dict_interm_probability.Item(list_to_do(1, j)), _
list_out
dict_interm_probability.Add list_to_do(2, j), list_out
' ArrOut_1 list_out
Next
End If
End Sub

'Как добраться до интересующего значения, используя x2/+nx для степеней
Sub map_todo(list_solution, int_wanted)
'На примере int_wanted = 5
'Степени "числа":
'1
'1 * 2 = 2 -> Array(1, 1, 2)
'2 * 2 = 4 -> Array(2, 2, 4)
'4 + 1 = 5 -> Array(4, 1, 5)

Dim int_current_id
Dim int_sum
Dim b_ascending
Dim i

int_current_id = 1
int_sum = 1
b_ascending = True
i = -1

Do
If b_ascending And 2 * int_current_id <= int_wanted Then
i = i + 1
ReDim Preserve list_solution(2, i)
list_solution(0, i) = int_current_id
list_solution(1, i) = int_current_id
list_solution(2, i) = 2 * int_current_id
int_current_id = 2 * int_current_id
int_sum = int_current_id
ElseIf b_ascending And 2 * int_current_id > int_wanted Then
b_ascending = False
int_sum = int_current_id
int_current_id = CInt(int_current_id / 2)  'чтобы возвращал именно integer
ElseIf Not b_ascending And int_sum + int_current_id <= int_wanted Then
i = i + 1
ReDim Preserve list_solution(2, i)
list_solution(0, i) = int_sum
list_solution(1, i) = int_current_id
list_solution(2, i) = int_sum + int_current_id
int_sum = int_sum + int_current_id
int_current_id = CInt(int_current_id / 2)  'чтобы возвращал именно integer
ElseIf Not b_ascending And int_sum + int_current_id > int_wanted Then
int_current_id = CInt(int_current_id / 2)  'чтобы возвращал именно integer
End If
Loop Until (int_sum = int_wanted)
End Sub

' "умножение" в столбик двух массивов/списков
Sub multiply_cins_orig(list_in_1, list_in_2, list_in)
Dim int_len_1
Dim int_len_2
int_len_1 = Ubound(list_in_1, 1)
int_len_2 = Ubound(list_in_2, 1)

Dim list_for_sum()
ReDim list_for_sum(int_len_2, int_len_1 + int_len_2)
Dim i, j, k, n
For i = 0 To int_len_2
j = 0
For n = 0 To int_len_2
If i = n Then
For k = 0 To int_len_1
list_for_sum(i, j) = list_in_1(k) * list_in_2(n)
j = j + 1
Next
Else
list_for_sum(i, j) = 0
j = j + 1
End If
Next
Next
'[list_in_1 X elem_2[0], 0, 0, 0, 0, 0]
'[0, list_in_1 X elem_2[1], 0, 0, 0, 0]
'[0, 0, list_in_1 X elem_2[2], 0, 0, 0]
'[0, 0, 0, list_in_1 X elem_2[3], 0, 0]
'[0, 0, 0, 0, list_in_1 X elem_2[4], 0]
'[0, 0, 0, 0, 0, list_in_1 X elem_2[5]]

'ArrOut_2 list_for_sum
Erase list_in
ReDim list_in(int_len_1 + int_len_2)
Dim sum_out
For j = 0 To int_len_1 + int_len_2
sum_out = 0
For i = 0 To int_len_2
sum_out = sum_out + list_for_sum(i, j)
Next
list_in(j) = sum_out
Next
' [1, 3, 6, 10, 15, 21, 25, 27, 27, 25, 21, 15, 10, 6, 3, 1]
'ArrOut_1 list_in
End Sub

'==================================================
Sub ArrOut_1(arr_in)
Dim str_out
Dim i
For i = 0 To UBound(arr_in)
If i = 0 Then
str_out = arr_in(i)
Else
str_out = str_out & " " & arr_in(i)
End If
Next
MsgBox str_out
End Sub

Sub ArrOut_2(arr_in)
Dim str_out
Dim i, j
For i = 0 To UBound(arr_in, 1)
For j = 0 To UBound(arr_in, 2)
If i = 0 And j = 0 Then
str_out = arr_in(i, j)
ElseIf j = 0 Then
str_out = str_out & vbNewLine & arr_in(i, j)
Else
str_out = str_out & " " & arr_in(i, j)
End If
Next
Next
MsgBox str_out
End Sub