GOOでL-99 (P23 指定した個数の要素をランダムに選択) — #:g1

Posted 2010-11-25 14:30:00 GMT

-(http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html)
以前は、L-99しかやってないブログと化していた程、L-99を色々なLISP方言で解いてみていましたが、どの方言でも完遂してはいません。

久々にちょっと久々に挑戦してみようかなと思い、ブログを眺めてみると、直近のエントリーは、2年前のGOOでの挑戦でした。
GOOもすっかり忘れているので、ちょっと書いて遊んでみることに。
久々に触ってみましたが、やっぱり色々と変わっています。
ちなみに、GOOはどういう言語かというと、Dylanの開発にも携わった、Jonathan Bachrach氏が開発した言語で、Dylan+Scheme+当時構想だけ発表されていたArcという感じのLISP方言です。
-(http://people.csail.mit.edu/jrb/goo/)
S式のDylanな感じもしつつ、Paul Graham氏の「生まれて3週間目のArc」を意識した機能と、短かすぎて逆に覚えられない関数名が特徴だと個人的には思っています。(GOOのページにもArcのパロディのような題名が多くあります)
ざっと目立つところだと
- Arc/Perl風の短い関数名(と動作)
- 基本的にメソッド主体で、総称関数
- Dylanっぽい構文
- Seriesが組み込み
- 多値の代わりにタプル
というところでしょうか。
結構面白いので変わったLISP方言が好きな方にはお勧めです。

P23 (**) Extract a given number of randomly selected elements from a list.
    The selected items shall be returned in a list.
    Example:
    * (rnd-select '(a b c d e f g h) 3)
    (E D A)

Hint: Use the built-in random number generator and the result of problem P20.

(df random-pop (u|<lst> => (tup <lst> <any>))
  (def rest (packer-fab <lst>))
  (def item (packer-fab <lst>))
  (def picknum (random (- (len u) 1)))
  (for ((e u)
        (i (from 0)))
    (if (= picknum i)
        (pack-in item e)
        (pack-in rest e)))
  (tup (packer-res rest)
       (1st (packer-res item))))

(df rnd-select (u|<lst> n|<int> => <lst>) (loc ((self1 (acc rest n) (if (or (zero? n) (empty? rest)) acc (let (((tup nrest item) (random-pop rest))) (self1 (pair item acc) nrest (- n 1)))))) (self1 () u n)))

実行例
(for ((i (range 1 <= 100)))
  (say out (rnd-select '(a b c d e f g h) 3) "\n"))
;-> 
;   (e g d)
;   (d e a)
;   (f d b)
;   (a b e)
;   (c a g)
;   (f d e)
;   (c f e)
;   (f g c)
;   (c f g)
;   (c g a)
;   (b e a)
;   (c a f)
;   (g f b)
;   (b a f)
;   (e d b)
;   (c a b)
;   (b f a)
;   (c g a)
;   (c b a)
;   (f e a)
;...

comments powered by Disqus