Common Lisp에서 가장 큰 숫자와 가장 작은 숫자와 두 번째로 작은 숫자 사이의 범위를 나타내는 함수를 만들고 있습니다.
이 함수는 가장 작은 숫자와 가장 큰 숫자를 만들 수 있습니다. (나는 그것을 확인했다). 하지만이 함수는 목록에서 '두 번째로 작은 숫자'를 만들 수 없습니다 ...
이 문제를 해결하려면 어떤 사항을 고려해야합니까? 이 기능을 만들기 위해 필요한 조건을 충분히 충족했다고 생각합니다 ..
당신의 큰 도움이 필요합니다. 이 결과는 다음과 같아야합니다.
(내 범위 '(0 7 10 2 3 -1)) => (-1 10)
이것은 내가 만든 코드입니다.
(defun my-range (list-of-numbers)
(let ((largest (first list-of-numbers))
(smallest (first list-of-numbers))
(secsmallest (first list-of-numbers)))
(dolist (element1 (rest list-of-numbers) largest)
(when (> element1 largest)
(setf largest element1)))
(dolist (element2 (rest list-of-numbers) smallest)
(when (< element2 smallest)
(setf smallest element2)))
(dolist (element3 (remove smallest list-of-numbers) secsmallest)
(when (< element3 secsmallest)
(setf secsmallest element3))
(return (list (- smallest secsmallest) largest)))))
목록에서 가장 작은 요소 두 개를 얻으려면 한 번에 작업 할 수 있습니다. 우리는 지금까지 본 가장 작은 값 두 개 (최대) 목록을 유지합니다. 항목을 스캔 할 때이 목록에 순서대로 삽입하고 항상 세 번째로 작은 값을 버립니다. 완료되면 두 개의 가장 작은 값 목록이 있습니다. (또는 목록에 그 개수 만있는 경우 0 값 또는 하나의 값 목록)
순서가없는 n : quickselect 목록 에서 k 개의 가장 작은 값 을 선택하는 효율적인 알고리즘이 있습니다 .
o (n log n) 성능 발생에 신경 쓰지 않는다면 전체 목록을 정렬하고 결과에서 처음 두 값을 선택할 수 있습니다.
정확히 두 개의 항목을 원하는 상황은 다음 줄을 따라 하드 코딩 할 수 있습니다.
(defun least-two (list)
(cond
((null list) nil)
((null (cdr list)) (car list))
(t (let ((a (car list))
(b (cadr list)))
(unless (< a b)
(rotatef a b))
(dolist (el (cddr list) (values a b))
(cond
((< el a) (shiftf b a el))
((< el b) (setf b el))))))))
매우 쉬움 : SE 브라우저 편집기에서 보는 그대로 정확히 입력하고 닫는 괄호 두 개를 제외하고 제대로 작동하는 것 같습니다. :)
values
목록 대신 여러 값을 반환 하는 데 자유롭게 사용할 수있었습니다. 목록을 원하면로 변경 해야 (list a b)
하며 메인의 두 번째 경우도 대신 cond
반환해야합니다 .list
(car list)
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다