Algorithms & Lambda Expressions

Algorithms Overview

En çok kullanılan bir takım algoritmalar STL kütüphanesinde bulunmaktadır. Bunlar iyi implemente ve test edilmiş algoritmalar olup hali hazırda kullandığımız container’larla da uyumludur.

Algorithms with Predicates

A predicate is a C++ function returning a boolean or an object having a bool operator() member. A unary predicate takes one argument, a binary takes two, and so on. Examples of questions predicates can answer for a particular algorithm are:

  • Is this element what we are looking for?
  • Is the first of two arguments ordered first in our order?
  • Are the two arguments equal?

Almost all STL algorithms take a predicate as last argument.

You can construct new predicates using standard, self-defined, and/or predicate-making classes (here is a good reference).

https://stackoverflow.com/questions/5921609/what-is-predicate-in-c

Algorithms with _if Versions

Algoritmaların predicate’li halidir. Belli bir koşulun gerçekleşmesi durumunda işlem yapar. Örneğin count algoritması verilen elemanın container içinde kaç tane bulunduğunu sayar. count_if fonksiyonunda bunu daha da özelleştirip belli bir koşula göre saymasını sağlayabiliyoruz.

vector <int> vec{3,5,6,8,10,5,5,6,8};

cout << count(vec.begin(), vec.end(), 5) << endl; //3
cout << count_if(vec.begin(), vec.end(), 
[](int n) {
  return n % 2 == 0; 
  }
) << endl; // 5

Lambda Expressions

isimsiz fonksiyonlardır. Başka bir fonksiyona atmak için normal bir fonksiyon yazmak istemiyorsanız kullanabilirsiniz.

  1. capture clause (Also known as the lambda-introducer in the C++ specification.)
  2. parameter list Optional. (Also known as the lambda declarator)
  3. mutable specification Optional.
  4. exception-specification Optional.
  5. trailing-return-type Optional.
  6. lambda body.

Capture

[]  // capture nothing
[=] // capture all by value
[&] // capture all by reference


[&total, factor] // capture by reference, capture by value
[factor, &total] // capture by value, capture by reference
[&, factor] // capture all by reference EXCEPT factor
[=, &total] // capture all by value EXCEPT total

mutable

Typically, a lambda’s function call operator is const-by-value, but use of the mutable keyword cancels this out. It doesn’t produce mutable data members. The mutable specification enables the body of a lambda expression to modify variables that are captured by value. Some of the examples later in this article show how to use mutable.

https://learn.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170

Pair Type

pair<int, string> myPair{5,"Hello"};
auto myPair {make_pair{5,"Hello"}}; // std::make_pair
pair myPair{5,"Hello"};   // C++11 CTAD

Insert Iterators

container’a yeni ögeler eklememize olanak tanır.

  • back_inserter() -> back_insert_iterator döndürür
  • front_inserter() -> front_insert_iterator döndürür
  • inserter -> insert_iterator döndürür
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

using namespace std;

int main() {
	auto printList = [](list<int> myList) {
		for (auto& i : myList) cout << i << ", ";
		cout << endl;
		};


	list<int> l{ 3,4,5 };
	printList(l);
	// 3, 4, 5,

	auto bi = back_inserter(l);
	*bi = 6;
	*bi = 7;
	*bi = 8;
	printList(l);
	// 3, 4, 5, 6, 7, 8,

	auto fi = front_inserter(l);
	*fi = 2;
	*fi = 1;
	*fi = 0;
	printList(l);
	// 0, 1, 2, 3, 4, 5, 6, 7, 8,

	auto loc = find(l.begin(), l.end(), 5);
	auto in = inserter(l, loc);
	*in = 99;
	*in = 99;
	*in = 99;
	printList(l);
	// 0, 1, 2, 3, 4, 99, 99, 99, 5, 6, 7, 8,
}

Library Function Objects

function object is any object for which the function call operator is defined. C++ provides many built-in function objects as well as support for creation and manipulation of new function objects.

https://en.cppreference.com/w/cpp/utility/functional

Searching Algorithms

find

N tane eleman içinde verilen tek bir elemanı arar. Bulduğu ilk elemanın iteratörünü döndürür.

	string str = "This is a string";
	string vowels = "aeiou";

	auto firstOne = find(str.begin(), str.end(), 'a');
	if (firstOne != str.end()) {
		cout << *firstOne; //a
		cout << distance(str.begin(), firstOne); //8
	}

https://cplusplus.com/reference/algorithm/find

find_end & search

N tane eleman içinde, S tane elemandan oluşan aralığı arar. Yani büyük bir parçanın içinde küçük bir parçayı arar.

  • search -> ilk görülen lokasyonu döndürür
  • find_end -> son görülen lokasyonu döndürür
	string str = "This thing is a string";
	string vowels = "ng";

	auto firstOne = search(str.begin(), str.end(), vowels.begin(), vowels.end());
	auto lastOne = find_end(str.begin(), str.end(), vowels.begin(), vowels.end());

	if (firstOne != str.end()) {
		cout << *firstOne; //n
		cout << distance(str.begin(), firstOne); //8
	}
	cout << endl;

	if (lastOne != str.end()) {
		cout << *lastOne; //n
		cout << distance(str.begin(), lastOne); //20
	}

find_first_of

N tane eleman içinde, S tane elemandan herhangi birini arar. Yani aranan ögenin elemanlarından bir tanesi tutsun da hangisi tutarsa tutsun.

	string str = "This is a string";
	string vowels = "aeiou";

	auto firstOne = find_first_of(str.begin(), str.end(), vowels.begin(), vowels.end());
	if (firstOne != str.end())
	  cout << *firstOne; // i
	

https://cplusplus.com/reference/algorithm/find_first_of

find_if & find_if_not

	vector<int> vec{ 1,2,3,4,5,6,7,8,9,10,12 };

	auto fi = *find_if(vec.begin(), vec.end(), [](int& i) { return i % 3 == 0; });
	auto fin = *find_if_not(vec.begin(), vec.end(), [](int& i) {return i % 2 == 1; });
	cout << fi << " " << fin << endl; // 3 2

adjacent_find

birbirine bitişik aynı elamanları arar. == operatörünü kullanır ama biz bir predicate vererek bu

	vector<int> vec0{ 0,1,0,0,1,0,0,0,1,1 };
	auto af0 = adjacent_find(vec0.begin(), vec0.end());


	vector<int> vec1{ 0,1,2,3,5,6,7 };
	auto f = [](int i, int j) { return i + 2 == j; };
	auto af1 = adjacent_find(vec1.begin(), vec1.end(), f);

	cout << distance(vec0.begin(), af0) << endl; // 2
	cout << distance(vec1.begin(), af1) << endl; // 3

search_n

verilen elemandan n adet yan yana gelirse

	vector<int> vec{ 0,1,0,0,1,0,0,0,1,1 };
	auto one = search_n(vec.begin(), vec.end(), 1, 0);
	auto two = search_n(vec.begin(), vec.end(), 2, 0);
	auto thr = search_n(vec.begin(), vec.end(), 3, 0);

	cout << distance(vec.begin(), one) << endl; // 0
	cout << distance(vec.begin(), two) << endl;	// 2
	cout << distance(vec.begin(), thr) << endl;	// 5

mismatch

İki conteiner’ı karşılaştırır, ilk eşleşmeyen elemanları pair<> şeklinde döndürür.

	vector<int> vec { 3, 5, 1,  7, 9, 11 };
	vector<int> vec2{ 3, 5, 1, 99, 9, 11 };

	auto p = mismatch(vec.begin(), vec.end(), vec2.begin());
	cout << *p.first << " " << *p.second << endl; // 7 99

all_of, none_of, any_of

  • all_of() -> predicate her eleman için true => true
  • none_of() -> predicate her eleman için false => true
  • any_of() -> predicate en az bir eleman için true => true
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
	auto is_odd = [](int& i) { return i % 2 == 1; };
	auto is_even = [](int& i) { return i % 2 == 0; };

	vector<int> vec{ 3,5,1,7,9,11 };
	auto b = vec.begin();
	auto e = vec.end();

	cout << all_of(b, e, is_odd) << endl;  // 1
	cout << all_of(b, e, is_even) << endl; // 0
	
	cout << none_of(b, e, is_odd) << endl; // 0
	cout << none_of(b, e, is_even) << endl;// 1

	vector<int> vec2{ 4,5,1,7,9,11 };
	b = vec2.begin();
	e = vec2.end();

	cout << any_of(b, e, is_odd) << endl; // 1
	cout << any_of(b, e, is_even) << endl;// 1		
}

Binary Search

Sıralı bir container’da, Binary Search algoritmasını kullanarak verilen aralıkta istenilen elemanı arar.

	vector<int> vec{ 3,5,1,7,9,11 };
	
	sort(vec.begin(), vec.end());
	
	if (binary_search(vec.begin(), vec.end(), 7))
		cout << "7 is an element of vec\n";
	else
		cout << "7 is not an element of vec\n";
		
// 7 is an element of vec

includes

Verilen elemanlar(vec2), bakılan aralıkta(vec) bir alt küme ise true döndürür. Container’ların sıralı olması gerekmektedir.

	vector<int> vec{ 3,5,1,7,9,11 };
	vector<int> vec2{11,1,3 };
	sort(vec.begin(), vec.end());
	sort(vec2.begin(), vec2.end());
	
	if (includes(vec.begin(), vec.end(), vec2.begin(),vec2.end()))
		cout << "vec includes vec2\n";
	else
		cout << "vec does not includes vec2\n";
		
	// vec includes vec2

Numeric Algorithms

iota

Fills the range [firstlast) with sequentially increasing values, starting with value and repetitively evaluating ++value.

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

using namespace std;

void pvec(vector<int> v) {
	for (auto& i : v) cout << i << ", ";
	cout << endl;
}
int main(){

	vector<int> vec0(10);
	vector<int> vec1(10);

	iota(vec0.begin(), vec0.end(), 0);
	iota(vec1.begin(), vec1.end(), 5);

	pvec(vec0);	// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
	pvec(vec1);	// 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
		
}

accumulate

Verilen aralığı toplar

std::accumulate performs a left fold. In order to perform a right fold, one must reverse the order of the arguments to the binary operator, and use reverse iterators.

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

using namespace std;

void pvec(vector<int> v) {
	for (auto& i : v) cout << i << ", ";
	cout << endl;
}
int main(){

	vector<int> vec(10);
	iota(vec.begin(), vec.end(), 7);
	pvec(vec);
	// 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,

	int initial_value0{ 0 }, initial_value1{ 20 };
	cout << accumulate(vec.begin(), vec.end(), initial_value0) << endl;
	cout << accumulate(vec.begin(), vec.end(), initial_value1) << endl;
	// 115
	// 135
	
	accumulate(vec.begin(), vec.end(), initial_value0,
		[](int& a, int& b) {
			cout << "a: " << a << "\tb: " << b << endl;
			return a + b;
		}
	);
	// a: 0    b: 7
	// a: 7    b: 8
	// a: 15   b: 9
	// a: 24   b: 10
	// a: 34   b: 11
	// a: 45   b: 12
	// a: 57   b: 13
	// a: 70   b: 14
	// a: 84   b: 15
	// a: 99   b: 16
}

reduce

accumulate’in modern versiyonu.

https://blog.tartanllama.xyz/accumulate-vs-reduce

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

using namespace std;

void pvec(vector<int> v) {
	for (auto& i : v) cout << i << ", ";
	cout << endl;
}
int main(){

	vector<int> vec(10);
	iota(vec.begin(), vec.end(), 7);
	pvec(vec);
	// 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
	
	int initial_value0{ 0 }, initial_value1{ 20 };
	cout << reduce(vec.begin(), vec.end(), initial_value0) << endl;
	cout << reduce(vec.begin(), vec.end(), initial_value1) << endl;
	// 115
	// 135
	
	reduce(std::execution::par,vec.begin(), vec.end(), initial_value0,
		[](int a, int b) {
			cout << "a: " << a << "\tb: " << b << endl;
			return a + b;
		}
	);
	// 	a: 0    b: a: 97
	// 	a:      b: 10
	// 	7       b: 8
	// 	a: 11   b: 12
	// 	a: 15   b: 16
	// 	a: 13   b: 14
	// 	a: 15   b: 19
	// 	a: 34   b: 23
	// 	a: 57   b: 31
	// 	a: 88   b: 27

}

Write-only Algorithms

fill & fill_n

fill, verilen elemanla istenilen aralığı doldurur.

	vector<int> vec(10);
	fill(vec.begin(), vec.end(), 5);
	pvec(vec); 

	fill_n(vec.begin(), 5, 3);
	pvec(vec); 

	// 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
	// 3, 3, 3, 3, 3, 5, 5, 5, 5, 5,

generate & generate_n

	int jj = 0; 
	auto f = [&jj]() {return ++jj; };

	vector<int> vec(10);
	generate(vec.begin(), vec.end(), f);
	pvec(vec); 

	generate_n(vec.begin(), 5, f);
	pvec(vec); 

	// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
	// 11, 12, 13, 14, 15, 6, 7, 8, 9, 10,

for_each Algorithm

	vector<int> vec{7,4,5,2,6,4,6,4,1,2,3};
	for_each(vec.begin(), vec.end(), [](int& i) {cout << i << ", "; });
	// 7, 4, 5, 2, 6, 4, 6, 4, 1, 2, 3,

Copying Algorithms

int main(){
	vector<int> vec{7,4,5,2,6,4,6,4,1,2,3};
	
	vector<int> vec1;
	copy(vec.begin(), vec.end(), back_inserter(vec1));
	pvec(vec1);
	// 7, 4, 5, 2, 6, 4, 6, 4, 1, 2, 3,


	vector<int> vec2(vec.size());
	copy_n(vec.begin(), 7, vec2.begin());
	pvec(vec2);
	// 7, 4, 5, 2, 6, 4, 6, 0, 0, 0, 0,


	vector<int> vec3(vec.size());
	copy_if(vec.begin(), vec.end(), vec3.begin(), [](int& i) {return i % 2; });
	pvec(vec3);
	// 7, 5, 1, 3, 0, 0, 0, 0, 0, 0, 0,
}

Write Algorithms (replace)

	string str = { "AATTSSSGGGGAA"};
	cout << str << endl;// AATTSSSGGGGAA


	replace(str.begin(), str.end(), 'A', 'T');
	cout << str << endl << endl;// TTTTSSSGGGGTT


	string str2;
	replace_copy(str.begin(), str.end(), back_inserter(str2), 'S', 'A');
	cout << str2 << endl; // TTTTAAAGGGGTT
	cout << str << endl;  // TTTTSSSGGGGTT


	replace_if(str.begin(), str.end(), [](const char& c) {return c != 'G'; }, '-');
	cout << str << endl;  // -------GGGG--

Removing Algorithms

remove

  • shifting yaparak eleman siler. Silinen elemanlar mantıksal olarak silinmiş olup container’ın boyutu değişmez.
  • _if ve _copy ‘li versiyonları mevcuttur.
	string str = { "AATTSSSGGGGAA"};
	cout << str << endl;

	auto it = remove(str.begin(), str.end(), 'A');
	cout << str << endl;

	string new_str(str.begin(), it);
	cout << new_str << endl;

	// AATTSSSGGGGAA // original
	// TTSSSGGGGGGAA // after remove
	// TTSSSGGGG     // new string by iterator 

erase

	vector<int> vec{3, 4, 8, 5, 5, 9, 0, 4, 5, 5, 6, 5, 0, 9, 7, 2, 3, 6, 4, 5};
	pvec(vec);

	erase(vec, 5);
	pvec(vec);

	// 3, 4, 8, 5, 5, 9, 0, 4, 5, 5, 6, 5, 0, 9, 7, 2, 3, 6, 4, 5,
	// 3, 4, 8, 9, 0, 4, 6, 0, 9, 7, 2, 3, 6, 4,

unique

Sıralanmış bir containerda tekrar eden elemanları, teke indirir. remove() gibi container boyutunda bir değişiklik yapmaz.

	vector<int> vec{3, 4, 8, 5, 5, 9, 0, 4, 5, 5, 6, 5, 0, 9, 7, 2, 3, 6, 4, 5};
	pvec(vec);

	sort(vec.begin(), vec.end());
	pvec(vec);

	auto it = unique(vec.begin(), vec.end());
	pvec(vec);

	vec.erase(it, vec.end());
	pvec(vec);

	// 3, 4, 8, 5, 5, 9, 0, 4, 5, 5, 6, 5, 0, 9, 7, 2, 3, 6, 4, 5,
	// 
	// 0, 0, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 9,
	// 0, 2, 3, 4, 5, 6, 7, 8, 9, 5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 9,
	// 
	// 0, 2, 3, 4, 5, 6, 7, 8, 9,

Transform Algorithm

verilen fonksiyonu istenilen aralığa uygular. 1 veya 2 container girdi olarak kullanılabilir. Çıktı ile girdi containerı aynı olabilir.

int main(){
	vector<int> vec{ 3, 4, 8, 5, 5, 9 };
	vector<int> vec2(vec.size());
	vector<int> vec3;


	cout << "to different container" << endl;
	std::transform(vec.begin(), vec.end(), vec2.begin(), [](int& i) {return i * 3; });
	cout << "vec : \t"; pvec(vec); 
	cout << "vec2: \t"; pvec(vec2);
	cout << endl << endl;

	cout << "to same container" << endl;
	std::transform(vec.begin(), vec.end(), vec.begin(), [](int& i) {return i * 4; });
	cout << "vec : \t"; pvec(vec);
	cout << endl << endl;

	cout << "back inserter" << endl;
	std::transform(vec.begin(), vec.end(), back_inserter(vec3), [](int& i) {return i + 2; });
	cout << "vec3: \t"; pvec(vec3);
	cout << endl << endl;         


	cout << "With 3 container (2 input 1 output) " << endl;
	std::transform(vec.begin(), vec.end(), vec2.begin(), vec3.begin(), [](int& a, int& b) { return a + b; });
	cout << "vec : \t"; pvec(vec ); 
	cout << "vec2: \t"; pvec(vec2);
	cout << "vec3: \t"; pvec(vec3);

	
	// to different container
	// vec :   3, 4, 8, 5, 5, 9,
	// vec2:   9, 12, 24, 15, 15, 27,
	// 
	// 
	// to same container
	// vec :   12, 16, 32, 20, 20, 36,
	// 
	// 
	// back inserter
	// vec3:   14, 18, 34, 22, 22, 38,
	// 
	// 
	// With 3 container (2 input 1 output)
	// vec :   12, 16, 32, 20, 20, 36,
	// vec2:   9, 12, 24, 15, 15, 27,
	// vec3:   21, 28, 56, 35, 35, 63,

}

Merging Algorithms

  • merge: iki container’ı birleştirir.
  • set_intersection: kesişim
  • set_union: birleşim
int main(){
	vector<int> vec0{ 3, 4, 8, 5, 5, 9 };
	vector<int> vec1{ 8, 5, 5, 9, 10, 25, 20 };
	vector<int> vec2, vec3, vec4;

	sort(vec0.begin(), vec0.end());
	sort(vec1.begin(), vec1.end());

	pvec(vec0); // 3, 4, 5, 5, 8, 9,
	pvec(vec1); // 5, 5, 8, 9, 10, 20, 25,
	cout << endl;
		

	merge(vec0.begin(), vec0.end(), vec1.begin(), vec1.end(), back_inserter(vec2));
	pvec(vec2); // 3, 4, 5, 5, 5, 5, 8, 8, 9, 9, 10, 20, 25,


	set_intersection(vec0.begin(), vec0.end(), vec1.begin(), vec1.end(), back_inserter(vec3));
	pvec(vec3); // 5, 5, 8, 9,


	set_union(vec0.begin(), vec0.end(), vec1.begin(), vec1.end(), back_inserter(vec4));
	pvec(vec4); // 3, 4, 5, 5, 8, 9, 10, 20, 25,
}

Reordering Algorithms

	vector<int> vec{ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };

	reverse(vec.begin(), vec.end()); pvec(vec);
	// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

	rotate(vec.begin(), vec.begin() + 2, vec.end()); pvec(vec);
	rotate(vec.begin(), vec.begin() + 2, vec.end()); pvec(vec);
	rotate(vec.begin(), vec.begin() + 2, vec.end()); pvec(vec);
	rotate(vec.begin(), vec.begin() + 2, vec.end()); pvec(vec);
	rotate(vec.begin(), vec.begin() + 2, vec.end()); pvec(vec);
	rotate(vec.begin(), vec.begin() + 2, vec.end()); pvec(vec);

	// 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
	// 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
	// 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
	// 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
	// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
	// 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,

Partitioning Algorithms

  • partition() : verilen predicate’e göre containerı sağ/sol böler. bir tarafta true olanlar öteki tarafta false olanlar.
  • stable_partition() : bölerken sıralama dikkat eder.
  • is_partition() : Bölünmüş mü diye kontrol eder.
  • partition_point() : bölünme noktasını forward iterator olarak verir.
int main(){
	vector<int> vec1{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	vector<int> vec2{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

	partition(vec1.begin(), vec1.end(), [](int i) {return i % 2; });
	pvec(vec1); // 9, 1, 7, 3, 5, 4, 6, 2, 8, 0,


	stable_partition(vec2.begin(), vec2.end(), [](int i) {return i % 2; });
	pvec(vec2); // 1, 3, 5, 7, 9, 0, 2, 4, 6, 8,


	cout << is_partitioned(vec2.begin(), vec2.end(), [](int i) {return i % 2; }) << endl; // 1
	
	
	auto it = partition_point(vec2.begin(), vec2.end(), [](int i) {return i % 2; });
	cout << *it << endl; // 0
	vector<int> vec3(vec2.begin(), it);
	pvec(vec3); // 1, 3, 5, 7, 9,
}

Sorting Algorithms

  • sort: verilen aralığı artan şekilde sıralar
  • stable sort: sıralama yaparken, aynı elemanlarını sıralamasına dikkat eder. Örneğin bir kuyrukta genç olanlara öncelik verilecektir. Lakin bu sıralamayı yaparken aynı yaştaki insanların kendi aralarındaki sıralaması korumak istiyoruz. işte bu tip durumlarda stable sort kullanılabilir
  • is_sorted: verilen aralığın sıralı olup olmadığını kontrol eder
  • is_sorted_until: sıralamayı bozan ilk elemanın iteratörünü döndürür.
  • partial_sort: Verilen aralıktaki ilk n elemanı sırala.

nth_element()

Rearranges the elements in the range [first,last), in such a way that the element at the nth position is the element that would be in that position in a sorted sequence.

The other elements are left without any specific order, except that none of the elements preceding nth are greater than it, and none of the elements following it are less.

The elements are compared using operator< for the first version, and comp for the second.

https://cplusplus.com/reference/algorithm/nth_element

Permutation Algorithms

Olası tüm sıralama kombinasyonlarını verir.



int main(){
	string str1{ "ABC" }, str2{ "CBA" };
	do {
		cout << str1 << endl;
	} while (next_permutation(str1.begin(), str1.end()));

	cout << str1 << endl;
	// ABC
	// ACB
	// BAC
	// BCA
	// CAB
	// CBA
	// ABC


	cout << endl;


	do {
		cout << str2 << endl;
	} while (prev_permutation(str2.begin(), str2.end()));
	cout << str2 << endl;
	// CBA
	// CAB
	// BCA
	// BAC
	// ACB
	// ABC
	// CBA

}

If the function can determine the next higher permutation, it rearranges the elements as such and returns true. If that was not possible (because it is already at the largest possible permutation), it rearranges the elements according to the first permutation (sorted in ascending order) and returns false.

https://cplusplus.com/reference/algorithm/next_permutation

Min and Max Algorithms

int main(){
	cout << min(10, 5) << endl; // 5 
	cout << max(10, 5) << endl; // 10

	cout << min({1,4,6,2,3,6,8,9,4,10}) << endl; // 1
	cout << max({1,4,6,2,3,6,8,9,4,10}) << endl; // 10

	// min max returns a pair<>

	auto mm0 = minmax(10, 5); 
	auto mm1 = minmax({ 1,4,6,2,3,6,8,9,4,10 });

	cout << mm0.first << "  " << mm0.second << endl; // 5  10
	cout << mm1.first << "  " << mm1.second << endl; // 1  10

	// _element
	vector<int> vec{1,4,6,2,3,6,8,9,4,10};

	cout << *min_element(vec.begin(), vec.end()) << endl; // 1
	cout << *max_element(vec.begin(), vec.end()) << endl; // 10

	auto mm2 = minmax_element(vec.begin(), vec.end());
	cout << *mm2.first << "  " << *mm2.second << endl; // 1  10

	// clamp
	cout << clamp(-5, 0, 10) << endl; // 0 
	cout << clamp( 5, 0, 10) << endl; // 5
	cout << clamp(15, 0, 10) << endl; // 10

}

Further Numeric Algorithms

int main(){
	// vec (a,b,c,... )
	// partial sum: (a, a+b, a+b+c, ... )
	// adjacent difference (a, b-a, c-b, ... )	
	vector<int> vec{1,6,4,27,21,6,2,32};
	pvec(vec); // 1, 6, 4, 27, 21, 6, 2, 32,	
	
	partial_sum(vec.begin(), vec.end(), vec.begin()); 
	pvec(vec); // 1, 7, 11, 38, 59, 65, 67, 99,
	adjacent_difference(vec.begin(), vec.end(), vec.begin()); 
	pvec(vec); // 1, 6, 4, 27, 21, 6, 2, 32,

	
	// vec1 (a1, b1, c1, ...)
	// vec2 (a2, b2, c2, ...)
	// inner product of vec1 and vec2: a1*a2 + b1*b2 + c1*c2 + ...
	vector<int> vec1{ 1,6,4 };
	vector<int> vec2{ 2,1,6 };
	pvec(vec1);
	pvec(vec2);

	cout << inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0) << endl; // 32

}

https://en.cppreference.com/w/cpp/numeric/special_functions

Introduction to Random Numbers

Random Numbers in Older C++

rand()

srand(time(0)) // time(0) return the current time (value return by time() only changes once per second)

Random Numbers in Modern C++

default_random_number_engine eng;

eng() // call the functor to get the next number

mt19937 //mersenne twister

destributution types
- bernoulli, normal, poissiion

random_device

Random Number Algorithms

shuffle()


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *