« PythonとRubyでデフォルト引数の評価されるタイミングは違う |Main| 日記 »

« PythonとRubyでデフォルト引数の評価されるタイミングは違う | Python | Just Another Python Hacker, その2 »

« PythonとRubyでデフォルト引数の評価されるタイミングは違う | Ruby | Just Another Ruby/Python Hacker, »

PythonとRubyでパスカルの三角形ワンライナー

rubyco(るびこ)の日記 - 呼び出し側のアスタリスクを読んで、「あ、そうか、それを使えば頭から二つずつ取ることができるか」とGame Scripting Memo - 続・パスカルの三角形のことを思い出しました。

>>> def get2(f, a, b, *rest):
	result = [f(a, b)]
	if rest:
		result += get2(f, *rest)
	return  result

>>> from operator import add
>>> def dup(aList):
	return reduce(add, [[v, v] for v in aList])

>>> dup([1,2,3])
[1, 1, 2, 2, 3, 3]
>>> def sandwich(bread, meat):
	return [bread] + meat + [bread]

>>> sandwich(0, dup([1, 2, 1]))
[0, 1, 1, 2, 2, 1, 1, 0]

>>> get2(add, *sandwich(0, dup([1, 2, 1])))
[1, 3, 3, 1]

とりあえずワンライナーにするために手を加えて…

>>> def get2(f, a, b, *rest):
	return rest and [f(a, b)] + get2apply(f, *rest) or [f(a, b)]

>>> def next(xs):
	return get2(add, *sandwich(0, dup(xs)))

>>> def next(xs):
	return get2(add, *sandwich(0, reduce(add, [[v, v] for v in xs])))

>>> def next(xs):
	return get2(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])

>>> next([1])
[1, 1]
>>> next(_)
[1, 2, 1]
>>> next(_)
[1, 3, 3, 1]
>>> next(_)
[1, 4, 6, 4, 1]
>>> def next(xs):
	g = lambda f, a, b, *rest: rest and [f(a, b)] + g(f, *rest) or [f(a, b)]
	return g(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])

>>> def next(xs): g = lambda f, a, b, *rest: rest and [f(a, b)] + g(f, *rest) or [f(a, b)]; return
g(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])

>>> next([1])
[1, 1]

いちおうワンライナーになりました。

>>> lambda xs: (lambda g: (lambda *args: g(g, *args)))(lambda g, f, a, b, *rest: rest and [f(a, b)] +
 g(g, f, *rest) or [f(a, b)])(add, *[0] + reduce(add, [[v, v] for v in xs]) + [0])
<function <lambda> at 0x0146BC70>
>>> _([1, 2, 1])
[1, 3, 3, 1]

これで文を使わない1つの式になりました。


__ Rubyは詳しくないので…ええっと、Proc.new{|x| x + 1}で無名関数のようなものができて、callでそれを呼べるんですかね。あ、 proc {...} で Proc.new{...} と同じだそうです。


$g = proc {|a, b, *rest|
	if rest.size == 1
		[a + b, rest[0]]
	else
		[a + b] + $g.call(*rest)
	end
}


(0..9).inject([1]){|xs, item|
	proc{|x| p x; x}.call(
		$g.call(0, *xs.map{|v| [v, v]}.flatten)
	)
}

三角形の頭が表示されないですけど一応動きました。


__

(0..9).inject([]){|xs, i|
  proc{|x| p x; x}.call(
    if i == 0
      [1]
    else
      proc{|xs|
        proc {|g|
          proc {|*args|
            g.call(g, *args)
          }
        }.call(
          proc {|g, a, b, *rest|
            if rest.size == 1
              [a + b, rest[0]]
            else
              [a + b] + g.call(g, *rest)
            end
          }
        ).call(
          0, *xs.map{|v| [v, v]}.flatten
        )
      }.call(xs)
    end
  )
}

できました。改行を取り除くのはお任せします。

トラックバック(Trackback)

Trackback URL: http://www.nishiohirokazu.org/mt/mt-tb.cgi/210

ご意見・ご感想をお送りください(フィードバック)

(フィードバックはメールで送信され、基本的に表示されませんが、内容によっては公開させていただくこともございます。ご了承ください。Your comment doesn't appear the page immediately. If the comment has value to other people, it will be put on the page or subsequent entries. Thank you.)

上の情報は、いずれも未記入でかまいません。 All of above questions are optional.