3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Juliaで組合せを求めた

Last updated at Posted at 2021-10-05

@StrawBerryMoon さんから御指摘を頂きまして修正を行いました。
御指摘有難うございます。 2021/10/06 18:20頃に修正済

#前提
私は組合せを簡単に求めたかっただけなのに・・・
4個の要素から3つ取り出す全ての順番の組合せを求めたかっただけなんですけどね。
一応自力で書いたので、それはそれでOKですが、ついでに既存のライブラリを探してみました。
最初に探しておけば良かったのですが・・・
方針として使えそうなライブラリを見つけると時間が有るときに試してみるというトライをするのが基本。
こんなに面倒くさい内容になるとは思わなかったです。
私は組合せを簡単に求めたかっただけなのに・・・
私のバックグラウンドは、高校は理数科で大学は理系ですが、専門は音楽、ついでに試験管とビーカーいう情けないものです。

#Combinatorics.jl
Julia Math Mathematics made easy in Juliaを眺めてみると、
Combinatorics.jl (Public) A combinatorics library for Julia
というのを見つけた。
https://github.com/orgs/JuliaMath/repositories
面白そうなので、見てみると
permutations関数が求める物っぽい
permutations(a): Generate all permutations of an indexable object a in lexicographic order.
で、
Generate all permutations of an indexable object a in lexicographic order. Because the number of permutations
can be very large, this function returns an iterator object.
Use collect(permutations(a)) to get an array of all permutations.
で、

using Combinatorics
ar = ["あ","い","う","え"]
collect(permutations(ar,3))

とすると、目的の組合せのコレクションが得られた。
更にiteratorとしても使えると書いてあるし。

ここで、止めとけば良かった。
一応、サンプルを作ったのでポストしますが・・・
私は組合せを簡単に求めたかっただけなのに・・・
だいたい**「超階乗」**ってなんだよ。超怪獣なら好きになれそうなんですが。

重要な告知
判る方はご自分で納得して私に聞かないでください。
判らない方は自分で調べて私に聞かないでください。

インストールは、
julia> Pkg.add("Combinatorics")
で簡単。

私がやりたかった事は、これだけです。

using Combinatorics

ar = ["あ","い","う","え"]
for i in permutations(ar,3)
    println(i)
end
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "い"]
    ["あ", "う", "え"]
    ["あ", "え", "い"]
          中略
    ["え", "い", "あ"]
    ["え", "い", "う"]
    ["え", "う", "あ"]
    ["え", "う", "い"]

以上終了です。

一応他の関数も簡単な翻訳とお試しをしてみました。
以下、ドキュメントから色々してみました。
順番はドキュメントに掲載されていた順です。
この二行は必須です。

using Combinatorics
ar = ["あ","い","う","え"]

#bellnum(n)
n番目のBell numberを返します。常にBigIntを返します。
https://ja.wikipedia.org/wiki/ベル数

    julia> bellnum(5)
    52

#catalannum(n)
n番目のカタラン数を返します; 常にBigIntを返します。
https://ja.wikipedia.org/wiki/カタラン数

    julia> catalannum(4)
    14

#lobbnum(m,n)
mとnの一般化されたカタラン数を返します。
https://ja.wikipedia.org/wiki/カタラン数

    julia> lobbnum(3,4)
    7

#narayana(n,k)
任意のnとkにおける一般的なナラヤナ数を返します;常にBigIntを返します。
https://en.wikipedia.org/wiki/Narayana_number

    julia> narayana(8,5)
    490

#combinations(a,n)
インデックス可能なオブジェクトaのn個の要素のすべての組み合わせを返します。
これは便利

    ar = ["あ","い","う","え"]
    for i in combinations(ar,3)
        println(i)
    end
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "え"]
    ["い", "う", "え"]

念の為説明すると、"う","え"の2つはこの要素の出現順?では、
3つの要素を含む順番を表す先頭になれないという事です。
#combinations(a,n)
companies(a,n)のすべての順序の組み合わせを返します。
これは便利 2番目の引数を省略すると全組合せ、指定すると長さ?を指定できる
例1

    ar = ["あ","い","う","え"]
    for i in combinations(ar)
        println(i)
    end
    ["あ"]
    ["い"]
    ["う"]
    ["え"]
    ["あ", "い"]
    ["あ", "う"]
    ["あ", "え"]
    ["い", "う"]
    ["い", "え"]
    ["う", "え"]
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "え"]
    ["い", "う", "え"]
    ["あ", "い", "う", "え"]

例2

    for i in combinations(ar,3)
        println(i)
    end
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "え"]
    ["い", "う", "え"]

#derangement(n)とsubfactorial(n)
n個の並べ替えの数を返します。
https://www.geeksforgeeks.org/count-derangements-permutation-such-that-no-element-appears-in-its-original-position/

    julia> derangement(4)
    9

    julia> subfactorial(4)
    9

#partialderangement(n, k)
k個の固定点を持つn個の順列の数を返します;常にBigIntを返します。
https://mathworld.wolfram.com/PartialDerangement.html

    julia> partialderangement(8,3)
    2464

#おまけで階乗の説明
階乗:n! は 1 から n までの整数を全てかけあわせたもの
例 指定できる値は、0から20まで、21以上は大き過ぎるのでエラーになる
21以上を渡す際には、 factorial(big(21))のようにbig()を使用する
当然、factorial(0)は、ゼロが返る
当然、factorial(0)は、1が返る
factorialは、Julia起動後にすぐに使える。
@StrawBerryMoon さんからの御指摘で、上記のように加筆と修正させて頂きました。
有難うございます。それに伴い下記にbig(21)の例を追加しました。

    julia> factorial(20)
    2432902008176640000

    julia> factorial(big(21))
    51090942171709440000

#doublefactorial(n)
2倍の階乗n!!! n!!を返します。 !が一つ多かったので修正
https://ja.wikipedia.org/wiki/二重階乗
二重階乗:n!! は一つおきにかけあわせたもの doublefactorial
階乗の一つ飛ばしバージョンを二重階乗と言うそうです。
3!!=3×1=3
4!!=4×2=8
5!!=5×3×1=15
6!!=6×4×2=48
double factorialが英語表記

    julia> doublefactorial(3)
    3

    julia> doublefactorial(4)
    8

    julia> doublefactorial(5)
    15

    julia> doublefactorial(6)
    48

#fibonaccinum(n)
n番目のフィボナッチ数; 常にBigIntを返します。
https://ja.wikipedia.org/wiki/フィボナッチ数
これは、あちこち例題で出てくるので知っていました。

    julia> fibonaccinum(10)
    55

#hyperfactorial(n)
n番目の超階乗、つまりprod([i^i for i = 2:n]; 常にBigIntを返します。
https://ja.wikipedia.org/wiki/超階乗
超階乗:n$ は n! の肩に n! を n!−1 個乗せたもの hyperfactorial
私には何に使うのか見当もつかない super factorialが英語表記

    julia> hyperfactorial(6)
    4031078400000

#integer_partitions(n)
数nのパーティションで構成されるVector{Int}を返します。
これは便利、なんかで使うかも

    julia> integer_partitions(5)
    7-element Vector{Vector{Int64}}:
     [1, 1, 1, 1, 1]
     [2, 1, 1, 1]
     [2, 2, 1]
     [3, 1, 1]
     [3, 2]
     [4, 1]
     [5]

#jacobisymbol(a,b)
ヤコビ記号(a/b)を返します。
https://ja.wikipedia.org/wiki/ヤコビ記号
例 wikipediaの表を参照してください 縦5,横6の例です。

    julia> jacobisymbol(5,6)
    1

#lassallenum(n)
arXiv:1009.4225 (OEIS A180874)で定義されたn番目のラサール数Anを返します;常にBigIntを返します。
https://oeis.org/A180874
ごめんなさい。私はよく理解していません。
例 URLに書かれた数字列の7番目と一致しています
(これ以上は判らないし、知りたくもないです)

    julia> lassallenum(7)
    1387815

#legendresymbol(a,p)
ルジャンドル記号(a/p)を返します。
https://ja.wikipedia.org/wiki/ルジャンドル記号
例 横3,縦7の例です。 wikipediaの表と違って、横,縦の順で指定します。

    julia> legendresymbol(3,7)
    -1

#lucasnum(n)
n番目のリュカ数を返します; 常にBigIntを返します。
https://ja.wikipedia.org/wiki/リュカ数列
例 wikipediaの例の先頭10個と一致しているので良しとします。

    julia> for i in 0:10
                print(lucasnum(i))
                print(" ")
            end
    2 1 3 4 7 11 18 29 47 76 123

#multifactorial(n)
m多因子n(!^m)を返します; 常にBigIntを返します。
https://en.wikipedia.org/wiki/Factorial#Multifactorials
ごめんなさい。私はよく理解していません。
ドキュメントには、multifactorial(n)と書かれていますが、ソースを見ると
function multifactorial(n::Integer, m::Integer)となっています。

    julia> multifactorial(10,4)
    120

#multinomial(k...)
k_1, ..., k_nのタプルを受け取り、多項式係数(n k)を計算します(n = sum(k))
https://ja.wikipedia.org/wiki/多項分布
指定された数値の和の階乗と、指定された数値の階乗の積との比を返します。つまり、多項係数を求めます。
私は、Julia Statistics(公式)に含まれているDistributions.jlを利用したことがあります。
https://github.com/JuliaStats/Distributions.jl
こちらの方が広く使われている(公式だから?)のかもしれません。
タプルで指定するメリットが判らなかったのでサンプルはパスです。

#multiexponents(m,n)
多項式展開(x₁ + x₂ + ... + xₘ)ⁿの指数を返します。
ごめんなさい。何回か読んだのですが、私は使い方をよく理解していません。

#primorial(n)
すべての正の素数<= nの積を返します。

    julia> primorial(7)
    210

以下と同じ答えになったので良しとします。

    julia> 2*3*5*7
    210

@StrawBerryMoon さんからの御指摘で、上記のように加筆と修正させて頂きました。
修正内容は、 julia> 12357julia> 235*7 に致しました
有難うございます。

#powerset(a)
インデックス可能なオブジェクトaのすべてのサブセットを返す
これは便利

    ar = ["あ","い","う","え"]
    for i in powerset(ar)
         println(i)
    end
    ["あ"]
    ["い"]
    ["う"]
    ["え"]
    ["あ", "い"]
    ["あ", "う"]
    ["あ", "え"]
    ["い", "う"]
    ["い", "え"]
    ["う", "え"]
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "え"]
    ["い", "う", "え"]
    ["あ", "い", "う", "え"]

combinations(a,n)との違いは、
function combinations(a, t::Integer)
function powerset(a, min::Integer=0, max::Integer=length(a))
なので、最小値と最大値を指定できるので更に便利

    for i in powerset(ar,2,4)
         println(i)
    end
    ["あ", "い"]
    ["あ", "う"]
    ["あ", "え"]
    ["い", "う"]
    ["い", "え"]
    ["う", "え"]
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "え"]
    ["い", "う", "え"]
    ["あ", "い", "う", "え"]

#stirlings1(n, k, signed=false)
(n,k)番目の第一種スターリング数を返す; signedが真の場合、数は符号付きとなる; BigIntが与えられた場合のみBigIntを返す
ごめんなさい。私はよく理解していません。
パス。
#stirlings2(n, k)
第2種の(n,k)番目のスターリング数を返します;BigIntが与えられた場合のみBigIntを返します。
https://ja.wikipedia.org/wiki/スターリング数
ごめんなさい。私はよく理解していません。
パス。

#nthperm(a, k)
Compute the kth lexicographic permutation of the vector a.
ベクトルaのk番目の辞書順列を計算する・・・・
Combinatorics.jl-master/test/permutations.jlの中でTestしていた、
nthperm([0, 1, 2], 6) == [2, 1, 0]
を見て、悩んでみたのですが、

    julia> nthperm([0, 1, 2], 6)
    3-element Vector{Int64}:
     2
     1
     0

    julia> nthperm([2, 1, 0], 6)
    3-element Vector{Int64}:
     0
     1
     2

諦めて次のpermutationsを使うことにします。

#permutations(a)
全ての組合せを生成します。
これがやりたかった事です。なんで最後に記述してあるのか・・・

    ar = ["あ","い","う","え"]
    for i in permutations(ar,3)
        println(i)
    end
    ["あ", "い", "う"]
    ["あ", "い", "え"]
    ["あ", "う", "い"]
    ["あ", "う", "え"]
    ["あ", "え", "い"]
    ["あ", "え", "う"]
    ["い", "あ", "う"]
    ["い", "あ", "え"]
    ["い", "う", "あ"]
    ["い", "う", "え"]
    ["い", "え", "あ"]
    ["い", "え", "う"]
    ["う", "あ", "い"]
    ["う", "あ", "え"]
    ["う", "い", "あ"]
    ["う", "い", "え"]
    ["う", "え", "あ"]
    ["う", "え", "い"]
    ["え", "あ", "い"]
    ["え", "あ", "う"]
    ["え", "い", "あ"]
    ["え", "い", "う"]
    ["え", "う", "あ"]
    ["え", "う", "い"]

疲れた
That's all folks.

3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?