LISP рекурсия с использованием автомобиля / CDR - PullRequest
0 голосов
/ 09 мая 2018

Мне нужна помощь в назначении с использованием LISP. Мне нужно создать программу (две разные функции), которая может принимать выходные данные, такие как ((PRO) (LAN)) и преобразовывать их в НАТО (PapaRomeoOscar LimaAlfaNovember). А также иметь возможность конвертировать НАТО в английский ((PapaRomeoOscar) (LimaAlfaNovember)) в pro. Lan.

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

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

(if (= car(L1 L2) "i")
  (format -t “India ”)
(format -t ""))

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

Тогда для преобразования НАТО в английский, я думаю, вам нужно составить список, взять машину из списка. Затем возьмите автомобиль из машины и используйте оператор if, аналогичный приведенному выше. Затем возьмите CDR и рекурсивно передайте его обратно. Я не уверен, как будет выглядеть код, поэтому мне нужна большая помощь. Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

Вы пишете Лисп с синтаксисом Си. Не делай этого. Даже не думайте, что вы можете использовать Алгол, например. Вы знаете C Python, с ассимиляцией, так как в то время как C, C ++, Perl и Python находятся в одном семействе языков Alhol, Lisp - нет. Мне потребовалось некоторое время, чтобы найти петлю for в те дни. Более года на самом деле.

Я думаю, что, возможно, ввод должен быть '((p r o) (l a n)), а не '((pro)(lan)). Они очень сильно меняют то, что вам нужно.

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

(defun my-reverse (list)
  (labels ((helper (list acc)
              (if (endp list)
                  acc
                  (helper (cdr list) (cons (car list) acc)))))
    (helper list '())))

(my-reverse '(1 2 3)) ; ==> (3 2 1)

Это ничего не читает и не печатает, за исключением того, что REPL печатает возвращенное значение из вызова функции.

Вам нужно разделить вашу проблему на более простые. Так что представьте, я делаю это для одного символа. например. (to-nato 'p) ; ==> papa тогда у вас есть кое-что, что вы можете использовать в рекурсивной функции, которая переводит структуру.

Удачи!

0 голосов
/ 14 мая 2018

Сначала алгоритм

Кажется, вы понимаете принцип этого. Рекурсивная итерация по списку - очень распространенная идиома, это Lisp: вы берете список, делаете что-то с FIRST, а затем вызываете себя с REST (CAR / CDR - это устаревшие имена, я предпочитаю использовать больше значимые, когда это возможно).

(defun print-every (objects)
  (print (first objects))
  (print-every (rest objects)))

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

(defun print-every (objects)
  (when objects
    (print (first objects))
    (print-every (rest objects))))

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

(defun add-every (numbers &optional sum)
  (if numbers
      (add-every (rest numbers (+ (first numbers) sum))
      sum))

Во-вторых, синтаксис

Как и с любым другим языком программирования, вам нужно быть очень осторожным и не использовать что-то из языка A на языке B.

Аргумент, начинающийся с тире, например -t, - это то, что вы увидите в bash, а не в Лиспе. (format t "foo") напечатает foo (и разрыв строки).

В Лиспе (foo bar(1 2) 3) будет НЕ передавать аргументы 1 и 2 функции bar. Если вы хотите, ваш код должен быть (foo (bar 1 2) 3).

Кроме того, в Лиспе, какие отдельные выражения являются круглыми скобками и пробелами. Таким образом, '(pro) - это список, содержащий ONE символ, а '(p r o) - список, содержащий THREE символов.

0 голосов
/ 09 мая 2018
(if (= car(L1 L2) "i")
  (format -t “India ”)
(format -t ""))

Некоторые проблемы в этом фрагменте:

  • (= car (L1 L2) "i") читается как: применить функцию = к трем аргументам: переменные с именами car, (L1 L2) и "i", где (L1 L2) - применение функции L1 к аргументу L2. Если вы хотите взять car из списка, используйте (car list).

  • = работает только с числами: передача чего-либо еще, например строки, не будет работать должным образом. Используйте string= при сравнении строк, или лучше, не используйте строки на этом шаге. См. Например assoc, symbol-name и string-capitalize.

  • -t в (format -t "") неверно. Если вы хотите записать в новую строку, используйте nil. Если вы хотите вывести на стандартный вывод, используйте t.

  • (format -t “India“): обратите внимание, что вы используете кавычки, которые не должны использоваться в ваших программах ("). Кроме того, вы всегда печатаете пробел, что является проблемой, если вы хотите объединить разные слова, как объяснено в задании (например, "AlfaBeta").

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