Как заменить число во вложенном списке символами?

Кажется, я должен сделать это подробно; это моя домашняя работа. Я не хочу копировать написанный вами код. я новичок; то, что я пытаюсь узнать, это то, как разложить объект на отдельные части, а затем сосредоточиться на том, какую функцию я должен использовать для решения проблемы. Самостоятельно справиться с этими задачами немного сложно, потому что я совсем новичок в Лиспе, на самом деле в программировании. Надеюсь, вы сможете мне помочь.

Вот проблема: есть заданная константа

(defconstant *storms* '((bob 65)
                        (chary 150)
                        (jenny 145)
                        (ivan 165)
                        (james 120)))

Каждый шторм представлен списком с его названием и скоростью ветра.

Скорости ветра следует классифицировать следующим образом:

3974 tropical
7595 cat-1
96110 cat-2
111130 cat-3
131155 cat-4
156 и более cat-5

Теперь мне нужно написать две функции:

  • storm-categories должен генерировать имена категорий, например: (bob tropical), (chary cat-1),

  • а storm-distribution должно генерировать количество штормов в каждой категории, например: (cat-1 1), (cat-2 0),

Я пытаюсь решить эту проблему следующим образом:

  1. Используйте операторы if, чтобы определить тип скорости ветра:

    (если (и (> x 39) (‹ x 73)) (выведите 'тропический)) (если (и (> x 74) (‹ x 95)) (выведите 'cat-1)) (если (и (> x 96) (‹ x 110)) (напечатать 'cat-2)) (если (и (> x 111) (‹ x 130)) (напечатать'cat-3)) (если (и (> x 131) ( ‹ x 155)) (print'cat-4)) (if (и (> x 156)) (print 'cat-5))

  2. Замените скорость ветра (например, 65) на тип ветра (например, cat-1).

    (цикл для x в storms do (rplacd x 'windtype)

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


person roccia    schedule 10.09.2011    source источник
comment
да, это моя домашняя работа. Я уже исправил задачу.   -  person roccia    schedule 10.09.2011
comment
вы должны использовать тег домашнего задания: «Домашнее задание» означает, что спрашивающий просит помочь с домашним заданием в школе. Это позволяет потенциальным ответчикам понять, что они должны направлять учащегося в решении проблемы, а не просто показывать полный ответ. '   -  person Rainer Joswig    schedule 10.09.2011
comment
В Вашем тексте много опечаток (например, "ШТРОМ-РАСПРЕДЕЛЕНИЕ" вместо "ШТОРМ-РАСПРЕДЕЛЕНИЕ").   -  person Rainer Joswig    schedule 10.09.2011


Ответы (3)


Хорошо, Рокча, ты опубликовал свой ответ. Вот мой взломанный за несколько минут, но он должен дать вам некоторые идеи:

Сначала начнем с данных:

(defparameter *storms2004*
  '((BONNIE 65)
    (CHARLEY 150)
    (FRANCES 145)
    (IVAN 165)
    (JEANNE 120)))

(defparameter *storm-categories*
  '((39  73  tropical-storm)
    (74  95  hurricane-cat-1)
    (96  110 hurricane-cat-2)
    (111 130 hurricane-cat-3)
    (131 155 hurricane-cat-4)
    (156 nil hurricane-cat-5)))

Функция, которая проверяет, находится ли значение между двумя границами. Если правая граница также может отсутствовать (NIL).

(defun between (value a b)
  (<= a value (if b b value)))

Обратите внимание, что Lisp допускает предикат сравнения с более чем двумя аргументами.

Найдем категорию бури. Функции Лиспа FIND и FIND-IF находят объекты в списках.

(defun storm-category (storm-speed)
  (third (find-if (lambda (storm)
                    (between storm-speed (first storm) (second storm)))
                  *storm-categories*)))

Давайте вычислим категорию для каждого шторма. Поскольку мы получаем список (скорость штормового ветра), мы просто сопоставляем функцию, которая вычисляет категорию по списку. Нам нужно вернуть список штормов и категории.

(defun storm-categories (list)
  (mapcar (lambda (storm)
            (list (first storm)
                  (storm-category (second storm))))
          list))

Теперь мы берем тот же список штормов, но используем хэш-таблицу, чтобы отслеживать, сколько штормов было в каждой категории. MAPC похож на MAPCAR, но только из-за побочного эффекта обновления хеш-таблицы. ÌNCF увеличивает счетчик. Когда мы заполнили хеш-таблицу, нам нужно отобразить ее с помощью MAPHASH. Для каждой пары ключа и значения в таблице мы просто помещаем пару в список результатов, а затем возвращаем этот результат.

(defun storm-distribution (storms)
  (let ((table (make-hash-table)))
    (mapc (lambda (storm)
            (incf (gethash (second storm) table 0)))
          (storm-categories storms))
    (let ((result nil))
      (maphash (lambda (key value)
                 (push (list key value) result))
               table)
      result)))

Тест:

CL-USER 33 > (storm-category 100)
HURRICANE-CAT-2

CL-USER 34 > (storm-categories *storms2004*)
((BONNIE TROPICAL-STORM)
 (CHARLEY HURRICANE-CAT-4)
 (FRANCES HURRICANE-CAT-4)
 (IVAN HURRICANE-CAT-5)
 (JEANNE HURRICANE-CAT-3))

CL-USER 35 > (storm-distribution *storms2004*)
((HURRICANE-CAT-5 1)
 (HURRICANE-CAT-4 2)
 (HURRICANE-CAT-3 1)
 (TROPICAL-STORM 1))

Выглядит хорошо для меня.

person Rainer Joswig    schedule 14.09.2011
comment
Это очень ясно. но я думаю, что мне все еще нужно больше времени, чтобы прочитать ваш код. особенно последняя часть, make-hash-table. меня это еще смутило.. - person roccia; 15.09.2011

DEFCONSTANT неправильно. Нет смысла делать ваш ввод постоянным. Переменная, определенная с помощью DEFVAR или DEFPARAMETER, подойдет.

Вместо ЕСЛИ используйте УСЛОВИЕ. COND позволяет тестировать несколько условий.

Вы не хотите использовать PRINT. Зачем что-то печатать. Вы хотите вычислить значение.

RPLACA тоже ошибается. Это используется для деструктивной модификации. Вы не хотите этого. Вы хотите создать новое значение. В функции РАСПРЕДЕЛЕНИЕ можно использовать что-то вроде RPLACA (см. ниже).

Используйте функциональную абстракцию. Какие функции полезны?

  • BETWEEN-P, является ли значение X между a и b ?

  • STORM-CATEGORY, для заданной скорости ветра вернуть категорию

  • STORM-CATEGORIES, для списка элементов (скорость штормового ветра) вернуть список элементов (категория шторма). Сопоставьте входной список, чтобы создать список результатов.

  • РАСПРЕДЕЛЕНИЕ, для списка элементов (категория тегов) вернуть список с элементами (категория число тегов в этой категории).

  • STORM-DISTRIBUTION, для списка элементов (категория шторма) вернуть список с элементами (категория количество штормов в этой категории). Это в основном вызывает DISTRIBUTION с правильными параметрами.

Функция РАСПРЕДЕЛЕНИЕ самая сложная из вышеперечисленных. Обычно в качестве промежуточной помощи для подсчета вхождений можно использовать хэш-таблицу или список ассоциированных элементов. Сопоставьте входной список и обновите соответствующий счетчик.

Также: хорошим введением в основы Лиспа является книга Common Lisp: A Gentle Introduction to Symbolic Computation — он доступен для бесплатного скачивания в виде PDF-файла. Более интересным и базовым введением в Лисп является книга Land of Lisp.

person Rainer Joswig    schedule 10.09.2011

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

(defconstant *storms2004* '((BONNIE 65)(CHARLEY 150)(FRANCES 145)(IVAN 165)(JEANNE 120)))

(defun storm-category (x) ; for given windspeed return the category
(cond
((and (> x 39) (< x 73) 'tropical-storm))
((and (> x 74) (< x 95) 'hurricane-cat-1))
((and (> x 96) (< x 110) 'hurricane-cat-2))
((and (> x 111) (< x 130) 'hurricane-cat-3))
((and (> x 131) (< x 155) 'hurricane-cat-4))
( t 'hurricane-cat-5)

)
);end storm-category

(defun storm-categories (lst) ;for a list of storm and windspeed return storm's name and wind type
(let ((result nil))
(dolist (x lst (reverse result)) ;
(push
(list (first x) (storm-category (second x)) ) result)
)

)

);end storm-categories

    (defun storm-distribution (lst)
    (setq stormcategories '(tropical-storm hurricane-cat-1 hurricane-cat-2 hurricane-cat-3 hurricane-cat-4 hurricane-cat-5))
    (setq stormlist (storm-categories lst))
     (let(    (tropicalcount 0)
              (hurricane-cat-1count 0)
              (hurricane-cat-2count 0)
              (hurricane-cat-3count 0)
              (hurricane-cat-4count 0)
              (hurricane-cat-5count 0)
              (result nil)
         )

    (dolist (y stormlist )

    (cond
         ((eql (second y) 'tropical-storm) (setq tropicalcount (+ tropicalcount 1)))
         ((eql (second y) 'hurricane-cat-1) (setq hurricane-cat-1count (+ hurricane-cat-1count 1)))
         ((eql (second y) 'hurricane-cat-2) (setq hurricane-cat-2count (+ hurricane-cat-2count 1)))
         ((eql (second y) 'hurricane-cat-3) (setq hurricane-cat-3count (+ hurricane-cat-3count 1)))
         ((eql (second y) 'hurricane-cat-4) (setq hurricane-cat-4count (+ hurricane-cat-4count 1)))
         ((eql (second y) 'hurricane-cat-5)(setq hurricane-cat-5count (+ hurricane-cat-5count 1)))
    )
    );ebd dolist


    (push
          (list  (list 'tropicalstorm tropicalcount ) 
                 (list 'hurricane-cat-1 hurricane-cat-1count) 
                 (list 'hurricane-cat-2  hurricane-cat-2count ) 
                 (list 'hurricane-cat-3  hurricane-cat-3count ) 
                 (list 'hurricane-cat-4  hurricane-cat-4count ) 
                 (list 'hurricane-cat-5  hurricane-cat-5count ) 
          ) ;end list
    result) ;end push

    );end let

    );end distribution
person roccia    schedule 14.09.2011