4 টি বুলিয়ান মান কিছু ক্ষেত্রে মেলে কিনা তা যাচাই করার জন্য কীভাবে যুক্তি উন্নত করবেন


118

আমার চারটি boolমান আছে:

bool bValue1;
bool bValue2;
bool bValue3;
bool bValue4;

গ্রহণযোগ্য মানগুলি হ'ল:

         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true       | true       | true
bValue2: true       | true       | false
bValue3: true       | true       | false
bValue4: true       | false      | false

সুতরাং, উদাহরণস্বরূপ, এই দৃশ্যটি গ্রহণযোগ্য নয়:

bValue1: false
bValue2: true
bValue3: true
bValue4: true

এই মুহূর্তে ifখারাপ পরিস্থিতি সনাক্ত করতে আমি এই বিবৃতিটি নিয়ে এসেছি :

if(((bValue4 && (!bValue3 || !bValue2 || !bValue1)) ||
   ((bValue3 && (!bValue2 || !bValue1)) ||
   (bValue2 && !bValue1) ||
   (!bValue1 && !bValue2 && !bValue3 && !bValue4))
{
    // There is some error
}

এই বিবৃতি যুক্তি উন্নত / সরল করা যেতে পারে?


8
আমি জটিল ifস্টেটমেন্টের পরিবর্তে একটি টেবিল ব্যবহার করব । অতিরিক্ত হিসাবে, এগুলি বুলিয়ান পতাকা হিসাবে, আপনি প্রতিটি দৃশ্যের ধ্রুবক হিসাবে মডেল করতে পারেন এবং এর বিপরীতে চেক করতে পারেন।
জেডেস্লাভ ভোজকোভিক

3
if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
মিচ

14
পরিস্থিতি আসলে কি? আপনি জিনিসগুলি যথাযথ নাম দিলে প্রায়শই জিনিসগুলি অনেক সহজ হয়ে যায়, যেমনbool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
idclev 463035818

6
অর্থবহ নাম ব্যবহার করে, আপনি প্রতিটি জটিল শর্তটি কোনও পদ্ধতিতে উত্তোলন করতে পারেন এবং যদি সেই অবস্থাতে সেই পদ্ধতিতে কল করতে পারেন। এটি অনেক বেশি পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য হবে। উদাহরণস্বরূপ লিঙ্কে প্রদত্ত উদাহরণটি একবার দেখুন। refactoring.guru/decompose-conditional
Hardik Modha

5
অবগতির জন্য en.wikipedia.org/wiki/Karnaugh_map
00__00__00

উত্তর:


195

আমি পঠনযোগ্যতার জন্য লক্ষ্য করব: আপনার কাছে মাত্র 3 টি দৃশ্য রয়েছে, 3 টি পৃথক আইএফএস নিয়ে তাদের সাথে ডিল করুন:

bool valid = false;
if (bValue1 && bValue2 && bValue3 && bValue4)
    valid = true; //scenario 1
else if (bValue1 && bValue2 && bValue3 && !bValue4)
    valid = true; //scenario 2
else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
    valid = true; //scenario 3

পড়তে এবং ডিবাগ করা সহজ, আইএমএইচও। এছাড়াও, আপনি whichScenarioএগিয়ে চলার সময় একটি পরিবর্তনশীল বরাদ্দ করতে পারেন if

মাত্র ৩ টি পরিস্থিতিতে আমি এই জাতীয় কিছু নিয়ে যাব না "যদি প্রথম 3 টি মান সত্য হয় তবে আমি অগ্রিম মানটি এড়াতে পারি": এটি আপনার কোডটি পড়া এবং বজায় রাখা আরও শক্ত করে তুলছে।

একটি মার্জিত সমাধান নয় হতে পারে অবশ্যই, তবে এই ক্ষেত্রে ঠিক আছে: সহজ এবং পঠনযোগ্য।

যদি আপনার যুক্তি আরও জটিল হয়ে যায় তবে সেই কোডটি ফেলে দিন এবং বিভিন্ন উপলভ্য পরিস্থিতিতে সংরক্ষণ করার জন্য আরও কিছু ব্যবহার করার কথা বিবেচনা করুন (যেমন জ্লাডেক পরামর্শ দিচ্ছেন)।

আমি এই উত্তরে প্রদত্ত প্রথম পরামর্শটি সত্যিই পছন্দ করি : পড়া সহজ, ত্রুটি প্রবণ নয়, রক্ষণাবেক্ষণযোগ্য

(প্রায়) বন্ধ বিষয়:

স্ট্যাকওভারফ্লোতে আমি এখানে প্রচুর উত্তর লিখি না। এটি সত্যিই মজার যে উপরোক্ত স্বীকৃত উত্তরটি আমার ইতিহাসের সবচেয়ে প্রশংসিত উত্তর (আমার ভাবার আগে কখনও 5-10-এরও বেশি উর্ধ্বে ছিল না) যদিও আসলে আমি যা করি তা করার সঠিক "সঠিক" উপায় নয়।

তবে সরলতা প্রায়শই "এটি করার সঠিক উপায়" হয়, অনেকের মনে হয় এটি মনে হয় এবং আমার চেয়ে আমার এটিকে আরও চিন্তা করা উচিত :)


1
নিশ্চিত @ শেসামেহেডিহ, এটি কেবলমাত্র সংখ্যক উপলভ্য দৃশ্যের জন্য ঠিক। যেমনটি আমি বলেছি, যদি বিষয়গুলি আরও জটিল হয়ে
Gian পাওলো

4
এটি পৃথক স্টেটমেন্ট ব্লকের মধ্যে পরিবর্তনের পরিবর্তে আরম্ভের জন্য সমস্ত শর্তটি আরম্ভকারীতে স্ট্যাক করে validএবং এগুলি পৃথক করে আরও সহজ করা যায়। আমি মন্তব্যে একটি উদাহরণ রাখতে পারি না তবে আপনি এটি খুব পরিষ্কার করে বামদিকে অপারেটরগুলি উল্লম্বভাবে সারিবদ্ধ করতে পারেন ; স্বতন্ত্র শর্তগুলি ইতিমধ্যে যতটা প্রয়োজন প্রথম বন্ধনী হিসাবে তৈরি করা হয়েছে (এর জন্য ) তাই আপনাকে ইতিমধ্যে যা আছে তার বাইরে এক্সপ্রেশনগুলিতে কোনও অক্ষর যুক্ত করার দরকার নেই। ||valid||if
লুশেনকো

1
@ লুশেনকো, আমি মনে করি যে মেশানো বন্ধনী, && এবং || শর্তাবলী বেশ ত্রুটিযুক্ত প্রবণ (অন্য কোনও উত্তরে কেউ বলেছিলেন যে ওপিতে কোডটিতে প্রথম বন্ধনে কোনও ত্রুটি ছিল, সম্ভবত এটি সংশোধন করা হয়েছে)। যথাযথ প্রান্তিককরণ অবশ্যই সাহায্য করতে পারে। তবে লাভ কী? আরও পাঠযোগ্য? বজায় রাখা সহজ? আমি তাই মনে করি না. অবশ্যই আমার মতামত. নিশ্চিত হয়ে নিন, কোডে আইএফএস থাকলে আমি সত্যই ঘৃণা করি।
জিয়ান পাওলো

3
আমি এটিকে এমনভাবে আবৃত করতাম if($bValue1)যা সর্বদা সত্য হতে হবে, প্রযুক্তিগতভাবে কিছুটা ছোটখাটো পারফরম্যান্স উন্নতি করতে দেওয়া (যদিও আমরা এখানে উপেক্ষিত পরিমাণের কথা বলছি)।
মার্টিজন

2
এফডাব্লুআইডাব্লু: মাত্র ২ টি পরিস্থিতি রয়েছে: প্রথম 2 একই দৃশ্য এবং নির্ভর করে নাbValue4
ড্যানক্রাম্ব

123

আমি সরলতা এবং পাঠযোগ্যতার জন্য লক্ষ্য করব।

bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
bool scenario2 = bValue1 && bValue2 && bValue3 && !bValue4;
bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

if (scenario1 || scenario2 || scenario3) {
    // Do whatever.
}

দৃশ্যের নাম এবং ফ্ল্যাশের নাম বর্ণনামূলক কিছু দিয়ে প্রতিস্থাপনের বিষয়টি নিশ্চিত করুন। এটি যদি আপনার নির্দিষ্ট সমস্যার জন্য অর্থবোধ করে তবে আপনি এই বিকল্পটি বিবেচনা করতে পারেন:

bool scenario1or2 = bValue1 && bValue2 && bValue3;
bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

if (scenario1or2 || scenario3) {
    // Do whatever.
}

এখানে যা গুরুত্বপূর্ণ তা হ'ল যুক্তি নয়। এটি আপনার ডোমেনটির বর্ণনা দিচ্ছে এবং আপনার উদ্দেশ্য পরিষ্কারভাবে প্রকাশ করছে ing এখানে কীটি সমস্ত ইনপুট এবং মধ্যস্থতাকার ভেরিয়েবলগুলিকে ভাল নাম দেওয়া। যদি আপনি ভাল পরিবর্তনশীল নামগুলি খুঁজে না পান তবে এটি একটি চিহ্ন হতে পারে যে আপনি সমস্যাটিকে ভুল উপায়ে বর্ণনা করছেন।


3
+1 এটি আমিও করতাম। ঠিক যেমন @ রেডফিল্টার নির্দেশ করে এবং গৃহীত উত্তরের বিপরীতে, এটি স্ব-ডকুমেন্টিং। পৃথক ধাপে দৃশ্যের নিজস্ব নাম দেওয়া অনেক বেশি পঠনযোগ্য।
Andreas

105

আমরা কর্নোগ মানচিত্র ব্যবহার করতে পারি এবং আপনার দৃশ্যের একটি যৌক্তিক সমীকরণে হ্রাস করতে পারি। আমি 4 টি ভেরিয়েবলের জন্য সার্কিট সহ অনলাইন কর্নফো মানচিত্র সলভার ব্যবহার করেছি ।

এখানে চিত্র বর্ণনা লিখুন

এই ফলন:

এখানে চিত্র বর্ণনা লিখুন

পরিবর্তন A, B, C, Dকরা bValue1, bValue2, bValue3, bValue4, এটি ছাড়া কিছুই নয়:

bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4

সুতরাং আপনার ifবিবৃতি হয়ে:

if(!(bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4))
{
    // There is some error
}
  • কার্নোখ মানচিত্র বিশেষত কার্যকর যখন আপনার অনেকগুলি ভেরিয়েবল এবং অনেক শর্ত থাকে যা মূল্যায়ন করা উচিত true
  • trueযৌক্তিক সমীকরণে পরিস্থিতিগুলি হ্রাস করার পরে, পরিস্থিতিগুলি নির্দেশ করে trueএমন প্রাসঙ্গিক মন্তব্য যুক্ত করা অনুশীলন।

96
প্রযুক্তিগতভাবে সঠিক হলেও, এই কোডটির কয়েক মাস পরে অন্য বিকাশকারী সম্পাদনা করার জন্য প্রচুর মন্তব্য প্রয়োজন।
জেডেস্লাভ ভোজকোভিক

22
@ জেডেস্লাভভোজকোভিচ: আমি সমীকরণটির সাথে একটি মন্তব্য যুক্ত করব। //!(ABC + AB'C'D') (By K-Map logic)। এটি বিকাশকারীদের কে-ম্যাপ শিখার জন্য ভাল সময় যদি সে ইতিমধ্যে তা না জানে।
পিডব্লিউ

11
আমি এটির সাথে একমত, কিন্তু আইএমও সমস্যাটি হ'ল এটি সমস্যা ডোমেনে স্পষ্টভাবে মানচিত্র করে না, অর্থাত্ প্রতিটি অবস্থার নির্দিষ্ট দৃশ্যে মানচিত্র কীভাবে এটি পরিবর্তন / প্রসারিত করা শক্ত করে তোলে। কি হবে আছে Eএবং Fঅবস্থার এবং 4 নতুন পরিস্থিতিতে? এই ifবিবৃতিটি সঠিকভাবে আপডেট করতে কতক্ষণ সময় লাগে ? কোড পর্যালোচনা ঠিক আছে কিনা তা যাচাই করে? সমস্যাটি প্রযুক্তিগত দিকের সাথে নয় তবে "ব্যবসায়" পক্ষের।
জেডেস্লাভ ভোজকোভিক

7
আমি মনে করি আপনি এগুলি নির্ধারণ করতে পারেন A: ABC + AB'C'D' = A(BC + B'C'D')( A(B ^ C)'(C + D')এটি 'সরলিকরণ' বলার ক্ষেত্রে আমি সতর্ক থাকিলেও এটি সজাগ হতে পারে)।
ম্যাকিয়েজ পাইচোটকা

28
@ পিডব্লিউ এই মন্তব্যটি কোডের মতোই বোধগম্য এবং এটি কিছুটা অর্থহীন। একটি ভাল মন্তব্য আপনাকে কীভাবে বাস্তবে সেই সমীকরণটি নিয়ে এসেছিল তা ব্যাখ্যা করবে, অর্থাত যে বিবৃতিটি টিটিটিটি, টিটিটিএফ এবং টিএফএফএফের জন্য ট্রিগার করা উচিত। এই মুহুর্তে আপনি পাশাপাশি কোডটিতে সেই তিনটি শর্ত লিখতে পারেন এবং কোনও ব্যাখ্যা দেওয়ার প্রয়োজন নেই।
বার্নহার্ড বার্কার

58

এখানে আসল প্রশ্নটি হল: যখন অন্য বিকাশকারী (বা এমনকি লেখক) কয়েক মাস পরে এই কোডটি পরিবর্তন করতে হবে তখন কী হয়।

আমি এটি বিট পতাকা হিসাবে মডেলিংয়ের পরামর্শ দেব:

const int SCENARIO_1 = 0x0F; // 0b1111 if using c++14
const int SCENARIO_2 = 0x0E; // 0b1110
const int SCENARIO_3 = 0x08; // 0b1000

bool bValue1 = true;
bool bValue2 = false;
bool bValue3 = false;
bool bValue4 = false;

// boolean -> int conversion is covered by standard and produces 0/1
int scenario = bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
bool match = scenario == SCENARIO_1 || scenario == SCENARIO_2 || scenario == SCENARIO_3;
std::cout << (match ? "ok" : "error");

যদি আরও অনেক পরিস্থিতিতে বা আরও বেশি পতাকা থাকে, তবে একটি টেবিলের পদ্ধতির পতাকা ব্যবহারের চেয়ে আরও বেশি পঠনযোগ্য এবং বর্ধনযোগ্য। নতুন দৃশ্যের সমর্থনে টেবিলের আরও একটি সারি প্রয়োজন।

int scenarios[3][4] = {
    {true, true, true, true},
    {true, true, true, false},
    {true, false, false, false},
};

int main()
{
  bool bValue1 = true;
  bool bValue2 = false;
  bool bValue3 = true;
  bool bValue4 = true;
  bool match = false;

  // depending on compiler, prefer std::size()/_countof instead of magic value of 4
  for (int i = 0; i < 4 && !match; ++i) {
    auto current = scenarios[i];
    match = bValue1 == current[0] && 
            bValue2 == current[1] && 
            bValue3 == current[2] && 
            bValue4 == current[3];
  }

  std::cout << (match ? "ok" : "error");
}

4
সর্বাধিক রক্ষণাবেক্ষণযোগ্য নয় তবে অবশ্যই যদি শর্তটি সহজ করে দেয়। সুতরাং বিটওয়াইজ অপারেশনগুলির চারপাশে কয়েকটি মন্তব্য রেখে যাওয়া ইমোতে একেবারে প্রয়োজনীয়তা হয়ে উঠবে।
আদম জহরান

6
আইএমও, টেবিলটি সর্বোত্তম পন্থা কারণ এটি অতিরিক্ত পরিস্থিতি এবং পতাকাগুলির সাথে আরও ভাল স্কেল করে।
জেডেস্লাভ ভোজকোভিক

আমি আপনার প্রথম সমাধানটি পড়তে সহজ এবং পরিবর্তনের জন্য খুলতে চাই। আমি 2 টি উন্নতি করব: 1: বুলিয়ান মানগুলির সুস্পষ্ট ইঙ্গিত সহ দৃশ্যের এক্সকে মান নির্ধারণ করুন, উদাহরণস্বরূপ SCENARIO_2 = true << 3 | true << 2 | true << 1 | false;2: SCENARIO_X ভেরিয়েবলগুলি এড়িয়ে চলুন এবং তারপরে সমস্ত উপলভ্য পরিস্থিতিতে একটিতে সংরক্ষণ করুন <std::set<int>। একটি mySet.insert( true << 3 | false << 2 | true << 1 | false;দৃশ্যাবলী যুক্ত করা কেবলমাত্র 3 টি পরিস্থিতিতে একটি সামান্য ওভারকিল হিসাবে কিছু হতে চলেছে , ওপি আমার উত্তরে আমার দ্রুত, নোংরা এবং সহজ সমাধানটি প্রস্তাব করেছিল।
জিয়ান পাওলো

4
আপনি যদি সি ++ ১৪ বা তার বেশি ব্যবহার করেন তবে আমি পরিবর্তে প্রথম সমাধানের জন্য বাইনারি লিটারালগুলি ব্যবহার করার পরামর্শ দেব - 0 বি 1111, 0 বি 1110 এবং 0 বি 01000 অনেক পরিষ্কার। আপনি সম্ভবত এটি স্ট্যান্ডার্ড লাইব্রেরি ( std::find?) ব্যবহার করে কিছুটা সহজ করতে পারেন ।
বার্নহার্ড বার্কার

2
আমি দেখতে পেয়েছি যে এখানে বাইনারি আক্ষরিকাগুলির প্রথম কোডটি পরিষ্কার করার জন্য একটি ন্যূনতম প্রয়োজন হবে। বর্তমান আকারে এটি সম্পূর্ণ ক্রিপ্টিক। বর্ণনামূলক শনাক্তকারীরা সাহায্য করতে পারে তবে আমি সে সম্পর্কে নিশ্চিতও নই। আসলে, scenarioমানটি তৈরির বিট অপারেশনগুলি আমাকে অযথা ত্রুটি-প্রবণ হিসাবে আঘাত করে।
কনরাড রুডল্ফ

27

আমার পূর্ববর্তী উত্তরটি ইতিমধ্যে স্বীকৃত উত্তর, আমি এখানে এমন কিছু যুক্ত করেছি যা আমি মনে করি পাঠযোগ্য, সহজ এবং এই ক্ষেত্রে ভবিষ্যতের পরিবর্তনের জন্য উন্মুক্ত:

@ জেডেস্লাভভোজকোভিক উত্তর দিয়ে শুরু করে (যা আমি বেশ ভাল দেখতে পাই), আমি এটি নিয়ে এসেছি:

#include <iostream>
#include <set>

//using namespace std;

int GetScenarioInt(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
{
    return bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
}
bool IsValidScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
{
    std::set<int> validScenarios;
    validScenarios.insert(GetScenarioInt(true, true, true, true));
    validScenarios.insert(GetScenarioInt(true, true, true, false));
    validScenarios.insert(GetScenarioInt(true, false, false, false));

    int currentScenario = GetScenarioInt(bValue1, bValue2, bValue3, bValue4);

    return validScenarios.find(currentScenario) != validScenarios.end();
}

int main()
{
    std::cout << IsValidScenario(true, true, true, false) << "\n"; // expected = true;
    std::cout << IsValidScenario(true, true, false, false) << "\n"; // expected = false;

    return 0;
}

এখানে কাজের সময়ে এটি দেখুন

ঠিক আছে, এটিই "মার্জিত এবং রক্ষণাবেক্ষণযোগ্য" (আইএমএইচও) সমাধান যা আমি সাধারণত লক্ষ্য করি, কিন্তু সত্যই, ওপি ক্ষেত্রে আমার পূর্ববর্তী "গুচ্ছ অফ" যদি উত্তর না দেয় তবে ওপি প্রয়োজনীয়তা আরও ভাল ফিট করে।


আপনি জানেন আপনি সর্বদা আপনার পূর্ববর্তী উত্তর সম্পাদনা করতে এবং উন্নতি করতে পারেন।
আন্দ্রেয়াস

20

আমি অন্য একটি পদ্ধতি জমা দিতে চাই would

আমার ধারণাটি হল বুলগুলি একটি পূর্ণসংখ্যায় রূপান্তর করা এবং তারপরে ভেরিয়াদিক টেম্পলেট ব্যবহার করে তুলনা করা:

unsigned bitmap_from_bools(bool b) {
    return b;
}
template<typename... args>
unsigned bitmap_from_bools(bool b, args... pack) {
    return (bitmap_from_bools(b) << sizeof...(pack)) | bitmap_from_bools(pack...);
}

int main() {
    bool bValue1;
    bool bValue2;
    bool bValue3;
    bool bValue4;

    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

    if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u) {
        //bad scenario
    }
}

এই সিস্টেমটি কীভাবে ইনপুট হিসাবে 32 টি পর্যন্ত পুল সমর্থন করতে পারে তা লক্ষ্য করুন। (বা ) এর unsignedসাথে প্রতিস্থাপন করা 64 টি ক্ষেত্রে সমর্থন বাড়ায়। আপনি যদি পছন্দ না করেন তবে আপনি আরও একটি ভিন্নধর্মী টেম্পলেট পদ্ধতি ব্যবহার করতে পারেন:unsigned long longuint64_tif (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u)

bool equals_any(unsigned target, unsigned compare) {
    return target == compare;
}
template<typename... args>
bool equals_any(unsigned target, unsigned compare, args... compare_pack) {
    return equals_any(target, compare) ? true : equals_any(target, compare_pack...);
}

int main() {
    bool bValue1;
    bool bValue2;
    bool bValue3;
    bool bValue4;

    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

    if (!equals_any(summary, 0b1111u, 0b1110u, 0b1000u)) {
        //bad scenario
    }
}

2
আমি এই পদ্ধতির পছন্দ করি, মূল ফাংশনটির নাম বাদে: "বুল থেকে… কী ?" - কেন স্পষ্টভাবে নয় bitmap_from_bools, বা bools_to_bitmap?
কনরাড রুডল্ফ

হ্যাঁ @ কনরাড রুডল্ফ, আমি সম্ভবত এটি ছাড়া আর কোনও ভাল নামের কথা ভাবতে পারি না bools_to_unsigned। বিটম্যাপ একটি ভাল কীওয়ার্ড; সম্পাদনা করা হয়েছে।
ড্যানি

আমি মনে করি আপনি চান summary!= 0b1111u &&...a != b || a != cযদি সর্বদা সত্য হয়b != c
মুজবয়েস

17

এখানে একটি সরলীকৃত সংস্করণ:

if (bValue1 && (bValue2 == bValue3) && (bValue2 || !bValue4)) {
    // acceptable
} else {
    // not acceptable
}

দ্রষ্টব্য, অবশ্যই, এই সমাধানটি আসলটির চেয়ে বেশি অবিচলিত, এর অর্থ বোঝা শক্ত হতে পারে।


আপডেট: মন্তব্যে MSalters একটি আরও সহজ অভিব্যক্তি পাওয়া গেছে:

if (bValue1&&(bValue2==bValue3)&&(bValue2>=bValue4)) ...

1
হ্যাঁ, তবে বোঝা শক্ত। তবে পরামর্শের জন্য ধন্যবাদ।
অ্যান্ড্রু ট্রাকল

রেফারেন্স হিসাবে আপনার সরলকরণের সাথে অভিব্যক্তি সহজীকরণের সংযোজনকারীদের দক্ষতার তুলনা করেছি: সংকলক এক্সপ্লোরার । gcc আপনার অনুকূল সংস্করণটি খুঁজে পায় নি তবে এর সমাধানটি এখনও ভাল। কলং এবং এমএসভিসি কোনও বুলিয়ান এক্সপ্রেশন সরলকরণ সম্পাদন করছে বলে মনে হয় না।
অলিভ

1
@ অ্যান্ড্রুট্রাকল: দ্রষ্টব্য, আপনার যদি আরও বেশি পাঠযোগ্য সংস্করণ প্রয়োজন হয় তবে দয়া করে এটি বলুন। আপনি "সরলীকৃত" বলেছেন, তবুও আপনি নিজের আসল সংস্করণটির চেয়ে আরও ভার্বোজ সংস্করণ গ্রহণ করেন।
গেজা

1
simpleআসলেই একটি অস্পষ্ট শব্দ term অনেকে এই প্রসঙ্গে এটিকে বিকাশকারীদের পক্ষে বোঝার পক্ষে সহজ হিসাবে বোঝেন এবং সংকলক কোড উত্পন্ন করার জন্য নয়, তাই আরও ভার্বোজ প্রকৃতপক্ষে সহজতর হতে পারে।
জেডেস্লাভ ভোজকোভিক

1
@ ইসমাইল মিগুয়েল: যখন কোনও যুক্তির সূত্র সংখ্যার জন্য অনুকূলিত হয়, তখন মূল অর্থটি সাধারণত হারিয়ে যায়। তবে কেউ এর চারপাশে একটি মন্তব্য রাখতে পারেন, সুতরাং এটি কী করে তা স্পষ্ট। এমনকি, গৃহীত উত্তরের জন্য, একটি মন্তব্য ক্ষতি করবে না।
গেজা

12

আপনার প্রোগ্রামে যতটা সম্ভব আপনার টেবিলগুলি অনুবাদ করার কথা বিবেচনা করুন। প্রোগ্রামটি যুক্তি দিয়ে নকল না করে টেবিলের উপর ভিত্তি করে ড্রাইভ করুন।

template<class T0>
auto is_any_of( T0 const& t0, std::initializer_list<T0> il ) {
  for (auto&& x:il)
    if (x==t0) return true;
  return false;
}

এখন

if (is_any_of(
  std::make_tuple(bValue1, bValue2, bValue3, bValue4),
  {
    {true, true, true, true},
    {true, true, true, false},
    {true, false, false, false}
  }
))

এটি সরাসরি সম্ভব আপনার সত্য টেবিলটি সংকলকটিতে এনকোড করে।

সরাসরি উদাহরণ

আপনি std::any_ofসরাসরি ব্যবহার করতে পারেন :

using entry = std::array<bool, 4>;
constexpr entry acceptable[] = 
  {
    {true, true, true, true},
    {true, true, true, false},
    {true, false, false, false}
  };
if (std::any_of( begin(acceptable), end(acceptable), [&](auto&&x){
  return entry{bValue1, bValue2, bValue3, bValue4} == x;
}) {
}

সংকলক কোডটি ইনলাইন করতে পারে এবং যে কোনও পুনরাবৃত্তি দূর করতে পারে এবং আপনার নিজস্ব যুক্তি তৈরি করতে পারে। এদিকে, আপনার কোডটি ঠিক কীভাবে আপনি সমস্যা থেকে মুক্তি পেয়েছিলেন তা প্রতিবিম্বিত করে।


প্রথম সংস্করণটি এত সহজে পড়া সহজ এবং এতই মূল বক্তব্য, আমি সত্যিই এটি পছন্দ করি। দ্বিতীয়টি কমপক্ষে আমার পক্ষে পড়া শক্ত, এবং সম্ভবত আমার একের চেয়ে সম্ভবত গড়ে একটি সি ++ দক্ষতার স্তর প্রয়োজন। সবাই লিখতে সক্ষম এমন কিছু নয়।
সবেমাত্র

11

কেউ আমার সমাধান দেখাতে বলেছে এমন মন্তব্যে আমি কেবল এখানে আমার উত্তর সরবরাহ করছি। আমি তাদের অন্তর্দৃষ্টি জন্য ধন্যবাদ জানাতে চাই।

শেষ পর্যন্ত আমি তিনটি নতুন "দৃশ্যাবলী" booleanপদ্ধতি যুক্ত করার পছন্দ করেছি:

bool CChristianLifeMinistryValidationDlg::IsFirstWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
{
    return (INCLUDE_ITEM1(pEntry) && 
           !INCLUDE_ITEM2(pEntry) && 
           !INCLUDE_ITEM3(pEntry) && 
           !INCLUDE_ITEM4(pEntry));
}

bool CChristianLifeMinistryValidationDlg::IsSecondWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
{
    return (INCLUDE_ITEM1(pEntry) &&
            INCLUDE_ITEM2(pEntry) &&
            INCLUDE_ITEM3(pEntry) &&
            INCLUDE_ITEM4(pEntry));
}

bool CChristianLifeMinistryValidationDlg::IsOtherWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
{
    return (INCLUDE_ITEM1(pEntry) && 
            INCLUDE_ITEM2(pEntry) && 
            INCLUDE_ITEM3(pEntry) && 
           !INCLUDE_ITEM4(pEntry));
}

তারপরে আমি আমার বৈধতার রুটিনগুলিকে এভাবে প্রয়োগ করতে সক্ষম হয়েছি:

if (!IsFirstWeekStudentItems(pEntry) && !IsSecondWeekStudentItems(pEntry) && !IsOtherWeekStudentItems(pEntry))
{
    ; Error
}

আমার লাইভ অ্যাপ্লিকেশনটিতে 4 টি বুল মানগুলি আসলে এমনটি থেকে বের করা হয় DWORDযার মধ্যে 4 টি মান এনকোড থাকে।

সবাইকে আবার ধন্যবাদ।


1
সমাধান ভাগ করে নেওয়ার জন্য ধন্যবাদ। :) পরিস্থিতি নরক হলে এটি জটিল থেকে ভাল। সম্ভবত আপনি এখনও INCLUDE_ITEM1আরও ভাল নামকরণ করতে পারেন এবং আপনি সব ভাল। :)
হার্ডিক মোদা

1
@ হার্দিকমোদা ভাল, প্রযুক্তিগতভাবে তারা "শিক্ষার্থী আইটেম" এবং পতাকাটি "অন্তর্ভুক্ত" হবে কিনা তা নির্দেশ করে। সুতরাং আমি মনে করি নামটি, যদিও জেনেরিক শোনানো হলেও এই প্রসঙ্গে আসলেই অর্থবহ। :)
অ্যান্ড্রু ট্রাকল

11

দৃশ্যগুলির নাম বলার জন্য আমি কোনও উত্তর দেখছি না, যদিও ওপির সমাধানটি ঠিক তেমনটি করে।

আমার কাছে প্রতিটি দৃশ্যের কোনও পরিবর্তনশীল নাম বা ফাংশন নামের মধ্যে কী মন্তব্য রয়েছে তা মন্তব্য করা ভাল to আপনি নামের চেয়ে একটি মন্তব্য উপেক্ষা করার সম্ভাবনা বেশি এবং ভবিষ্যতে যদি আপনার যুক্তি পরিবর্তন হয় তবে আপনি একটি মন্তব্যের চেয়ে একটি নাম পরিবর্তন করার সম্ভাবনা বেশি। আপনি কোনও মন্তব্য রিফ্যাক্টর করতে পারবেন না।

যদি আপনি এই ফাংশনটির বাইরে এই পরিস্থিতিগুলি পুনরায় ব্যবহার করার পরিকল্পনা করেন (বা করতে চান) তবে তারপরে এমন একটি ফাংশন তৈরি করুন যা এটি মূল্যায়ন করে বলে ( constexpr/ noexceptalচ্ছিক তবে প্রস্তাবিত):

constexpr bool IsScenario1(bool b1, bool b2, bool b3, bool b4) noexcept
{ return b1 && b2 && b3 && b4; }

constexpr bool IsScenario2(bool b1, bool b2, bool b3, bool b4) noexcept
{ return b1 && b2 && b3 && !b4; }

constexpr bool IsScenario3(bool b1, bool b2, bool b3, bool b4) noexcept
{ return b1 && !b2 && !b3 && !b4; }

সম্ভব হলে এই শ্রেণিবদ্ধ পদ্ধতিগুলি তৈরি করুন (যেমন ওপি এর সমাধানে)। আপনি যদি যুক্তিটি পুনরায় ব্যবহার করবেন না বলে মনে করেন আপনি আপনার ফাংশনের অভ্যন্তরে ভেরিয়েবলগুলি ব্যবহার করতে পারেন:

const auto is_scenario_1 = bValue1 && bValue2 && bValue3 && bValue4;
const auto is_scenario_2 = bvalue1 && bvalue2 && bValue3 && !bValue4;
const auto is_scenario_3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

সংকলকটি সম্ভবত বাছাই করবে যে যদি bValue1 মিথ্যা হয় তবে সমস্ত পরিস্থিতিতে মিথ্যা। এটিকে দ্রুত, সঠিক এবং পঠনযোগ্য করার বিষয়ে চিন্তা করবেন না। আপনি যদি নিজের কোডটিকে প্রোফাইল করেন এবং এটিকে একটি বাধা হিসাবে মনে করেন কারণ সংকলকটি -O2 বা ততোধিক সংখ্যক উপ-অনুকূল কোড তৈরি করে তবে এটি পুনরায় লেখার চেষ্টা করুন।


আমি এটি জিয়ান পাওলো (ইতিমধ্যে দুর্দান্ত) সমাধানের চেয়ে কিছুটা বেশি পছন্দ করি: এটি নিয়ন্ত্রণ প্রবাহ এবং ওভাররাইট করা একটি পরিবর্তনশীল - আরও কার্যকরী শৈলীর ব্যবহার এড়ানো যায়।
ডার্ক হেরম্যান

9

এসি / সি ++ উপায়

bool scenario[3][4] = {{true, true, true, true}, 
                        {true, true, true, false}, 
                        {true, false, false, false}};

bool CheckScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
{
    bool temp[] = {bValue1, bValue2, bValue3, bValue4};
    for(int i = 0 ; i < sizeof(scenario) / sizeof(scenario[0]); i++)
    {
        if(memcmp(temp, scenario[i], sizeof(temp)) == 0)
            return true;
    }
    return false;
}

এই পদ্ধতির পরিমাপযোগ্য যেমন বৈধ শর্তের সংখ্যা বৃদ্ধি পায়, আপনি সহজেই তাদের দৃশ্যপট তালিকায় আরও কিছু যুক্ত করুন add


যদিও আমি নিশ্চিত যে এটি ভুল হয়েছে pretty এটি ধরে নিয়েছে যে সংকলকটির জন্য কেবল একটি একক বাইনারি উপস্থাপনা ব্যবহার করা হয়েছে true। একটি সংকলক যা "শূন্য-বিহীন কিছু সত্য" ব্যবহার করে এই কোডটিকে ব্যর্থ করে। নোট যে রূপান্তর করা trueআবশ্যক , এটি ঠিক যেমন সংরক্ষণ করা প্রয়োজন হবে না । 1
এমসাল্টাররা

@ এসএমএলটার্স, টিএনএক্স, আমি আপনার বক্তব্যটি পেয়েছি এবং আমি সে সম্পর্কে অবগত আছি 2 is not equal to true but evaluates to true, আমার মত কোডটি জোর করে না int 1 = trueএবং যতক্ষণ না সত্যের সমস্ত একই মান হিসাবে রূপান্তরিত হয় ততক্ষণ কাজ করে, তাই এখানে আমার প্রশ্ন: সংকলক কেন রূপান্তর করার ক্ষেত্রে এলোমেলো আচরণ করবে? অন্তর্নিহিত অন্তর্নিহিত সত্য, আপনি আরও বিস্তারিত বলতে পারেন?
হেসাম হেডিহ

একটি পারফর্মিং memcmpবুলিয়ান শর্ত পরীক্ষার জন্যে না সি ++ উপায় আমি বরং সন্দেহ নেই যে এটা একটি প্রতিষ্ঠিত সি উপায়, হয়, এবং।
কনরাড রুডল্ফ

@ শেসমহেদীহ: আপনার যুক্তিতে সমস্যাটি "অন্তর্নিহিত অন্তর্নিহিতকে সত্য রূপান্তর"। যে না কিভাবে কম্পাইলার কাজ করে,
MSalters

আপনার কোড ও (1) থেকে ও (এন) পর্যন্ত জটিলতা বৃদ্ধি করে। কোনও ভাষায় যাওয়ার উপায় নয় - সি / সি ++ রেখে দিন।
mabel

9

এটি লক্ষ্য করা সহজ যে প্রথম দুটি পরিস্থিতি একই রকম - তারা বেশিরভাগ শর্ত ভাগ করে দেয়। আপনি যদি এই মুহুর্তে কোন দৃশ্যে বাছাই করতে চান তবে আপনি এটি এটি লিখতে পারেন (এটি একটি পরিবর্তিত @ জিয়ান-পাওলো এর সমাধান):

bool valid = false;
if(bValue1 && bValue2 && bValue3)
{
    if (bValue4)
        valid = true; //scenario 1
    else if (!bValue4)
        valid = true; //scenario 2
}
else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
    valid = true; //scenario 3

আরও এগিয়ে যেতে পারেন, আপনি খেয়াল করতে পারেন, প্রথম বুলিয়ানটি সর্বদা সত্য হওয়া দরকার, যা একটি প্রবেশের শর্ত, সুতরাং আপনি এতে শেষ করতে পারেন:

bool valid = false;
if(bValue1)
{
    if(bValue2 && bValue3)
    {
        if (bValue4)
            valid = true; //scenario 1
        else if (!bValue4)
            valid = true; //scenario 2
    }
    else if (!bValue2 && !bValue3 && !bValue4)
        valid = true; //scenario 3
}

আরও বেশি, আপনি এখন স্পষ্ট দেখতে পাচ্ছেন যে, bValue2 এবং bValue3 কিছুটা সংযুক্ত রয়েছে - আপনি আরও কিছু উপযুক্ত নাম সহ কিছু বাহ্যিক ফাংশন বা ভেরিয়েবলগুলিতে তাদের অবস্থাটি বের করতে পারেন (যদিও এটি সর্বদা সহজ বা উপযুক্ত নয়):

bool valid = false;
if(bValue1)
{
    bool bValue1and2 = bValue1 && bValue2;
    bool notBValue1and2 = !bValue2 && !bValue3;
    if(bValue1and2)
    {
        if (bValue4)
            valid = true; //scenario 1
        else if (!bValue4)
            valid = true; //scenario 2
    }
    else if (notBValue1and2 && !bValue4)
        valid = true; //scenario 3
}

এটি এভাবে করার কিছু সুবিধা এবং অসুবিধা রয়েছে:

  • শর্তগুলি ছোট, তাই তাদের সম্পর্কে যুক্তি করা সহজ,
  • এই শর্তগুলি আরও বোধগম্য করার জন্য সুন্দর নামকরণ করা সহজ,
  • তবে তাদের সুযোগটি বুঝতে হবে,
  • তবুও এটি আরও কঠোর

যদি আপনি ভবিষ্যদ্বাণী করেন যে উপরের যুক্তিটিতে কিছু পরিবর্তন আসবে তবে আপনার @ জিয়ান-পাওলো দ্বারা উপস্থাপিত হিসাবে আরও সরল পদ্ধতি ব্যবহার করা উচিত ।

অন্যথায়, যদি এই শর্তগুলি যথাযথভাবে প্রতিষ্ঠিত হয় এবং এমন এক ধরণের "কঠিন নিয়ম" হয় যা কখনই পরিবর্তিত হয় না, আমার শেষ কোড স্নিপেট বিবেচনা করুন।


7

এমসিএইচের পরামর্শ অনুসারে আপনি এটি করতে পারেন:

if(!((bValue1 && bValue2 && bValue3) || 
  (bValue1 && !bValue2 && !bValue3 && !bValue4))
)

যেখানে প্রথম লাইনটি দুটি প্রথম ভাল কেসকে কভার করে এবং দ্বিতীয় লাইনটি সর্বশেষটি আবরণ করে।

Live Demo, যেখানে আমি চারপাশে খেলেছি এবং এটি আপনার কেসগুলি পাস করে।


7

@ জিয়ানপাওলো এর সূক্ষ্ম উত্তরে সামান্য প্রকরণ, যা কিছু পড়তে সহজ হতে পারে:

bool any_of_three_scenarios(bool v1, bool v2, bool v3, bool v4)
{
  return (v1 &&  v2 &&  v3 &&  v4)  // scenario 1
      || (v1 &&  v2 &&  v3 && !v4)  // scenario 2
      || (v1 && !v2 && !v3 && !v4); // scenario 3
}

if (any_of_three_scenarios(bValue1,bValue2,bValue3,bValue4))
{
  // ...
}

7

প্রতিটি উত্তর অত্যধিক জটিল এবং পড়া কঠিন। এর সেরা সমাধানটি একটি switch()বিবৃতি। এটি উভয়ই পঠনযোগ্য এবং অতিরিক্ত কেসগুলি যুক্ত / সংশোধন করা সহজ করে তোলে। সংকলকগণ switch()বিবৃতিও অনুকূলকরণে ভাল ।

switch( (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1) )
{
    case 0b1111:
        // scenario 1
        break;

    case 0b0111:
        // scenario 2
        break;

    case 0b0001:
        // scenario 3
        break;

    default:
        // fault condition
        break;
}

আপনি অবশ্যই caseআরও বেশি পঠনযোগ্যতার জন্য স্টেটমেন্টগুলিতে ধ্রুবকগুলি এবং তাদের একসাথে ব্যবহার করতে পারেন ।


পুরানো সি-প্রোগ্রামার হওয়ার কারণে, আমি একটি "প্যাকবুলস" ম্যাক্রো সংজ্ঞায়িত করব এবং "সুইচ (প্যাকবুলস (ক, খ, সি, ডি))" এবং উভয়ের ক্ষেত্রে যেমন, সরাসরি "কেস প্যাকবুলস" (সত্য) , সত্য ...) "বা তাদের স্থানীয় কনস্ট্যান্টস হিসাবে নির্ধারণ করুন const
সাইমন এফ

6

আমি স্বচ্ছতার জন্য শর্টকাট ভেরিয়েবলগুলিও ব্যবহার করব। যেমন পূর্বে উল্লিখিত হয়েছে 1 দৃশ্যের 2 সমান, কারণ bValue4 এর মান এই দুটি পরিস্থিতিতে সত্যকে প্রভাবিত করে না।

bool MAJORLY_TRUE=bValue1 && bValue2 && bValue3
bool MAJORLY_FALSE=!(bValue2 || bValue3 || bValue4)

তাহলে আপনার অভিব্যক্তি beomes:

if (MAJORLY_TRUE || (bValue1 && MAJORLY_FALSE))
{
     // do something
}
else
{
    // There is some error
}

মেজরট্রি এবং মেজরফলস ভেরিয়েবলগুলিকে (পাশাপাশি বাস্তবে বিভালিউ * ওয়ার্সে) অর্থবহ নাম দেওয়া পাঠযোগ্যতা এবং রক্ষণাবেক্ষণে অনেক সহায়তা করবে।


6

সমস্যার পাঠযোগ্যতার উপর ফোকাস করুন, নির্দিষ্ট "যদি" বিবৃতিটি নয়।

যদিও এটি কোডের আরও লাইন তৈরি করবে এবং কেউ কেউ এটিকে ওভারকিল বা অপ্রয়োজনীয় হিসাবে বিবেচনা করতে পারে। আমি পরামর্শ দিচ্ছি যে নির্দিষ্ট বুলিয়ানগুলি থেকে আপনার পরিস্থিতিতে বিমূর্ত করা পাঠযোগ্যতা বজায় রাখার সেরা উপায়।

জিনিসগুলিকে শ্রেণিতে বিভক্ত করে (কেবলমাত্র ফাংশন ব্যবহার করতে নির্দ্বিধায় বা অন্য যে কোনও সরঞ্জাম আপনি পছন্দ করেন) বোধগম্য নামগুলি দিয়ে - আমরা প্রতিটি দৃশ্যের পিছনে অর্থগুলি আরও সহজেই প্রদর্শন করতে পারি। আরও গুরুত্বপূর্ণ, অনেকগুলি চলমান অংশবিশিষ্ট একটি সিস্টেমে - আপনার বিদ্যমান সিস্টেমে বজায় রাখা এবং যোগদান করা আরও সহজ (আবারও, অতিরিক্ত কোডটি কী পরিমাণে ইনভল করা হয়েছে তার পরেও)।

#include <iostream>
#include <vector>
using namespace std;

// These values would likely not come from a single struct in real life
// Instead, they may be references to other booleans in other systems
struct Values
{
    bool bValue1; // These would be given better names in reality
    bool bValue2; // e.g. bDidTheCarCatchFire
    bool bValue3; // and bDidTheWindshieldFallOff
    bool bValue4;
};

class Scenario
{
public:
    Scenario(Values& values)
    : mValues(values) {}

    virtual operator bool() = 0;

protected:
    Values& mValues;    
};

// Names as examples of things that describe your "scenarios" more effectively
class Scenario1_TheCarWasNotDamagedAtAll : public Scenario
{
public:
    Scenario1_TheCarWasNotDamagedAtAll(Values& values) : Scenario(values) {}

    virtual operator bool()
    {
        return mValues.bValue1
        && mValues.bValue2
        && mValues.bValue3
        && mValues.bValue4;
    }
};

class Scenario2_TheCarBreaksDownButDidntGoOnFire : public Scenario
{
public:
    Scenario2_TheCarBreaksDownButDidntGoOnFire(Values& values) : Scenario(values) {}

    virtual operator bool()
    {
        return mValues.bValue1
        && mValues.bValue2
        && mValues.bValue3
        && !mValues.bValue4;
    }   
};

class Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere : public Scenario
{
public:
    Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(Values& values) : Scenario(values) {}

    virtual operator bool()
    {
        return mValues.bValue1
        && !mValues.bValue2
        && !mValues.bValue3
        && !mValues.bValue4;
    }   
};

Scenario* findMatchingScenario(std::vector<Scenario*>& scenarios)
{
    for(std::vector<Scenario*>::iterator it = scenarios.begin(); it != scenarios.end(); it++)
    {
        if (**it)
        {
            return *it;
        }
    }
    return NULL;
}

int main() {
    Values values = {true, true, true, true};
    std::vector<Scenario*> scenarios = {
        new Scenario1_TheCarWasNotDamagedAtAll(values),
        new Scenario2_TheCarBreaksDownButDidntGoOnFire(values),
        new Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(values)
    };

    Scenario* matchingScenario = findMatchingScenario(scenarios);

    if(matchingScenario)
    {
        std::cout << matchingScenario << " was a match" << std::endl;
    }
    else
    {
        std::cout << "No match" << std::endl;
    }

    // your code goes here
    return 0;
}

5
কিছু পর্যায়ে, ভারবোসিটি পাঠযোগ্যতার ক্ষতি করতে শুরু করে। আমি মনে করি এটি অনেক দূরে চলে যায়।
জলিজোকার 13

2
@ জলিজোকার আমি এই নির্দিষ্ট পরিস্থিতিতে আসলেই একমত - যদিও ওপি যেভাবে সমস্ত কিছুকে অত্যন্ত উদারতার সাথে নাম দিয়েছেন তার থেকে আমার অন্ত্র অনুভূতিটি হ'ল তাদের "প্রকৃত" কোড সম্ভবত তারা যে উদাহরণ দিয়েছেন তার চেয়ে অনেক জটিল is সত্যই, আমি এই বিকল্পটি কেবল সেখানেই রাখতে চেয়েছিলাম, কারণ আমি আরও জটিল / জড়িত কোনও কিছুর জন্য এটি কীভাবে গঠন করব। তবে আপনি ঠিক বলেছেন - ওপিএসের নির্দিষ্ট উদাহরণের জন্য, এটি অতিরিক্ত ভার্জোজ এবং বিষয়টি আরও খারাপ করে তোলে।

5

এটি তাদের প্রতিনিধিত্ব করে তার উপর নির্ভর করে।

উদাহরণস্বরূপ, যদি 1 কী হয়, এবং 2 এবং 3 এমন দুটি ব্যক্তি যাকে সম্মত হতে হবে (তারা যদি রাজি হয় তবে তাদের NOTতৃতীয় ব্যক্তির দরকার হয় - 4 - নিশ্চিত করার জন্য) সর্বাধিক পঠনযোগ্য হতে পারে:

1 &&
    (
        (2 && 3)   
        || 
        ((!2 && !3) && !4)
    )

জনপ্রিয় অনুরোধ দ্বারা:

Key &&
    (
        (Alice && Bob)   
        || 
        ((!Alice && !Bob) && !Charlie)
    )

2
আপনি সঠিক হতে পারেন, তবে আপনার পয়েন্টটি চিত্রিত করতে সংখ্যাগুলি ব্যবহার করা আপনার উত্তর থেকে সরে যায়। বর্ণনামূলক নাম ব্যবহার করার চেষ্টা করুন।
jxh

1
@jxh এগুলি হল ওপি ব্যবহৃত নম্বর numbers আমি শুধু মুছে bValue
ইস্পিরো

@jxh আমি আশা করি এটি এখন আরও ভাল।
ইস্পিরো

4

বিটওয়াইজ অপারেশন করা খুব পরিষ্কার এবং বোধগম্য মনে হয়।

int bitwise = (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1);
if (bitwise == 0b1111 || bitwise == 0b0111 || bitwise == 0b0001)
{
    //satisfying condition
}

1
বিটওয়াইজ তুলনাটি আমার কাছে পঠনযোগ্য বলে মনে হচ্ছে। অন্যদিকে, রচনাটি কৃত্রিম দেখাচ্ছে।
xtofl

3

আমি স্বচ্ছতার জন্য ক, খ, সি, ডি এবং পরিপূরক হিসাবে এ, বি, সি, ডি বোঝাচ্ছি

bValue1 = a (!A)
bValue2 = b (!B)
bValue3 = c (!C)
bValue4 = d (!D)

সমীকরণ

1 = abcd + abcD + aBCD
  = a (bcd + bcD + BCD)
  = a (bc + BCD)
  = a (bcd + D (b ^C))

আপনার উপযুক্ত অনুসারে যে কোনও সমীকরণ ব্যবহার করুন।


3
If (!bValue1 || (bValue2 != bValue3) || (!bValue4 && bValue2))
{
// you have a problem
}
  • খ 1 সর্বদা সত্য হতে হবে
  • বি 2 অবশ্যই সর্বদা বি 3 এর সমান হবে
  • এবং বি 4 মিথ্যা হতে পারে না যদি বি 2 (এবং বি 3) সত্য হয়

সহজ


3

গৃহীত উত্তরের চেয়ে কেবল একটি ব্যক্তিগত পছন্দ, তবে আমি লিখব:

bool valid = false;
// scenario 1
valid = valid || (bValue1 && bValue2 && bValue3 && bValue4);
// scenario 2
valid = valid || (bValue1 && bValue2 && bValue3 && !bValue4);
// scenario 3
valid = valid || (bValue1 && !bValue2 && !bValue3 && !bValue4);

2

প্রথমে ধরে নেওয়া, আপনি কেবল দৃশ্য চেকটি সংশোধন করতে পারবেন, আমি পঠনযোগ্যতার উপর ফোকাস করব এবং কেবল কোনও ফাংশনে চেকটি জড়িয়ে দেব যাতে আপনি কেবল কল করতে পারেন if(ScenarioA())


এখন ধরে নিলাম, আপনি আসলে এটি পছন্দ করতে চান / প্রয়োজন, আমি দৃ linked়ভাবে সংযুক্ত বুলিয়ানদের ধ্রুবক পূর্ণ সংখ্যায় রূপান্তর করার এবং তাদের উপর বিট অপারেটর ব্যবহার করার পরামর্শ দেব

public class Options {
  public const bool A = 2; // 0001
  public const bool B = 4; // 0010
  public const bool C = 16;// 0100
  public const bool D = 32;// 1000
//public const bool N = 2^n; (up to n=32)
}

...

public isScenario3(int options) {
  int s3 = Options.A | Options.B | Options.C;
  // for true if only s3 options are set
  return options == s3;
  // for true if s3 options are set
  // return options & s3 == s3
}

এটি এর অংশটি তালিকাবদ্ধ করার মতো পরিস্থিতিতে দৃশ্যের প্রকাশকে সহজ করে তোলে, আপনাকে সঠিক অবস্থানে যাওয়ার জন্য একটি স্যুইচ স্টেটমেন্ট ব্যবহার করতে দেয় এবং এমন ডেভেলপারদের বিভ্রান্ত করে তোলে যারা এর আগে এটি দেখেনি। (সি # রেজেকসঅ্যাপশনগুলি পতাকা নির্ধারণের জন্য এই প্যাটার্নটি ব্যবহার করে, আমি জানি না যে এখানে সি ++ গ্রন্থাগারের উদাহরণ রয়েছে কিনা)


প্রকৃতপক্ষে আমি চারটি বুল মান ব্যবহার করছি না তবে একটি এমডব্লিউড চারটি এমবেডেড বোল সহ। এখনই এটি পরিবর্তন করতে খুব দেরী। তবে আপনার পরামর্শের জন্য ধন্যবাদ।
অ্যান্ড্রু ট্রাকল

2

নেস্টেড ifকিছু লোকের পক্ষে পড়া সহজ হতে পারে। এখানে আমার সংস্করণ

bool check(int bValue1, int bValue2, int bValue3, int bValue4)
{
  if (bValue1)
  {
    if (bValue2)
    {
      // scenario 1-2
      return bValue3;
    }
    else
    {
      // scenario 3
      return !bValue3 && !bValue4;
    }
  }

  return false;
}

ব্যক্তিগতভাবে, আমি সাধারণত সম্ভব হলে বিবৃতি দিলে বাসা বাঁধতাম। যদিও এই কেসটি সুন্দর এবং পাঠযোগ্য, একবার নতুন সম্ভাবনা যুক্ত হয়ে গেলে, নীড়গুলি পড়া খুব কঠিন হয়ে উঠতে পারে। তবে যদি পরিস্থিতিগুলি কখনও পরিবর্তন না হয় তবে এটি অবশ্যই একটি দুর্দান্ত এবং পঠনযোগ্য সমাধান।
Dnomyar96

@ Dnomyar96 আমি সম্মত আমি ব্যক্তিগতভাবে নেস্টেড ifs এড়ানো। কখনও কখনও যুক্তি জটিল হলে আমার পক্ষে যুক্তিটিকে টুকরো টুকরো করে ভেঙে বোঝা আরও সহজ। উদাহরণস্বরূপ, একবার আপনি bValue1ব্লক প্রবেশ করান , তারপরে আপনি এটিকে সমস্ত কিছু আপনার মানসিক প্রক্রিয়াতে নতুন তাজা পৃষ্ঠা হিসাবে বিবেচনা করতে পারেন। আমি বাজি ধরেছি যে সমস্যার দিকে যাওয়ার উপায়টি খুব ব্যক্তিগত বা এমনকি সাংস্কৃতিক জিনিসও হতে পারে।
সারডোক

1

এই প্রশ্নের বেশ কয়েকটি সঠিক উত্তর দেওয়া হয়েছে, তবে আমি একটি ভিন্ন দৃষ্টিভঙ্গি নেব: কোডটি যদি খুব জটিল দেখায়, তবে কিছু সঠিক নয় । কোডটি ডিবাগ করা কঠিন এবং "কেবলমাত্র এক-ব্যবহারের" হওয়ার সম্ভাবনা বেশি।

বাস্তব জীবনে যখন আমরা এইরকম পরিস্থিতি পাই:

         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true       | true       | true
bValue2: true       | true       | false
bValue3: true       | true       | false
bValue4: true       | false      | false

যখন চারটি রাজ্য এই জাতীয় একটি নিখুঁত নিদর্শন দ্বারা সংযুক্ত থাকে, আমরা আমাদের মডেলটিতে কিছু "সত্তা" কনফিগারেশন নিয়ে কাজ করি

একটি চূড়ান্ত রূপক হ'ল আমরা কীভাবে একটি "মানুষ" কে একটি মডেলটিতে বর্ণনা করব, যদি আমরা স্বাধীনতার নির্দিষ্ট ডিগ্রিতে সংযুক্ত উপাদানগুলির সাথে একক সত্তা হিসাবে তাদের অস্তিত্ব সম্পর্কে অবগত না হতাম: "টোরসো" এর স্বাধীন রাষ্ট্রগুলি বর্ণনা করতে হত, "বাহু", "পা" এবং "মাথা" যা বর্ণিত সিস্টেমটির বোধ করা জটিল করে তুলবে। একটি তাত্ক্ষণিক ফলাফল অপ্রাকৃতভাবে জটিল বুলিয়ান এক্সপ্রেশন হবে।

স্পষ্টতই, জটিলতা হ্রাস করার উপায় হ'ল বিমূর্ততা এবং সি ++ এর পছন্দসই একটি সরঞ্জাম হ'ল বস্তুর দৃষ্টান্ত

সুতরাং প্রশ্ন: কেন এমন প্যাটার্ন আছে? এটি কী এবং এটি কী উপস্থাপন করে?

যেহেতু আমরা উত্তরটি জানি না, তাই আমরা আবার গাণিতিক বিমূর্তকরণের পিছনে পড়ে যেতে পারি: অ্যারে : আমাদের তিনটি পরিস্থিতি রয়েছে, যার প্রতিটিই এখন অ্যারে।

                0   1   2   3
Scenario 1:     T   T   T   T
Scenario 2:     T   T   T   F
Scenario 3:     T   F   F   F

কোন পর্যায়ে আপনার প্রাথমিক কনফিগারেশন রয়েছে। একটি অ্যারে হিসাবে। যেমন std::arrayএকটি সমতা অপারেটর রয়েছে:

কোন বিন্দুতে আপনার বাক্য গঠনটি হয়ে যায়:

if( myarray == scenario1 ) {
  // arrays contents are the same

} 
else if ( myarray == scenario2 ) {
  // arrays contents are the same

} 

else if ( myarray == scenario3 ) {
  // arrays contents are the same

} 
else {
  // not the same

}

জিয়ান পাওলো যেমন উত্তর দিয়েছেন তেমনি এটি সংক্ষিপ্ত, স্বচ্ছ এবং সহজেই যাচাইযোগ্য / ডিবাগযোগ্য। এই ক্ষেত্রে, আমরা বুলিয়ান এক্সপ্রেশনগুলির বিবরণটি সংকলককে অর্পণ করেছি।


1

আপনি যদি বুলিয়ান পতাকাগুলি থেকে মুক্তি পান তবে আপনাকে বুলিয়ান পতাকাগুলির অবৈধ সংমিশ্রণগুলির বিষয়ে চিন্তা করতে হবে না।

গ্রহণযোগ্য মানগুলি হ'ল:

         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true       | true       | true
bValue2: true       | true       | false
bValue3: true       | true       | false
bValue4: true       | false      | false

আপনার স্পষ্টত তিনটি রাজ্য রয়েছে (দৃশ্যপট)। এটির মডেল করা এবং সেই রাজ্যগুলির কাছ থেকে অন্যভাবে নয়, বুলিয়ান বৈশিষ্ট্যগুলি অর্জন করা ভাল ।

enum State
{
    scenario1,
    scenario2,
    scenario3,
};

inline bool isValue1(State s)
{
    // (Well, this is kind of silly.  Do you really need this flag?)
    return true;
}

inline bool isValue2(State s)
{
    switch (s)
    {
        case scenario1:
        case scenario2:
            return true;
        case scenario3:
            return false;
    }
}

inline bool isValue3(State s)
{
    // (This is silly too.  Do you really need this flag?)
    return isValue2(s);
}

inline bool isValue4(State s)
{
    switch (s)
    {
        case scenario1:
            return true;
        case scenario2:
        case scenario3:
            return false;
    }
}

এটি অবশ্যই জিয়ান পাওলোর উত্তরের চেয়ে বেশি কোড , তবে আপনার পরিস্থিতির উপর নির্ভর করে এটি আরও অনেক বেশি রক্ষণাবেক্ষণযোগ্য হতে পারে:

  • অতিরিক্ত বুলিয়ান বৈশিষ্ট্য বা দৃশ্যাবলী যুক্ত করা হলে সংশোধন করার জন্য একটি ফাংশনগুলির কেন্দ্রীয় সেট রয়েছে।
    • বৈশিষ্ট্য যুক্ত করার জন্য কেবল একটি একক ক্রিয়াকলাপ যুক্ত করা দরকার।
    • যদি কোনও দৃশ্যের যোগ করা হয়, বিবৃতিতে হাতছাড়া enumকেসগুলি সম্পর্কে সংকলক সতর্কতাগুলি সক্ষম করা switchসেই সম্পত্তি-প্রাপককে ধরবে যা সেই পরিস্থিতিটি পরিচালনা করে না।
  • আপনার যদি বুলিয়ান বৈশিষ্ট্যগুলি গতিশীলভাবে সংশোধন করতে হয় তবে আপনার সর্বত্র সর্বত্র তাদের সংমিশ্রণগুলিকে পুনরায় বৈধতা দেওয়ার দরকার নেই। পৃথক বুলিয়ান পতাকা টগল করার পরিবর্তে (এর ফলে পতাকাগুলির অবৈধ সংমিশ্রণ হতে পারে) পরিবর্তে আপনার কাছে এমন একটি রাষ্ট্রীয় মেশিন থাকবে যা এক দৃশ্যে অন্য দৃশ্যে রূপান্তরিত হয়।

এই পদ্ধতির খুব দক্ষ হওয়ার পার্শ্ব সুবিধাও রয়েছে।


0

আমার 2 সেন্ট: একটি ভেরিয়েবল যোগফল (পূর্ণসংখ্যা) ঘোষণা করুন যাতে

if(bValue1)
{
  sum=sum+1;
}
if(bValue2)
{
  sum=sum+2;
}
if(bValue3)
{
  sum=sum+4;
}
if(bValue4)
{
  sum=sum+8;
}

আপনি যে শর্তটি চান তার বিরুদ্ধে যোগফল পরীক্ষা করুন এবং এটিই। আপনি পড়াতে একেবারে সোজা রেখে ভবিষ্যতে সহজে আরও শর্ত যুক্ত করতে পারেন।


0

গ্রহণযোগ্য উত্তর ঠিক আছে যখন আপনি কেবল 3 টি কেস পেয়েছেন এবং যেখানে প্রতিটিটির জন্য যুক্তিটি সহজ।

তবে যদি প্রতিটি মামলার যুক্তি আরও জটিল হয়ে ওঠে বা আরও অনেকগুলি কেস থাকে তবে চেইন-অফ-দায়িত্বের নকশার প্যাটার্নটি ব্যবহার করা এর চেয়ে আরও ভাল বিকল্প ।

আপনি এমন একটি তৈরি করেন BaseValidatorযার মধ্যে একটি রেফারেন্স BaseValidatorএবং একটি পদ্ধতি validateএবং রেফারেন্সযুক্ত বৈধকারীর বৈধতা যাচাই করার জন্য একটি পদ্ধতি রয়েছে।

class BaseValidator {
    BaseValidator* nextValidator;

    public:
    BaseValidator() {
        nextValidator = 0;
    }

    void link(BaseValidator validator) {
        if (nextValidator) {
            nextValidator->link(validator);
        } else {
            nextValidator = validator;
        }
    }

    bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
        if (nextValidator) {
            return nextValidator->validate(v1, v2, v3, v4);
        }

        return false;
    }

    virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
        return false;
    }
}

তারপরে আপনি বেশ কয়েকটি সাবক্ল্যাস তৈরি করেন যা উত্তরাধিকার সূত্রে উত্তরাধিকার সূত্রে প্রাপ্ত হয় BaseValidator, validateপ্রতিটি বৈধকারীর জন্য প্রয়োজনীয় যুক্তি দিয়ে পদ্ধতিটিকে ওভাররাইড করে ।

class Validator1: public BaseValidator {
    public:
    bool validate(bool v1, bool v2, bool v3, bool v4) {
        if (v1 && v2 && v3 && v4) {
            return true;
        }

        return nextValidator->callLinkedValidator(v1, v2, v3, v4);
    }
}

তারপরে এটি ব্যবহার করা সহজ, আপনার প্রত্যেকে যাচাই করে নিন এবং সেগুলির প্রত্যেককে অন্যের মূল হিসাবে সেট করুন:

Validator1 firstValidator = new Validator1();
Validator2 secondValidator = new Validator2();
Validator3 thirdValidator = new Validator3();
firstValidator.link(secondValidator);
firstValidator.link(thirdValidator);
if (firstValidator.validate(value1, value2, value3, value4)) { ... }

সারাংশ, প্রত্যেক বৈধতা ক্ষেত্রে তার নিজস্ব শ্রেণী যা (ক) জন্য দায়ী নির্ধারণের হয়েছে থাকে বৈধতা ম্যাচ যে মামলার সাথে এবং (খ) শৃঙ্খলে থাকা অন্য কারও কাছে বৈধতা প্রেরণ

দয়া করে মনে রাখবেন যে আমি সি ++ এর সাথে পরিচিত নই। আমি অনলাইনে পাওয়া কয়েকটি উদাহরণ থেকে বাক্য গঠনটি মেলানোর চেষ্টা করেছি, তবে এটি যদি কাজ না করে তবে এটি আরও সিউডোকোডের মতো আচরণ করুন। নীচে আমার কাছে একটি সম্পূর্ণ কার্যকারী পাইথন উদাহরণ রয়েছে যা যদি পছন্দ হয় তবে ভিত্তি হিসাবে ব্যবহার করা যেতে পারে।

class BaseValidator:
    def __init__(self):
        self.nextValidator = 0

    def link(self, validator):
        if (self.nextValidator):
            self.nextValidator.link(validator)
        else:
            self.nextValidator = validator

    def callLinkedValidator(self, v1, v2, v3, v4):
        if (self.nextValidator):
            return self.nextValidator.validate(v1, v2, v3, v4)

        return False

    def validate(self, v1, v2, v3, v4):
        return False

class Validator1(BaseValidator):
    def validate(self, v1, v2, v3, v4):
        if (v1 and v2 and v3 and v4):
            return True
        return self.callLinkedValidator(v1, v2, v3, v4)

class Validator2(BaseValidator):
    def validate(self, v1, v2, v3, v4):
        if (v1 and v2 and v3 and not v4):
            return True
        return self.callLinkedValidator(v1, v2, v3, v4)

class Validator3(BaseValidator):
    def validate(self, v1, v2, v3, v4):
        if (v1 and not v2 and not v3 and not v4):
            return True
        return self.callLinkedValidator(v1, v2, v3, v4)

firstValidator = Validator1()
secondValidator = Validator2()
thirdValidator = Validator3()
firstValidator.link(secondValidator)
firstValidator.link(thirdValidator)
print(firstValidator.validate(False, False, True, False))

আবার, আপনার নির্দিষ্ট উদাহরণের জন্য আপনি এই ওভারকিলটি পেতে পারেন, তবে যদি আপনি পূরণ করা প্রয়োজন এমন আরও জটিল মামলার সেটটি শেষ করেন তবে এটি অনেক ক্লিনার কোড তৈরি করে।


-2

একটি সহজ পদ্ধতির উত্তরটি আপনার পক্ষে গ্রহণযোগ্য বলে মনে করছেন finding

হ্যাঁ = (বুলিয়ান 1 এবং& বুলিয়ান 2 এবং& বুুলিয়ান 3 এবং& বুলিয়ান 4) + + ...

এখন সম্ভব হলে বুলিয়ান বীজগণিত ব্যবহার করে সমীকরণটি সহজ করুন।

এই ক্ষেত্রে, গ্রহণযোগ্য 1 এবং 2 এর সাথে একত্রিত হন (boolean1 && boolean2 && boolean3)

অতএব চূড়ান্ত উত্তরটি হ'ল:

(boolean1 && boolean2 && boolean3) || 
((boolean1 && !boolean2 && !boolean3 && !boolean4)

-3

বিট ফিল্ড ব্যবহার করুন :

unoin {
  struct {
    bool b1: 1;
    bool b2: 1;
    bool b3: 1;
    bool b4: 1;
  } b;
  int i;
} u;

// set:
u.b.b1=true;
...

// test
if (u.i == 0x0f) {...}
if (u.i == 0x0e) {...}
if (u.i == 0x08) {...}

পিএস :

এটি সিপিপার্সের জন্য একটি বড় দুঃখের বিষয়। তবে, ইউবি আমার উদ্বেগ নয়, এটি http://coliru.stacked-crooked.com/a/2b556abfc28574a1 এ দেখুন


2
এটি একটি নিষ্ক্রিয় ইউনিয়ন ক্ষেত্রে অ্যাক্সেসের কারণে ইউবির কারণ হয়।
হলিব্ল্যাকগ্যাট

সাধারনত এটি সি ++ এ ইউবি, আপনি ইউনিয়নের একজন সদস্য নির্ধারণ করতে এবং অন্যের কাছ থেকে পড়তে পারবেন না। টেকনিক্যালি এটি টেম্পলেটেড গেটারস-ইন্টিগ্রাল ভ্যালু বিটের জন্য সেটটারগুলি প্রয়োগ করা ভাল।
সুইফ্ট - শুক্রবার পাই

আমি মনে করি যে আচরণটি ইউনিয়নটির ঠিকানাটিকে একটিতে রূপান্তর করতে পারলে বাস্তবায়ন-সংজ্ঞায়িত হয়ে উঠবে unsigned char*, যদিও আমি মনে করি যে এর মতো কিছু ব্যবহার করা ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1সম্ভবত আরও দক্ষ হবে।
সুপারক্যাট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.