Нужна подсказка по домашнему заданию, в котором предлагается добавить числа в список определенным образом

Это вопрос домашнего задания

Функция принимает список в качестве параметра, который может содержать столько слоев, сколько подсписок, сколько необходимо. Например, '(a (1 b 3)) или' ((a 3 5) (b (3 1) 4)). Выходные данные имеют ту же структуру списка, что и входные (это означает, что поддерживаются подсписки), но основной частью каждого списка является сумма всех чисел в списке. И все другие нечисловые значения отбрасываются. В качестве примера вывода рассмотрим «((a 3 5) (b (3 1) 4)), вывод должен быть» (16 (8) (8 (4))). Кроме того, используйте только инструкции / операции базовой схемы, такие как + - * /, car, cdr, cons, append, null ?, number ?, if / else, cond и т. Д. Невозможно использовать вспомогательный метод .

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

(define partialsums*
  (lambda (lis)
    (cond
      [(null? lis) '(0)]
      [(list? (car lis)) (cons (partialsums* (car lis)) (if (not (null? (cdr lis))) (partialsums* (cdr lis)) '()))]
      [(number? (car lis)) (cons (+ (car lis) (car (partialsums* (cdr lis)))) '())]
      [else (cons (+ 0 (car (partialsums* (cdr lis)))) '())])))

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

Кроме того, я не могу использовать вспомогательный метод. Все нужно делать внутри одной функции в рекурсивном стиле. letrec тоже не допускается.


person Isaac    schedule 29.01.2020    source источник
comment
Требование, которое говорит и т. Д., Не очень полезно. let базовый? lambda? (ИМХО, требование писать код наиболее подробным и наименее удобным способом - не очень хорошее обучение, если сразу не следует обратное.)   -  person molbdnilo    schedule 30.01.2020
comment
вы говорите, что все другие нечисловые значения отбрасываются, но затем вы показываете результат, в котором также отбрасываются все числовые значения и остаются только суммы. это тот результат, который вам нужен?   -  person Will Ness    schedule 31.01.2020
comment
Да, после добавления числа к сумме его следует удалить.   -  person Isaac    schedule 31.01.2020


Ответы (1)


Чтобы упростить жизнь, вы должны смоделировать данные. Поскольку типов нет, мы можем сделать это неформально.

Какова структура ввода?

Мы можем смоделировать это как «Определения данных» из Как разрабатывать программы. Прочтите раздел «Переплетенные данные», потому что наше определение данных похоже на определение S-выражение.

; A NestedElem is one of:
; - Atom
; - NestedList

; An Atom is one of:
; - Number
; - Symbol

; A NestedList is one of
; - '()
; - (cons NestedElem NestedList)

Мы можем определить предикат atom?, который поможет нам различать предложения типов данных в нашей программе.

; Any -> Boolean
; is `a` an atom?
(define atom?
  (lambda (a)
    (or (number? a)
        (symbol? a))))

Структура программы должна соответствовать структуре Данных.

Итак, мы определяем «шаблон» для наших данных. Он различает и разбивает все данные на пункты. Это дополнительно деструктурирует правую часть предложения.

; NestedElem -> ...
(define nested-elem-template
  (lambda (ne)
    (cond
      [(atom? ne) ...]
      [else ...])))

; Atom -> ...
(define atom-template
  (lambda (atom)
    (cond [(number? atom) ...]
          [(symbol? atom) ...])))

; NestedList -> ...
(define nested-list-template
  (lambda (nl)
    (cond [(null? nl) ...]
          [else (... (car nl)... (cdr nl))])))

Мы определенно знаем больше о данных. (car nl) в nested-list-template относится к типу NestedElem. Поэтому мы можем заполнить некоторые ... вызовами шаблонов, которые работают с такими данными. Точно так же мы можем обернуть рекурсивные вызовы вокруг выражений известного нам типа данных.

; NestedElem -> ...
(define nested-elem-template
  (lambda (ne)
    (cond
      [(atom? ne) (atom-template ne)]
      [else (nested-list-template ne)])))

; Atom -> ...
(define atom-template
  (lambda (atom)
    (cond [(number? atom) ...]
          [(symbol? atom) ...])))

; NestedList -> ...
(define nested-list-template
  (lambda (nl)
    (cond [(null? nl) ...]
          [else (... (nested-elem-template (car nl))
                     ... (nested-list-template (cdr nl)))])))

Теперь мы можем «заполнить пробелы».

Мы можем «фильтровать», «отображать» и «складывать» эту структуру данных. Все это можно определить, используя шаблон как основу.

Примечание 1: ваше аппаратное обеспечение просит вас выполнить несколько задач:

  1. удалить символы
  2. суммировать числа
  3. cons сумма по каждому списку

Не пытайтесь делать все в одной функции. Делегируйте несколько вспомогательных функций / обходов.

Примечание 2. Я не моделировал тип вывода. Это то же самое, что и тип ввода, за исключением того, что символ больше не является атомом.

person Atharva Shukla    schedule 29.01.2020
comment
О, я забыл упомянуть, я не могу использовать вспомогательный метод. Все нужно делать внутри одной функции в рекурсивном стиле. - person Isaac; 30.01.2020
comment
Вы можете использовать letrec? - person Atharva Shukla; 30.01.2020
comment
к сожалению нет. - person Isaac; 30.01.2020