দুটি পরিসরের মধ্যে অবতরণ ক্রমে একটি ভেক্টর বাছাই করা


14

বলুন আমার কাছে পূর্ণসংখ্যার ভেক্টর রয়েছে:

std::vector<int> indices;
for (int i=0; i<15; i++) indices.push_back(i);

তারপরে আমি এটিকে সাজানো ক্রম অনুসারে বাছাই করেছি:

sort(indices.begin(), indices.end(), [](int first, int second) -> bool{return indices[first] > indices[second];})
for (int i=0; i<15; i++) printf("%i\n", indices[i]);

এটি নিম্নলিখিত উত্পাদন করে:

14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

এখন আমি 3, 4, 5 এবং 6 নম্বরগুলি শেষ পর্যন্ত স্থানান্তরিত করতে চাই এবং তাদের জন্য উতরিত ক্রমটি রাখি (পছন্দমতো sortদ্বিতীয়বার ব্যবহার না করে)। অর্থাৎ আমি যা চাই তা এখানে:

14
13
12
11
10
9
8
7
2
1
0
6
5
4
3

এটি std::sortঅর্জনের তুলনা কার্যটি আমি কীভাবে সংশোধন করব ?


4
return indices[first] > indices[second]মানে না return first < second;?
acraig5075

2
একটি সহজ অবতরণ সাজানোর জন্য, std::greaterথেকে <functional>আপনার ল্যাম্বদার জায়গায় ব্যবহার করা যেতে পারে। আপনার প্রশ্নের হিসাবে, আরও ভার্বোজ তুলনামূলক লেখা যা আপনার মানগুলি যেভাবে চান তা তুলনা করে তা নিশ্চিত করার পক্ষে এটি করা সহজতম উপায়।
মধ্যাহ্নে

4
@ acraig5075, অবতরণ ক্রমে এটি হওয়া উচিত return first > second
ks1322

1
@ acraig5075 আমার মনে আমি কিছু অনুপস্থিত করছি, অথবা মানুষের মধ্যে পার্থক্য জানেন না আরোহী এবং সাজানো ?
sweenish

3
হয়তো আপনি খুঁজছেন std :: আবর্তন ?
সুপার

উত্তর:


8

আপনার তুলনা ফাংশনটি ভুল যেহেতু আপনি যে মানগুলি পেয়েছেন firstএবং secondএটি উপাদান হিসাবে রয়েছে std::vector। সুতরাং এগুলি সূচক হিসাবে ব্যবহার করার দরকার নেই। সুতরাং, আপনি পরিবর্তন প্রয়োজন

return indices[first] > indices[second];

প্রতি

return first > second;

এখন, সমস্যাটি সমাধান করার চেষ্টা করুন ...

আপনি অন্যান্য উপাদানগুলির সাথে তুলনা ছাড়াই 3, 4, 5 এবং 6 রেখে যেতে পারেন এবং এখনও একে অপরের সাথে তুলনা করতে পারেন:

std::sort(
    indices.begin(), indices.end(),
    [](int first, int second) -> bool {
        bool first_special = first >= 3 && first <= 6;
        bool second_special = second >= 3 && second <= 6;
        if (first_special != second_special)
            return second_special;
        else
            return first > second;
    }
);

ডেমো


@ নটক্র্যাকার হ্যাঁ, আমি সম্মত হই যে শীর্ষস্থানীয় মানদণ্ডটি প্রথমে পাওয়া ভাল n
স্তূপ ওভারফ্লো

5

থেকে কার্যাবলী মান আলগোরিদিম গ্রন্থাগার মত iota, sort, find, rotateএবং copyআপনার জীবন সহজ করতে হবে। আপনার উদাহরণ নীচে আসে:

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


int main()
{
  std::vector<int> indices(15);
  std::iota(indices.begin(), indices.end(), 0);
  std::sort(indices.begin(), indices.end(), std::greater<>());

  auto a = std::find(indices.begin(), indices.end(), 6);
  auto b = std::find(indices.begin(), indices.end(), 3);
  std::rotate(a, b + 1, indices.end());

  std::copy(indices.begin(), indices.end(), std::ostream_iterator<int>(std::cout, "\n"));
  return 0;
}

আউটপুট:

14
13
12
11
10
9
8
7
2
1
0
6
5
4
3


মন্তব্যগুলিতে @ টেডলিঙ্গমো ভাল পয়েন্টটি দেয় যে এটি দিয়ে / উন্নত করা উচিত:

auto a = std::lower_bound(indices.begin(), indices.end(), 6, std::greater<int>{});
auto b = a + 4;

auto b = a + 4;ভুল (যদি আপনি পূর্ববর্তী স্নিপেটের সাথে ধারাবাহিকতা রাখতে চান)। এটি হওয়া উচিত auto b = a + 3;কারণ std::rotateআপনি ব্যবহার করছেনb + 1
বিয়াজিও ফেস্টা

3

সমাধান ঘ

একটি অ-রৈখিক তুলনামূলক সঙ্গে সোজা পদ্ধতি ।

inline constexpr bool SpecialNumber(const int n) noexcept {
  return n < 7 && 2 < n;
}

void StrangeSortSol1(std::vector<int>* v) {
  std::sort(v->begin(), v->end(), [](const int a, const int b) noexcept {
    const bool aSpecial = SpecialNumber(a);
    const bool bSpecial = SpecialNumber(b);

    if (aSpecial && bSpecial) return b < a;
    if (aSpecial) return false;
    if (bSpecial) return true;
    return b < a;
  });
}

সমাধান 2

std::algorithmগুলি (পার্টিশন) ব্যবহার করে !

inline constexpr bool SpecialNumber(const int n) noexcept {
  return n < 7 && 2 < n;
}

void StrangeSortSol2(std::vector<int>* v) {
  auto pivot = std::partition(v->begin(), v->end(), std::not_fn(SpecialNumber));
  std::sort(v->begin(), pivot, std::greater{});
  std::sort(pivot, v->end(), std::greater{});
}

পারফরম্যান্স বিবেচনা

পার্টিশনের ওভারহেডের কারণে এটি দ্বিতীয় সমাধানটি ধীর গতির মতো দেখায়। সম্ভবত এটি আধুনিক প্রসেসরগুলিতে ক্যাশে এবং মিস-ব্রাঞ্চের পূর্বাভাসের কারণে নয়।

মাপকাঠি


যে কোনও ভাল সংকলক n <= 6 && 3 <= n টার্গেট সিপিইউর জন্য সবচেয়ে ভাল কাজ করে এমনটিতে রূপান্তরিত হওয়া উচিত যাতে আপনি 2 এবং 7 সংখ্যাটি দেখিয়ে কিছুই অর্জন করতে পারেন তবে সম্ভাব্য বিভ্রান্তি - এবং কেন রেফারেন্সের পরিবর্তে ভেক্টরটিতে কোনও পয়েন্টার নিন?
টেড লিঙ্গমো

আর্গুমেন্ট ফাংশন হিসাবে `const int সংখ্যা` ব্যবহার করবেন না
এন্টোইন মরিয়ার

1
@ এন্টাইনমুরিয়ার কেন?
ওভারফ্লো

@ হিপ ওভারফ্লো কারণ কনস্ট্যান্ড ব্যবহার না করেই এটি সমান :)।
এন্টোইন মরিয়ার

@ অ্যান্টাইনমারিয়র আমি এটি একরকম মনে করি না। constপাঠককে কি বলে না যে ফাংশনটি মান পরিবর্তন করে না? ওয়ান-লাইনারের এই বিশেষ ক্ষেত্রে এটি পরিষ্কার হতে পারে, তবে সাধারণভাবে তা হয় না।
গাদা ওভারফ্লো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.