在MATLAB中生成随机'su doku'类型矩阵

时间:2012-03-27 11:15:43

标签: matlab random sudoku

我需要在MATLAB中生成一些5x6矩阵。它们需要由1-6范围内的随机生成的整数组成,但是,在特定的行或列中,整数不能出现多次。

以下是我目前用于生成随机5x6矩阵的脚本:

mat=zeros(5,6);

rows=5;
columns=6;
for i=1:rows
  for j=1:columns
      mat(i,j)=round(rand*(high-low)+low);
  end
end
disp(mat)

但我不知道如何将关于重复的规则插入到此中。

我确信这是一个相对简单的问题,但我对MATLAB很新,并且无法生成满足这些条件的东西。我会很乐意为任何人提供帮助。

3 个答案:

答案 0 :(得分:4)

试试这个:

    m = zeros(5,6);

    for row = 1:5
        flag = 1;
        while(flag)
            flag = 0;
            R = randperm(6);
            for testRow = 1:row
                flag = flag + sum(m(testRow,:) == R);
            end;
            if (~flag)
                m(row,:) = R;
            end;
        end;

    end;

    m

答案 1 :(得分:3)

不要试图一次完全随机地填充矩阵。作为有效拼图网格的可能性非常低。

相反,use the same method as used by Sudoku generators - 以空白矩阵开头,并按规则限制一次填写一个元素。

如果您对该条目有多个选择,请随机选择其中一个。

你可能会进步这样的事情(简洁的4x4例子 - 允许的数字1-4)

x x x x
x x x x
x x x x
x x x x

用骰子掷骰子选择第一个数字:3。

3 x x x
x x x x
x x x x
x x x x

从允许数字列表中选择第二个数字:[1,2,4]。

3 1 x x
x x x x
x x x x
x x x x

从允许数字列表中选择第三个数字,[1,4]:

3 1 4 x
x x x x
x x x x
x x x x

等等。

如果某个插入步骤中的“允许号码列表”为空集,则无法挽救您的矩阵,您可能需要重新开始。

另外一个10x10矩阵有5个唯一的整数显然是不可能的 - 插入一些逻辑来测试这个琐碎的错误情况。


编辑:因为它不是传统意义上的作业,因为这是一个有趣的问题......

function arena = generate_arena(num_rows, num_cols, num_symbols)
    % Generate an "arena" by repeatedly calling generate_arena_try
    % until it succeeds.
    arena = 0;
    number_of_tries = 0;
    while ~(arena)
        arena = generate_arena_try(num_rows, num_cols, num_symbols);
        number_of_tries = number_of_tries + 1;
    end
    sprintf('Generating this matrix took %i tries.', number_of_tries)
end

function arena = generate_arena_try(num_rows, num_cols, num_symbols)
    % Attempts to generate a num_rows by num_cols matrix of random integers
    % from the range 1:num_symbols, with no symbols repeated in each row or
    % column.
    %
    % returns 0 on failure, or the random matrix if it succeeds.

    arena = zeros(num_rows, num_cols);
    symbols = 1:num_symbols;
    for n = 1:num_rows
        for m = 1:num_cols
           current_row = arena(n,:);
           current_col = arena(:,m);
           % find elements in $symbols that are not in the current row or col
           choices = setdiff ( symbols, [current_row current_col'] );
           if isempty(choices)
               arena = 0;
               return;
           end
           % Pick one of the valid choices at random.
           arena(n,m) = choices(randi(length(choices)));
        end
    end
    return;
end

调用和输出如下:

>> generate_arena(5,6,6)

ans =

Generating this matrix took 5 tries.


ans =

     2     3     6     4     5     1
     6     1     5     3     4     2
     1     5     4     2     6     3
     4     6     2     1     3     5
     3     4     1     5     2     6

不要说我从来没有给你什么。 ;)

答案 2 :(得分:3)

这是另一种方法:

从一个已知的有效解决方案开始,比如说这个:

>> A = mod(meshgrid(1:size) - meshgrid(1:size)', size) + 1

A =

     1     2     3     4     5     6
     6     1     2     3     4     5
     5     6     1     2     3     4
     4     5     6     1     2     3
     3     4     5     6     1     2
     2     3     4     5     6     1

然后随机交换行和列。您可以证明每个交换在每行和每列中保留“无重复”属性。

假设您交换第1行和第2行。您没有更改行的内容,因此“每行中没有重复”属性保持为真。同样,您没有更改任何列的内容 - 只是排序 - 因此“每列中没有重复”属性也保持为真。

以下是我提出的建议:

function arena = gen_arena_2 (size)
    arena = mod(meshgrid(1:size) - meshgrid(1:size)', size) + 1;
    %repeatedly shuffle rows and columns
    for i = 1:10
        arena = arena(:,randperm(size))'; %shuffle columns and transpose
    end
end

使用示例:

>> gen_arena_2(6)

ans =

     3     5     4     2     1     6
     6     2     1     5     4     3
     5     1     6     4     3     2
     4     6     5     3     2     1
     1     3     2     6     5     4
     2     4     3     1     6     5

我不确定这可能是“随机”的另一种方式 - 但这种方式很快,并且不需要任何逻辑来检测故障(因为它(可证明地)总是会产生正确的结果。 )