Как случайным образом бросать числа в двумерную доску - PullRequest
0 голосов
/ 13 ноября 2018

Теперь у меня есть двумерная доска размером 50x50 с пустыми ячейками.Я хочу заполнить ячейки 20% ячейками 0, 30% ячейками 1, 30% ячейками 2 и 20% ячейками 3. Как случайным образом бросить эти 4 числа на доску с процентами?

  import numpy as np
  from numpy import random

  dim = 50
  map = [[" "for i in range(dim)] for j in range(dim)]
  print(map)

Ответы [ 4 ]

0 голосов
/ 13 ноября 2018

Поскольку проценты суммируются до 1, вы можете начать с доски нулей

bsize = 50
board = np.zeros((bsize, bsize))

В этом подходе позиции доски интерпретируются как 1D позиции, тогда нам нужен набор позиций, эквивалентный 80% всех позиций.

for i, pos in enumerate(np.random.choice(bsize**2, int(0.8*bsize**2), replace=False)):
    # the fisrt 30% will be set with 1
    if i < int(0.3*bsize**2):
        board[pos//bsize][pos%bsize] = 1
    # the second 30% (between 30% and 60%) will be set with 2
    elif i < int(0.6*bsize**2):
        board[pos//bsize][pos%bsize] = 2
    # the rest 20% (between 60% and 80%) will be set with 3
    else:
        board[pos//bsize][pos%bsize] = 3

В конце последние 20% позиций останутся нулями


Как предполагает @alexis в комментариях, этот подход может стать более простым, если использовать метод shuffle из random module:

из случайного импорта shuffle

bsize = 50
board = np.zeros((bsize, bsize))

l = list(range(bsize**2))
shuffle(l)

for i, pos in enumerate(l):
        # the fisrt 30% will be set with 1
        if i < int(0.3*bsize**2):
            board[pos//bsize][pos%bsize] = 1
        # the second 30% (between 30% and 60%) will be set with 2
        elif i < int(0.6*bsize**2):
            board[pos//bsize][pos%bsize] = 2
        # the rest 20% (between 60% and 80%) will be set with 3
        elif i < int(0.8*bsize**2):
            board[pos//bsize][pos%bsize] = 3

Последние 20% позиций снова останутся нулями.

0 голосов
/ 13 ноября 2018

Другой подход (по общему признанию, он вероятностный, поэтому вы не получите идеальных пропорций, как решение, предложенное Брэдом Соломоном)

import numpy as np
res = np.random.random((50, 50))

zeros = np.where(res <= 0.2, 0, 0)
ones = np.where(np.logical_and(res <= 0.5, res > 0.2), 1, 0)
twos = np.where(np.logical_and(res <= 0.8, res > 0.5), 2, 0)
threes = np.where(res > 0.8, 3, 0)

final_result = zeros + ones + twos + threes

Бег

np.unique(final_result, return_counts=True)

уступил

(array([0, 1, 2, 3]), array([499, 756, 754, 491]))
0 голосов
/ 13 ноября 2018

Один из способов получения такого рода случайности - начать со случайной перестановки чисел от 0 до общего количества клеток, у вас есть минус один.

perm = np.random.permutation(2500)

теперь вы делите перестановку в соответствии спропорции, которые вы хотите получить, и обрабатывайте записи перестановки как индексы массива.

array = np.empty(2500)
p1 = int(0.2*2500)
p2 = int(0.3*2500)
p3 = int(0.3*2500)
array[perm[range(0, p1)]] = 0
array[perm[range(p1, p1 + p2)]] = 1
array[perm[range(p1 + p2, p3)]] = 2
array[perm[range(p1 + p2 + p3, 2500)]] = 3
array = array.reshape(50, 50)

Таким образом вы обеспечиваете пропорции для каждого числа.

0 голосов
/ 13 ноября 2018

Вот подход с np.random.choice для перетасовки индексов, затем заполнение этих индексов повторениями вставленных целых. Он заполнит массив в точных пропорциях, которые вы укажете:

import numpy as np
np.random.seed(444)

board = np.zeros(50 * 50, dtype=np.uint8).flatten()

# The "20% cells with 0" can be ignored since that is the default.
#
# This will work as long as the proportions are "clean" ints
# (I.e. mod to 0; 2500 * 0.2 is a clean 500.  Otherwise, need to do some rounding.)

rpt = (board.shape[0] * np.array([0.3, 0.3, 0.2])).astype(int)
repl = np.repeat([1, 2, 3], rpt)

idx = np.random.choice(board.shape[0], size=repl.size, replace=False)

board[idx] = repl
board = board.reshape((50, 50))

Результирующие частоты:

>>> np.unique(board, return_counts=True)
(array([0, 1, 2, 3], dtype=uint8), array([500, 750, 750, 500]))
>>> board
array([[1, 3, 2, ..., 3, 2, 2],
       [0, 0, 2, ..., 0, 2, 0],
       [1, 1, 1, ..., 2, 1, 0],
       ...,
       [1, 1, 2, ..., 2, 2, 2],
       [1, 2, 2, ..., 2, 1, 2],
       [2, 2, 2, ..., 1, 0, 1]], dtype=uint8)

подход

Свести доску. Проще работать с индексами, когда доска (временно) одномерна.

rpt - это 1-й вектор числа повторений на целое число. Он «упакован» вместе с [1, 2, 3] для создания repl, длина которого составляет 2000. (80% от размера доски; вам не нужно беспокоиться о 0 в этом примере.)

Индексы уплощенного массива эффективно перетасовываются (idx), а длина этого перетасованного массива ограничена размером кандидатов на замену. Наконец, эти индексы на 1-й доске заполнены заменами, после чего их можно снова сделать 2-мя.

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