物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

2個の自作クラスの配列(std::vector<MyClass>)から重複とかを探す

2個の数列(std::vector<int>とか)から重複とかを探す - 物理の駅 Physics station by 現役研究者 の続き

2個の自作クラスの配列(ベクター)から重複等を探す方法を紹介する。Linuxのjoinコマンドを高速化する場合などに使える。

#include <algorithm>に便利な関数が用意されている。

std::sortでソートして、std::uniqueeraseで重複を削除した後、set_intersection, set_union, set_differenceで、積集合、和集合、差集合を得ることができる。自作クラスに比較演算子等がないため、自分で関数を作って与える必要がある。この3つの関数に与える演算子は比較 (<) 演算子である。

今回は比較演算用の関数の使い回しが多いため、ラムダ式ではなく関数として定義する。 古い例ではインライン関数 inlineが与えられていることがあるが、最近のコンパイラは賢く、勝手に最適化してくれるのでユーザーがわざわざつける必要はない(らしい)。

#include <random>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>

class MyClass
{
public:
    unsigned int id;
    double x, y, ax, ay;
};

bool mycomp_size(const MyClass &a, const MyClass &b) { return (a.id < b.id); }      //大小比較
bool mycomp_equal(const MyClass &a, const MyClass &b) { return (a.id == b.id); }   //イコール比較

void main()
{
    const int Ntrk = 10000000;

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, Ntrk - 1);
    std::vector<MyClass> list1, list2;

    for (int i = 0; i < Ntrk; ++i)
    {
        MyClass t;
        t.id = dis(gen);    //乱数を作成
        list1.emplace_back(t);
        t.id = dis(gen);    //乱数を作成
        list2.emplace_back(t);
    }

    std::sort(list1.begin(), list1.end(), mycomp_size); //ソート
    std::sort(list2.begin(), list2.end(), mycomp_size); //ソート

    std::cout << list1.size() << " (unique)-> ";
    //重複を削除
    list1.erase(std::unique(list1.begin(), list1.end(), mycomp_equal), list1.end());
    std::cout << list1.size() << std::endl;

    std::cout << list2.size() << " (unique)-> ";
    //重複を削除
    list2.erase(std::unique(list2.begin(), list2.end(), mycomp_equal), list2.end());
    std::cout << list2.size() << std::endl;

    std::vector<MyClass> list_inter;
    //list1とlist2の両方にある値 (積集合 intersection)
    std::set_intersection(list1.begin(), list1.end(), list2.begin(), list2.end(), std::back_inserter(list_inter), mycomp_size);

    std::vector<MyClass> list_union;
    //list1かlist2のどちらかに存在する値 (和集合 union)
    std::set_union(list1.begin(), list1.end(), list2.begin(), list2.end(), std::back_inserter(list_union), mycomp_size);

    std::vector<MyClass> list_dif1;
    //list1にあってlist2にない値 (差集合 dif1)
    std::set_difference(list1.begin(), list1.end(), list2.begin(), list2.end(), std::back_inserter(list_dif1), mycomp_size);

    std::vector<MyClass> list_dif2;
    //list2にあってlist1にない値 (差集合 dif2)
    std::set_difference(list2.begin(), list2.end(), list1.begin(), list1.end(), std::back_inserter(list_dif2), mycomp_size);

    //結果の確認
    std::cout << "dif1 + dif2 + inter = union" << std::endl;
    printf_s("%u + %u + %u = %u\n", list_dif1.size(), list_dif2.size(), list_inter.size(), list_union.size());
}

OneDriveで非常に小さいファイルの同期が終わらない問題

OneDrive上でgitのリポジトリを管理している。 そして、頻繁にOneDriveの同期(アップロード)が終わらない問題が発生する。 gitのcommitのタイミングとOneDriveの同期のタイミングが衝突して、システムファイル関係が(MFT マスターファイルテーブルとか?)が変になっているのではないかと推測。 なので、以下のコマンドをWindowsが起動している状態で実行してみた。

chkdsk
chkdsk /scan

をしたら、ちゃんと同期が完了した。なぜだろうね。因果関係は追跡調査していく。

追記:

2017年現在、この問題は発生していない。

PDFで作成したグラフをベクタ形式としてPowerPointに貼り付ける方法の検討

PDFで作成したグラフを無圧縮、つまりベクタ形式でPowerPointで貼り付ける方法を検討した。

使ったのはCERNが開発するRootで作ったPDFファイルである。

f:id:onsanai:20161114183010p:plain:w500

試した方法は、有料のAcrobat ProとCCのIllustratorを使った5方法

結論としては、4番目の方法であるIllustratorでepsに変換してPowerPointに貼り付ける、次点で1番目のAcrobatでepsに変換してPowerPointに貼り付けるがうまくいった。

Acrobatでepsに変換してPowerPointに貼り付ける方法

変換はできるものの、文字サイズやフォント等の再現性が悪い。

f:id:onsanai:20161114183453p:plain:w500

Acrobatpngに変換してPoiwerPointに貼り付ける方法

再現性は良いが、ベクタ形式に変換できていない。

f:id:onsanai:20161114183507p:plain:w500

Acrobatでpptxに変換する方法

Acrobatがpptxに変換するときに対応している線の種類に制限があるのか、正しく変換できていない。

f:id:onsanai:20161114183522p:plain:w500

Illustratorでepsに変換してPowerPointに貼り付ける方法

最もよく再現できている。若干文字の太さが違う。

f:id:onsanai:20161114183535p:plain:w500

Illustratorでwmfに変換してPowerPointに貼り付ける方法

IllustratorではPDFからwmfにベクタ形式としては変換できない。

f:id:onsanai:20161114183558p:plain:w500

結論としては、最初に述べた通りIllustratorでepsに変換してPowerPointに貼り付けるのが良いだろう。参考にされたし。

次回、無料のツールを使って変換する方法を試す予定。

ELECOM LANケーブル LD-TWST/BM200 レビュー

問:カテゴリ7対応のLANケーブル、20メートル長で10Gbpsは出るのか?

周辺環境によってエラーレートが変わるのは承知しているが、まずは原理的に速度ができるのかを確認した。

使ったのは、

  • ハブ:NETGEAR
  • LANカード:10GbpsIntel 540-t2
  • ツール:CrystalDiskMark 3または4スレッド
  • ディスク:RAMDA 物理メモリ上のRAMディスク

intel X540-T2

intel X540-T2

f:id:onsanai:20161109161206p:plain:w500

f:id:onsanai:20161109161209p:plain:w500

netstat -sの結果の抜粋

IPv4 統計

  受信したパケット                 = 84892211
  受信したヘッダー エラー          = 0
  受信したアドレス エラー          = 221
  転送されたデータグラム           = 0
  受信した不明プロトコル           = 4
  受信後に破棄されたパケット       = 1418
  受信後に配信されたパケット       = 84891132
  出力要求                         = 10380822
  ルーティング破棄                 = 0
  破棄された送信パケット           = 9
  ルートのない送信パケット         = 0
  再構築が必要                     = 0
  再構築                           = 0
  再構築エラー                     = 0
  正常に断片化されたデータグラム   = 0
  断片化できなかったデータグラム   = 0
  作成された断片                   = 0

IPv4 の TCP 統計

  アクティブ オープン              = 243
  パッシブ オープン数              = 75
  失敗した接続試行数               = 13
  リセットされた接続               = 33
  現在の接続                       = 15
  受信したセグメント               = 84885347
  送信したセグメント               = 61786533
  再送信されたセグメント           = 271


IPv4 の UDP 統計

  受信したデータグラム    = 4086
  ポートなし              = 1339
  受信エラー              = 80
  送信したデータグラム    = 598

答:10Gbpsは出そう。7.5Gbpsは確実に出る。エラーレートも高くない。

仕様通り出るのは当然ではあるが、Amazonなどでは1Gbpsのポート+ルータで1Gbpsが出ました!とかいう報告しかなくて少し心配だった。 だがこれで一安心。