You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I can't find a utility that can tell me if any two lists share structure anywhere.
TAILP only works correctly if you provide it the concrete tail of the list. Running TAILP for every element of the other list mostly achieves the goal but has quadratic time complexity, which is painful, plus one needs to remember to handle dotted lists.
I propose adding a TAILP* operator which uses a hash table for detection of shared structure and therefore can do this in linear time and linear memory. Oh, and it also handles circularities.
A quick and hasty implementation:
(defuntailp* (object-1 object-2)
(let ((hash-table (make-hash-table:test#'eq)))
;; Populate the hash table with objects from the first list.
(typecase object-1
(atom (setf (gethash object-1 hash-table) :first))
(cons (loop for cons on object-1
when (gethashconshash-table)
;; For cyclic lists, return gracefully.returnnil
else
;; Mark cons cell as visited.do (setf (gethashconshash-table) :first)
when (atom (cdrcons))
;; For proper and dotted lists, remember the last CDR.do (setf (gethash (cdrcons) hash-table) :first))))
;; Check if any list structure of the second list is in the hashtable.
(typecase object-2
(atom (when (eq (gethash object-2 hash-table) :first) object-2))
(cons (loop for cons on object-2
for result = (gethashconshash-table)
when (eq result :first)
;; We found the tail, return it.returnconswhen (eq result :second)
;; If we hit a cycle in this list, there is no match.returnnil
else
;; Mark cell as visited.do (setf (gethashconshash-table) :second)
when (atom (cdrcons))
;; For proper and dotted lists, check the last CDR.when (gethash (cdrcons) hash-table)
return (cdrcons))))))
In the flurry of activity I overlooked this issue. If you're still interested this seems like a good idea, although it could use a more descriptive name (common-tail-p?).
I can't find a utility that can tell me if any two lists share structure anywhere.
TAILP
only works correctly if you provide it the concrete tail of the list. RunningTAILP
for every element of the other list mostly achieves the goal but has quadratic time complexity, which is painful, plus one needs to remember to handle dotted lists.I propose adding a
TAILP*
operator which uses a hash table for detection of shared structure and therefore can do this in linear time and linear memory. Oh, and it also handles circularities.A quick and hasty implementation:
Some quick and hasty REPL tests:
How does this sound? I can clean this up, add more tests, and make a PR if this sounds like a good addition.
The text was updated successfully, but these errors were encountered: