#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <functional>
#include <string>
using namespace std;
// 알고리즘의종류
int foo( int a, int b );
int main()
{
        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int y[10];
        int* p1 = remove( x, x+10, 3 );         // 알고리즘의 in place 버전
        int* p2 = remove_copy( x, x+10, y, 3 ); // 알고리즘의 copy 버전
        
        int* p3 = remove_if( x, x+10, foo );  // 알고리즘의 조건자 버전.
        int* p4 = remove_copy_if( x, x+10, y, foo );
// sort의 조건자버전- 조건자이름구별..
// sort 같은 알고리즘은 조건자 버전은 인자가 3개이고 조건자를 사용하지 않은 버전은
// 인자가 2개이다. 그러므로 sort함수는 조건자 버전과 그렇지 않은 버전을 명확이 구분
// 할 수 있으므로 _if 가 붙지 않는다!!!
        sort( x, x+10 );
        sort( x, x+10, foo );
}
// sort에사용하는조건자함수규칙
// 아래함수를평가해보세요.
int foo( int a, int b )
{
        //return a <= b;       // 같을때바꾼다는건말도안됨. 1번에어긋남
        return a < b;          // ok.
}
// Strict Weak Ordering ( sort의조건의원칙?? )
// 1) f(a, a)는반드시false여야한다.
// 2) f(a, b)가참이면f(b, a)는거짓이다.
// 3) f(a, b)가참이고f(b, c)가참이면f(a, c)도참이다.
/////////////////////////////////////////////////
// 1. accumulate
void main()
{
        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        // 기본연산자버전+ 버전
        int n1 = accumulate( x, x+10, 0 );
        cout << n1 << endl;
        int n2 = accumulate( x, x+10, 1, multiplies<int>() );
        cout << n2 << endl;
}
/////////////////////////////////////////////////
void main()
{
        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int* p1 = find( x, x+10, 3 );      // 변경불가sequence 알고리즘
        int* p2 = remove( x, x+10, 3 );    // 변경가능sequence 알고리즘
        sort( x, x+10 );    // 정렬 관련 알고리즘
        int n = accumulate( x, x+10, 0 ); // 범용수치알고리즘     "numeric"
        cout << n << endl;
}
// 2. 구간삭제 erase
void main()
{
        int x[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        vector<int> v( x, x+10 );
        vector<int>::iterator p = remove( v.begin(), v.end(), 5 );
// v.begin() ~ p까지가 유효한 구간이다. 나머지 유효하지 않은 구간을 지우자!
        v.erase( p, v.end() );
        int n = accumulate( v.begin(), v.end(), 0 );
        cout << n << endl;
}
// 3. copy, copy_backward
void main()
{
        string s1 = "ABCDE";
        // left shift
        //copy( s1.begin() + 1, s1.end(), s1.begin() );
        // right shift
        //copy( s1.begin(), s1.end() - 1, s1.begin() + 1 );
        // AAAAA가 출력 뒤에서 부터 copy해야 한다.
        copy_backward( s1.begin(), s1.end() - 1, s1.end() );
        int x[5] = { 1, 2, 3, 4, 5 };
        int y[5];
        //int* p = copy_if( x, x+5, y, foo ); // copy_if가없다. 짜보자!!
        cout << s1 << endl;
}
// 4. partial_sum
void main()
{
        int x[10] = { 1, 2, 3, 4, 5, -6, 7, 8, 9, 10 };
        int y[10];
        // x, x+10 까지의_부분합을구해라.
        partial_sum( x, x+10, y );
        copy( y, y+10, ostream_iterator<int>(cout, " ") );
}