【发布时间】:2021-06-19 22:46:10
【问题描述】:
我花了一些时间从 SICP 第 2.2.3 节 - 作为常规接口的序列 中生成“素数对”,例如:
-
(1 3)不,因为 sum = 4 -
(1 4)是的,因为 sum = 5(素数)
这是我从头开始的,它有效:
#lang sicp
; RANGE helper function
(define (range a b) ; a to b
(if (> a b) nil
(cons a (range (+ 1 a) b))
))
; FILTER helper function
(define (filter func sequence)
(cond ((null? sequence) nil)
((func (car sequence)) (cons (car sequence) (filter func (cdr sequence))))
(else (filter func (cdr sequence)))))
; PRIME helper function
(define (prime? n)
(cond ((or (= n 1) (= n 2)) #t)
((=(modulo n 2) 0) #f)
(else ; see if no modulos=0 under length of sqrt(N)
(= 0
(length (filter (lambda (i) (eq? i #t))
(map (lambda (d) (= (modulo n d) 0)) (range 3 (sqrt n)))))))))
; MAP helper
(define (flatmap func seq)
(if (null? seq) nil (append (func (car seq)) (flatmap func (cdr seq)))))
以及实际功能:
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(flatmap (lambda (i)
(map (lambda (j)
(list i j))
(range 1 (- i 1))))
(range 1 n)))
(define (get-prime-pairs n)
(filter (lambda (p) (prime? (apply + p)))
(get-pairs n)))
(get-prime-pairs 4)
; ((2 1) (3 2) (4 1) (4 3))
相当整洁。现在我正在尝试编写相同的函数,而不是仅仅做对,而是做一个size 的元组。到目前为止,这是我所拥有的:
(define (get-n-tuples size n)
(define (get-n-tuples-internal i args)
(cond ((= i size) (map (lambda (i) (cons i args)) (range 1 n)))
(else
(flatmap (lambda (k)
(get-n-tuples-internal (+ i 1) (cons k args)))
(range 1 n)))))
(get-n-tuples-internal 1 '()))
(define (get-prime-seqs size num)
(filter (lambda (p) (prime? (apply + p)))
(get-n-tuples size num)))
(get-prime-seqs 4 4)
; ...
; (3 2 4 4)
; (2 3 4 4)
; (1 4 4 4))
我发现困难的一件事是通过执行(range i (- (min args) 1)) 之类的操作来删除函数本身中的重复项。因此,我对所有循环都使用了相同的 (range 1 n)。
我将如何正确转换它以模拟初始函数,以便列表中的每个连续数字都必须更小,即如果序列中有三个数字,那么1 <= num1 < num2 < num3 <= N,并且有效的一对将是(4 2 1) 但不是 (1 2 4) 或 (5 1 1) ?
【问题讨论】:
标签: scheme lisp racket primes sicp