定义一个计算方阵轨迹的scheme函数

定义一个计算方阵轨迹的scheme函数,scheme,lisp,Scheme,Lisp,范例 (trace'((1234)(456)(789))应计算为15(1+5+9)。 提示:使用map获取可递归应用跟踪的较小矩阵。矩阵应该是平方的 我试着去做,但我似乎做不到,我试着先得到对角线 define (diagonals m n) (append (for/list ([slice (in-range 1 (- (* 2 n) 2))]) (let ((z (if (< slice n) 0 (add1 (- slice n))))) (for/list ([j (

范例

(trace'((1234)(456)(789))
应计算为15(1+5+9)。 提示:使用
map
获取可递归应用跟踪的较小矩阵。矩阵应该是平方的

我试着去做,但我似乎做不到,我试着先得到对角线

define (diagonals m n)

(append

(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))))
(+(第n个3'(3 4 5))(第n个2'(3 4 5))(第n个3'(3 4 5)))


虽然我不认为回答家庭作业的问题是一个好主意,但我无法抗拒,因为这是一个例子,既展示了Lisp程序的美妙之处,也展示了Lisp程序的可怕之处

什么是如此美丽:

  • 递归算法几乎等同于归纳法的数学证明,它非常漂亮和聪明
什么是如此可怕:

  • 矩阵不是语义上嵌套的列表,假装它们是一个可怕的双关语(我不确定我使用
    first
    rest
    是更好还是更糟)
  • 它就像疯了一样毫无理由
  • 我很确定它的时间复杂度是n^2,而它可能是n
当然,Lisp程序不必如此可怕

要计算矩阵的轨迹,请执行以下操作:

  • 如果矩阵为空,则跟踪为0
  • 否则,通过删除第一行和第一列,将左上角的元素添加到矩阵的跟踪中
或:

您可能会认为下面的函数更好,但它在上述所有方面都同样糟糕,而对于不熟悉使用累加器技巧的辅助尾部递归函数的人来说,它更难阅读:

(define (awful-trace/not-actually-better m)
  (define (awful-loop mm tr)
    (if (null? mm)
        tr
        (awful-loop (map rest (rest mm))
                    (+ tr (first (first mm))))))
  (awful-loop m 0))
尝试:

当然,把它变成一个函数

要处理大于3x3的矩阵,我们需要更多的索引


由于
map
在遍历最短的列表时停止,因此
(0 1 2)
列表可以手动填充到最大值。。。在毕业之前,您最好猜测Scheme中嵌套列表所代表的最大矩阵,以后再也看不到这些内容。

请将代码从注释移动到问题,并正确设置格式。使用“编辑”按钮。好的,我会的,谢谢。现在请修复parens和indentation并删除不必要的注释(我将删除我的注释)。你看,我不是lisp方面的专业人士,因此不擅长indentationEmacs可以按我们期望的方式为你缩进代码:-)lisp中的列表是线性访问,因此到达对角线只能是二次访问。这就是说,
map
重新构建顶级cons结构,从而获得二次空间行为;您可以为第n行应用
cdr
n次,以获得恒定的空间(当然时间仍然是二次的)。为第n行调用
cdr
n次也无济于事,这不是因为Lisp“糟糕”,而是因为使用了数据结构你的累积代码仍然调用map;它所能做到的就是避免O(n)深度叠加——与二次空间和时间相比,这并不重要。我在抽什么?!当然可以使用第n个而不是第n个cdr。我认为它仍然是线性的,所以总体上是二次的OTOH OP使用的是
向量ref
,所以它们的矩阵可能是向量列表?这将改变一切。@WillNess:是的,它是二次的,正如你所说的,计算这样一个结构的轨迹的任何东西都不能比这更好(即使是OP将它变成向量的技术,因为这样做本身就是二次的)。累加器版本在空间上是线性的,比如GC或等价物:在成为垃圾之前,它一次不需要超过n个新的conse。我显然不认为Lisp很糟糕:我认为一些程序(用Lisp和其他语言)很糟糕,包括这一个。在“糟糕”的引语后面有一个隐含的微笑。应该说得很清楚至于累积版本的空间线性:你是对的。我在考虑新消费的数量,所以这是一个时间复杂的事情。当然,一个足够聪明的编译器只需维护一堆指向原始结构的指针,根本不需要考虑。从这个角度来看,(第一个)代码变成了一个高级描述,而且很漂亮,imho.)
(define (awful-trace m)
  (if (null? m)
      ;; the trace of the null matrix is 0
      0
      ;; otherwise the trace is the top left element added to ...
      (+ (first (first m))
         ;; the trace of the matrix without its first row and column which
         ;; we get by mapping rest over the rest of the matrix
         (awful-trace (map rest (rest m))))))
(define (awful-trace/not-actually-better m)
  (define (awful-loop mm tr)
    (if (null? mm)
        tr
        (awful-loop (map rest (rest mm))
                    (+ tr (first (first mm))))))
  (awful-loop m 0))
(apply + (map (lambda (index row) (list-ref row index))
             '(0 1 2)
             '((1 2 3) (4 5 6) (7 8 9))))