Случайный выбор с оговоркой / критериями

У меня есть сетка 6 х 6. У меня есть 36 образцов, разделенных на три равные группы (A, B и C).

Я хочу, чтобы формула располагала образцы в этой сетке случайным образом. Однако каждая строка и каждый столбец должны содержать две группы. Делать это вручную один или два раза легко, но существует огромное количество комбинаций.

Я открыт в плане выбора программного обеспечения, если оно бесплатное или на основе Microsoft Office.

Спасибо!

2 ответа

Я собрал инструмент для генерации случайных перестановок строк / столбцов с помощью нескольких формул и некоторого VBA. Макет листа выглядит следующим образом:

Excel snip

Сетка ссылок - это тривиальный пример действительной матрицы, опубликованной в предварительном ответе ученика Гэри (возможно, с тех пор, как он был удален). Перестановки строк и столбцов включают в себя все возможные уникальные комбинации перестановок для сетки 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 операции, а также быстрая проверка работоспособности в виде сумм строк и столбцов:

Excel snip

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

введите описание здесь

Затем возьмите первый образец, например, SAMPLE_A_1, и поместите его случайным образом в один из A-слотов. Затем продолжите обработку каждого из оставшихся 35 образцов.


Если такой подход приемлем, я опубликую короткую программу для заполнения матрицы. Если подход не является приемлемым, я удалю этот пост.

Другие вопросы по тегам