From: Mattias Nilsson
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <558a7872-1ffc-477e-b71a-a1697013d566@m44g2000hsc.googlegroups.com>
On Mar 21, 10:58 pm, Ken Tilton <···········@optonline.net> wrote:
> [...]
> This is somewhat distorted, but the labeled fn show-one is what I really
> have to do: given a mask and a list of numbers some of whom have already
> been "used" indicated by (= 1 (bit mask <that number>)), pick a number
> at random from those still unused. Without consing.
> [...]

I don't know if this is any better, but at least it is different:

(let* ((nums (list 0 1 2 3 4 5 6 7))
       (used (make-array (length nums)
                         :element-type 'bit
                         :initial-element 0)))
  (loop for i below (length nums)
        do (show-one nums used)))

(defun show-one (list mask)
  (let ((position (pick-one mask)))
    (when position
      (setf (bit mask position) 1)
      (print (nth position list)))))

(defun pick-one (mask)
  (let ((first (position 0 mask)))
    (when first
      (let* ((choices (- (length mask) first 1))
             (random (+ first
                        (if (zerop choices) 0 (random choices)))))
        (case (random 2)
          (0 (or (position 0 mask :start first :end random :from-end
t)
                 (position 0 mask :start random)))
          (1 (or (position 0 mask :start random)
                 (position 0 mask :start first :end random :from-end
t))))))))

(I hope Google Groups didn't mess that up...)

The CASE is a bit ugly, but this was just a quickie...

Mattias

From: Mattias Nilsson
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <2b4400db-1e9d-4793-bceb-405ea8687e57@b64g2000hsa.googlegroups.com>
;;;; Before someone else complains:

(let* ((nums (list 0 1 2 3 4 5 6 7))
       (used (make-array (length nums)
                         :element-type 'bit
                         :initial-element 0)))
  (loop for i below (length nums)
        do (show-one nums used)))

(defun show-one (list mask)
  (let ((position (pick-one mask)))
    (when position
      (setf (bit mask position) 1)
      (print (nth position list)))))

;;; Slightly improved randomization:

(defun pick-one (mask)
  (let ((first (position 0 mask)))
    (when first
      (let* ((choices (- (length mask) first))
             (random (+ first (random choices))))
        (case (random 2)
          (0 (or (position 0 mask :start first :end random
                                  :from-end t)
                 (position 0 mask :start random)))
          (1 (or (position 0 mask :start random)
                 (position 0 mask :start first :end random
                                  :from-end t))))))))


;;; Mattias
From: Ken Tilton
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <47e50d29$0$25063$607ed4bc@cv.net>
I better make a better example before you all go postal on me. :)

gimme a sec.

  k

Mattias Nilsson wrote:
> ;;;; Before someone else complains:
> 
> (let* ((nums (list 0 1 2 3 4 5 6 7))
>        (used (make-array (length nums)
>                          :element-type 'bit
>                          :initial-element 0)))
>   (loop for i below (length nums)
>         do (show-one nums used)))
> 
> (defun show-one (list mask)
>   (let ((position (pick-one mask)))
>     (when position
>       (setf (bit mask position) 1)
>       (print (nth position list)))))
> 
> ;;; Slightly improved randomization:
> 
> (defun pick-one (mask)
>   (let ((first (position 0 mask)))
>     (when first
>       (let* ((choices (- (length mask) first))
>              (random (+ first (random choices))))
>         (case (random 2)
>           (0 (or (position 0 mask :start first :end random
>                                   :from-end t)
>                  (position 0 mask :start random)))
>           (1 (or (position 0 mask :start random)
>                  (position 0 mask :start first :end random
>                                   :from-end t))))))))
> 
> 
> ;;; Mattias

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Ken Tilton
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <47e518bc$0$15206$607ed4bc@cv.net>
Ken Tilton wrote:
> I better make a better example before you all go postal on me. :)

(defun test-it ()
   (let* ((nums (delete-duplicates
                 (loop repeat 20
                     collecting (random 5000))))
          (used (make-array 5000 :element-type 'bit :initial-element 0)))
     (flet ((unused (n)
              (zerop (bit used n))))
       (loop while (every #'unused nums)
           do (loop for n in nums
                  do (setf (bit used n) (random 2))))

       ; pick one
       (let ((pick (pick-one nums used))
             (*print-length* 20))
         (assert (unused pick))
         (assert (find pick nums))
         (print `(i like ,pick :out-of ,(loop for n in nums
                                                   when (unused n)
                                                   collect n)))
         pick))))

My original (kinda):

(defun pick-one (nums used)
   (loop thereis
         (loop for n in nums
             when (and (zerop (bit used n))
                    (zerop (random 50)))
               return n)))

I'd show Barry's suggestion but he just served me with an NDA.

kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Mattias Nilsson
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <d77e241d-6948-48ea-9d78-7eca5bace8f4@n75g2000hsh.googlegroups.com>
On Mar 22, 3:33 pm, Ken Tilton <···········@optonline.net> wrote:
> Ken Tilton wrote:
> > I better make a better example before you all go postal on me. :)

Yes, and I should have read through the problem desrcription three
more times
before posting. :)

> I'd show Barry's suggestion but he just served me with an NDA.

Yes, his idea seems to lead to some nice code.


Mattias
From: danb
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <a2e868ca-6dde-4e2e-a9f3-c30e249b8a63@n58g2000hsf.googlegroups.com>
> > Count the number of unused elements,
> > pick a random integer N between 1
> > and that count, then find the Nth unused element.

On Mar 23, 6:22 am, Mattias Nilsson <········@bredband.net> wrote:
> Yes, his idea seems to lead to some nice code.

What's so great about it?  Finding a location in the
bit field takes O(N) time.  Just break the Knuth
shuffling aglorithm into individual steps and each
number takes O(1) time.

(let (nums num-nums)
  (defun init-nums (size)
    (setf nums (make-array size))
    (dotimes (n size) (setf (aref nums n) n))
    (setf num-nums size))
  (defun pick-one ()
    (and (plusp num-nums)
         (let* ((n (random num-nums)))
           (rotatef (aref nums n)
                    (aref nums (1- num-nums)))
           (decf num-nums)
           (aref nums num-nums))))
  (defun reset-nums ()
    (setf num-nums (length nums))))

CL-USER> (init-nums 5000)
5000
CL-USER> (dotimes (_ 100) (format t "~D " (pick-one)))
4857 4493 4883 2811 548 2647 217 4312 493 279 1751 4001 916 2747 2240
2645 1583 4442 2817 4790 4449 4418 4260 3706 2080 3378 1145 3134 191
1912 2953 3430 3218 192 2782 2971 250 3972 4171 1416 1693 369 4591
3604 1656 3667 3422 3983 4511 406 4238 1094 4414 1262 764 1573 335 555
3209 3561 2832 474 193 19 2525 2158 782 2194 1659 2120 85 1029 3303
1434 4541 3620 2716 623 128 2308 1074 2014 791 167 4212 2529 3631 3698
1605 4793 2821 34 1072 814 42 3672 3313 2148 397 4393

--Dan

------------------------------------------------
Dan Bensen
http://www.prairienet.org/~dsb/
From: Barry Margolin
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <barmar-EFD07B.17503723032008@newsgroups.comcast.net>
In article 
<····································@n58g2000hsf.googlegroups.com>,
 danb <·········@gmail.com> wrote:

> > > Count the number of unused elements,
> > > pick a random integer N between 1
> > > and that count, then find the Nth unused element.
> 
> On Mar 23, 6:22 am, Mattias Nilsson <········@bredband.net> wrote:
> > Yes, his idea seems to lead to some nice code.
> 
> What's so great about it?  Finding a location in the
> bit field takes O(N) time.  Just break the Knuth

He said the list of numbers is short, so I don't see a problem with the 
algorithm being O(length(list)).

> shuffling aglorithm into individual steps and each
> number takes O(1) time.

The bit array is a required input for the exercise.  You can't change 
the parameters of the problem.

> 
> (let (nums num-nums)
>   (defun init-nums (size)
>     (setf nums (make-array size))
>     (dotimes (n size) (setf (aref nums n) n))
>     (setf num-nums size))
>   (defun pick-one ()
>     (and (plusp num-nums)
>          (let* ((n (random num-nums)))
>            (rotatef (aref nums n)
>                     (aref nums (1- num-nums)))
>            (decf num-nums)
>            (aref nums num-nums))))
>   (defun reset-nums ()
>     (setf num-nums (length nums))))
> 
> CL-USER> (init-nums 5000)
> 5000
> CL-USER> (dotimes (_ 100) (format t "~D " (pick-one)))
> 4857 4493 4883 2811 548 2647 217 4312 493 279 1751 4001 916 2747 2240
> 2645 1583 4442 2817 4790 4449 4418 4260 3706 2080 3378 1145 3134 191
> 1912 2953 3430 3218 192 2782 2971 250 3972 4171 1416 1693 369 4591
> 3604 1656 3667 3422 3983 4511 406 4238 1094 4414 1262 764 1573 335 555
> 3209 3561 2832 474 193 19 2525 2158 782 2194 1659 2120 85 1029 3303
> 1434 4541 3620 2716 623 128 2308 1074 2014 791 167 4212 2529 3631 3698
> 1605 4793 2821 34 1072 814 42 3672 3313 2148 397 4393
> 
> --Dan
> 
> ------------------------------------------------
> Dan Bensen
> http://www.prairienet.org/~dsb/

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: danb
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <62c47e10-6942-4d02-b38b-5178ec579ba9@m44g2000hsc.googlegroups.com>
On Mar 23, 4:50 pm, Barry Margolin <······@alum.mit.edu> wrote:
> He said the list of numbers is short, so I don't see a problem
> with the algorithm being O(length(list)).

Okay, I get it.  In that case, the bit field is a waste of space.
You can just put the short list in an array and shuffle that.

> The bit array is a required input for the exercise.
> You can't change the parameters of the problem.

I would question them though.  Something just doesn't sound right.

Thanks for the explanation.

--Dan

------------------------------------------------
Dan Bensen
http://www.prairienet.org/~dsb/
From: Barry Margolin
Subject: Re: Another From the Trenches Kenny Gotta Be a Better Way Challenge
Date: 
Message-ID: <barmar-788974.20581124032008@newsgroups.comcast.net>
In article 
<····································@m44g2000hsc.googlegroups.com>,
 danb <·········@gmail.com> wrote:

> On Mar 23, 4:50 pm, Barry Margolin <······@alum.mit.edu> wrote:
> > He said the list of numbers is short, so I don't see a problem
> > with the algorithm being O(length(list)).
> 
> Okay, I get it.  In that case, the bit field is a waste of space.
> You can just put the short list in an array and shuffle that.
> 
> > The bit array is a required input for the exercise.
> > You can't change the parameters of the problem.
> 
> I would question them though.  Something just doesn't sound right.

Homework problems are often artificial, to make a specific point, it 
doesn't have to "sound right" for a real application.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***