Ракетка: Поток отрицательный и проблема с i-м элементом - PullRequest
0 голосов
/ 21 мая 2019

У меня два вопроса по домашнему заданию по программированию на ракетке:

Первый: написать функцию kth-item, которая принимает два аргумента, первый - это поток s, а второй - число k, и он выдает результат извлечения k элементов из потока, возвращая только последний элемент , Очень похоже на предыдущий, но возвращает только один элемент. Вы можете предположить, что k больше 0.

Второй: написать поток negate-2-and-5, который подобен потоку натуральных чисел (т. Е. 1, 2, 3, ...), за исключением того, что числа, кратные 2 или 5, сводятся на нет (т. Е. , 1, -2, 3, -4, -5, -6, 7, -8, 9, -10, 11, -12, 13, -14, ...). Помните, что поток - это thunk, который при вызове создает пару, где автомобиль пары - это следующее число, а cdr будет продолжением потока.

Что касается первых вопросов, я знаю, как получить список ih, но я не представляю, как продолжить получать последний элемент.

Что касается второго вопроса, я знаю, как получить 2 или 5 работ, но я не знаю, как их объединить, поэтому оба 2 и 5 могут работать одновременно.

(define (next-k-items s k)
  (if (<= k 0)
      empty
      (cons (car (s))
            (next-k-items (cdr (s)) (- k 1)))))


(define (negate-2-and-5)
  (define (f x) (cons (if (= 0 (remainder x 5)) (- x) x)
                      (lambda () (f (+ x 1)))))
  (f 1))

Вот коды тестирования:

(ожидаемый чек (нац-элемент натс 3) 3)

(ожидаемый чек (next-k-items negate-2-and-5 7) '(1 -2 3 -4 -5 -6 7))

1 Ответ

2 голосов
/ 21 мая 2019
(require racket)

Потоки можно рассматривать как бесконечные списки, в которых cdr упакован в thunk (лямбда без аргументов)

(define-syntax-rule (cons-stream x y)
  (cons x (lambda () y)))

Чтобы упростить работу с потоками, мы определяем следующий интерфейс:

(define stream? pair?)
(define null-stream null)
(define null-stream? null?)
(define stream-first car)
(define (stream-rest s) ((cdr s)))

Поток может быть создан с использованием собственной ссылки:

(define ones (cons-stream 1 ones))

Мы можем определить карту (ы) для потоков:

(define (stream-map f s)
  (if (null-stream? s)
      null-stream
      (cons-stream (f (stream-first s))
                   (stream-map f (stream-rest s)))))

(define (stream-map2 f s1 s2)
  (if (null-stream? s1)
      null-stream
      (cons-stream (f (stream-first s1) (stream-first s2))
                   (stream-map2 f (stream-rest s1)
                                (stream-rest s2)))))

... и использовать его для создания потока nats:

(define nats (cons-stream 1 (stream-map2 + ones nats)))

Функция, которую вы хотите, может быть четко определена с помощью вышеуказанных функций:

;; Stream Number -> Number
;; the kth item of s
(define (kth-item s k)
  (if (= k 1)
      (stream-first s)
      (kth-item (stream-rest s) (sub1 k))))


(check-expect (kth-item nats 1) 1)
(check-expect (kth-item nats 2) 2)
(check-expect (kth-item nats 3) 3)

В вашем коде (s) не правильно, потому что s не лямбда. Нам нужно минусить первый элемент (car s) и force остальной поток ((cdr s)). Об этом позаботятся stream-first и stream-rest.

;; Stream Number -> Stream
;; builds a list of first k items of s
(define (next-k-items s k)
  (if (= k 0)
      empty
      (cons (stream-first s)
                   (next-k-items (stream-rest s) (- k 1)))))

(check-expect (next-k-items nats 10) '(1 2 3 4 5 6 7 8 9 10))

Определение карты снова оказывается полезным:

;; Stream -> Stream
;; negates the multiples of 2 and 5
(define (negate-2-and-5 s)
  (stream-map (λ (x) (if (or (zero? (modulo x 2))
                             (zero? (modulo x 5)))
                         (* -1 x)
                         x))
              s))

... и next-k-items

(check-expect (next-k-items (negate-2-and-5 nats) 7) '(1 -2 3 -4 -5 -6 7))
...