Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-02-12

L-99 (23)

| 21:21 | L-99 (23) - わだばLisperになる を含むブックマーク はてなブックマーク - L-99 (23) - わだばLisperになる

L-99 23問目に挑戦 - L-99:Ninety-Nine Lisp Problems

P23

解答
;; Common Lisp
(defun split (list n)
  (do ((l list (cdr l))
       (c 0 (1+ c))
       (retlist '() (if (< c n)
			`(,@retlist ,(car l))
			(return `(,retlist ,l)))))
      ((endp l) retlist)))

(defun remove-at (list n)
  (destructuring-bind (1st 2nd)
      (split list (1- n))
    (values `(,@1st ,@(cdr 2nd)) (car 2nd))))

(defun rnd_select (list n)
  (labels ((rnd_select1 (l c retlist)
	     (if (zerop c)
		 retlist
		 (multiple-value-bind (rest item) 
		     (remove-at l (1+ (random (length l))))
		   (rnd_select1 rest 
				(1- c) 
				`(,item ,@retlist))))))
    (rnd_select1 list n '())))

;; Scheme
(use srfi-27)
(use util.match)

(define split
  (lambda (ls n)
    (letrec ((split1
	      (lambda (l c rl)
		(call/cc
		 (lambda (return)
		   (if (null? l)
		       rl
		       (split1 (cdr l) 
			       (+ c 1)
			       (if (< c n)
				   `(,@rl ,(car l))
				   (return `(,rl ,l))))))))))
      (split1 ls 0 '()) )))

(define remove-at
  (lambda (l n)
    (match-let (((1st 2nd) (split l (- n 1))))
	       (values 
		`(,@1st ,@(cdr 2nd)) (car 2nd)))))

(define rnd_select
  (lambda (ls n)
    (let rnd_select1 ((l ls) (c n) (rl '()))
      (if (zero? c)
	  rl
	  (call-with-values 
	      (lambda () (remove-at l (+ 1 (random-integer (length l)))))
	    (lambda (rest item)
	      (rnd_select1 rest (- c 1) `(,item ,@rl))))))))

問題のヒントを読むとP20のremove-atを使ってみよう、

とある。がしかし、L-99のremove-atを見てみても、

remove-atが使えるとはあまり思えず。

L-99の元になったP-99のサイトのremove-atをみてみた

ところP-99のremove-atは取り除くアイテムと残りのリ

ストの2値を返すようになっていたので、remove-atを使っ

てみよという意味にも納得。

remove-atも多値を返すように変更してみて回答を作成

してみた。splitもなんとなく改訂。