2015-02-13 2 views
0

Я новичок в Racket, и я пытаюсь написать рекурсивную функцию, которая принимает число n и возвращает сумму квадратов первых целых чисел n. Например, (this-function 3) возвращает 14, потому что 14 равно 9 + 4 + 1 + 0.Racket рекурсивная функция для возврата суммы списка квадратов чисел

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

(define (squared my-list) 
    (cond [(empty? my-list) empty] 
     [(zero? my-list) 0] 
     [else (cons (expt my-list 2) 
        (cons (squared (sub1 my-list)) empty))])) 

, который, если я бегу (squared 3) возвращается (cons 9 (cons (cons 4 (cons (cons 1 (cons 0 empty)) empty)) empty)).

При запуске второй функции (функция суммы):

(define (sum numbers) 
    (cond 
    [(empty? numbers) 0] 
    [else (+ (first numbers) (sum (rest numbers)))])) 

и запустить (sum (squared 3)) я получаю сообщение об ошибке, потому что (squared 3) возвращает дополнительные «минусы» в списке.

Как это исправить?

+0

Это звучит как домашнее задание. Разрешено ли вам использовать такие функции, как 'foldl' и' map'? –

+0

Это так. Я зашел так далеко, но все еще сосать из-за лишних минусов. И нет, мы не изучили склад и карту. – Ryan

ответ

1

Ваша логика в squared немного прочь. Я объясню предложение вопросов по-поводу.

[(empty? my-list) empty] 

Это не имеет никакого смысла, так как my-list никогда не будет даже список. Фактически, my-list плохо назван. Параметр squared принимает номер, а не список. Этот пункт может быть полностью удален.

[(zero? my-list) 0] 

Это то, что фактическое прекращения дело должно быть, но он не должен возвращаться 0. Помните, squared должен вернуть список, а не номер. Этот случай должен вернуть empty.

[else (cons (expt my-list 2) 
      (cons (squared (sub1 my-list)) empty))])) 

И, наконец, этот пункт слишком сложный. У вас есть правильная идея: до cons новый номер на остальной части списка, но вы слишком много раз задумываетесь. Помните, что результат (squared (sub1 my-list)) сам по себе является списком, а второй аргумент cons - это остальная часть списка. Вам не нужны дополнительные минусы - вы можете просто полностью его устранить.

Сочетание этих изменений, вы получите это, который делает то, что вы хотите:

(define (squared my-list) 
    (if (zero? my-list) empty 
     (cons (expt my-list 2) 
      (squared (sub1 my-list))))) 

(. Я также заменил cond с if так cond больше нет необходимости)


Это говорит, этот код не очень Racket-y.У вас была хорошая идея разбить вашу функцию на две функции - в функциональном программировании функции должны действительно делать только один вещь, но вы можете сломать это дальше! В частности, вы можете использовать встроенные функции более высокого порядка Racket, чтобы сделать этот тип вещей чрезвычайно простым.

Вы можете заменить всю вашу функцию squared путем соответствующего объединения map и range. Например, следующее создает список квадратов от 0-3.

(map (curryr expt 2) (range 4))

(Вам нужно позвонить (range 4), потому что список генерируется range от 0 до N-1.)

Далее, вы можете легко подвести список, используя apply. Подводя вышеупомянутый список, вы могли бы сделать что-то вроде этого:

(apply + (map (curryr expt 2) (range 4)))

Это дает вам соответствующий результат 14. Очевидно, что вы можете инкапсулировать это в свою функцию для ясности, но гораздо яснее то, что делает вышеприведенный код, когда вы изучаете функциональные конструкции Racket.

(Тем не менее, я не уверен, что если вы разрешили использовать те, так как ваш вопрос выглядит как домашнее задание. Просто отметить для дальнейшего использования и полноты.)

+0

Большое вам спасибо, я очень ценю это. И объяснение это очень помогло. – Ryan

1

Наиболее простым решением является использование закрытой формы:

(define (sum-of-squares n) 
    (* 1/6 n (+ n 1) (+ n n 1))) 

Кредит: WolframAlpha

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