2016-04-26 3 views
0

Я новичок в Scheme, и я ударил стену. У меня есть мои сортировки и средние функции, и я пытаюсь изменить медианную функцию, которую я нашел на этом сайте. Однако, независимо от того, что я пытаюсь, я продолжаю получать ошибки, когда у меня есть более одного выражения в медианной функции, или когда я пытаюсь использовать сортировку в медианной функции, она «неопределена».Scheme - Как найти медиану, используя пользовательские сортировки и средние функции?

(define (sort1 L) 
    (if (or (null? L) (<= (length L) 1)) L 
    (let loop ((l null) (r null) 
     (pivot (car L)) (rest (cdr L))) 
     (if (null? rest) 
      (append (append (sort1 l) (list pivot)) (sort1 r)) 
     (if (<= (car rest) pivot) 
      (loop (append l (list (car rest))) r pivot (cdr rest)) 
      (loop l (append r (list (car rest))) pivot (cdr rest))))))) 

(define (avg lst) 
    (let loop ((count 0) (sum 0) (args lst)) 
    (if (not (null? args)) 
     (loop (add1 count) (+ sum (car args)) (cdr args)) 
     (/ sum count)))) 

(define (median L) 
(if (null? L) (error "The list is empty") 
    (let loop ((L1 L) (L2 L)) 
     (cond ((null? (cdr L2)) (car L1)) 
      ((null? (cddr L2)) (list (car L1) (cadr L1))) 
      (else (loop (cdr L1) (cddr L2))))))) 

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

Любая помощь будет оценена, спасибо заранее.

+0

Я вижу много основных ошибок в скобках. Например, в определении «медианный» есть два парагона перед первым «let», который вы, вероятно, не намеревались, и есть также два parens после '(sort1 lst)', что означает, что это 'let' отсутствует тело. Тогда вам также не хватает пара до «let loop». Исправьте их, а затем задайте свой реальный вопрос. Помните, что круглые скобки обычно означают применение функции. –

+0

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

+0

Если вы хотите сделать что-то одно, то сделайте еще один, это функциональная композиция. Итак, вы хотите отсортировать список, а затем применить эту медианную функцию? Переименуйте медианную функцию в 'median/sorted' и определите реальную функцию median как состав' sort1' и 'median/sorted'. –

ответ

0

Как я уже сказал в комментарии, что вы хотите, не let, это композиция функций ,

Ваше текущее медиана функция заключается в следующем:

(define (median L) 
    (if (null? L) 
     (error "The list is empty") 
     (let loop ((L1 L) (L2 L)) 
     (cond ((null? (cdr L2)) (car L1)) 
       ((null? (cddr L2)) (list (car L1) (cadr L1))) 
       (else (loop (cdr L1) (cddr L2))))))) 

Но, как Оскар Лопес отметил, это не правильно вычислить медиану. Тем не менее, он выполняет некоторые работы, поэтому сохраните их. Переименуйте его в median-helper или что-то в этом роде.

(define (median-helper L) 
    (if (null? L) 
     (error "The list is empty") 
     (let loop ((L1 L) (L2 L)) 
     (cond ((null? (cdr L2)) (car L1)) 
       ((null? (cddr L2)) (list (car L1) (cadr L1))) 
       (else (loop (cdr L1) (cddr L2))))))) 

Затем вы можете использовать функцию композицию для определения «реальные» срединные функций:

(define (median lst) 
    (median-helper (sort1 lst))) 

Это возвращает средний элемент для списков нечетной длины, а среднего-два элемента даже списки длины , Если это так хочется, отлично. Если нет, то вы можете исправить median-helper, вернув среднее значение во втором случае cond. Итак, вместо (list (car L1) (cadr L1)) у вас будет (avg (list (car L1) (cadr L1))).

;; median-helper : (Listof Number) -> Number 
(define (median-helper L) 
    (if (null? L) 
     (error "The list is empty") 
     (let loop ((L1 L) (L2 L)) 
     (cond ((null? (cdr L2)) (car L1)) 
       ((null? (cddr L2)) (avg (list (car L1) (cadr L1)))) 
       (else (loop (cdr L1) (cddr L2))))))) 

;; median : (Listof Number) -> Number 
(define (median lst) 
    (median-helper (sort1 lst))) 
+0

... I не могу поверить, что я не понял этого из вашего комментария, эти две строки кода для медианных были все, что мне нужно. Спасибо! –

+0

Должны ли вы отметить это как принято тогда? –

+0

Да, делал некоторые последние штрихи на случай, если я столкнулся с другими проблемами. Еще раз спасибо. –

1

Я думаю, вы неправильно понимаете определение median. Очень простой (если не особенно эффективная) реализация следующим образом:

(define (my-sort L) 
    (sort L <)) 

(define (average x y) 
    (exact->inexact (/ (+ x y) 2))) 

(define (median L) 
    (if (null? L) 
     (error "The list is empty") 
     (let* ((n (length L)) 
      (sorted (my-sort L)) 
      (half (quotient n 2))) 
     (if (odd? n) 
      (list-ref sorted half) 
      (average (list-ref sorted half) 
        (list-ref sorted (sub1 half))))))) 

Он работает, как определено:

(median '()) 
=> The list is empty 
(median '(3 2 1 5 4)) 
=> 3 
(median '(6 4 3 1 2 5)) 
=> 3.5 
+0

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

+0

@WolvenOmega Я назвал 'average' тем, что вы называете' mean', но это намного проще, чем вы думаете, вам нужно только вычислить среднее из двух средних элементов в отсортированном списке с четным числом элементов –

Смежные вопросы