Случайный выбор с оговоркой / критериями
У меня есть сетка 6 х 6. У меня есть 36 образцов, разделенных на три равные группы (A, B и C).
Я хочу, чтобы формула располагала образцы в этой сетке случайным образом. Однако каждая строка и каждый столбец должны содержать две группы. Делать это вручную один или два раза легко, но существует огромное количество комбинаций.
Я открыт в плане выбора программного обеспечения, если оно бесплатное или на основе Microsoft Office.
Спасибо!
2 ответа
Я собрал инструмент для генерации случайных перестановок строк / столбцов с помощью нескольких формул и некоторого VBA. Макет листа выглядит следующим образом:
Сетка ссылок - это тривиальный пример действительной матрицы, опубликованной в предварительном ответе ученика Гэри (возможно, с тех пор, как он был удален). Перестановки строк и столбцов включают в себя все возможные уникальные комбинации перестановок для сетки 6x6. (Это можно легко изменить, чтобы включить неуникальные перестановки, если это необходимо.) Значения в E12:E26
а также L12:L26
выбираются случайным образом либо в ноль, либо в единицу, чтобы обеспечить основу для выполнения или отсутствия заданной перестановки. Колонны D
а также K
просто преобразуйте их в логические значения для упрощенной обработки в VBA (см. ниже). Переставленная сетка генерируется пользовательской функцией doSwap
, введенный как формула массива. прессование F9
вызвать пересчет листа вызывает различные RAND
функции для генерации их случайных значений, изменения серии перестановок, которые должны быть выполнены.
Код VBA, который включает это поведение:
Function doSwap(srcRg As Range, rowSwaps As Range, colSwaps As Range) As Variant
Dim workVt As Variant
Dim iter As Long
workVt = srcRg.Value
' Do row swaps
For iter = 1 To rowSwaps.Rows.Count
With rowSwaps
If .Cells(iter, 3).Value Then
workVt = swapRow(workVt, .Cells(iter, 1), .Cells(iter, 2))
End If
End With
Next iter
' Do col swaps
For iter = 1 To colSwaps.Rows.Count
With colSwaps
If .Cells(iter, 3).Value Then
workVt = swapCol(workVt, .Cells(iter, 1), .Cells(iter, 2))
End If
End With
Next iter
' Store and return
doSwap = workVt
End Function
Function swapCol(ByVal inArr As Variant, idx1 As Long, idx2 As Long) As Variant
Dim tempVal As Variant, workVt As Variant
Dim iter As Long
' Check if Range or Array input
If IsObject(inArr) Then
If TypeOf inArr Is Range Then
workVt = inArr.Value
Else
swapCol = "ERROR"
Exit Function
End If
Else
workVt = inArr
End If
' Just crash if not correct size
' Do swap
For iter = LBound(workVt, 1) To UBound(workVt, 1)
tempVal = workVt(iter, idx1)
workVt(iter, idx1) = workVt(iter, idx2)
workVt(iter, idx2) = tempVal
Next iter
' Return
swapCol = workVt
End Function
Function swapRow(ByVal inArr As Variant, idx1 As Long, idx2 As Long) As Variant
Dim tempVal As Variant, workVt As Variant
Dim iter As Long
' Check if Range or Array input
If IsObject(inArr) Then
If TypeOf inArr Is Range Then
workVt = inArr.Value
Else
swapRow = "ERROR"
Exit Function
End If
Else
workVt = inArr
End If
' Just crash if not correct size
' Do swap
For iter = LBound(workVt, 2) To UBound(workVt, 2)
tempVal = workVt(idx1, iter)
workVt(idx1, iter) = workVt(idx2, iter)
workVt(idx2, iter) = tempVal
Next iter
' Return
swapRow = workVt
End Function
Вышеприведенный код не является достаточно обоснованным, но служит настоящей цели. Расширение / обобщение должно быть довольно простым, если это необходимо. В частности, он должен обрабатывать как-бы любой размер двумерной эталонной сетки, даже не квадратный. Главное, чтобы массивы инструкций перестановки были настроены правильно.
РЕДАКТИРОВАТЬ: немного поиграв, становится ясно, что это решение не предоставляет доступ ко всему пространству возможных перестановок. Итак, я подправил его, добавив случайный " сдвиг битов", чтобы поменять метки типов между собой. Чтобы упростить вещи, я перешел с ABC
ярлыки для 123
метки, что позволяет реализацию простым MOD
операции, а также быстрая проверка работоспособности в виде сумм строк и столбцов:
Существует очень простой способ сделать это. Сначала предварительно назначьте слоты каждому из трех типов:
Затем возьмите первый образец, например, SAMPLE_A_1, и поместите его случайным образом в один из A-слотов. Затем продолжите обработку каждого из оставшихся 35 образцов.
Если такой подход приемлем, я опубликую короткую программу для заполнения матрицы. Если подход не является приемлемым, я удалю этот пост.