Случайное число в диапазоне с заданной вероятностью


#1

Добрый день!
Пожалуйста, подскажите, как можно реализовать выпадение случайных чисел в диапазоне с заданной вероятностью
допустим:
числа от 1 до 10
1 10%
2 40%
3 20%
4 5%
5 7%
6 3%
7 1%
8 11%
9 2%
10 1%
в сумме 100%

Я так понимаю на других языках тема уже пережевана миллион раз, и есть энное количество вариантов как это сделать. но как это сделать на языке Swift - к сожалению, нагуглить ничего не смог

ЗЫ: изучением языка занимаюсь 3 дня :blush: с полного нуля. сильно не ругайтесь )


#2

Первое, что приходит на ум - заполнить массив из 100 элементов необходимым количеством каждого из элементов.

let array = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, ....] // массив из 100 элементов

либо можно записать массив как сумму других массивов:

var array10 = Array(repeatElement(10, count: 5))  // [10, 10, 10, 10, 10]
var array20 = Array(repeatElement(20, count: 10)) // [20, 20, 20, 20, 20, 20, 20, 20, 20, 20] 
let array = array10 + array20  // [10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20] 

Следующее - можно использовать словарь, для ключа (числа) и значения (значение вероятности).

let dictionary = [1: 10, 2: 40, 3: 20, 4: 5, 5: 7, 8: 11, 9: 2, 10: 1]

Соответственно и то и другое можно спокойно использовать для расчета.
Наверняка есть и более изящные варианты, но привел то, что на поверхности.


#3

Так это довольно таки сложная задача, если делать ее правильно! так многие онлайн казино работают!
Но вот если в лоб, то я согласен с administrator и его вариантом с массивом!

Вот только нужно написать красивую функци, которая на вход принимает например массив тюплов: (число, процентное соотношение), а на выходе отдает Вам готовый массив!

Вот вам как раз и задание для начала изучения - написать такую функцию!
Как раз основные базовые темы затрагивает!


#4

Большое спасибо за ответ! . буду пробовать применять данный способ ! Надеюсь на вашу поддержку в случае возникновения вопросов)

Так же, буду благодарен за любые другие предложенные способы реализации данного задания !


#5

Еще раз, всем привет !
По вашему мнению, имеет ли право на жизнь вот такая вот история ?

var a = 80  // настройка процента для А

var b = 40 // настройка процента для B

var c = 40 // настройка процента для C

var overallPercentage = a + b + c

var a1 = (overallPercentage / 100) * a

var b1 = (overallPercentage / 100) * b

var c1 = (overallPercentage / 100) * c

var percent = Int(arc4random()) % (overallPercentage + 1)


var a2 = (0 + a)
var b2 = a2 + b
var c2 = b2 + c

switch percent {
case 0...a2: print("a")
case a2...b2: print("b")
case b2...c2: print("c")
default:
    break
}

что то намудрил. но не могу понять что )


#6

Что-то хитрите. Все ведь намного проще. Как я и писал ранее, Вы просто создаете массив и потом рандомно обращаетесь к какому-либо элементу вот и все.
Будет что-то вроде этого:

var array10 = Array(repeatElement(10, count: 5))  // [10, 10, 10, 10, 10]
var array20 = Array(repeatElement(20, count: 10)) // [20, 20, 20, 20, 20, 20, 20, 20, 20, 20] 
let array = array10 + array20  // [10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20]

let randomIndex = arc4random_uniform(100)
let randomNumber = array[randomIndex] // returns random number of array

#7

Не слушаете вы меня))) это ведь проще и универсальней…


#8

Сдаюсь )

Ну поэкспериментировал немного) это же здоровью не вредит )

Ещё раз огромное спасибо )

:thumbsup:


#9
typealias Element = Int
let arr:[(Element, Double)] = [
    (1, 0.10),
    (2, 0.40),
    (3, 0.20),
    (4, 0.05),
    (5, 0.07),
    (6, 0.03),
    (7, 0.01),
    (8, 0.11),
    (9, 0.02),
    (10, 0.01),
    ]

var sum = 0.0
var machineArray = arr.map {
    (item: (Element, Double)) -> (Range<Double>, Element) in
    let range = Double(sum)..<Double(sum) + item.1
    sum += item.1
    return (range, item.0)
}

func getnum(_ random: Double) -> Element? {
    let random = random * sum
    guard 0...sum ~= random else {
        return nil
    }
    
    return (machineArray.first { $0.0.contains(random) } ?? machineArray.last!).1
}

for var i in stride(from: 0, through: 1, by: 0.01) {
    print(getnum(i) ?? "nil", i)
}

func random() -> Double {
    return Double(arc4random()) / Double(UINT32_MAX)
}

print(getnum(random()))

#10

Спасибо за ответ.)

Все работает )

Осталось только понять, что здесь за что отвечает )) и какие вычисления происходят)

Боюсь, я пойму это не скоро ) я еще слишком сырой )