9月 052017
 

出現確率が一様な抽選は、インデックスを一様乱数で求めればいいので実装が簡単です。

public static T sample<T>(T[] values)
{
    return values[UnityEngine.Random.Range(0, values.Length)];
}
public static T sample<T>(List<T> values)
{
    return values[UnityEngine.Random.Range(0, values.Count)];
}

ちなみに、この抽選は引いたくじを除外せずに次回も有効となる独立試行です。このような抽選を復元抽出と呼ぶそうです。

各要素の出現確率(重み)を設定して復元抽出したいとき、上の手法ではうまくいかないので、ひと工夫する必要があります。例えば、レア度によって出現確率の異なるガチャを実装したいといったケースですね。

以下、Unity向けに実装しますが、乱数取得部分を変えればUnity以外でも使えます。

Continue reading »

9月 042017
 

C#のstring.Format()は便利ですが使いにくいです。大まかな理由は下記にまとまると思います。

  1. インスタンスメソッドでない
  2. インデックスを正確に割り振る必要がある
  3. 書式が覚えられない

1.と2.に対して、C# 6.0でひとつの解決法は示されました。

ただ、私はPython使いでもあるので、Pythonぐらい文字列操作が柔軟であると嬉しいなと思ってしまうわけです。

詳しいことは順に説明することとして、名前をキーにしたDictionaryに対応したFormat()を実装するというゴールを目指します。

Continue reading »

9月 042017
 

C#の書式指定文字列の仕様はC#独自のものであるため、色んな言語を経験していると混乱します。そして、覚えられません。多機能かもしれませんが、かえって使いにくくなっています(※個人の感想です)。

C#自体は好きな言語なのですが、数少ない気に入らない点のひとつがこのフォーマット仕様です。

例えば、

  • 10進整数を表示
  • 正の符号も表示
  • 数値は9桁(符号含め10文字)
  • ゼロパディング(ゼロ埋め)する
  • 3桁ごとにカンマ区切り

この書式をC#で実装してみます。

var format = "{0:+0,00000000;-0,00000000}";
var result1 = string.Format(format, 0);
var result2 = string.Format(format, 1280);
var result3 = string.Format(format, -1280);

ゼロパディングするだけならd9のようにd(10進数)書式を採用すればいいのですが、これはテンプレ書式であって、正の数値に対して符号を出すためにカスタム数値書式を採用すると使えなくなります。このように書式が複数のルールから成り立ち、複雑です。記述も長くなりがち。

ドキュメントがもうね、膨大すぎて読む気が起きないですよ・・・。

やりたい内容からググって逆引き的に情報探したほうが実装が早いという始末。

ちなみに、さっきの例をPythonで書くとこうなります。

format = "{:+010,}"
result1 = format.format(0)
result1 = format.format(1280)
result1 = format.format(-1280)

各条件に対応する記述が最小限ですし、記述する順序もあまり混乱しないと思います。

ドキュメントもすっきり。

Pythonの場合、波括弧で囲んだ中に書式を書くという点ではC#に似ていますが、細かい書式オプションについては、C言語のprintf()ベースになります。

C言語がとても古い言語であるということもあり、その書式が理想的かと問われれば首を傾げますが、たくさんの言語に取り入れられた実績のある仕様です。従って、ある程度共通化された文化であると言えます。しかし、この知識がC#で使えないし、C#の独自仕様は遥かに仰々しい。つらい。

どうしても多機能を実現したいなら、独自フォーマッタをクラスで定義できるようにすれば、それで十分だと思うんですよね。

基本機能はわかりやすくシンプルに。プログラミングの鉄則だと思います。

9月 032017
 

Unity 5.5からC#コンパイラがアップデートされたので、C# 6としてのコンパイルが可能です。

但し、標準ライブラリ側が.NET Framework 3.5相当のまま古いので、C# 6の言語機能をすべて使えるわけではありません。async/awaitなど新しいライブラリに依存する機能は使えず、シンタックスシュガーである文字列補間などは問題なく使えます。

そういった事情からか、Unity 5.5~5.6ではデフォルトでC# 4としてビルドされるようになっています。これをC# 6でビルドさせるように修正する方法をまとめます。

Continue reading »

9月 032017
 

これまでC#の安定ソートが欲しくて色々と検討していました。

アロケーションを気にしなければ、LinkedListについては各要素にインデックス振ったListを作ってSort()するのが速いという結果が出ていました。その実装をここにまとめます。List版もありますが、先の記事で検討したマージソートの方が速いので、Listではそっちを使ったほうがいいです。性能比較については前回の記事を参照。

Continue reading »

9月 032017
 

(2017/09/10 パフォーマンス比較にOrderByを追加。それに伴い、結論をやや修正)

ListとLinkedListの挿入ソートおよびマージソートを実装します。どちらも安定ソートです。

何を考えて実装したのか、長々と別の記事に書いてあるので、興味があればそっちもよろしくです。

マージソートを単純に実装するより、対象となる要素数が少ない時は挿入ソートのほうが速いので、挿入ソートに差し替える対応をします。なので、マージソートの実装がメインで、最適化の副産物で挿入ソートもあるよ、という感じです。

Continue reading »

9月 032017
 

Unityでゲームプログラムを書いていると、C#で気軽に使える安定ソートが欲しくなるのですが、これという機能が標準で用意されていません。

今更ソートなんて自前で実装したくないんですが、欲しいものがなければ作るしかない。実装までに検討した色々なことをこの記事ではまとめていきます。

実装したものは別の記事にまとめたので、そちらをどうぞ。

アルゴリズム系の実装コードって何故かほとんど可読性が低いですよね。主に変数名がやっつけすぎて理解に時間がかかります。バグの温床だと思うので、そのへんも私なりに読みやすくしています。

その点、これからいくらか紹介する.NETやMonoの実装はとても綺麗で理解しやすいです。

Continue reading »

Top