Нахождение общего среднего числа вложенных списков в схеме? - PullRequest
0 голосов
/ 02 ноября 2010

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

(average-lists (list 1 2 (list 3 (list 4 5)) 6)))

Должен вернуться 3.5. Я играл со следующим кодом в течение нескольких дней, и сейчас я получаю его, возвращая сумму, но не среднее значение. Кроме того, важно, чтобы значения самых внутренних списков вычислялись первыми, поэтому не нужно извлекать все значения и просто их усреднять.

Вот что у меня есть:

(define (average-lists data)
  (if (null? data)
      0.0
      (if (list? (car data))
            (+ (average-lists (car data)) (average-lists (cdr data)))
            (+ (car data) (average-lists (cdr data))))))

Я пробовал этот подход, а также пытался использовать map для рекурсивного сопоставления лямбда-функции и некоторых других, но я просто не могу ее найти. Я думаю, что я делаю вещи сложнее, чем должно быть.

Я написал следующее, пытаясь найти и другие пути, которые могут оказаться полезными:

(define (list-num? x)    ;Checks to see if list only contains numbers
  (= (length (filter number? x)) (length x)))

(define (list-avg x)     ;Returns the average of a list of numbers
  (/ (accumulate + 0 x) (length x)))

Ваша помощь очень ценится! Эта проблема была для меня кошмаром. :)

Ответы [ 2 ]

3 голосов
/ 02 ноября 2010

Если параметры не требуют иного, вы захотите определить вспомогательную процедуру, которая может вычислять как sum , так и count от количества элементов в каждом списке.Как только вы сможете усреднить один список, его легко адаптировать к вложенным спискам, проверив, является ли car списком.

Этот метод даст вам среднее значение за один проход по списку, скореечем два или более проходов, что решения, которые сглаживают список или делают подсчет и суммы в двух отдельных проходах.Вы должны были бы получить сумму и подсчеты отдельно от подсписков, чтобы получить общее среднее значение (см. Комментарий zinglon ниже).

Редактировать:

В одну сторонучтобы получить и сумму, и счет обратно, нужно передать его обратно в паре:

(define sum-and-count  ; returns (sum . count)
  (lambda (ls) 
   (if (null? ls)
       (cons 0 0)
       (let ((r (sum-and-count (cdr ls))))
         (cons (+ (car ls) (car r))
               (add1 (cdr r)))))))

Эта процедура получает сумму и количество элементов списка.Сделайте то, что вы сделали со своим собственным average-lists, чтобы заставить его просматривать глубоко вложенные списки.Затем вы можете получить среднее значение, выполнив (/ (car result) (cdr result)).

. Или вы можете написать отдельные процедуры deep-sum и deep-count, а затем выполнить (/ (deep-sum ls) (deep-count ls)), но для этого требуется два прохода по списку.

3 голосов
/ 02 ноября 2010
(define (flatten mylist)
  (cond ((null? mylist) '())
        ((list? (car mylist)) (append (flatten (car mylist)) (flatten (cdr mylist))))
        (else (cons (car mylist) (flatten (cdr mylist))))))


(define (myavg mylist)
  (let ((flatlist (flatten mylist)))
    (/ (apply + flatlist) (length flatlist))))

Первая функция выравнивает список.То есть он конвертирует '(1 2 (3 (4 5)) 6) в '(1 2 3 4 5 6). Тогда нужно просто применить + к плоскому списку и сделать среднее.

Ссылка для первой функции: http://www.dreamincode.net/code/snippet3229.htm

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...