Problem:
Score : 300 points

Problem Statement

N tiles are arranged in a row from left to right. The initial color of each tile is represented by a string S of length N.

The i-th tile from the left is painted black if the i-th character of S is 0, and painted white if that character is 1.

You want to repaint some of the tiles black or white, so that any two adjacent tiles have different colors.

At least how many tiles need to be repainted to satisfy the condition?

Constraints

1 \leq |S| \leq 10^5

S_i is 0 or 1.

Input

Input is given from Standard Input in the following format:

S

Output

Print the minimum number of tiles that need to be repainted to satisfy the condition.

Sample Input 1

000

Sample Output 1

1

The condition can be satisfied by repainting the middle tile white.

Sample Input 2

10010010

Sample Output 2

3

Sample Input 3

0

Sample Output 3

0

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <fstream> 
#include <array>
#define _USE_MATH_DEFINES
#include <math.h>
#include <unordered_set>
#include<unordered_map>
#include<stdio.h>

using namespace std;


inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v; }
template<class T> inline string toString(T x) { ostringstream sout; sout << x; return sout.str(); }


typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<long long int> vll;
typedef vector<vll> vvll;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef unsigned long long ull;

//repetition
//------------------------------------------
#define REP(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n)  REP(i,0,n)
#define rrep(i,n) for(int i=(n);i>=0;i--)
#define VEC_2D(a,b) vector<vector<int> >(a, vector<int>(b, 0))
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define pb push_back
#define mp make_pair
#define INF (1001000000)
#define SZ(a) int((a).size())
#define EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())
#define UNIQ(c) (c).erase(unique((c).begin(),(c).end()), (c).end());
#define MOD 1000000007LL
#define MS(v,n) memset((v),(n),sizeof(v))


//input
#define VEC(type, c, n) std::vector<type> c(n);for(auto& i:c)std::cin>>i;

//output
#define P(p) cout<<(p)<<endl;
#define FSP(a) cout << fixed << setprecision(a)

template<typename T> T gcd(T x, T y) {
	if (y == 0) return x;
	else return gcd(y, x%y);
}

template<typename T> T lcm(T a, T b) {
	return a / gcd(a, b) * b;
}

template<typename T> bool is_prime(T n) {
	for (int i = 2; i * i <= n; i++) {
		if (n % i == 0) return false;
	}
	return n != 1;
}

map<ll, ll> prime_factor(ll n) {
	map<ll, ll> res;
	for (int i = 2; i * i <= n; i++) {
		while (n % i == 0) {
			++res[i];
			n /= i;
		}
	}
	if (n != 1) res[n] = 1;
	return res;
}

int extgcd(int a, int b, int& x, int& y) {//
	int d = a;
	if (b != 0) {
		d = extgcd(b, a%b, y, x);
		y -= (a / b)*x;
	}
	else {
		x = 1; y = 0;
	}
	return d;
}



ll mod_pow(ll x, ll n, ll mod) {
	if (n == 0) return 1;
	ll res = mod_pow(x * x % mod, n / 2, mod);
	if (n & 1) res = res * x % mod;
	return res;
}

ll comb(ll a, ll b, ll mod) {
	ll mul = 1;
	ll div = 1;
	rep(i, b) {
		mul *= (a - (ll)i);
		mul %= mod;
		div *= ((ll)i + 1);
		div %= mod;
	}

	mul *= mod_pow(div, mod - 2,mod);
	return mul%mod;
}


vector<string> split(const string &str, char delim) {
	vector<string> res;
	size_t current = 0, found;
	while ((found = str.find_first_of(delim, current)) != string::npos) {
		res.push_back(string(str, current, found - current));
		current = found + 1;
	}
	res.push_back(string(str, current, str.size() - current));
	return res;
}

bool is_kadomatsu(int a, int b, int c) {
	if (a == b || a == c || b == c)return false;
	if (a > b && c > b) return true;
	if (a < b && c < b)return true;
	return false;
}


struct UF {
	int n;
	vi d;
	UF() {}
	UF(int n) :n(n), d(n, -1) {}
	int root(int v) {
		if (d[v] < 0) return v;
		return d[v] = root(d[v]);
	}
	bool same(int a, int b) {
		return root(a) == root(b);
	}
	bool unite(int x, int y) {
		x = root(x); y = root(y);
		if (x == y) return false;
		if (size(x) < size(y)) swap(x, y);
		d[x] += d[y];
		d[y] = x;
		return true;
	}
	int size(int v) { return -d[root(v)]; }
};

struct Fibonacci {

	vvll fib;
	Fibonacci() {
		fib.resize(2, vll(2));
		fib[0][0] = 1; fib[0][1] = 1;
		fib[1][0] = 1; fib[1][1] = 0;
	}

	vvll mul(vvll &A, vvll &B) {
		vvll C(2, vll(2));
		rep(i, 2) {
			rep(k, 2) {
				rep(j, 2) {
					C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % MOD;
				}
			}
		}
		return C;
	}

	ll pow(ll n) {
		vvll A = fib;
		vvll B(2, vll(2));
		rep(i, 2) {
			B[i][i] = 1;
		}
		while (n > 0) {
			if (n & 1)B = mul(B, A);
			A = mul(A, A);
			n >>= 1;
		}
		return B[1][0];
	}
	
};



vector<int> divisor(int n) {
	if (n == 1) return{};
	vi res;
	for (int i = 1; i*i <= n; i++) {
		if (n%i == 0) {
			res.emplace_back(i);
			if (i != 1 && i != n / i)res.emplace_back(n / i);
		}
	}
	return res;
}

struct Bellmanford {
	int n;
	struct edge {
		int from, to, cost;
	};
	vector<edge> E;
	vi d;
	Bellmanford(int n) :n(n), d(n) {
		E.resize(n);
	}
	void add_edge(int x, int y, int cost) {
		edge e;
		e.from = x; e.to = y; e.cost = cost;
		E.push_back(e);
	}
	void shortest_path(int s) {
		rep(i, n)d[i] = INF;
		d[s] = 0;
		while (true) {
			bool update = false;
			for (auto e : E) {
				if (d[e.from] != INF && d[e.to] > d[e.from] + e.cost) {
					d[e.to] = d[e.from] + e.cost;
					update = true;
				}
			}
			if (!update) break;
		}
	}
};
struct Dijkstra {
	int n;
	struct edge {
		int to; ll cost;
	};
	vector<vector<edge>> G;
	vll d;
	Dijkstra(int n) :n(n), d(n) {
		G.resize(n);
	}
	void add_edge(int x, int y, ll cost) {
		edge e;
		e.to = y; e.cost = cost;
		G[x].push_back(e);
	}
	void shortest_path(int s) {
		rep(i, n)d[i] = 100000000000000000;
		d[s] = 0;
		priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> que;
		que.push(make_pair(0, s));

		while (!que.empty()) {
			pii p = que.top(); que.pop();
			int v = p.second;
			if (d[v] < p.first) continue;
			for (auto e : G[v]) {
				if (d[e.to] > d[v] + e.cost) {
					d[e.to] = d[v] + e.cost;
					que.push(make_pair(d[e.to], e.to));
				}
			}
		}
	}
};

struct Segmenttree {
	int n;
	vector<int> dat;
	Segmenttree(int n_) {
		n = 1;
		while (n < n_) n *= 2;
		dat = vector<int>(2 * n - 1, 0);
	}

	void add(int idx, ll val) {//0-indexed
		idx += n - 1;
		dat[idx] += val;
		while (idx > 0) {
			idx = (idx - 1) / 2;
			dat[idx] += val;
		}
	}
	int query(int a, int b) {
		return query_seg(a, b, 0, 0, n);
	}
	int query_seg(int a, int b, int k, int l, int r) {
		if (r <= a || b <= l) return 0;
		if (a <= l && r <= b)return dat[k];
		else {
			return query_seg(a, b, k * 2 + 1, l, (l + r) / 2) + query_seg(a, b, k * 2 + 2, (l + r) / 2, r);
		}
	}
};

struct Trie {
	Trie *next[26];

	Trie() {
		fill(next, next + 26, (Trie *)0);
	}

	void insert(char *s) {
		if (*s == '\0') return;
		if (this->next[*s - 'a'] == NULL) {
			this->next[*s - 'a'] = new Trie();
		}
		this->next[*s - 'a']->insert(s + 1);
	}

	bool find(char *s) {
		if (*s == '\0') return true;
		if (this->next[*s - 'a'] == NULL) {
			return false;
		}
		return this->next[*s - 'a']->find(s + 1);
	}
};

struct BIT {
	int n;
	vi bit;
	BIT() {}
	BIT(int n):n(n) {
		bit.resize(n + 1);
	}
	int sum(int i) {
		int s = 0;
		while (i > 0) {
			s += bit[i];
			i -= i&-i;
		}
		return s;
	}

	void add(int i, int x) {
		while (i <= n) {
			bit[i] += x;
			i += i&-i;
		}
	}
};

/*
struct edge { int to, cap, rev; };

vector<edge> G[200005];
int level[200005];
int iter[200005];

void add_edge(int from, int to, int cap) {
	G[from].push_back({ to, cap, (int)G[to].size() });
	G[to].push_back({ from, 0, (int)G[from].size() - 1 });
}
void fbfs(int s) {
	memset(level, -1, sizeof(level));
	queue<int> que;
	level[s] = 0;
	que.push(s);
	while (!que.empty()) {
		int v = que.front(); que.pop();
		for (edge &e : G[v]) {
			if (e.cap > 0 && level[e.to] < 0) {
				level[e.to] = level[v] + 1;
				que.push(e.to);
			}
		}
	}
}
int fdfs(int v, int t, int f) {
	if (v == t) return f;
	for (edge &e : G[v]) {
		if (e.cap > 0 && level[v] < level[e.to]) {
			int d = fdfs(e.to, t, min(f, e.cap));
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s, int t) {
	int flow = 0;
	for (;;) {
		fbfs(s);
		if (level[t] < 0) return flow;
		memset(iter, 0, sizeof(iter));
		int f;
		while ((f = fdfs(s, t, INF)) > 0) {
			flow += f;
		}
	}
}
*/

//------------------------


int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	string s;
	cin >> s;
	int n = s.length();
	
	int ans1=0, ans2 = 0;
	
	rep(i, n) {//01010
		if (i % 2 == 0) {
			if (s[i] != '0')ans1++;
		}
		else {
			if (s[i] != '1')ans1++;
		}
	}
	rep(i, n) {//10101
		if (i % 2 == 0) {
			if (s[i] != '1')ans2++;
		}
		else {
			if (s[i] != '0')ans2++;
		}
	}
	P(min(ans1, ans2));
	return 0;

}