December 17, 2025Dec 17 Forgive my ignorance, I am a LISP beginner.I have used OM docs and resorted to gemini-LLM.I simply cannot believe that there's not an easier solution for the problem I am looking for.Please let me know if I am right and please help me extending my LISP skills - thanks.Basically I have a list (level 0) which contains multiple sublists (level 1) which themselves hold on next level 2 two sublists as elements.I want to randomly pick one of the lists on level 1.I'd expect that the picked list is one level below the top and it resembles the original substructure below, i.e. holding two sublists as elements.I have expected that OM's (rnd-pick ..) and (rnd-sample 1 ..) will do the job.But if I have not completely messed it up they seem not to work as I expected.With help on AI I somehow got it to work, but it seems a bit too complicated.LISP aficionados / OM experts: any easier solution?;;; Musical Motivation ---------------------------- ;;; ;;; Combine LCCOTO with Triad Pair technique ;;; ;;; Process: ;;; We choose a parent scale ;;; From that scale we create all possible triads ;;; Next we find pairs of chords which have no overapping pitches ;;; These pairs have the property to cover the scale widely. ;;; Hence using them as cells for melodic material might be compositionally interesting. ;;; ;;; Below I intend to find these pairs and randomy pick one ;;; Setup ------------------------------------ ;; Choose a Scale (setf my-scale (expand-tonality '(c4 lydian))) => (c4 d4 e4 fs4 g4 a4 b4) ;; Get all triads of this scale and keep them all in one octave (defun get-triad (x) (subseq x 0 3)) (setf triads-mat (ambitus-octaves 'c4 1 (mapcar 'get-triad (pitch-melodize (mclist (gen-chord-series my-scale my-scale :width 30 :type 3)))))) => ((c4 e4 g4) (d4 fs4 a4) (e4 g4 b4) (fs4 a4 c4) (g4 b4 d4) (a4 c4 e4) (b4 d4 fs4)) ;; Looks OK :-) ;; Find non-overlapping triads (defun find-disjoint-pairs (list-of-lists) (loop for (sub1 . rest) on list-of-lists append (loop for sub2 in rest when (null (intersection sub1 sub2)) collect (list sub1 sub2)))) (setf all-triad-pairs (find-disjoint-pairs triads-mat)) => (((c4 e4 g4) (d4 fs4 a4)) ((c4 e4 g4) (b4 d4 fs4)) ((d4 fs4 a4) (e4 g4 b4)) ((e4 g4 b4) (fs4 a4 c4)) ((fs4 a4 c4) (g4 b4 d4)) ((g4 b4 d4) (a4 c4 e4)) ((a4 c4 e4) (b4 d4 fs4))) ;; Looks OK :-) ;; Is a list with Level 0, level 1, level 2 ;; I want to pick on level 1 ;; i.e. a valid solution would be: ((d4 fs4 a4) (e4 g4 b4)) ;; thats 3rd row ;;; Issue start here -------------------------------- (setf one-triad-pair (rnd-pick all-triad-pairs)) => (fs4 a4 c4) ;; Not what I'd expect; it should be a list with two sub-list-elements (setf one-triad-pair (rnd-sample 1 all-triad-pairs)) => ((fs4 a4 c4)) ;; Again, not what I'd expect ;;; Solution , but a bit complex --------------------- (setf one-triad-pair (nth (rnd-pick (gen-integer (- (length all-triad-pairs) 1))) all-triad-pairs)) => ((d4 fs4 a4) (e4 g4 b4)) ;; Valid solution ;;; Question: Is this complicated solution really needed? ;;; Is there a OM function which does the sampling from outside to inside ?
December 18, 2025Dec 18 I only had a quick look/read and built something like this: at level 0 you get a random pick of the pairs, at level 1 a sequence within a pair, and at level 2 a single value from a sequence of a pair. Was that what you meant? For me, level 0 is not the whole list (i.e. the outermost parentheses), but rather all the pairs inside the outermost parentheses. If I do (length alist), I get 7 here, not 1. So there are 3 levels possible (0 to 2);;; (setf alist '(((c4 e4 g4) (d4 fs4 a4)) ((c4 e4 g4) (b4 d4 fs4)) ((d4 fs4 a4) (e4 g4 b4)) ((e4 g4 b4) (fs4 a4 c4)) ((fs4 a4 c4) (g4 b4 d4)) ((g4 b4 d4) (a4 c4 e4)) ((a4 c4 e4) (b4 d4 fs4)))) (defun pick-from-level (alist level) (cond ((= level 0) (nth (random (length alist)) alist)) ((= level 1) (rnd-pick (nth (random (length alist)) alist))) ((= level 2) (rnd-pick (flatten alist))))) (pick-from-level alist 0) => ((g4 b4 d4) (a4 c4 e4)) (pick-from-level alist 1) => (c4 e4 g4) (pick-from-level alist 2) => b4If you want it nested—that is, pick from pick…—then you just need to nest the function. It will then always pick within the same level, either going down or up.(pick-from-level (pick-from-level alist 0) 0) => (fs4 a4 c4)"It will then always pick within the same level,..." : PATH not LEVEL
Create an account or sign in to comment