以一种“重叠”的方式向列表添加值

4

我来用数学的方式解释一下,这是我正在努力用Scheme编写代码实现的转换:

(f '(a b c) '(d e f)) = '(ad (+ bd ae) (+ cd be af) (+ ce bf) cf)

当两个字母像ad这样在一起时,意思是(* a d)

我正在尝试以纯函数的方式编写它,但我很难看出如何做到。任何建议都将不胜感激。

下面是一些示例:

(1mul '(0 1) '(0 1)) = '(0 0 1)
(1mul '(1 2 3) '(1 1)) = '(1 3 5 3)
(1mul '(1 2 3) '(1 2)) = '(1 4 7 6)
(1mul '(1 2 3) '(2 1)) = '(2 5 8 3)
(1mul '(1 2 3) '(2 2)) = '(2 6 10 6)
(1mul '(5 5 5) '(1 1)) = '(5 10 10 5)
(1mul '(0 0 1) '(2 5)) = '(0 0 2 5)
(1mul '(1 1 2 3) '(2 5)) = '(2 7 9 16 15)

所以,这个模式就像我一开始发布的那样:
将列表中的第一个数字乘以第二个列表中的每个数字(ad,ae,af),然后继续进行(bd,be,bf,cd,ce,cf),并“某种方式”排列数字以添加相应的值。我称其为重叠,因为你可以类比为这样:
(list
       aa'
    (+ ba' ab')
    (+ ca' bb' ac')
        (+ cb' bc')
               cc')

再次提醒,
(f '(a b c) '(d e f)) = '(ad (+ bd ae) (+ cd be af) (+ ce bf) cf)

然而,这不仅适用于3x3列表,还适用于任何大小的列表。

你的括号不平衡,所以我不确定你想要什么。请澄清。 - leppie
你在哪里遇到过这种操作?你想使用这个操作实现什么目的? - soegaard
这类似于手算乘法。这个关于二进制乘法的网页可以帮助说明我的意思:http://www.cs.uaf.edu/~cs301/notes/Chapter5/node5.html - snario
你对术语的分组看起来有些奇怪...直到我意识到你可能在隐式使用位值。也就是说,你使用列表'(1 2 3)来表示数字123。在这种情况下,你的分组将相关术语与具有相同数量零的术语关联。这样理解是否正确? - John Clements
这看起来像是多项式乘法。 - Theo Belaire
+* 子句中,术语的顺序是否重要? - Theo Belaire
3个回答

1

这是我的代码。它是用Racket编写的。

#lang racket

(define (drop n xs)
  (cond [(<= n 0) xs]
        [(empty? xs) '()]
        [else (drop (sub1 n) (rest xs))]))        

(define (take n xs)
  (cond [(<= n 0) '()]
        [(empty? xs) '()]
        [else (cons (first xs) (take (sub1 n) (rest xs)))]))        


(define (mult as bs)
  (define (*- a b)
    (list '* a b))
  (define degree (length as))
  (append 
   (for/list ([i  (in-range 1 (+ 1 degree))])
     (cons '+ (map *- (take i as) (reverse (take i bs)))))
   (for/list ([i  (in-range 1 degree)])
     (cons '+ (map *- (drop i as) (reverse (drop i bs)))))))

"

for/list只是一种在数字列表上进行映射并将结果收集到列表中的方法。如果需要,我可以重新表述为仅进行映射操作。

"

0

这个问题适合使用递归吗?不确定,但这是你要求的直接翻译。

(define (f abc def)
  (let ((a (car abc)) (b (cadr abc)) (c (caddr abc))
        (d (car def)) (e (cadr def)) (f (caddr def)))
    (list (* a d)
          (+ (* b d) (* a e))
          (+ (* c d) (* b e) (* a f))
          (+ (* c e) (* b f))
          (* c f))))

抱歉,我应该解释得更清楚。我需要的是一个函数,可以处理任意长度的两个列表,而不仅仅是3x3。 - snario
@soegaard 提出了一个好观点;如果你只想要交叉乘积,那么他的答案是最有意义的。让我们在继续之前先搞清楚这一点。 - Faiz

0

你想进行这个计算,这样做是正确的吗?

(a+b+c)*(d+e+f) = a(d+e+f) + b(d+e+f) + c(d+e+f) 
                = ad+ae+af + bd+be+bf + cd+ce+cf

如果是这样,那就很简单了:
(define (f xs ys)
   (* (apply + xs) (apply + ys))

如果你对象征性版本感兴趣:

#lang racket
(define (f xs ys)
  (define (fx x)
    (define (fxy y)
      (list '* x y))
    (cons '+ (map fxy ys)))
  (cons '+ (map fx xs)))

这里有一个测试:

> (f '(a b c) '(d e f))
'(+ (+ (* a d) (* a e) (* a f)) 
    (+ (* b d) (* b e) (* b f)) 
    (+ (* c d) (* c e) (* c f)))

抱歉,那不完全正确,我需要生成一个列表来使用该计算,但它还需要将值放在正确的位置。我已经在第一篇帖子中添加了一些示例和更多信息。 - snario

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接