関数合成でcollatzしよう

collatz chainLength
1.関数の合成
[b]このワークシートは[url=https://www.geogebra.org/m/twxxx3yq]Math by Code[/url]の一部です。[br][/b][br]関数の合成は役に立つ。[br][br]関数プログラミングの視点からみると[br][br]関数は[br]リストを別のリストに変形する(mapなど)[br]リストから新リストを作る(filterなど)[br]2つのリストを合体する(連結やZip)[br]リストを集計する(countやsumとか)[br]などの操作をする。[br][br]この場合の関数は、数学でよく使う代数式の関数とはちがう。[br]しかし、Inputに対して必ずOutputがあるようにすれば、[br]returnのないとか、elseがないような手続き型の処理とはちがって、[color=#0000ff][b][size=150]関数[/size][/b][/color]と呼ぶことができるだろう。[br][br][color=#0000ff][size=150][b][u]関数から返されたデータを次の関数に渡すと、関数をつないでパイプラインのように合成できるね。[br][/u][/b][/size][/color][br]合成関数は、数学では通常、f(g(h(x)))という記法はf*g*h とか、f◯g◯hxとかいたりする。[br]xに対してh,g,fの順、右から作用させていく。[br][br]haskellの合成関数は.(dot)を使って、[color=#0000ff][b][size=150]f.g.h = \x ->f(g(h x)) [/size][/b][/color]の意味でかくこともできるようです。[br][br]juliaはパイプ演算子|> を使って、引数xのあとに左から作用させていく。 [br][br][b][color=#0000ff][size=150][size=200]x |> h |> g |> f [br][/size][br][/size][/color][/b]とかくこともできます。[br]パイプ演算子の有無と書き方は、言語によってちがうので、そこは調べてみよう。[br][br][br][b][br][/b]
2.コラッツ数列の調査
コラッツ数列というのは有名は未解決の予想問題に関係があるね。[br][br]整数を[b][size=150][u]偶数なら2で割り、奇数なら3倍して1を足す[/u][/size][/b]ということを繰り返すと、[br]どんな自然数も[color=#0000ff][u][b][size=150]最後は1になるチェーンができる[/size][/b][/u][/color]という[color=#0000ff][b]予想の証明[/b][/color]がまだ未解決だ[br][br]というのは有名な話だね。[br][br][color=#0000ff][b][size=150]コラッツ数列になれるための課題として、100以下の自然数すべてに対して、[br]1までのチェーンの長さが100をこえるものが何個あり、それが何かを調べてみよう。[br][/size][/b][/color][br][b][size=150][u][color=#9900ff]質問:この課題解決のためのコードは、関数の合成を使うとどんな作りになりますか。[br][/color][/u][/size][/b][br]では、まず、何をやっているかわかりやすくするためにhaskellを使ってみよう。[br][br]コラッツ数列の連鎖を作る再帰関数で作ります。それがchain。[br][br]1から100までの整数1つ1つにchainをマップし、連鎖の長さが100をこえたものだけfilterします。[br]それにあてはまる個数を出します。[br]つまり length( filter(map )))の[b]合成関数[/b]を作ります。[br]その結果がnumLongChainsです。[br]どの整数からスタートしているかを知りたいので、filter(map))までは同じで、そのあと連鎖の先頭だけ取り出します。だから、map head( filter(map ))します。その結果がlongListです。[br][br][color=#0000ff][b][size=150]#[IN]Haskell[br]--=======================================================[br]chain :: Integer -> [Integer][br]chain 1=[1][br]chain n [br] | even n = n : chain ( n `div` 2)[br] | odd n = n : chain ( n * 3 + 1)[br][br]numLongChains :: Int[br]numLongChains = length (filter isLong (map chain [1..100]))[br] where isLong xs = length xs > 100[br]longList = map head ( filter isLong (map chain [1..100]))[br] where isLong xs = length xs > 100[br]--=======================================================[br][/size][/b][/color][OUT][br]ghci> numLongChains[br]15[br]ghci> longList[br][27,31,41,47,54,55,62,63,71,73,82,83,94,95,97][br][br]juliaでは、コラッツ数列作りは再帰ではなくてwhile文で作ってみる。[br]where文がないので、使う関数を並べておき、それをつないで[b][color=#0000ff][size=150]関数合成[/size][/color][/b]してみよう。[br][br][color=#0000ff][b][size=150]#[IN]Julia[br]#=======================================================[/size][br]function chain(n)[br] result = [n][br] while n != 1[br] n = isodd(n) ? 3n + 1 : div(n, 2)[br] push!(result, n)[br] end[br] return result[br]end[br]lst=[x for x in 1:100][br]mapping(xs)= map(chain,xs)[br]long(xs) = filter(xs -> length(xs) > 100, xs)[br]head(xs) = map(x -> x[1],xs) #リストxのリストxsから先頭x[1]のリストを作る。[br]println(length(long(mapping(lst))))[br]println(head(long(mapping(lst))))[br][size=150]#=======================================================[/size][br][/b][/color][OUT][br]15[br][27, 31, 41, 47, 54, 55, 62, 63, 71, 73, 82, 83, 94, 95, 97][br][br]かっこが入れ子になりすぎるのがイヤなら、パイプ演算子で次のようにかいてもいいね。[br][size=150][b][color=#9900ff]#=======================================================[br]lst |> mapping |> long |> length |> println[br]lst |> mapping |> long |> head |> println[br][/color][/b][b][color=#9900ff]#=======================================================[br][/color][/b][/size][OUT][br]15[br][27, 31, 41, 47, 54, 55, 62, 63, 71, 73, 82, 83, 94, 95, 97][br]
3.コラッツ数列の連鎖長の見える化
コラッツ数列の連鎖長が100超えが15%もあるのはビックリだ。[br]でも、長さに規則性がないだろうか?[br]それを探るために、1000までの連鎖長をリスト化して見える化してみよう。[br][b][color=#9900ff]#=======================================================[/color][/b][br]lst=[x for x in 1:1000][br]lst |> mapping |> len |> println[br][b][color=#9900ff]#=======================================================[br][/color][/b][OUT][br][1, 2, 8, 3, 6, 9, 17, 4, 20, 7, 15, 10, 10, 18, 18, 5, 13, 21, 21, 8, 8, 16, 16, 11, 24, 11, 112, 19, 19, 19, 107, 6, 27, 14, 14, 22, 22, 22, 35, 9, 110, 9, 30, 17, 17, 17, 105, 12, 25, 25, 25, 12, 12, 113, 113, 20, 33, 20, 33, 20, 20, 108, 108, 7, 28, 28, 28, 15, 15, 15, 103, 23, 116, 23, 15, 23, 23, 36, 36, 10, 23, 111, 111, 10, 10, 31, 31, 18, 31, 18, 93, 18, 18, 106, 106, 13, 119, 26, 26, 26, 26, 26, 88, 13, 39, 13, 101, 114, 114, 114, 70, 21, 13, 34, 34, 21, 21, 34, 34, 21, 96, 21, 47, 109, 109, 109, 47, 8, 122, 29, 29, 29, 29, 29, 42, 16, 91, 16, 42, 16, 16, 104, 104, 24, 117, 117, 117, 24, 24, 16, 16, 24, 37, 24, 86, 37, 37, 37, 55, 11, 99, 24, 24, 112, 112, 112, 68, 11, 50, 11, 125, 32, 32, 32, 81, 19, 32, 32, 32, 19, 19, 94, 94, 19, 45, 19, 45, 107, 107, 107, 45, 14, 120, 120, 120, 27, 27, 27, 120, 27, 19, 27, 40, 27, 27, 89, 89, 14, 40, 40, 40, 14, 14, 102, 102, 115, 27, 115, 53, 115, 115, 71, 71, 22, 53, 14, 14, 35, 35, 35, 128, 22, 84, 22, 128, 35, 35, 35, 53, 22, 22, 97, 97, 22, 22, 48, 48, 110, 48, 110, 66, 110, 110, 48, 48, 9, 123, 123, 123, 30, 30, 30, 79, 30, 123, 30, 22, 30, 30, 43, 43, 17, 30, 92, 92, 17, 17, 43, 43, 17, 43, 17, 61, 105, 105, 105, 43, 25, 30, 118, 118, 118, 118, 118, 56, 25, 74, 25, 118, 17, 17, 17, 43, 25, 38, 38, 38, 25, 25, 87, 87, 38, 131, 38, 38, 38, 38, 56, 56, 12, 25, 100, 100, 25, 25, 25, 144, 113, 51, 113, 25, 113, 113, 69, 69, 12, 113, 51, 51, 12, 12, 126, 126, 33, 126, 33, 126, 33, 33, 82, 82, 20, 126, 33, 33, 33, 33, 33, 51, 20, 46, 20, 46, 95, 95, 95, 46, 20, 20, 46, 46, 20, 20, 46, 46, 108, 64, 108, 59, 108, 108, 46, 46, 15, 33, 121, 121, 121, 121, 121, 121, 28, 59, 28, 77, 28, 28, 121, 121, 28, 20, 20, 20, 28, 28, 41, 41, 28, 41, 28, 134, 90, 90, 90, 134, 15, 134, 41, 41, 41, 41, 41, 33, 15, 59, 15, 54, 103, 103, 103, 41, 116, 28, 28, 28, 116, 116, 54, 54, 116, 28, 116, 54, 72, 72, 72, 98, 23, 116, 54, 54, 15, 15, 15, 41, 36, 129, 36, 129, 36, 36, 129, 129, 23, 36, 85, 85, 23, 23, 129, 129, 36, 36, 36, 28, 36, 36, 54, 54, 23, 49, 23, 23, 98, 98, 98, 142, 23, 49, 23, 142, 49, 49, 49, 98, 111, 23, 49, 49, 111, 111, 67, 67, 111, 62, 111, 36, 49, 49, 49, 62, 10, 36, 124, 124, 124, 124, 124, 62, 31, 124, 31, 124, 31, 31, 80, 80, 31, 31, 124, 124, 31, 31, 23, 23, 31, 23, 31, 49, 44, 44, 44, 137, 18, 44, 31, 31, 93, 93, 93, 44, 18, 137, 18, 31, 44, 44, 44, 88, 18, 44, 44, 44, 18, 18, 62, 62, 106, 57, 106, 31, 106, 106, 44, 44, 26, 31, 31, 31, 119, 119, 119, 31, 119, 57, 119, 119, 119, 119, 57, 57, 26, 75, 75, 75, 26, 26, 119, 119, 18, 57, 18, 70, 18, 18, 44, 44, 26, 132, 39, 39, 39, 39, 39, 70, 26, 132, 26, 132, 88, 88, 88, 132, 39, 26, 132, 132, 39, 39, 39, 39, 39, 31, 39, 31, 57, 57, 57, 132, 13, 52, 26, 26, 101, 101, 101, 39, 26, 145, 26, 101, 26, 26, 145, 145, 114, 52, 52, 52, 114, 114, 26, 26, 114, 52, 114, 145, 70, 70, 70, 96, 13, 65, 114, 114, 52, 52, 52, 65, 13, 65, 13, 39, 127, 127, 127, 39, 34, 127, 127, 127, 34, 34, 127, 127, 34, 127, 34, 65, 83, 83, 83, 171, 21, 34, 127, 127, 34, 34, 34, 65, 34, 26, 34, 26, 34, 34, 52, 52, 21, 47, 47, 47, 21, 21, 47, 47, 96, 34, 96, 140, 96, 96, 47, 47, 21, 140, 21, 21, 47, 47, 47, 96, 21, 91, 21, 47, 47, 47, 47, 140, 109, 21, 65, 65, 109, 109, 60, 60, 109, 34, 109, 153, 47, 47, 47, 60, 16, 34, 34, 34, 122, 122, 122, 153, 122, 34, 122, 60, 122, 122, 122, 122, 29, 122, 60, 60, 29, 29, 78, 78, 29, 78, 29, 104, 122, 122, 122, 73, 29, 60, 21, 21, 21, 21, 21, 73, 29, 47, 29, 135, 42, 42, 42, 135, 29, 42, 42, 42, 29, 29, 135, 135, 91, 135, 91, 42, 91, 91, 135, 135, 16, 29, 135, 135, 42, 42, 42, 86, 42, 42, 42, 42, 42, 42, 34, 34, 16, 60, 60, 60, 16, 16, 55, 55, 104, 29, 104, 148, 104, 104, 42, 42, 117, 148, 29, 29, 29, 29, 29, 179, 117, 148, 117, 29, 55, 55, 55, 148, 117, 117, 29, 29, 117, 117, 55, 55, 73, 148, 73, 47, 73, 73, 99, 99, 24, 68, 117, 117, 55, 55, 55, 117, 16, 68, 16, 55, 16, 16, 42, 42, 37, 130, 130, 130, 37, 37, 130, 130, 37, 130, 37, 68, 130, 130, 130, 117, 24, 130, 37, 37, 86, 86, 86, 130, 24, 174, 24, 86, 130, 130, 130, 37, 37, 37, 37, 37, 37, 37, 29, 29, 37, 29, 37, 29, 55, 55, 55, 130, 24, 50, 50, 50, 24, 24, 24, 143, 99, 50, 99, 37, 99, 99, 143, 143, 24, 99, 50, 50, 24, 24, 143, 143, 50, 24, 50, 37, 50, 50, 99, 99, 112, 94, 24, 24, 50, 50, 50, 50, 112][br][br]これをみてもピンとこないのでgeogebraで視覚化してみよう。[br][br]xs=sequence(1000)で、x座標を1から1000までの整数で作る。[br]そして、ys=上にある1000個のデータ[br]でy座標とする。[br]最後にzip((p,q),p,xs,q,ys)をすると、2つのリストxsとysから要素p,qを取り出してその順序対ができる。[br]これで、関数とグラフが即出来上がりだ。[br][br]たとえば、連続する値で長さが同じ長さになる部分があることや、[br]長さが直線上にように分布しているような、うろこ状に見えるところが多くあるね。[br][br][color=#9900ff][b][u][size=150][size=200]質問:下のコラッツの連鎖長の分布になにか他に気づいたことはありますか?[/size][/size][/u][/b][/color]
collatz chainLength

Information: 関数合成でcollatzしよう