C# 配列、リストへのランダムアクセスの速度

配列を使った時とリストを使った時とで、
ランダムアクセスのスピードがどれくらい違うのかを調べてみた。

長さ 5e7 の配列の 0 番目の要素を 5e7 回見るとき、

  • 配列では、86 ms で、
  • リストでは、95 ms であった。

2割ぐらい違う。

ボトルネックがランダムアクセスの時、
少し気をつけるないといけない。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
public class BenchMark
{
    public static void Main()
    {
        new BenchMark().Do();
    }//Main

    void Do()
    {
        const int len = (int)5e7;
        Stopwatch sw = new Stopwatch();
        int[] array = new int[len];
        var list = new List<int>();
        Random rand = new Random();
        for (int i = 0; i < array.Length; i++)
            list.Add(array[i] = rand.Next());

        sw.Restart();
        int a = 0;
        for (int i = 0; i < len; i++)
        {
            a += array[0];
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        sw.Restart();
        int b = 0;
        for (int i = 0; i < len; i++)
        {
            b += list[0];
        }
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        Console.WriteLine(a+" "+b);

    }



}//BenchMark

C# リストの連結の測度

リストを要素とするリスト List> の要素を
全て連結させて1つのリストを作りたい。
例えば、{{3,2},{1,0},{-1}} を {3,2,1,0,-1} にしたい。


作戦とは2つ。

  1. 2重ループを用いて、要素の要素を全てリストに突っ込む
  2. Concat 関数を用いて、for 文1回で IEnumerable としてくっつけてから、ToList() をする。


後者の方が速いんじゃないかなぁとか思ったけど、
そんなことはなかった。


void Entry()
    {
        const int len = 1000;
        const int numElement = 10;

        List<int>[] lists = new List<int>[len];
        for (int i = 0; i < lists.Length; i++)
        {
            lists[i] = new List<int>();
            for (int k = 0; k < numElement; k++)
            {
                lists[i].Add(i + k);
            }//for k
        }//for i

        //全ての要素を見る
        Stopwatch sw = new Stopwatch();
        sw.Restart();
        List<int> a = new List<int>();
        foreach (var list in lists)
        {
            foreach (var v in list)
            {
                a.Add(v);
            }//foreach c
        }//foreach item
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);

        //リストのまま連結
        sw.Restart();
        IEnumerable<int> b = Enumerable.Range(0, 0);
        foreach (var list in lists)
        {
            b = b.Concat(list);
        }//foreach item
        List<int> c = b.ToList();
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);


        //本質とは関係ないコード
        long sum = 0;
        foreach (var item in a)
        {
            sum += item;
        }//foreach item
        Console.WriteLine(sum);
        foreach (var item in c)
        {
            sum += item;
        }//foreach item
        Console.WriteLine(sum);
    }

PDFの図が切れる

問題の環境

  • matlabで作った図を編集して .eps で保存
  • .tex で、includegraphics を用いてその図を呼び出す
  • willshell を使って、.dvi, .pdf を作る。

ということをやっていた。

  1. .dvi の時点でそもそも切れていたり
  2. .dvi では OK だが、.pdf の時だけ切れたり

する状態であった。

原因

  1. については、そもそも .eps への変換がおかしかった
  2. については、図が大きすぎて、切れていた

(この切れるの意味は、図を挿入する枠があって、
 枠からはみ出た部分がだけ切れていたということではなく、
 枠から少しでも出たせいで、一定の部分が切れてしまっていたという意味)

対処法

  1. については、EPS-convの詳細情報 : Vector ソフトを探す! を使った。
  2. については、Inkscape を使った。



  • EPS-convは、2,3回実行したらようやく動き始めた。

やることは、ドラッグ&ドロップだけ。
変換されたものが、勝手に元のファイルと同じ場所に保存される。
(ので、名前に注意する必要があると思う)

  • Inkscape は、.eps を読み込んで、図を小さくして保存しなおしたら、うまくいった。

C#でのメルセンヌツイスター

C++マニアック,Mersenne Twister,メルセンヌ・ツイスタ,高性能擬似乱数発生器,C#ポート,Pseudo Random Number,csharp porting
にコードがある。

暇があるときにアルゴリズムを理解しないと。

ポーカーの役判定(ペア系)

ポーカーの役判定プログラム(C#): amongの雑記
を見た。

ストレート、フラッシュの判定は簡単にできるが、

ペア系の判定が面倒だと思ったが、以下のコードでできる。

5枚のカードを持つリスト hand を受け取る。

int cnt = 0;
for (int i = 0; i < hand.Count; i++)
{
 for (int j = i+1; j < hand.Count; j++)
 {
 if (hand[i] と hand[j] の数字が同じ)
 {
  cnt++;
 }//if
 }//for j
}//for i
cnt==1 → ワンペア
cnt==2 → ツーペア
cnt==3 → スリーカード
cnt==4 → フルアウス
cnt==6 → フォーカード

cnt 自体は何を数えているか意味不明だが、
よくよく場合分けをしてみると、
これで正しいことが分かる。

トランプのあれは数字でいいのだろうか。
AJQKは数字じゃないよなぁ。

C++の動的ライブラリの作り方

チュートリアル: ダイナミック リンク ライブラリの作成と使用 (C++)

を見ればできた。

 

他のHPに書いてあるように、

プロジェクトの新規作成するときに、

クラスライブラリプロジェクトを選択するとよくわからないことになった。

上にあるように、"Win32 コンソール アプリケーション"を選択していけばできる。