2016-08-25 2 views
2

2つの配列が等しいかどうかを調べる必要がありますが、不一致の要素を見つけたら3番目の配列(他の2つと同じサイズ)それを無視することができます。C++は3つの配列を基準として等しいかどうかを確認します

私はそれを解決するための簡単なアルゴリズムを書くことができますが、これを解決するにはstdアルゴリズムを使用するC++のようなスタイルがあるかどうかを知りたいと思います。

例:

A = [1, 2, 3, 4, 5, 6] 
B = [1, 2, 3, A, 5, 6] 
M = [true, true, true, false, true, true] 
N = [true, true, true, true, true, true] 

bool equal1 = the_equal(begin_A, end_A, begin_B, begin_M); // Should return true, even if '4' is different from 'A' since in the same position of the found mismatch, in the M sequence, we have a false that indicates that position should be ignored. 

bool equal2 = the_equal(begin_A, end_A, begin_B, begin_N); // Should return false, since '4' is different from 'A' and we have a true in sequence N for that position. 

のようなものによって解決することができます

template<I1, I2, I3> // iterators 
bool the_equal(I1 first1, I1 last1, I2 first2, I3 first3) { 
    while (first1 != last1) { 
    if (*first1 != *first2 && *first3 != false) 
     return false; 
    ++first1; ++first2; ++first3; 
    } 

    return true; 
} 

編集:私は、私はC++ 98のによるツールチェーンの制限でこれを解決する必要があると言うことを忘れてしまった:(

+1

if(first1!= * first2 && * first3!= false) '(if first1!= first2 && first3!= false)'とすることができますか? (参照解除のために追加されたアスタリスクに注意してください) – Arun

+0

あなたは何をしたいですか?それはコーディングスタイルについてですか?私はこのような簡単な例でも、おそらくそれを行う方法はたくさんありますが、おそらくあなたが思いついたものより悪く見える可能性があります。 – user1810087

+0

@Arunが修正されました。ありがとうございます。 – Valmir

答えて

3

あなたは(変更可能)ファンクターを作成することが

std::cout << std::equal(A.begin(), A.end(), 
         B.begin(), 
         MakeCmpWithMask(M.begin())) << std::endl; 
std::cout << std::equal(A.begin(), A.end(), 
         B.begin(), 
         MakeCmpWithMask(N.begin())) << std::endl; 
+0

実際これはかなりいいです:) – user1810087

+0

これはまさに私が探していたものです=) – Valmir

1

std::equalは近いですが、直接使用できるかどうかは不明ですが、あなたのコードはかなり良いと思います。

template<I1, I2, I3> // iterators 
bool equal_with_mask(I1 first1, I1 last1, I2 first2, I3 first3) { 
    for (; first1 != last1; ++first1, ++first2, ++first3) { 
    if (*first3 && (*first1 != *first2)) { 
     return false; 
    } 
    } 
    return true; 
} 

(平等)比較が重い場合は、最初にマスクをチェックするのが良いかもしれません。

トリビア:第3のシーケンス(first3)は、TCAM(Ternary Content Addressable Memory)などの一部のハードウェアデバイスで使用されるマスクのようなものです。

template <typename IT> 
struct CmpWithMask 
{ 
    CmpWithMask(IT it) : it(it) {} 

    template <typename LHS, typename RHS> 
    bool operator() (const LHS& lhs, const RHS& rhs) { 
     return !*it++ || lhs == rhs; 
    } 
    IT it; 
}; 

template <typename IT> 
CmpWithMask<IT> MakeCmpWithMask(IT it) { return CmpWithMask<IT>{it}; } 

をそして、std::equalを使用します:

+0

ここのエラー 'template ' –

+0

はい@Arun、あなたはポイントを持っています。 3番目のシーケンスはマスクになります。 – Valmir

+0

@BiagioFestaありがとう、私は質問のテキストを使用し、それを変更しました。私はコンパイラをつかんでしばらくの間、完全な構文を扱いましょう。 – Arun

0

は、私はまた、あなたのコードだけで罰金だと思います。あなたは標準関数の1つを使うことができますが、コードの読みやすさを損なう可能性があるため、常に推奨されるわけではありません。最高の解決策はあなたが読むことができるものです。しかし、ここで溶液(多くの可能な実装の1つ)std::mismatch使用:

template<typename I1, typename I2, typename I3> // iterators 
bool the_equal2(I1 first1, I1 last1, I2 first2, I3 first3) { 
    auto p = std::mismatch(first1, last1, first2); 
    if(p.first != last1) 
    return (!first3[p.first - first1] ? true : the_equal2(p.first+1, last1, p.second+1, first3)); 

    return false; 
} 

アクションでhereを参照してください、そして、バグチェックされていない注意してください...

をしかし、それはより良い例よりのように見えるんArunが投稿されましたか?再帰とauto pでは、不一致が返ってくるかどうかわからない場合は、pのタイプを調べなければなりません(std::pair<I1, I2>)?あなたはiterator_traitsやfancy find_if/equal/mismatchの組み合わせを使って再帰を取り除き、それをもっと読めないようにすることによっても改善することができます。

+1

単純なループで再帰を取り除くだけで十分です。 – Jarod42

関連する問題