I don't know C# enough to tell you how to implement this, but I'll try to explain
what these functions do. I believe that you would use different data structures
in C# (and in modern Common Lisp, too, actually).
klactose wrote:
Code: Select all
(defun COUNT-HIGHEST (lists)
"Returns the highest occuring pattern in its arg."
(let* ((sorted-numbers (my-sort #'< (mapcar #'second lists)))
(numbers-only (remove-duplicates sorted-numbers))
(counts (count-them numbers-only sorted-numbers)))
(find-all (nth (position (first (my-sort #'> counts)) counts) numbers-only) lists)))
This takes a list of lists. The second item of each of these lists is
supposed to be a number. The function then finds the number with the
highest count and returns a list of all those lists that have this
number as second item (I presume, because I don't know how FIND-ALL is
defined).
Example:
Code: Select all
(count-highest '((A 2 B) (C 3 D) (E 5 F) (G 3 H)))
=> ((C 3 D) (G 3 H))
If we assume that FIND-ALL is defined like this (which is a bit bad
because a more general behaviour would usually be expected from a
function named like this):
Code: Select all
(defun find-all (number lists)
"Returns all lists in lists that have number as second element"
(remove number lists :test-not #'= :key #'second))
COUNT-HIGHEST could be defined much more efficiently like this:
Code: Select all
(defun count-highest (lists)
"Returns a list of those lists in lists that have the number with the highest
count as second element."
(let ((counts (make-hash-table)))
(flet ((count-up (number)
(if (gethash number counts)
(incf (gethash number counts))
(setf (gethash number counts) 1))))
(dolist (l lists)
(count-up (second l)))
(let ((highest-count (loop with max-count = 0
for c being the hash-keys of counts
do (when (> (gethash c counts) max-count)
(setf max-count c))
finally (return max-count))))
(find-all highest-count lists)))))
I believe that this is also more readily understood. I am using a hashtable for keeping the counts, because I don't know the range of numbers to expect. If that range is not too large and known, the hashtable could be replaced by an array.
Code: Select all
(defun MY-SORT (function lists)
"Non-destructive sort function."
(loop for item in (sort (loop for array-2 in lists
collect (list array-2)) function :key #'car)
collect (first item)))
This takes a function to sort by (e.g. #'<) and a list of lists.
It
then wraps each member of that list of lists into another list, sorts
them by the original members, and finally unwraps them into the result
list. What array-2
is outside of the loop is totally irrelevant,
because the "for" inside the loop establishes a local binding. The
use of the name array-2
in this context might be a code smell.
Anyway, this could have been achieved in a simpler and more
obviously correct form like this:
Code: Select all
(defun my-sort (function lists)
"Non-destructive sort function."
(sort (copy-list lists) function))
Code: Select all
(defun COUNT-THEM (singles numbers)
"Returns the counts of its first arg in its second arg."
(if (null singles)()
(cons (count (first singles) numbers)
(count-them (rest singles) numbers))))
This takes two lists and returns a list of counts, which are the
individual counts of each element from the first list in the second.
Example:
Code: Select all
(count-them '(a b c) '(a b c a c a b))
=> (3 2 2)
;; there are 3 a, 2 b, and 2 c in the second list
This function could be made tail-recursive (if recursion is desired),
but it would usually be implemented simpler like this:
Code: Select all
(defun count-them (singles numbers)
(mapcar (lambda (s)
(count s numbers))
singles))
"Just throw more hardware at it" is the root of all evil.
Svante