[プログラミング] Algodooで使用できるThyme(タイム)言語による追加関数

プログラミング

Algodooでは、Thyme(タイム)と呼ばれる独自のスクリプト言語を使用します。
デフォルトで埋め込み(ビルトイン)関数も用意されていますが、追加の関数(function)を定義してあげることで、より便利に使うことができます。

本記事は、こちらの英語ドキュメント(Thyme Additional Functions)から、使用頻度が高そうな関数に絞って解説します。
完全に主観で選んでいますので、全体を知りたい場合は、こちらの英語ドキュメントを参照ください。

Thyme Additional Functions
Thyme Additional Functions by Doc Desk with help from Lapse and Erikfassett. All functions in this document are intended...

埋め込み(ビルトイン)関数

Algodooのシーンを開き、F10を押してコンソールを起動します。
タブキーを入力することで、埋め込み関数一覧を表示することができます。

入力補完にも対応していますので、例えば「math.p」までを入力して、タブキーを押すと、候補となる関数(この場合はmath.pi, math.posivate, math.powが出力される結果となります。

math.pow(2, 10)と入力して実行すると、2の10乗の結果が得られます。

Scene.myスコープ

以下の追加関数は、いずれもScene.myではじまるスコープに保存されます。
同様にScene.myと入力して、タブキーを押すと、候補となる変数や関数が一覧で表示されます。

Nanotechnology Part 1: Nanomechanics and Algodoo Simulator
Understanding nanotechnology using analogies: macroscale physics simulator and nanoscale back-of-envelope calculationss

リスト操作(List manipulation)

これらはF10を押したコンソール上から実行することを想定しています。
一度実行すると、開いているシーンのScene.my.<関数名>で保存されますので、毎回実行する必要はありません。

all

リスト内のすべての要素が指定された条件を満たす場合は true を返します。

  • 使用法: Scene.my.all(<リスト>, <条件>)
  • 例: Scene.my.all([1,2,3], (number)=>{number > 0 })はtrueを返す(リスト内のすべての数値が 0 より大きいため)
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<条件>関数各要素をチェックする条件
boolを返す必要がある
実行コード
Scene.my.all := (list, predicate)=>{
    listLength := string.length(list);
    if_then_else(listLength == 0, {
        true;
    }, {
        if_then_else(predicate(list(0)), {
            Scene.my.all(list(1 .. (listLength - 1)), predicate);
        }, {
            false;
        });
    });
};

any

リスト内のいずれかの要素が指定された条件を満たす場合は true を返します。

  • 使用法: Scene.my.any(<リスト>, <条件>)
  • 例: Scene.my.any([-3,0], (number)=>{number > 0 })はfalseを返す(リスト内の数字はどれも 0 より大きくないため)
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<条件>関数各要素をチェックする条件
boolを返す必要がある
実行コード
Scene.my.any := (list, predicate)=>{
   listLength := string.length(list);
   if_then_else (listLength == 0 , {
       false ;
   }, {
       if_then_else (predicate(list( 0 )), {
           true ;
       }, {
           Scene.my.any(list( 1  .. (listLength - 1 )), predicate);
       });
   });
};

average

指定された数値リストの平均を返します。

  • 使用法: Scene.my.average(<リスト>)
  • 例: Scene.my.average([ 3 , 4 , 5 ])は4を返す 
引数パラメータタイプ説明
<リスト>フロートリスト操作対象のリスト

ここで出てくる「フロートリスト」は、整数または浮動小数点数で構成されたリストと認識ください。

実行コード
Scene.my.average := (list)=>{
    sum := 0;
    listLength := string.length(list);
    for(listLength, (i)=>{
        sum = sum + list(i);
    });
    sum / listLength;
};

contains

指定された要素がリスト内に存在する場合は true を返します。

  • 使用法: Scene.my.contains(<リスト>, <要素>)
  • 例: Scene.my.contains([ 3 , 4 , 5 ], 3 )は true を返す(リスト[ 3 , 4 , 5 ]には3が含まれているため)
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<要素>ブール型、浮動小数点型、文字列、または、それらのリストリストをチェックする要素
実行コード
Scene.my.contains := (list, element)=>{
    contains := false;
    for(string.length(list), (i)=>{
        if_then_else(list(i) == element, {
            contains = true
        }, {})
    }); 
    contains
};

filter

指定された条件を満たす、指定されたリストのすべての要素を含むリストを返します。

  • 使用法: Scene.my.filter(<リスト>, <条件>)
  • 例: Scene.my.filter(0..10, (n)=>{n > 5 })は[ 6 , 7 , 8 , 9 , 10 ]  (0から10までの範囲内の5より大きい整数) を返す
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<条件>関数各要素をチェックする条件
boolを返す必要がある
実行コード
Scene.my.filter := (list, predicate)=>{
    newList := [];
    for(string.length(list), (i)=>{
        if_then_else(predicate(list(i)), {
            newList = newList ++ list[i];
        }, {});
    });
    newList;
};

fold

リストに対して関数(func)を実行し、リストの要素を結合して単一の値を返します。

  • 使用方法: Scene.my.fold(<初期値>, <リスト>, <関数>)
  • 例: Scene.my.fold( 0 , [ 3 , 4 , 5 ], (total, number)=>{total + number}) は12  (リスト内の数字の合計) を返す。
引数パラメータタイプ説明
<初期値>Any初期値
<リスト>リスト操作対象のリスト
<関数>関数累積関数
実行コード
Scene.my.fold := (initialValue, list, func)=>{
   accumulator := initialValue;
   for (string.length(list), (i)=>{
       accumulator = func(accumulator, list(i))
   });
   accumulator
};

indexOf

指定されたリスト内の指定された要素の最初のインスタンスのインデックスを返します。
要素が見つからない場合は -1 を返します。

  • 使用法: Scene.my.indexOf(<リスト>, <要素>)
  • 例: Scene.my.indexOf([ “Hello” , “World” , “From” , “Thyme” ], “From” )は2を返す
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<要素>Anyインデックスを検索する要素
実行コード
Scene.my.indexOf := (list, element)=>{
    index := -1;
    for(string.length(list), (i)=>{
        if_then_else(index == -1 && list(i) == element, {
            index = i
        }, {})
    });
    index
};

insertAtIndex

指定された要素をリストの指定されたインデックスに挿入し、新しいリストを返します。

  • 使用方法: Scene.my.insertAtIndex(<リスト>, <インデックス>, <要素>)
  • 例: Scene.my.insertAtIndex([ 3 , 4 , 5 ], 1 , 6 )は[ 3 , 6 , 4 , 5 ] を返す
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<インデックス>整数新しい要素を挿入する場所
0の場合は先頭に挿入する
<要素>Anyリストに挿入する新しい要素
実行コード
Scene.my.insertAtIndex := (list, index, element)=>{
    list(0 .. (index - 1)) ++ [element] ++ list((index) .. (string.length(list) - 1))
};

map

指定されたリストの各要素に指定された関数を適用し、結果のリストを返します。

  • 使用法: Scene.my.map(<リスト>, <関数>)
  • 例: Scene.my.map( 0  .. 5 , (n)=>{n + 3 })は[ 3 , 4 , 5 , 6 , 7 , 8 ]  (3から8までの整数) を返す
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<関数>関数適用する関数
実行コード
Scene.my.map := (list, func)=>{
    newList := [];
    for(string.length(list), (i)=>{
        newList = newList ++ [func(list(i))];
    });
    newList;
};

max

指定された数値リストの最大値を返します。

  • 使用法: Scene.my.max(<リスト>)
  • 例: Scene.my.max([ 3 , 4 , 5 ])は5を返す
引数パラメータタイプ説明
<リスト>フロートリスト操作対象のリスト
実行コード
Scene.my.max := (list)=>{
   max := -inf;
   for (string.length(list), (i)=>{
       if_then_else (list(i) > max, {
           max = list(i);
       }, {})
   });
   max;
};

min

指定された数値リストの最小値を返します。

  • 使用法: Scene.my.min(<リスト>)
  • 例: Scene.my.min([ 3 , 4 , 5 ])は3を返す 
引数パラメータタイプ説明
<リスト>フロートリスト操作対象のリスト
実行コード
Scene.my.min := (list)=>{
   min := +inf;
   for (string.length(list), (i)=>{
       if_then_else (list(i) < min, {
           min = list(i);
       })
   });
   min;
};

modifyAtIndex

リスト内の指定されたインデックスの要素を変更し、新しいリストを返します。

  • 使用方法: Scene.my.modifyAtIndex(<リスト>, <インデックス>, <要素>)
  • 例: Scene.my.modifyAtIndex([ 3 , 4 , 5 ], 1 , 6 )は[ 3 , 6 , 5 ] を返す 
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<インデックス>整数変更する要素を指すインデックス
0の場合は先頭の要素を変更する
<要素>Anyリストに追加する新しい要素
実行コード
Scene.my.modifyAtIndex := (list, index, newElement)=>{
   list( 0  .. (index - 1 )) ++ [newElement] ++ list((index + 1 ) .. (string.length(list) - 1 ))
};

quickSort

クイック ソート アルゴリズムを使用してリストをソートし、ソートされたリストを返します。

  • 使用法: Scene.my.quickSort(<リスト>)
  • 例: Scene.my.quickSort([ 3 , 5 , 4 ]) は[ 3 , 4 , 5 ] を返す
引数パラメータタイプ説明
<リスト>フロートリストソートするリスト
実行コード
Scene.my.quickSort = (arr)=>{
    len := string.length(arr);
    len <= 1 ? arr : {
        average := 0;
        for(len, (i)=>{
            average = average + arr(i)
        });
        average = math.tofloat(average) / len;
        smaller := [];
        larger := [];
        equal := [];
        for(len, (i)=>{
            arr(i) > average ? {
                larger = larger ++ [arr(i)]
            } : {};
            arr(i) < average ? {
                smaller = smaller ++ [arr(i)]
            } : {};
            arr(i) == average ? {
                equal = equal ++ [arr(i)]
            } : {}
        });
        Scene.my.quickSort(smaller) ++ equal ++ Scene.my.quickSort(larger)
    }
};

removeAtIndex

指定されたインデックスの要素をリストから削除し、新しいリストを返します。

  • 使用方法: Scene.my.removeAtIndex(<リスト>, <インデックス>)
  • 例: Scene.my.removeAtIndex([ 3 , 4 , 5 ], 2 )は[ 3 , 4 ] を返す
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
<インデックス>整数削除する要素を指すインデックス
0の場合は先頭の要素を削除する
実行コード
Scene.my.removeAtIndex := (list, index)=>{
   list( 0  .. (index - 1 )) ++ list((index + 1 ) .. (string.length(list) - 1 ))
};

removeFirstItem

リストから最初に一致する項目を削除し、新しいリストを返します。

  • 使用方法: Scene.my.removeFirstItem(<リスト>, <要素>)
  • 例: Scene.my.removeFirstItem([ 7 , 6 , 5 , 6 , 4 ], 6 )は[ 7 , 5 , 6 , 4 ] を返す
引数パラメータタイプ説明
<リスト>整数 or 浮動小数点数 or 文字列のリスト操作対象のリスト
(数値のみ、または、文字列のみのリスト)
<要素>整数 or 浮動小数点数 or 文字列削除する要素
実行コード
Scene.my.removeFirstItem := (list, item)=>{
    output = [];
    removedItem := false;
    for(string.length(list), (i)=>{
        ! removedItem && list(i) == item ? {
            removedItem = true
        } : {
            output = output ++ [list(i)]
        }
    });
    output
};

removeItem

リストからアイテムに一致するすべての要素を削除し、新しいリストを返します。
整数 or 浮動小数点数 or 文字列のリストでのみ機能します。
リストには数値と文字列を混在させることはできません。

注意:リストに重複した項目がある場合、ターゲットになっていない場合でも、すべての重複は 1 つの項目にまとめられます。

  • 使用方法: Scene.my.removeItem(<リスト>, <アイテム>)
  • 例: Scene.my.removeItem([ 7 , 6 , 5 , 6 , 4 ], 6 )は[ 7 , 5 , 4 ] を返す
引数パラメータタイプ説明
<リスト>整数 or 浮動小数点数 or 文字列のリスト操作対象のリスト
(数値のみ、または、文字列のみのリスト)
<アイテム>整数 or 浮動小数点数 or 文字列削除する要素
実行コード
Scene.my.removeItem := (list, item)=>{
    newList := set.merge([item], list);
    newList(1 .. (string.length(newList) - 1))
};

removeItems

リスト#1から、リスト#2の項目に一致するすべての要素を削除し、新しいリストを返します。
整数 or 浮動小数点数 or 文字列のリストでのみ機能します。
リストには数値と文字列を混在させることはできません。

注意:リストに重複した項目がある場合、ターゲットになっていない場合でも、すべての重複は 1 つの項目にまとめられます。

  • 使用方法: Scene.my.removeItems(<リスト#1>, <リスト#2>)
  • 例: Scene.my.removeItems([ 7 , 6 , 5 , 6 , 4 ], [ 5 , 6 ])は[ 7 , 4 ] を返す
引数パラメータタイプ説明
<リスト#1>整数 or 浮動小数点数 or 文字列のリスト操作対象のリスト
(数値のみ、または、文字列のみのリスト)
<リスト#2>整数 or 浮動小数点数 or 文字列のリスト削除するリスト
(数値のみ、または、文字列のみのリスト)
実行コード
Scene.my.removeItems := (list, items)=>{
    newList := set.merge(items, list);
    newList(string.length(items) .. (string.length(newList) - 1))
};

reverse

指定されたリストの順序を逆にしたリストを返します。

  • 使用法: Scene.my.reverse(<リスト>)
  • 例: Scene.my.reverse([ 3 , 4 , 5 ]) は[ 5 , 4 , 3 ] を返す 
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
実行コード
Scene.my.reverse := (list)=>{
    newList := [];
    listLength := string.length(list);
    for(listLength, (i)=>{
        newList = newList ++ [list(listLength - 1 - i)];
    });
    newList;
};

shuffle

指定されたリストをシャッフルします。

  • 使用方法: Scene.my.shuffle(<リスト>)
  • 例: Scene.my.shuffle([ 0 , 1 , 2 ])は[ 1 , 0 , 2 ] を返す 
引数パラメータタイプ説明
<リスト>リスト操作対象のリスト
実行コード
Scene.my.shuffle := (list)=>{
    input := list;
    output := [];
    for(string.length(list), (i)=>{
        index := math.toInt(rand.uniform01 * string.length(input));
        output = output ++ [input(index)];
        input = input(0 .. index - 1) ++ input(index + 1 .. string.length(input) - 1)
    });
    output
};

まとめ

本記事では、リスト操作などの使用頻度が高そうな関数に絞って解説しました。
有用そうな関数については都度追加していきます。

Nanotechnology Part 1: Nanomechanics and Algodoo Simulator
Understanding nanotechnology using analogies: macroscale physics simulator and nanoscale back-of-envelope calculationss

コメント

タイトルとURLをコピーしました