在矩阵中获取对角线

时间:2014-04-21 14:58:00

标签: matrix scheme racket diagonal

使用Racket,并避免任何有状态的功能(以感叹号结尾的功能),我试图获得所有"对角线条"在列表列表中,如果更容易,则使用向量。

这是解决" N-Queens"国际象棋问题,但我不想看到破坏者如何解决整个问题。相关性是我试图确定是否有任何女王可以攻击任何其他女王对角。我想我可以按照水平和垂直攻击的方式进行操作 - 将每行或每列转换为自己的列表,看看该列表中是否存在多个Queen。

然而,创建斜条带变得非常难看和复杂的代码!必须有一个很好,简洁的方法来解决这个问题。

示例:

1  2  3  4
5  6  7  8
9  10 11 12
13 14 15 16

我想从此形成以下列表:

'(1 6 11 16) '(2 5) '(2 7 12) '(3 6 9) '(3 8) '(4 7 10 13) '(5 10 15)
'(9 14) '(8 11 14) '(12 15)

我注意到这些列表的格式是其他元素比前一个元素多(+ n 1),或者比前一个元素多(- n 1),但边界检查其他问题使我的代码太复杂,并且不太可能解决合理的解决方案。 (在这种情况下,n是一维的长度。)

我是以错误的方式来做这件事的吗?是否有更简单的方法来检查对角线是否受到另一位女王的威胁?或者这是正确的想法,但我错过了一些方便的功能,这使得这一切都比我想的更简单?

1 个答案:

答案 0 :(得分:2)

一些想法:

  1. 您不需要所有对角线的列表,您需要的是每个女王在董事会中的两个对角线
  2. 如果你真的想要所有的对角线,那么最好更改数据结构。虽然我确定使用列表可以解决这个问题,但我宁愿切换到向量,这样我就可以有效地使用索引
  3. 当然,无论如何,您可以通过list-ref编写一个引用列表上的索引的解决方案,但它不会高效/优雅。或者您可以使用list->vector将列表转换为向量,使用vector-ref编写基于索引的解决方案,然后返回到包含vector->list的列表

    例如,您可以尝试以下解决方案(改编自此post)。它接收矢量矢量作为输入(如果你想使用列表列表作为输入,只需用vector-ref替换list-ref,它的效率会低一些),并返回一个列表列表对角线。元素以不同的顺序添加,但值是正确的(读者练习:格式化输出,使其与问题中的样本匹配)。注意我是如何使用iterations and comprehensions进行循环的,这是惯用的Racket,适用于严重依赖索引的这类问题:

    ; Returns a list of lists with all the diagonals in a square matrix
    ; omitting the diagonals that have a single element
    ; m: the matrix represented as a vector of vectors
    ; n: the number of rows (or columns, because it's square)
    (define (diagonals m n)
      ; join two results
      (append
      ; first: the leading diagonals
       (for/list ([slice (in-range 1 (- (* 2 n) 2))])
         (let ((z (if (< slice n) 0 (add1 (- slice n)))))
           (for/list ([j (in-range z (add1 (- slice z)))])
             (vector-ref (vector-ref m (sub1 (- n j))) (- slice j)))))
      ; second: the antidiagonals
       (for/list ([slice (in-range 1 (- (* 2 n) 2))])
         (let ((z (if (< slice n) 0 (add1 (- slice n)))))
           (for/list ([j (in-range z (add1 (- slice z)))])
             (vector-ref (vector-ref m j) (- slice j)))))))
    

    您可以按如下方式测试它,它按预期工作:

    (define matrix '#(#(1 2 3 4) #(5 6 7 8) #(9 10 11 12) #(13 14 15 16)))
    (diagonals matrix 4)
    
    => '((14 9)
         (15 10 5)
         (16 11 6 1)
         (12 7 2)
         (8 3)
         (2 5)
         (3 6 9)
         (4 7 10 13)
         (8 11 14)
         (12 15))