リスト

ベクトルや行列など、さまざまな場面でリストが利用されます。 角カッコの中で要素をカンマで区切って並べたものがリストです。

要素の取得

関数 機能
length(list) listの長さ
first(list) 最初の要素
last(list) 最後の要素

要素の取得は、リスト名[番号] で取得できます。 ただし、注意が必要なのが、番号は 1 から始まるということです。

list:[3,1,4,1];
と定義したとき、最初の要素は list[1] となります。
list[1];
実行結果. 3

要素数の取得は、lengthを用います。

例.

list:[3,1,4,1]$ length(list);
実行結果. 4

要素の追加と削除

関数 機能
cons(a,list) list の先頭に a を追加
endcons(a,list) list の末尾に a を追加
append(list1,list2) list1 と lits2 を結合する
delete(a,list) a を list から削除

注意が必要なのが、どれも適用したリスト自身を変化させないということです。

例.

list:[3,1,4,1];
と定義します。このあとで
endcons(5,list);
を実行すると、 実行結果. [3,1,4,1,5]
が得られますが、次に
list;
を実行すると 実行結果. [3,1,4,1]
となり、list自身は変化していないことが確認できます。
元の list 自体を変更したい場合は
list:endcons(5,list);
とします。

要素の並べ替えと重複要素の削除

関数 機能
sort(list) 並べ替え
unique(list) 重複要素を削除

やはり、こられも適用したリスト自身を変化させません。

例.

list:[1,3,2,1]$ sort(list);
実行結果. [1,1,2,3]
list:[1,3,2,1]$ unique(list);
実行結果. [1,2,3]

規則的なリストの構成

makelist(f(n),n,a,b) の形で用いて、次のリストを返します

[f(a),f(a+1),...,f(b)]

例1.

makelist(n,n,1,10);
実行結果. [1,2,3,4,5,6,7,8,9,10]

例2.

makelist(2*n+1,n,1,10);
実行結果. [3,5,7,9,11,13,15,17,19,21]

条件に合うデータを取り出す

関数 f(x) を x に関して ture か false を返すような関数とします。 このとき
sublist(list,f) は、f(x) が true となるような要素 x 全体のリストを返します。

例1.

f(x):= if mod(x,3)=0 then true else false;
として関数 f を定義します。つまり \[ f(x) = \begin{cases} \text{true} &\text{$x$が3の倍数のとき} \\ \text{false} &\text{その他の場合} \end{cases} \] ということです。このとき
sublist([1,2,3,4,5,6,7,8,9],f);
実行結果.[3,6,9]

が得られます。

以下、すこし高度な話になります。上の例では、関数 f をわざわざ別で定義するのは面倒です。 そこで、匿名関数である「ラムダ式」 というものが利用できます。 次のようにすると、上の結果と同じ結果が得られます。

sublist([1,2,3,4,5,6,7,8,9],lambda([x],mod(x,3)=0));
実行結果.[3,6,9]

lambda([x],mod(x,3)=0) は匿名関数をあらわします。[x] の x は引数を意味します。

高度な機能

関数 g を2変数関数とします。このとき例えば rreduce(g,[x1,x2,x3,x4,x5]) では、最初に
g(x4,x5)が計算されます。(これを y と置きます.) 次に
g(x3,y) が計算されます。(これを改めてyと置きます.)次に
g(x2,y) が計算されます。(これをまた改めてyと置きます.) 最後に
g(x1,y)が計算され、この結果を返します。

例1. 2変数関数g(x,y)をリスト [1,2,3,4] に適用した場合.

(%i114)	rreduce(g,[1,2]);
(%o114)	g(1,2)
(%i115)	rreduce(g,[1,2,3]);
(%o115)	g(1,g(2,3))
(%i116)	rreduce(g,[1,2,3,4]);
(%o116)	g(1,g(2,g(3,4)))
例2. 2 変数関数 x+2*y をリスト [1,2,3] に適用した場合.
rreduce(lambda([x,y],x+5*y),[1,2,3]);
実行結果. 86

数式による表現. \[1+5\cdot(2+5\cdot3) = 86\]

Note. rreduceとは逆の順序で作用する lreduce というものもあります。

lreduce(lambda([x,y],x+5*y),[1,2,3]);
実行結果. 26

数式による表現. \[(1+5\cdot2)+5\cdot3 = 26\]

連分数への応用

連分数というのは、1次分数関数の合成関数を考えていることになります。 $\circ$によって関数の合成を表現すれば \begin{align} 1+\frac{1}{2+\cfrac{1}{3}} = \left( 1+ \frac{1}{x} \right) \circ \left( 2 + \cfrac{1}{x} \right) \circ 3 \end{align} と書けるということです。 rreduceは関数の合成を計算するものなので、これを用いると連分数は表現できます。

rreduce(lambda([x,y],x+1/y),[1,2,3,4]);
実行結果. 43/30

上の結果は \[ \frac{43}{30} = 1+\frac{1}{2+\cfrac{1}{3+\cfrac{1}{4}}} \] を意味します。

次のような一般の連分数も計算できます。 \[ \cfrac{y_1}{x_1 + \cfrac{y_2}{x_2 + \cfrac{y_3}{x_3 + \cfrac{y_4}{x_4 +\lower{5pt} \ddots}}}} \]

(%i181)	a(k):=k;b(k):=k^2;list:endcons(0,makelist([a(k),b(k)],k,1,5));
(%o179)	a(k):=k
(%o180)	b(k):=k^2
(list)	[[1,1],[2,4],[3,9],[4,16],[5,25],0]

上のコードでは、まず連分数のもととなる列 a(k)=k,b(k)=k^2 を定義しています。 そして、リスト [a(k),b(k)] を要素とするリストを

makelist([a(k),b(k)],k,1,5)
で作ってます。そして、endcons を用いて最後に要素「0」を追加しています。
結果として list は [[1,1],[2,4],[3,9],[4,16],[5,25],0] として定義されます。
この list に対して、次のようにrreduceを適用します。
rreduce(lambda([x,y],x[2]/(x[1]+y)),list);
実行結果. 167/339

この結果は \[ \frac{167}{339} = \cfrac{1}{1+\cfrac{4}{2+\cfrac{9}{3+\cfrac{16}{4+\cfrac{25}{5+0}}}}}\] を意味します。

上で定義したlistに対して次を実行すると、LaTeXコードも生成できます。

rreduce(lambda([x,y],printf(false,"\\cfrac{~a}{~a+~a}",x[2],x[1],y)),list);
実行結果. "\cfrac{1}{1+\cfrac{4}{2+\cfrac{9}{3+\cfrac{16}{4+\cfrac{25}{5+0}}}}}"

printf の使用法はちょっと自信がありませんので解説は省略しますが、とりあえずは正しいLaTeXのコードが得られます。

一般的な合成関数への応用

例1.

rreduce(lambda([x,y],x+1/y^2),[1,2,3,4]);
実行結果. 31348165/25583364

これは次を意味します。

\[ \frac{31348165}{25583364} = 1 + \frac{1}{{{\left( 2 + \cfrac{1}{{{ \left( 3 + \cfrac{1}{ 4^{2} } \right) }^{2}}} \right) }^{2}}}\]

例2.

rreduce(lambda([x,y],sqrt(x+y)),[2,2,2,2,2,2,0])$ float(%);
実行結果. 1.999397637392408

これは次を計算していることになります。

\[ \sqrt{2+\sqrt{2+\sqrt{2+\sqrt{2+\sqrt{2+\sqrt{2}}}}}}\]