Как получить сумму всех элементов>10 в данном списке, используя схему Chez?

Если создать схему Chez ex, которая делает СУММ всех элементов из lista_de_elemente

(define lista_de_elemente (list 2 4 1 12 32 3 34 12))

(define suma
    (lambda()
        (apply + lista_de_elemente)))

Как мне сделать сумму только элементов больше 10?

5 ответов

Решение

Общая техника состоит в том, чтобы сначала сформировать список элементов, которые вы хотите обработать. У вас уже есть этот список. Затем вы хотите применить одно или несколько преобразований к списку ввода. В этом случае нам не нужно делать никаких преобразований. Затем вы фильтруете список, чтобы получить только те элементы, которые удовлетворяют определенному условию. Наконец, вы применяете операции, объединяющие элементы в отфильтрованном списке.

Этот общий способ обработки списков описан в SICP как

enumerate -> transform (map) -> filter -> accumulate

Теперь, в этом случае, нам не нужно ничего перечислять или отображать, потому что у нас уже есть наш входной список, как я упоминал ранее.

(define (filter predicate sequence) (cond
   ((null? sequence) '())
   (else (cond
   ((predicate (car sequence)) (cons (car sequence) (filter predicate (cdr sequence))))
   (else (filter predicate (cdr sequence)))))))



(define (accumulate op initial sequence) (cond
                   ((null? sequence) initial)
                   (else (op (car sequence) (accumulate op initial (cdr sequence))))))


(define (sum-list list) (accumulate + 0 (filter (lambda(x) (cond ((> x 10) #t) (else #f)))list)))


(sum-list (list 1 2 3 45 12))
;Output: 57

predicate это просто условие, которое оценивается как истинное или ложное.

Я думаю, что вы можете обобщить это немного, поэтому я сделал filter-sum такой, что вы можете сделать это:

#!r7rs                                ; #!r6rs for r6rs
(import (scheme)                      ; replace scheme with rnrs for r6rs
        (only (srfi :1) filter fold)) ; remove filter for r6rs

;; I renamed you list
(define *lista-de-elemente* '(2 4 8 10 12 14 16))

(define (suma)
  (define (>10? x)
    (> x 10))

  (filter-sum >10? *lista-de-elemente*)) 

(suma) ; ==> 42

Вот несколько возможных версий filter-sum, У нас есть прямой рекурсивный путь:

(define (filter-sum predicate lst)
  (cond ((null? lst) 0)
        ((not (predicate (car lst))) (filter-sum predicate (cdr lst)))
        (else (+ (car lst) (filter-sum predicate (cdr lst))))))

Но это не очень хорошо, так как порядок или цифры не важны. Мы можем сделать этот хвост рекурсивно с аккумулятором, здесь с именем let вместо подмышечной процедуры:

(define (filter-sum predicate lst)
  (let loop ((lst lst)(acc 0))
    (if (null? lst)
        acc
        (loop (cdr lst) 
              (if (predicate (car lst))
                  (+ acc (car lst))
                  acc)))))

Теперь такие петли с хвостовой рекурсией и аккумулятором можно превратить в складку. Вы найдете склад в библиотеке списка SRFI-1:

(define (filter-sum predicate lst)
  (fold (lambda (x acc)
          (if (predicate x)
              (+ acc x)
              acc))
        0
        lst))

Большая часть кода теперь, если вы должны добавить или нет. С filter Вы можете отфильтровать так, чтобы можно было добавить каждый элемент в сгибе:

(define (filter-sum predicate lst)
  (fold + 0 (filter predicate lst)))

filter также находится в списке библиотеки SRFI-1. Теперь, если вы знаете, что ваш список чисел выше 10 короткий. Как несколько сотен, вы можете полностью изменить fold для apply и это может даже стать немного быстрее, но вы делаете ограничения на длину списка. (Многие системы схем выдвигают аргументы в стеке ограниченного размера, в то время как сворачивание накапливает список по одному элементу за раз.)

Используя filter:

(define suma
  (lambda()
    (apply + (filter (lambda (e) (> e 10)) lista_de_elemente))))

КСТАТИ, suma должен иметь список в качестве аргумента:

(define suma
  (lambda(lst)
    (apply + (filter (lambda (e) (> e 10)) lst))))

(suma lista_de_elemente)

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

(define elems (list 2 4 1 12 32 3 34 12))

(define (suma lst)
  (apply + lst))

(suma (filter (lambda (x) (> x 10)) elems))

Теперь у вас есть ваш обобщенный sum, и вы передаете ему только ту часть исходного списка, которую вы намереваетесь суммировать.

Добавьте функцию, которая возвращает список, отфильтровывая числа не больше 10. Передайте возвращаемое значение этого в apply как у тебя.

(define (get-greater-than-ten lst)

  (define (helper in out)
    (if (null? in)
      out
      (if (> (car in) 10)
        (helper (cdr in) (append out (list (car in))))
        (helper (cdr in) out)))

  (helper lst `()))

Используйте это как:

(define suma
    (lambda()
        (apply + (get-greater-than-ten lista_de_elemente))))
Другие вопросы по тегам