M.Hiroi's Home Page

Linux Programming

お気楽C++プログラミング超入門

[ PrevPage | C++ | NextPage ]

Yet Another C++ Problems (3)

●シーケンス (列) とは?

要素を一列に並べたデータ構造を「シーケンス (sequence)」とか「列」と呼びます。たとえば、Common Lisp はリスト、一次元配列 (ベクタ)、文字列を列型データとして統一して扱うことができます。列を操作する関数を列関数といい、Common Lisp には便利な列関数が多数用意されています。

C++の場合、vector, array, list, forward_list などのコンテナクラスは、シーケンスとして共通な操作を考えることができます。今回はシーケンスを操作する関数をテンプレートで作ってみましょう。

●問題21

シーケンスの中から最大値を求める関数 maximum と、最小値を求める関数 minimum を定義してください。引数は先頭と終端を示すイテレータで、返り値は求めた要素へのイテレータとします。

解答

●問題22

シーケンスを線形探索する関数 member, position, count を定義してください。member の返り値は bool、position の返り値は見つけた位置 (見つからない場合は -1)、count の返り値は見つけた要素の個数です。

解答

●問題23

引数の叙述関数が真を返すデータを線形探索する高階関数 member_if, position_if, count_if を定義してください。

解答

●問題24

シーケンスの要素に引数の関数オブジェクト func を適用して、その結果を新しいシーケンスに格納して返す高階関数 mapcar を定義してください。このような操作を「マッピング (写像)」といいます。

解答

●問題25

引数 x と等しい要素をシーケンスから削除する関数 remove と、叙述関数が真を返す要素をシーケンスから削除する関数 remove_if を定義してください。なお、どちらの関数も引数にはシーケンスのイテレータ (始点と終点) を受け取り、シーケンスを破壊的に修正することにします。返り値は最後に書き込んだ要素の次を示すイテレータです。

解答

●問題26

シーケンスの要素を先頭から畳み込む高階関数 fold_left と末尾から畳み込む fold_right を定義してください。

解答

●問題27

シーケンスの要素に叙述関数 p を適用し、一つでも真を返す要素があれば真を返す関数 any と、一つでも偽を返す要素があれば偽を返す (全てが真の場合に真を返す) 関数 every を定義してください。

解答

●問題28

シーケンスに整数 n から始まる数列をセットする関数 iota と、n から始まる数列の要素に関数 f を適用して、その結果をシーケンスにセットする高階関数 tabulate を定義してください。

解答

●問題29

引数 x と等しいシーケンスの要素を引数 y に置換する関数 substitute と、叙述関数が真を返す要素を引数 y に置換する関数 substitute_if を定義してください。なお、これらの関数は引数のシーケンスを破壊的に修正するものとします。

解答

●問題30

「連想リスト (association list : a-list)」は Lisp でよく用いられるデータ構造で、キーとデータの組を要素とする連結リストで実現することができます。

上図の場合、文字列 "a", "b", "c", "d" がキーで、整数 1, 2, 3, 4 がデータとなります。C++の場合、連想リストは list<pair<K, V>> で表すことができます。また、他のコンテナクラスを使っても簡単に実装することができます。

連想リストの先頭にキーと値を追加する関数 acons と、連想リストからキーを線形探索する関数 assoc を定義してください。

解答


●解答21

リスト : 最大値と最小値

template<class It>
It maximum(It first, It last)
{
  if (first == last) return last;
  It m = first++;
  while (first != last) {
    if (*m < *first) m = first;
    ++first;
  }
  return m;
}

template<class It>
It minimum(It first, It last)
{
  if (first == last) return last;
  It m = first++;
  while (first != last) {
    if (*m > *first) m = first;
    ++first;
  }
  return m;
}

どちらの関数も引数 first から last までの区間から最大値 (または最小値) を探します。これ以降、シーケンスの区間を [first, last) と記述することにします。first と last が等しい場合は last を返します。そして、先頭要素へのイテレータを変数 m にセットして、first を次の要素へ進めます。あとは、while ループで要素を順番にチェックしていき、*m よりも *frist が大きい (または小さい) 場合は m を first に書き換えます。最後に m を返すだけです。

なお、STL の algorithm には同等の機能を持つ関数 max_element と min_element が用意されています。

●解答22

探索する区間をイテレータ [first, last) で渡すことにすると、プログラムは次のようになります。

リスト : シーケンスの線形探索 (1)

template<class It, class T>
bool member(It first, It last, const T& val)
{
  while (first != last)
    if (*first++ == val) return true;
  return false;
}

template<class It, class T>
int position(It first, It last, const T& val)
{
  int i = 0;
  while (first != last) {
    if (*first++ == val) return i;
    i++;
  }
  return -1;
}

template<class It, class T>
int count(It first, It last, const T& val)
{
  int c = 0;
  while (first != last)
    if (*first++ == val) c++;
  return c;
}

テンプレート仮引数の It がイテレータ、T が探索するデータの型を表します。member は *first と val が等しければ true を返します。postion は位置 (添字) i を返します。count は *first と val が等しければ変数 c を +1 して、最後に c を返します。

シーケンス自身をそのまま渡すこともできます。次のリストを見てください。

リスト : シーケンスの線形探索 (2)

template<class T, class U>
bool member(const T& seq, const U& val)
{
  for (auto& x : seq)
    if (x == val) return true;
  return false;
}

template<class T, class U>
int position(const T& seq, const U& val)
{
  int i = 0;
  for (auto& x : seq) {
    if (x == val) return i;
    i++;
  }
  return -1;
}

template<class T, class U>
int count(const T& seq, const U& val)
{
  int c = 0;
  for (auto& x : seq)
    if (x == val) c++;
  return c;
}

T がシーケンスのデータ型を表す仮引数で、U が探索するデータの型です。シーケンスの要素は範囲 for 文で順番に取り出すことができます。データ型の指定も auto を使えば簡単です。関数型言語の場合、このような仕様が一般的ですが、C++ではイテレータを渡すのが普通のようです。

●解答23

リスト : 線形探索 (高階関数版)

template<class It, class F>
bool member_if(It first, It last, F func)
{
  while (first != last)
    if (func(*first++)) return true;
  return false;
}

template<class It, class F>
int position_if(It first, It last, F func)
{
  int i = 0;
  while (first != last) {
    if (func(*first++)) return i;
    i++;
  }
  return -1;
}

template<class It, class F>
int count_if(It first, It last, F func)
{
  int c = 0;
  while (first != last)
    if (func(*first++)) c++;
  return c;
}

It がイテレータを表す仮引数、F が関数オブジェクトを表す仮引数です。区間 [first, last) から叙述関数 func が真を返す要素を探索します。member_if は func(*first) が真ならば true を返します。positon_if は位置 (添字) i を返します。count_if は変数 c の値を +1 して、最後に c を返します。

シーケンス自身を渡す場合は次のようになります。

リスト : 線形探索 (高階関数版)

template<class T, class F>
bool member_if(const T& seq, F func)
{
  for (auto& x : seq)
    if (func(x)) return true;
  return false;
}

template<class T, class F>
int position_if(const T& seq, F func)
{
  int i = 0;
  for (auto& x : seq)
    if (func(x)) return i;
  return -1;
}

template<class T, class F>
int count_if(const T& seq, F func)
{
  int c = 0;
  for (auto& x : seq)
    if (func(x)) c++;
  return c;
}

func(x) が真を返すとき、member_if は true を返し、position_if は変数 i を返し、count_if は変数 c を +1 して、最後に c を返します。

●解答24

リスト : マッピング

template<class T, class F>
T mapcar(const T& seq, F func)
{
  T new_seq(seq.size());
  auto iter = new_seq.begin();
  for (auto& x : seq)
    *iter++ = func(x);
  return new_seq;
}

最初に、コンストラクタで大きさ seq.size() の新しいシーケンス new_seq を生成します。そして、新しいシーケンスの先頭要素を示すイテレータ iter を生成します。あとは範囲 for 文でシーケンス seq から要素 x を取り出し、*iter に func(x) の返り値をセットします。最後に new_seq を返します。

メンバ関数に push_back があるならば、空の新しいシーケンスを生成して、そこに push_back で追加していく方法もあります。ただし、forward_list には push_back がないので、今回はこのようなプログラムにしてみました。

シーケンスをイテレータで渡す場合は次のようになります。

リスト : マッピングの別解

template<class It, class F>
It mapcar(It first, It last, F func, It result)
{
  while (first != last)
    *result++ = func(*first++);
  return result;
}

引数 result は結果を格納するシーケンスへのイテレータです。この場合、mapcar を呼び出す前に出力先のシーケンスを生成しておいてください。

●解答25

リスト : 要素の削除

template<class It, class U>
It remove(It first, It last, const U& val)
{
  It result = first;
  while (first != last) {
    if (*first != val) *result++ = *first;
    ++first;
  }
  return result;
}

remove は区間 [first, last) の中から val と等しい要素を削除します。変数 result は書き込む位置を表すイテレータで、first に初期化します。あとは、*first と val が等しくなければ、*resulte に *first をセットするだけです。区間を上書きすることに注意してください。最後に result を返します。つまり、区間 [first, result) に要素を削除した結果がセットされます。

リスト : 要素の削除 (高階関数版)

template<class It, class F>
It remove_if(It first, It last, F func)
{
  It result = first;
  while (first != last) {
    if (!func(*first)) *result++ = *first;
    ++first;
  }
  return result;
}

remove_if は叙述関数 func が真を返す要素を削除します。処理は remove とほとんど同じです。なお、STL の algorithm には同等の機能を持つ関数 remove, remove_if が用意されています。

●解答26

リスト : 畳み込み

template<class T, class U, class F>
U fold_left(const T& seq, U init, F func)
{
  for (auto& x : seq) init = func(init, x);
  return init;
}

template<class T, class U, class F>
U fold_right(const T& seq, U init, F func)
{
  for (auto iter = seq.crbegin(); iter != seq.crend(); ++iter)
    init = func(*iter, init);
  return init;
}

テンプレート仮引数 T がシーケンスのデータ型、U が初期値のデータ型、F が 2 引数の関数オブジェクトを表します。fold_left は範囲 for 文を使えば簡単です。init の値を func(init, x) で書き換えていくだけです。fold_right は reverse イテレータを使います。なお、forward_list は reverse イテレータをサポートしていないので、fold_right を適用することはできません。

func の引数は fold_left と fold_right で逆になっていることに注意してください。なお、畳み込み fold_left と fold_right の仕様は、プログラミング言語によって異なります。関数型言語でも統一されているわけではありません。ご注意くださいませ。

イテレータを渡す場合は次のようになります。

リスト : 別解

template<class It, class T, class F>
T fold(It first, It last, T init, F func)
{
  while (first != last) init = func(init, *first++);
  return init;
}

とくに難しいところはないと思います。

●解答27

リスト : any と every

template<class It, class F>
bool any(It first, It last, F func)
{
  while (first != last)
    if (func(*first++)) return true;
  return false;
}

template<class It, class F>
bool every(It first, It last, F func)
{
  while (first != last)
    if (!func(*first++)) return false;
  return true;
}

どちらの関数もイテレータ [first, last) が表す区間の要素に関数オブジェクト func を適用し、any は真を返す要素がひとつでもあれば true を返します。every は偽を返す要素が一つでもあれば false を返します。C++の algorithm には同等の機能を持つ関数 any_of と all_of が用意されています。

シーケンス自身を渡す場合は次のようになります。

リスト : 別解

template<class T, class F>
bool any(const T& seq, F func)
{
  for (auto& x : seq)
    if (func(x)) return true;
  return false;
}

template<class T, class F>
bool every(const T& seq, F func)
{
  for (auto& x : seq)
    if (!func(x)) return false;
  return true;
}

範囲 for 文を使えば簡単にプログラムすることができます。

●解答28

リスト : iota と tabulate

template<class T>
void iota(T& seq, int n)
{
  for (auto& x : seq) x = n++;
}

template<class T, class F>
void tabulate(T& seq, int n, F func)
{
  for (auto& x : seq) x = func(n++);
}

iota は範囲 for 文で要素への参照 x に整数値 n をセットしていくだけです。tabulate は func(n++) をセットしていくだけです。なお、C++ (C++11) の STL numeric には同等の機能を持つ関数 iota が用意されています。

●解答29

シーケンスをイテレータ [first, last) で渡す場合は次のようになります。

リスト : シーケンスの置換

template<class It, class U>
void substitute(const U& x, const U& y, It first, It last)
{
  while (first != last) {
    if (*first == x) *first = y;
    first++;
  }
}

template<class It, class U, class F>
void substitute_if(F func, const U& y, It first, It last)
{
  while (first != last) {
    if (func(*first)) *first = y;
    first++;
  }
}

substitute は *frist と引数 x が等しいとき、*first に引数 y を代入します。substitute_if は func(*first) が真を返すとき、*first に y を代入します。

シーケンス自身を渡す場合は次のようになります。

リスト : 別解

template<class T, class U>
void substitute(const U& x, const U& y, T& seq)
{
  for (auto& z : seq) {
    if (z == x) z = y;
  }
}

template<class T, class U, class F>
void substitute_if(F func, const U& y, T& seq)
{
  for (auto& x : seq) {
    if (func(x)) x = y;
  }
}

どちらの関数も範囲 for 文を使うと簡単にプログラムすることができます。

●解答30

リスト : 連想リスト

template<class K, class V, class T>
void acons(const K& key, const V& val, T& seq)
{
  seq.emplace_front(key, val);
}

template<class K, class It>
It assoc(const K& key, It first, It last)
{
  while (first != last) {
    if (first->first == key) return first;
    ++first;
  }
  return first;
}

テンプレート仮引数の K がキーを、V が値を表します。acons は emplace_front を使うと簡単です。これで、シーケンスの先頭にキーと値の組を追加することができます。assoc はイテレータ [first, last) の中からキー key を探索し、見つけたらその組を指し示すイテレータを返します。見つからない場合は last を返します。


●プログラムリスト

//
// yacp3.cpp : Yet Another C++ Problems (3)
//
//             Copyright (C) 2015-2023 Makoto Hiroi
//
#include <iostream>
#include <vector>
#include <list>
using namespace std;

// Q21 最大値と最小値
template<class It>
It maximum(It first, It last)
{
  if (first == last) return last;
  It m = first++;
  while (first != last) {
    if (*m < *first) m = first;
    ++first;
  }
  return m;
}

template<class It>
It minimum(It first, It last)
{
  if (first == last) return last;
  It m = first++;
  while (first != last) {
    if (*m > *first) m = first;
    ++first;
  }
  return m;
}

// Q22
template<class T, class U>
bool member(const T& seq, const U& val)
{
  for (auto& x : seq)
    if (x == val) return true;
  return false;
}

template<class It, class T>
bool member(It first, It last, const T& val)
{
  while (first != last)
    if (*first++ == val) return true;
  return false;
}

template<class T, class U>
int position(const T& seq, const U& val)
{
  int i = 0;
  for (auto& x : seq) {
    if (x == val) return i;
    i++;
  }
  return -1;
}

template<class It, class T>
int position(It first, It last, const T& val)
{
  int i = 0;
  while (first != last) {
    if (*first++ == val) return i;
    i++;
  }
  return -1;
}

template<class T, class U>
int count(const T& seq, const U& val)
{
  int c = 0;
  for (auto& x : seq)
    if (x == val) c++;
  return c;
}

template<class It, class T>
int count(It first, It last, const T& val)
{
  int c = 0;
  while (first != last)
    if (*first++ == val) c++;
  return c;
}

// Q23
template<class T, class F>
bool member_if(const T& seq, F func)
{
  for (auto& x : seq)
    if (func(x)) return true;
  return false;
}

template<class It, class F>
bool member_if(It first, It last, F func)
{
  while (first != last)
    if (func(*first++)) return true;
  return false;
}

template<class T, class F>
int position_if(const T& seq, F func)
{
  int i = 0;
  for (auto& x : seq)
    if (func(x)) return i;
  return -1;
}

template<class It, class F>
int position_if(It first, It last, F func)
{
  int i = 0;
  while (first != last) {
    if (func(*first++)) return i;
    i++;
  }
  return -1;
}

template<class T, class F>
int count_if(const T& seq, F func)
{
  int c = 0;
  for (auto& x : seq)
    if (func(x)) c++;
  return c;
}

template<class It, class F>
int count_if(It first, It last, F func)
{
  int c = 0;
  while (first != last)
    if (func(*first++)) c++;
  return c;
}

// Q24
template<class T, class F>
T mapcar(const T& seq, F func)
{
  T new_seq(seq.size());
  auto iter = new_seq.begin();
  for (auto& x : seq)
    *iter++ = func(x);
  return new_seq;
}

template<class It, class F>
It mapcar(It first, It last, F func, It result)
{
  while (first != last)
    *result++ = func(*first++);
  return result;
}

// Q25
template<class It, class U>
It remove(It first, It last, const U& val)
{
  It result = first;
  while (first != last) {
    if (*first != val) *result++ = *first;
    ++first;
  }
  return result;
}

template<class It, class F>
It remove_if(It first, It last, F func)
{
  It result = first;
  while (first != last) {
    if (!func(*first)) *result++ = *first;
    ++first;
  }
  return result;
}

// Q26
template<class T, class U, class F>
U fold_left(const T& seq, U init, F func)
{
  for (auto& x : seq) init = func(init, x);
  return init;
}

template<class T, class U, class F>
U fold_right(const T& seq, U init, F func)
{
  for (auto iter = seq.crbegin(); iter != seq.crend(); ++iter)
    init = func(*iter, init);
  return init;
}

template<class It, class T, class F>
T fold(It first, It last, T init, F func)
{
  while (first != last) init = func(init, *first++);
  return init;
}

// Q27
template<class T, class F>
bool any(const T& seq, F func)
{
  for (auto& x : seq)
    if (func(x)) return true;
  return false;
}

template<class It, class F>
bool any(It first, It last, F func)
{
  while (first != last)
    if (func(*first++)) return true;
  return false;
}

template<class T, class F>
bool every(const T& seq, F func)
{
  for (auto& x : seq)
    if (!func(x)) return false;
  return true;
}

template<class It, class F>
bool every(It first, It last, F func)
{
  while (first != last)
    if (!func(*first++)) return false;
  return true;
}

// Q28
template<class T>
void iota(T& seq, int n)
{
  for (auto& x : seq) x = n++;
}

template<class T, class F>
void tabulate(T& seq, int n, F func)
{
  for (auto& x : seq) x = func(n++);
}

// Q29
template<class T, class U>
void substitute(const U& x, const U& y, T& seq)
{
  for (auto& z : seq) {
    if (z == x) z = y;
  }
}

template<class It, class U>
void substitute(const U& x, const U& y, It first, It last)
{
  while (first != last) {
    if (*first == x) *first = y;
    first++;
  }
}

template<class T, class U, class F>
void substitute_if(F func, const U& y, T& seq)
{
  for (auto& x : seq) {
    if (func(x)) x = y;
  }
}

template<class It, class U, class F>
void substitute_if(F func, const U& y, It first, It last)
{
  while (first != last) {
    if (func(*first)) *first = y;
    first++;
  }
}

// Q30 連想リスト (emplace_front が必要)
template<class K, class V, class T>
void acons(const K& key, const V& val, T& seq)
{
  seq.emplace_front(key, val);
}

template<class K, class It>
It assoc(const K& key, It first, It last)
{
  while (first != last) {
    if (first->first == key) return first;
    ++first;
  }
  return first;
}

template<class T>
void print_seq(const T& seq)
{
  for (auto& x : seq) cout << x << " ";
  cout << endl;
}

bool is_even(int x) { return x % 2 == 0; }
bool is_odd(int x) { return x % 2 != 0; }
int square(int x) { return x * x; }

int main()
{
  vector<int> a = {1, 3, 5, 7, 9};
  list<int> b = {2, 4, 6, 8, 10};
  cout << "-- maximum --\n";
  auto m1 = maximum(a.begin(), a.end());
  cout << *m1 << endl;
  auto m2 = maximum(b.begin(), b.end());
  cout << *m2 << endl;
  cout << "-- minimum --\n";
  auto m3 = minimum(a.begin(), a.end());
  cout << *m3 << endl;
  auto m4 = minimum(b.begin(), b.end());
  cout << *m4 << endl;
  cout << "-- member --\n";
  cout << member(a, 1) << endl;
  cout << member(a, 10) << endl;
  cout << member(b, 1) << endl;
  cout << member(b, 10) << endl;  
  cout << member(a.begin(), a.end(), 1) << endl;
  cout << member(a.begin(), a.end(), 10) << endl;
  cout << member(b.begin(), b.end(), 1) << endl;
  cout << member(b.begin(), b.end(), 10) << endl;
  cout << "-- position--\n";
  cout << position(a, 1) << endl;
  cout << position(a, 10) << endl;
  cout << position(b, 1) << endl;
  cout << position(b, 10) << endl;
  cout << position(a.begin(), a.end(), 1) << endl;
  cout << position(a.begin(), a.end(), 10) << endl;
  cout << position(b.begin(), b.end(), 1) << endl;
  cout << position(b.begin(), b.end(), 10) << endl;
  cout << "-- count --\n";
  cout << count(a, 1) << endl;
  cout << count(a, 10) << endl;
  cout << count(b, 1) << endl;
  cout << count(b, 10) << endl;
  cout << count(a.begin(), a.end(), 1) << endl;
  cout << count(a.begin(), a.end(), 10) << endl;
  cout << count(b.begin(), b.end(), 1) << endl;
  cout << count(b.begin(), b.end(), 10) << endl;

  cout << "-- member_if --\n";
  cout << member_if(a, is_even) << endl;
  cout << member_if(a, is_odd) << endl;
  cout << member_if(b, is_even) << endl;
  cout << member_if(b, is_odd) << endl;
  cout << member_if(a.begin(), a.end(), is_even) << endl;
  cout << member_if(a.begin(), a.end(), is_odd) << endl;
  cout << member_if(b.begin(), b.end(), is_even) << endl;
  cout << member_if(b.begin(), b.end(), is_odd) << endl;
  cout << "-- position_if --\n";
  cout << position_if(a, is_even) << endl;
  cout << position_if(a, is_odd) << endl;
  cout << position_if(b, is_even) << endl;
  cout << position_if(b, is_odd) << endl;
  cout << position_if(a.begin(), a.end(), is_even) << endl;
  cout << position_if(a.begin(), a.end(), is_odd) << endl;
  cout << position_if(b.begin(), b.end(), is_even) << endl;
  cout << position_if(b.begin(), b.end(), is_odd) << endl;
  cout << "-- count_if --\n";
  cout << count_if(a, is_even) << endl;
  cout << count_if(a, is_odd) << endl;
  cout << count_if(b, is_even) << endl;
  cout << count_if(b, is_odd) << endl;
  cout << count_if(a.begin(), a.end(), is_even) << endl;
  cout << count_if(a.begin(), a.end(), is_odd) << endl;
  cout << count_if(b.begin(), b.end(), is_even) << endl;
  cout << count_if(b.begin(), b.end(), is_odd) << endl;

  cout << "-- mapcar --\n";
  vector<int> c1 = mapcar(a, square);
  print_seq(c1);
  list<int> c2 = mapcar(b, square);
  print_seq(c2);
  vector<int> d1(a.size());
  mapcar(a.begin(), a.end(), square, d1.begin());
  print_seq(d1);
  list<int> d2(b.size());
  mapcar(b.begin(), b.end(), square, d2.begin());
  print_seq(d2);
  cout << "-- remove --\n";
  vector<int> e1 = {1, 2, 3, 4, 5, 6, 7, 8};
  auto iter1 = remove(e1.begin(), e1.end(), 5);
  for (auto iter = e1.begin(); iter != iter1; ++iter)
    cout << *iter << " ";
  cout << endl;
  auto iter2 = remove_if(e1.begin(), e1.end(), is_even);
  for (auto iter = e1.begin(); iter != iter2; ++iter)
    cout << *iter << " ";
  cout << endl;
  list<int> e2 = {1, 2, 3, 4, 5, 6, 7, 8};
  auto iter3 = remove(e2.begin(), e2.end(), 5);
  for (auto iter = e2.begin(); iter != iter3; ++iter)
    cout << *iter << " ";
  cout << endl;
  auto iter4 = remove_if(e2.begin(), e2.end(), is_even);
  for (auto iter = e2.begin(); iter != iter4; ++iter)
    cout << *iter << " ";
  cout << endl;
  cout << "-- fold --\n";
  cout << fold_left(a, 0, plus<int>()) << endl;
  cout << fold_right(a, 0, plus<int>()) << endl;
  cout << fold_left(b, 0, plus<int>()) << endl;
  cout << fold_right(b, 0, plus<int>()) << endl;
  cout << fold(a.begin(), a.end(), 0, plus<int>()) << endl;
  cout << fold(b.begin(), b.end(), 0, plus<int>()) << endl;

  cout << "-- any --\n";
  cout << any(a, is_even) << endl;
  cout << any(a, is_odd) << endl;
  cout << any(b, is_even) << endl;
  cout << any(b, is_odd) << endl;
  cout << any(a.begin(), a.end(), is_even) << endl;
  cout << any(a.begin(), a.end(), is_odd) << endl;
  cout << any(b.begin(), b.end(), is_even) << endl;
  cout << any(b.begin(), b.end(), is_odd) << endl;

  cout << "-- every --\n";
  cout << every(a, is_even) << endl;
  cout << every(a, is_odd) << endl;
  cout << every(b, is_even) << endl;
  cout << every(b, is_odd) << endl;
  cout << every(a.begin(), a.end(), is_even) << endl;
  cout << every(a.begin(), a.end(), is_odd) << endl;
  cout << every(b.begin(), b.end(), is_even) << endl;
  cout << every(b.begin(), b.end(), is_odd) << endl;
  
  cout << "-- iota  --\n";
  vector<int> h1(10);
  iota(h1, 1);
  for (int x : h1) cout << x << " ";
  cout << endl;
  list<int> h2(10);
  iota(h2, 11);
  for (int x : h2) cout << x << " ";
  cout << endl;
  cout << "-- tabulate --\n";
  vector<int> i1(10);
  tabulate(i1, 1, square);
  for (int x : i1) cout << x << " ";
  cout << endl;
  list<int> i2(10);
  tabulate(i2, 11, square);
  for (int x : i2) cout << x << " ";
  cout << endl;

  cout << "-- substitute --\n";
  vector<int> j1 = {1, 2, 3, 1, 2, 3, 1, 2, 3};
  substitute(2, 4, j1);
  for (int x : j1) cout << x << " ";
  cout << endl;
  substitute(1, 10, j1.begin(), j1.end());
  for (int x : j1) cout << x << " ";
  cout << endl;
  list<int> j2 = {1, 2, 3, 1, 2, 3, 1, 2, 3};
  substitute(2, 4, j2);
  for (int x : j2) cout << x << " ";
  cout << endl;
  substitute(1, 10, j2.begin(), j2.end());
  for (int x : j2) cout << x << " ";
  cout << endl;

  cout << "-- substitute_if --\n";
  vector<int> k1 = {1,2,3,4,5,6,7,8};
  substitute_if(is_even, 0, k1);
  for (int x : k1) cout << x << " ";
  cout << endl;
  substitute_if(is_odd, 1, k1.begin(), k1.end());
  for (int x : k1) cout << x << " ";
  cout << endl;
  list<int> k2 = {1,2,3,4,5,6,7,8};
  substitute_if(is_even, 0, k2);
  for (int x : k2) cout << x << " ";
  cout << endl;
  substitute_if(is_odd, 1, k2.begin(), k2.end());
  for (int x : k2) cout << x << " ";
  cout << endl;

  cout << "-- acons --\n";
  list<pair<string, int>> alist;
  acons("foo", 1, alist);
  acons("bar", 2, alist);
  acons("baz", 3, alist);
  for (auto& p : alist)
    cout << p.first << "," << p.second << " ";
  cout << endl;
  auto aiter1 = assoc("foo", alist.begin(), alist.end());
  if (aiter1 != alist.end())
    cout << aiter1->second << endl;
  else
    cout << "not found\n";
  auto aiter2 = assoc("oops", alist.begin(), alist.end());
  if (aiter2 != alist.end())
    cout << aiter2->second << endl;
  else
    cout << "not found\n";
  
}
$ clang++ yacp3.cpp
$ ./a.out 
-- maximum --
9
10
-- minimum --
1
2
-- member --
1
0
0
1
1
0
0
1
-- position--
0
-1
-1
4
0
-1
-1
4
-- count --
1
0
0
1
1
0
0
1
-- member_if --
0
1
1
0
0
1
1
0
-- position_if --
-1
0
0
-1
-1
0
0
-1
-- count_if --
0
5
5
0
0
5
5
0
-- mapcar --
1 9 25 49 81 
4 16 36 64 100 
1 9 25 49 81 
4 16 36 64 100 
-- remove --
1 2 3 4 6 7 8 
1 3 7 
1 2 3 4 6 7 8 
1 3 7 
-- fold --
25
25
30
30
25
30
-- any --
0
1
1
0
0
1
1
0
-- every --
0
1
1
0
0
1
1
0
-- iota  --
1 2 3 4 5 6 7 8 9 10 
11 12 13 14 15 16 17 18 19 20 
-- tabulate --
1 4 9 16 25 36 49 64 81 100 
121 144 169 196 225 256 289 324 361 400 
-- substitute --
1 4 3 1 4 3 1 4 3 
10 4 3 10 4 3 10 4 3 
1 4 3 1 4 3 1 4 3 
10 4 3 10 4 3 10 4 3 
-- substitute_if --
1 0 3 0 5 0 7 0 
1 0 1 0 1 0 1 0 
1 0 3 0 5 0 7 0 
1 0 1 0 1 0 1 0 
-- acons --
baz,3 bar,2 foo,1 
1
not found

初版 2015 年 10 月 11 日
改訂 2023 年 4 月 15 日

Copyright (C) 2015-2023 Makoto Hiroi
All rights reserved.

[ PrevPage | C++ | NextPage ]