import { readFileSync } from 'fs'
function main() {
  const input = readFileSync('/dev/stdin', 'utf8')
  const [n, a, b, c] = input.trim().split('\n').map(v => v.trim().split(' ').map(string => parseInt(string)))
  console.log(n, a, b, c)
  let result = 0
  for (let i = 0; i < a.length; i++) {
    const number = a[i] - 1
    result += b[number]
    if (number !== a.length && i + 1 !== a.length && a[i] + 1 === a[i + 1]) {
      result += c[number]
    }
  }
  console.log(result)
}
main()


import { readFileSync } from 'fs'
function main() {
  const input = readFileSync('/dev/stdin', 'utf8')
  const [n, a, b, c] = input.trim().split('\n').map(v => v.split(' ').map(string => parseInt(string)))
  console.log(n, a, b, c)
  let result = 0
  for (let i = 0; i < a.length; i++) {
    const number = a[i] - 1
    result += b[number]
    if (number !== a.length && i + 1 !== a.length && a[i] + 1 === a[i + 1]) {
      result += c[number]
    }
  }
  console.log(result)
}
main()


S=input()
t=S[0::2].count('0')+S[1::2].count('1')
print(min(t,len(S)-t))


s = input()
c = s[::2].count("0") + s[1::2].count("1")
print(min(c, len(s)-c))


s = input()
h = s[::2].count('1') + s[1::2].count('0')
print(min(h, len(s)-h))


from collections import Counter
moji = str(input())
guall = len(moji)//2
kiall = guall + len(moji) % 2
gucount=dict(Counter(moji[1::2]))
kicount=dict(Counter(moji[0::2]))
if max(gucount, key=gucount.get) != max(kicount, key=kicount.get):
    ans = guall - max(gucount.values()) + kiall - max(kicount.values())
else:
    if kiall - max(kicount.values()) > guall - max(gucount.values()):
        ans = max(kicount.values()) + guall - max(gucount.values())
    else:
        ans = max(gucount.values()) + kiall - max(kicount.values())
print(ans)


s=input()
s=list(s)
c=0
for i in range(0,len(s)-1,2):
    if s[i]=='0':
        c+=1
    if s[i+1]=='1':
        c+=1
print(min(c,len(s)-c))


S = list(input())
ans = len(S)
for i in range(2):
  cnt = 0
  for j in range(ans):
    if j % 2 == 0 and S[j] != str(i): cnt += 1
    if j % 2 == 1 and S[j] == str(i): cnt += 1
  ans = min(ans,cnt)
print(ans)


import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import static java.lang.Math.*;

public class Main {

	public static void main(String[] args) throws Exception {

		byte c;
		int x = 0, y = 0;
		boolean b = true;
		while ( (c = in.read()) != '\n' ) {
			if ( b && c == '1' || !b && c == '0' )
				x++;
			else
				y++;
			b = !b;
		}

		out.println(min(x, y));

	}

	static PrintStream out = System.out;
	static FastReader in = new FastReader();
}

class FastReader {
	final private int BUF_SIZE = 1 << 16;
	private DataInputStream din;
	private byte[] buffer = new byte[BUF_SIZE];
	private int bufferPointer, bytesRead;

	FastReader() {
		din = new DataInputStream(System.in);
	}

	String s() throws IOException {
		byte[] buf = new byte[64];
		int cnt = 0, c;
		while ((c = read()) != -1) {
			if (c == '\n') break;
			buf[cnt++] = (byte) c;
		}
		return new String(buf, 0, cnt);
	}

	int i() throws IOException {
		int ret = 0;
		byte c = read();
		while (c <= ' ') c = read();
		boolean neg = (c == '-');
		if (neg) c = read();
		do {
			ret = ret * 10 + c - '0';
		}
		while ((c = read()) >= '0' && c <= '9');
		return neg ? -ret : ret;
	}

	long l() throws IOException {
		long ret = 0;
		byte c = read();
		while (c <= ' ') c = read();
		boolean neg = (c == '-');
		if (neg) c = read();
		do {
			ret = ret * 10 + c - '0';
		}
		while ((c = read()) >= '0' && c <= '9');
		return neg ? -ret : ret;
	}

	double d() throws IOException {
		double ret = 0, div = 1;
		byte c = read();
		while (c <= ' ') c = read();
		boolean neg = (c == '-');
		if (neg) c = read();
		do {
			ret = ret * 10 + c - '0';
		}
		while ((c = read()) >= '0' && c <= '9');
		if (c == '.')
			while ((c = read()) >= '0' && c <= '9')
				ret += (c - '0') / (div *= 10);
		return neg ? -ret : ret;
	}

	private void fillBuffer() throws IOException {
		bytesRead = din.read(buffer, bufferPointer = 0, BUF_SIZE);
		if (bytesRead == -1) buffer[0] = -1;
	}

/*	private */ byte read() throws IOException {
		if (bufferPointer == bytesRead) fillBuffer();
		return buffer[bufferPointer++];
	}

	void close() throws IOException {
		if (din != null) din.close();
	}
}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.NoSuchElementException;

public class Main {
	private static void solve() {
		char[] cs = nes().toCharArray();
		int n = cs.length;
		char[] t = { '0', '1' };
		int n1 = 0;
		int n2 = 0;
		for (int i = 0; i < n; i++) {
			if (cs[i] == t[i % 2])
				n1++;
			else
				n2++;
		}
		out(min(n1, n2));
	}

	// returns (x, y, d) s.t. ax + by = d
	static long[] exgcd(long a, long b) {
		int sa = a < 0 ? -1 : 1;
		int sb = b < 0 ? -1 : 1;
		a *= sa;
		b *= sb;
		long x = 1;
		long y = 0;
		long z = 0;
		long w = 1;
		while (b > 0) {
			long q = a / b;
			long t = z;
			z = x - q * z;
			x = t;
			t = w;
			w = y - q * w;
			y = t;
			t = b;
			b = a - q * b;
			a = t;
		}
		return new long[] { x * sa, y * sb, a };
	}

	static int[] lis(int[] s) {
		int n = s.length;
		int[] dp = new int[n];
		int[] ids = new int[n];
		int[] pids = new int[n];
		dp[0] = s[0];
		int len = 1;
		int lidx = 0;
		for (int i = 1; i < n; i++) {
			int idx = bs(s[i], dp, 0, len);
			dp[idx] = s[i];
			ids[idx] = i;
			if (idx == len) {
				lidx = i;
				len++;
			}
			if (idx > 0)
				pids[i] = ids[idx - 1];
		}
		int[] lis = new int[len];
		lis[len - 1] = s[lidx];
		for (int i = len - 1; i >= 0; i--) {
			lis[i] = s[lidx];
			lidx = pids[lidx];
		}
		return lis;
	}

	static int bs(int a, int[] as, int from, int num) {
		int min = from;
		int max = from + num - 1;
		while (min < max) {
			int mid = min + max >> 1;
			if (as[mid] < a)
				min = mid + 1;
			else if (as[mid] > a)
				max = mid;
			else
				return mid;
		}
		return as[min] < a ? min + 1 : min;
	}

	static int gcd(int x, int y) {
		x = (x ^ x >> 31) - (x >> 31);
		y = (y ^ y >> 31) - (y >> 31);
		if (x < y) {
			x ^= y;
			y ^= x;
			x ^= y;
		}
		int z = x % y;
		if (z == 0)
			return y;
		return gcd(y, z);
	}

	static long gcd(long x, long y) {
		x = (x ^ x >> 63) - (x >> 63);
		y = (y ^ y >> 63) - (y >> 63);
		if (x < y) {
			x ^= y;
			y ^= x;
			x ^= y;
		}
		long z = x % y;
		if (z == 0)
			return y;
		return gcd(y, z);
	}

	static long modinv(long a, long mod) {
		return modpow(a, mod - 2, mod);
	}

	static long modpow(long a, long b, long mod) {
		if (b == 0)
			return 1;
		if ((b & 1) == 0) {
			long sqrt = modpow(a, b >> 1, mod);
			return sqrt * sqrt % mod;
		}
		return a * modpow(a, b - 1, mod) % mod;
	}

	static long fact(long n) {
		if (n <= 1)
			return 1;
		long res = 2;
		for (long i = 3; i <= n; i++) {
			res *= i;
		}
		return res;
	}

	static long modfact(long n, long mod) {
		if (n <= 1)
			return 1 % mod;
		long res = 2;
		for (long i = 3; i <= n; i++) {
			res *= i;
			res %= mod;
		}
		return res % mod;
	}

	// returns facts([0]) and invfacts([1])
	static long[][] enumfacts(int n, long mod) {
		int num = n + 10;
		long[][] res = new long[2][num];
		long[] facts = res[0];
		long[] invfacts = res[1];
		for (int i = 0; i < num; i++) {
			if (i <= 1) {
				facts[i] = 1;
				invfacts[i] = 1;
			} else {
				facts[i] = facts[i - 1] * i % mod;
				invfacts[i] = modinv(facts[i], mod);
			}
		}
		return res;
	}

	static long modcomb(long n, long m, long mod) {
		if (m > n)
			return 0;
		if (m > n - m) {
			m = n - m;
		}
		long numer = 1;
		for (int i = 0; i < m; i++) {
			numer = numer * (n - i) % mod;
		}
		long denom = modfact(m, mod);
		return numer * modinv(denom, mod) % mod;
	}

	static long modcomb(int n, int m, long[] facts, long[] invfacts, long mod) {
		if (m > n)
			return 0;
		long numer = facts[n];
		long denom = invfacts[m] * invfacts[n - m] % mod;
		return numer * denom % mod;
	}

	// res[i][0]: prime factor, res[i][1]: exponent
	static int[][] factorize(int n) {
		int[][] pfs = new int[32][2];
		int num = 0;
		for (int i = 2; i * i <= n; i++) {
			int count = 0;
			while (n % i == 0) {
				n /= i;
				count++;
			}
			if (count > 0) {
				pfs[num][0] = i;
				pfs[num][1] = count;
				num++;
			}
		}
		if (n > 1) {
			pfs[num][0] = n;
			pfs[num][1] = 1;
			num++;
		}
		int[][] res = new int[num][2];
		for (int i = 0; i < num; i++) {
			res[i][0] = pfs[i][0];
			res[i][1] = pfs[i][1];
		}
		return res;
	}

	static long lcm(long x, long y) {
		x = (x ^ x >> 63) - (x >> 63);
		y = (y ^ y >> 63) - (y >> 63);
		return x / gcd(x, y) * y;
	}

	static int abs(int x) {
		return x < 0 ? -x : x;
	}

	static long abs(long x) {
		return x < 0 ? -x : x;
	}

	static int min(int a, int b) {
		return a < b ? a : b;
	}

	static long min(long a, long b) {
		return a < b ? a : b;
	}

	static int max(int a, int b) {
		return a > b ? a : b;
	}

	static long max(long a, long b) {
		return a > b ? a : b;
	}

	static int clamp(int a, int min, int max) {
		return a < min ? min : a > max ? max : a;
	}

	static long clamp(long a, long min, long max) {
		return a < min ? min : a > max ? max : a;
	}

	static double clamp(double a, double min, double max) {
		return a < min ? min : a > max ? max : a;
	}

	static void out(String val) {
		IO.out(val);
	}

	static void out(Object val) {
		IO.out(String.valueOf(val));
	}

	static void out(int val) {
		IO.out(String.valueOf(val));
	}

	static void out(long val) {
		IO.out(String.valueOf(val));
	}

	static void out(char val) {
		IO.out(String.valueOf(val));
	}

	static void out(double val) {
		IO.out(Double.isFinite(val) ? BigDecimal.valueOf(val).toPlainString() : String.valueOf(val));
	}

	static void out(boolean val) {
		IO.out(val ? "true" : "false");
	}

	static void kil(String val) {
		IO.out(val);
		IO.flush();
		System.exit(0);
	}

	static void kil(Object val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(int val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(long val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(char val) {
		IO.out(String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(double val) {
		IO.out(Double.isFinite(val) ? BigDecimal.valueOf(val).toPlainString() : String.valueOf(val));
		IO.flush();
		System.exit(0);
	}

	static void kil(boolean val) {
		IO.out(val ? "true" : "false");
		IO.flush();
		System.exit(0);
	}

	static String nes() {
		return IO.next();
	}

	static int nei() {
		return IO.nextInt();
	}

	static long nel() {
		return IO.nextLong();
	}

	static double ned() {
		return IO.nextDouble();
	}

	static char nec() {
		return IO.nextChar();
	}

	static String[] nss(int n) {
		String[] as = new String[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.next();
		}
		return as;
	}

	static int[] nis(int n) {
		int[] as = new int[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextInt();
		}
		return as;
	}

	static long[] nls(int n) {
		long[] as = new long[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextLong();
		}
		return as;
	}

	static double[] nds(int n) {
		double[] as = new double[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextDouble();
		}
		return as;
	}

	static char[] ncs(int n) {
		char[] as = new char[n];
		for (int i = 0; i < n; i++) {
			as[i] = IO.nextChar();
		}
		return as;
	}

	static String[][] nss2(int n, int m) {
		String[][] as = new String[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.next();
			}
		}
		return as;
	}

	static int[][] nis2(int n, int m) {
		int[][] as = new int[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextInt();
			}
		}
		return as;
	}

	static long[][] nls2(int n, int m) {
		long[][] as = new long[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextLong();
			}
		}
		return as;
	}

	static double[][] nds2(int n, int m) {
		double[][] as = new double[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextDouble();
			}
		}
		return as;
	}

	static char[][] ncs2(int n, int m) {
		char[][] as = new char[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				as[i][j] = IO.nextChar();
			}
		}
		return as;
	}

	static int parseInt(String val) {
		return Integer.parseInt(val);
	}

	static int parseInt(char val) {
		return Integer.parseInt(String.valueOf(val));
	}

	static long parseLong(String val) {
		return Long.parseLong(val);
	}

	public static void main(String[] args) {
		try {
			solve();
			IO.flush();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}
}

final class IO {
	private static final InputStream in = System.in;
	private static final PrintWriter out = new PrintWriter(System.out, false);
	private static final byte[] buffer = new byte[1024];
	private static int ptr = 0;
	private static int len = 0;

	private static boolean hasNextByte() {
		if (ptr < len)
			return true;
		ptr = 0;
		try {
			len = in.read(buffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return len > 0;
	}

	private static int readByte() {
		if (hasNextByte())
			return buffer[ptr++];
		else
			return -1;
	}

	static boolean hasNext() {
		byte c;
		while (hasNextByte() && ((c = buffer[ptr]) < '!' || c > '~'))
			ptr++;
		return hasNextByte();
	}

	static String next() {
		if (!hasNext())
			throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		int b = readByte();
		while (b >= '!' && b <= '~') {
			sb.append((char) b);
			b = readByte();
		}
		return sb.toString();
	}

	static char nextChar() {
		if (!hasNext())
			throw new NoSuchElementException();
		return (char) readByte();
	}

	static long nextLong() {
		if (!hasNext())
			throw new NoSuchElementException();
		long n = 0;
		int sign = 1;
		int b = readByte();
		if (b == '-') {
			sign = -1;
			b = readByte();
		}
		if (b < '0' || '9' < b)
			throw new NumberFormatException();
		while (true) {
			if ('0' <= b && b <= '9')
				n = n * 10 + b - '0';
			else if (b == -1 || b < '!' || b > '~')
				return n * sign;
			else
				throw new NumberFormatException();
			b = readByte();
		}
	}

	static int nextInt() {
		if (!hasNext())
			throw new NoSuchElementException();
		int n = 0;
		int sign = 1;
		int b = readByte();
		if (b == '-') {
			sign = -1;
			b = readByte();
		}
		if (b < '0' || '9' < b)
			throw new NumberFormatException();
		while (true) {
			if ('0' <= b && b <= '9')
				n = n * 10 + b - '0';
			else if (b == -1 || b < '!' || b > '~')
				return n * sign;
			else
				throw new NumberFormatException();
			b = readByte();
		}
	}

	static double nextDouble() {
		return Double.parseDouble(next());
	}

	static void out(String val) {
		out.println(val);
	}

	static void flush() {
		out.flush();
	}
}


import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class Main {
    static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader()
        {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException
        {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException
        {
            byte[] buf = new byte[100000]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1)
            {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException
        {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do
            {
                ret = ret * 10 + c - '0';
            }  while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        public long nextLong() throws IOException
        {
            long ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');
            if (neg)
                return -ret;
            return ret;
        }

        public double nextDouble() throws IOException
        {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();

            do {
                ret = ret * 10 + c - '0';
            }
            while ((c = read()) >= '0' && c <= '9');

            if (c == '.')
            {
                while ((c = read()) >= '0' && c <= '9')
                {
                    ret += (c - '0') / (div *= 10);
                }
            }

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

        private byte read() throws IOException
        {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException
        {
            if (din == null)
                return;
            din.close();
        }
    }
    public static void main(String args[]) throws IOException{
        Reader in = new Reader();
        String s = in.readLine();
        int zSMC = 0, oSMC = 0;
        for (int i = 0; i < s.length(); i++){
            if (i % 2 == 0){
                if ('0' == s.charAt(i))
                    zSMC++;
                else
                    oSMC++;
            }
            else {
                if ('1' == s.charAt(i))
                    zSMC++;
                else
                    oSMC++;
            }
        }
        System.out.println(Math.min(zSMC, oSMC));
    }
}


import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		int ans0 = 0;
		int ans1 = 0;
		for (int i = 0; i < s.length(); i++) {
			int target = s.charAt(i)-'0';
			if ((target & 1)==0) {
				ans0++;
			}else {
				ans1++;
			}
		}
		System.out.println(Math.min(ans0, ans1));
	}

}


import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.*;

public class Main {

    public static void main(String[] args) {
        FastScanner sc = new FastScanner();
        String s = sc.next();
        int[] d = new int[s.length()];
        d[0]=s.charAt(0);
        int ans = 0;
        for (int i=1;i<s.length();i++){
            d[i]=s.charAt(i)-'0';
            if (d[i-1]==d[i]){
                ans++;
                d[i]=(d[i]+1)%2;
            }
        }
        System.out.println(Math.min(ans,s.length()-ans-1));
    }
    public static class FastScanner {
        private final InputStream in = System.in;
        private final byte[] buffer = new byte[1024];
        private int ptr = 0;
        private int buflen = 0;
        private boolean hasNextByte() {
            if (ptr < buflen) {
                return true;
            }else{
                ptr = 0;
                try {
                    buflen = in.read(buffer);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (buflen <= 0) {
                    return false;
                }
            }
            return true;
        }
        private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
        private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
        public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
        public String next() {
            if (!hasNext()) throw new NoSuchElementException();
            StringBuilder sb = new StringBuilder();
            int b = readByte();
            while(isPrintableChar(b)) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }
        public long nextLong() {
            if (!hasNext()) throw new NoSuchElementException();
            long n = 0;
            boolean minus = false;
            int b = readByte();
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            if (b < '0' || '9' < b) {
                throw new NumberFormatException();
            }
            while(true){
                if ('0' <= b && b <= '9') {
                    n *= 10;
                    n += b - '0';
                }else if(b == -1 || !isPrintableChar(b)){
                    return minus ? -n : n;
                }else{
                    throw new NumberFormatException();
                }
                b = readByte();
            }
        }
        public int nextInt() {
            long nl = nextLong();
            if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
            return (int) nl;
        }
        public double nextDouble() { return Double.parseDouble(next());}
    }
    public static class BasicMath {
        private final int MAX = 510000;
        private final int MOD = 1000000007;
        private final long[] fac = new long[MAX];
        private final long[] finv= new long[MAX];
        private final long[] inv = new long[MAX];
        public long factorial(long num){
            if (num<2)return 1;
            else return num*factorial(num-1);
        }
        public int arraySum(int[] array){
            int ans = 0;
            for (int value : array) ans += value;
            return ans;
        }
        public double log(double base,double antilogarithm){
            return Math.log(antilogarithm)/Math.log(base);
        }
        public int gcd(int x,int y){
            if (y==0)return x;
            else return gcd(y,x%y);
        }
        public int lcm(int x,int y){
            return x/gcd(x,y)*y;
        }
        public HashMap<Long,Long> factorization(long num){
            HashMap<Long,Long> hash = new HashMap<>();
            long n = num;
            long count = 2;
            while (n>1){
                while (n%count==0){
                    n/=count;
                    if (hash.containsKey(count))hash.put(count,hash.get(count)+1);
                    else hash.put(count,1L);
                }
                count++;
            }
            return hash;
        }
        public int sum(int[] num){
            int ans = 0;
            for (int i = 0; i < num.length;i++){
                ans += num[i];
            }
            return ans;
        }
        public int[] reduce(int small, int big){
            int ins = 2;
            while (ins<=small){
                if (small%ins==0&&big%ins==0){
                    small/=ins;
                    big/=ins;
                    ins = 2;
                }else {
                    ins++;
                }
            }
            return new int[]{small, big};
        }
        public int reduceCount(int small, int big){
            int ins = 2;
            int ans = 0;
            while (ins<=small){
                if (small%ins==0&&big%ins==0){
                    small/=ins;
                    big/=ins;
                    ins = 2;
                    ans++;
                }else {
                    ins++;
                }
            }
            return ans;
        }
        public int binarySearch(int[] array, int target){
            int pos = -1;
            int left = 0;
            int right = array.length-1;
            int middle;
            while (pos==-1&&left<=right){
                middle = (left+right)/2;
                if (array[middle]==target)pos=middle;
                else if (array[middle]>target)right=middle-1;
                else left=middle+1;
            }
            return pos;
        }
        public long modPow(long a, long n, long mod){
            long res = 1;
            while (n>0){
                if ((n&1)!=0)res = res*a%mod;
                a=a*a%mod;
                n >>= 1;
            }
            return res;
        }
        public long modinv(long a, long mod){return modPow(a,mod-2,mod);}
        public void COMinit(){
            fac[0]=1;
            fac[1]=1;
            finv[0]=1;
            finv[1]=1;
            inv[1]=1;
            for (int i=2;i<MAX;i++){
                fac[i]=fac[i-1]*i%MOD;
                inv[i]=MOD-inv[MOD%i]*(MOD/i)%MOD;
                finv[i]=finv[i-1]*inv[i]%MOD;
            }
        }
        public long COM(int n, int k){
            if (n<k)return 0;
            if (n<0||k<0)return 0;
            return fac[n]*(finv[k]*finv[n-k]%MOD)%MOD;
        }
        public long HCOM(int n, int k){
            return COM(n+k-1,k);
        }
    }
    public static class Queue<T>{
        private final int max = 1000000;
        private final T[] queue = (T[]) new Object[max];
        private int tail = 0; private int head = 0;
        public void init(){this.head = 0; tail = 0;}
        public boolean isEmpty(){return (head==tail);}
        public boolean isFull(){return (head == (tail+1)%max);}
        public void enqueue(T v){
            if (isFull()){
                System.out.println("error: queue is full.");
                return;
            }
            queue[tail++] = v;
            if (tail == max) tail = 0;
        }
        public T dequeue(){
            if (isEmpty()){
                System.out.println("error: queue is empty");
                return null;
            }
            T res = queue[head];
            ++head;
            if (head == max) head = 0;
            return res;
        }
    }
    public static class Stack<T>{
        private final int max = 100000;
        private final T[] stack =(T[]) new Object[max];
        private int top = 0;
        public boolean isEmpty(){return (top==0);}
        public boolean isFull(){return (top==max);}
        public void init(){top=0;}
        public void push(T v){
            if (isFull()){
                System.out.println("error: stack is full.");
                return;
            }
            stack[top++] = v;
        }
        public T pop(){
            if (isEmpty()){
                System.out.println("error: stack is empty");
                return null;
            }
            return stack[--top];
        }
    }
    public static class Pair<T>{
        private T A;
        private T B;
        Pair(T a,T b){
            A=a;
            B=b;
        }
        public void changeA(T a){A=a;}
        public void changeB(T b){B=b;}
        public void changeAB(T a,T b){A=a;B=b;}
        public static Comparator numberSortWithA = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Pair p = (Pair)o1;
                Pair q = (Pair)o2;
                if ((Long)p.A<(Long)q.A)return -1;
                else if ((long)p.A==(long)q.A)return 0;
                else return 1;
            }
        };
        public static Comparator numberSortWithB = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Pair p = (Pair)o1;
                Pair q = (Pair)o2;
                if ((long)p.B<(long)q.B)return -1;
                else if ((long)p.B==(long)q.B)return 0;
                else return 1;
            }
        };
    }
    public static class Graph<T>{
        private final HashMap<T,HashSet<T>> graph = (HashMap<T,HashSet<T>>) new Object();
        private T[] nodeList;
        private HashMap<T,Integer> dictionary = new HashMap<>();
        private int Size;
        private int[] Depth;
        Graph(T[] nodes){
            for (T t : nodes)graph.put(t,new HashSet<>());
            Size = nodes.length;
            nodeList = nodes.clone();
            for (int i=0;i<Size;i++)dictionary.put(nodeList[i],i);
        }
        public void addEdge(T node1,T node2){
            if (graph.containsKey(node1)&&graph.containsKey(node2)){
                graph.get(node1).add(node2);
                graph.get(node2).add(node1);
            }
        }
        public int[] Depth(T root){
            Queue<T> q = new Queue<>();
            q.enqueue(root);
            boolean[] seen = new boolean[Size];
            Arrays.fill(seen, false);
            seen[dictionary.get(root)]=true;
            int[] depth = new int[Size];
            depth[dictionary.get(root)]=0;
            while (!q.isEmpty()){
                T v = q.dequeue();
                int vNum = dictionary.get(v);
                for (T u : graph.get(v)){
                    if (!seen[dictionary.get(u)]){
                        int uNum = dictionary.get(u);
                        seen[uNum]=true;
                        q.enqueue(u);
                        depth[uNum]=depth[vNum]+1;
                    }
                }
            }
            Depth = depth.clone();
            return depth;
        }
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.*;

public class Main {

    public static void main(String[] args) {
        FastScanner sc = new FastScanner();
        String s = sc.next();
        int[] d = new int[s.length()];
        d[0]=s.charAt(0);
        int ans = 0;
        for (int i=1;i<s.length();i++){
            d[i]=s.charAt(i)-'0';
            if (d[i-1]==d[i]){
                ans++;
                d[i]=(d[i]+1)%2;
            }
        }
        System.out.println(Math.min(ans,s.length()-ans));
    }
    public static class FastScanner {
        private final InputStream in = System.in;
        private final byte[] buffer = new byte[1024];
        private int ptr = 0;
        private int buflen = 0;
        private boolean hasNextByte() {
            if (ptr < buflen) {
                return true;
            }else{
                ptr = 0;
                try {
                    buflen = in.read(buffer);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (buflen <= 0) {
                    return false;
                }
            }
            return true;
        }
        private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
        private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
        public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
        public String next() {
            if (!hasNext()) throw new NoSuchElementException();
            StringBuilder sb = new StringBuilder();
            int b = readByte();
            while(isPrintableChar(b)) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }
        public long nextLong() {
            if (!hasNext()) throw new NoSuchElementException();
            long n = 0;
            boolean minus = false;
            int b = readByte();
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            if (b < '0' || '9' < b) {
                throw new NumberFormatException();
            }
            while(true){
                if ('0' <= b && b <= '9') {
                    n *= 10;
                    n += b - '0';
                }else if(b == -1 || !isPrintableChar(b)){
                    return minus ? -n : n;
                }else{
                    throw new NumberFormatException();
                }
                b = readByte();
            }
        }
        public int nextInt() {
            long nl = nextLong();
            if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
            return (int) nl;
        }
        public double nextDouble() { return Double.parseDouble(next());}
    }
    public static class BasicMath {
        private final int MAX = 510000;
        private final int MOD = 1000000007;
        private final long[] fac = new long[MAX];
        private final long[] finv= new long[MAX];
        private final long[] inv = new long[MAX];
        public long factorial(long num){
            if (num<2)return 1;
            else return num*factorial(num-1);
        }
        public int arraySum(int[] array){
            int ans = 0;
            for (int value : array) ans += value;
            return ans;
        }
        public double log(double base,double antilogarithm){
            return Math.log(antilogarithm)/Math.log(base);
        }
        public int gcd(int x,int y){
            if (y==0)return x;
            else return gcd(y,x%y);
        }
        public int lcm(int x,int y){
            return x/gcd(x,y)*y;
        }
        public HashMap<Long,Long> factorization(long num){
            HashMap<Long,Long> hash = new HashMap<>();
            long n = num;
            long count = 2;
            while (n>1){
                while (n%count==0){
                    n/=count;
                    if (hash.containsKey(count))hash.put(count,hash.get(count)+1);
                    else hash.put(count,1L);
                }
                count++;
            }
            return hash;
        }
        public int sum(int[] num){
            int ans = 0;
            for (int i = 0; i < num.length;i++){
                ans += num[i];
            }
            return ans;
        }
        public int[] reduce(int small, int big){
            int ins = 2;
            while (ins<=small){
                if (small%ins==0&&big%ins==0){
                    small/=ins;
                    big/=ins;
                    ins = 2;
                }else {
                    ins++;
                }
            }
            return new int[]{small, big};
        }
        public int reduceCount(int small, int big){
            int ins = 2;
            int ans = 0;
            while (ins<=small){
                if (small%ins==0&&big%ins==0){
                    small/=ins;
                    big/=ins;
                    ins = 2;
                    ans++;
                }else {
                    ins++;
                }
            }
            return ans;
        }
        public int binarySearch(int[] array, int target){
            int pos = -1;
            int left = 0;
            int right = array.length-1;
            int middle;
            while (pos==-1&&left<=right){
                middle = (left+right)/2;
                if (array[middle]==target)pos=middle;
                else if (array[middle]>target)right=middle-1;
                else left=middle+1;
            }
            return pos;
        }
        public long modPow(long a, long n, long mod){
            long res = 1;
            while (n>0){
                if ((n&1)!=0)res = res*a%mod;
                a=a*a%mod;
                n >>= 1;
            }
            return res;
        }
        public long modinv(long a, long mod){return modPow(a,mod-2,mod);}
        public void COMinit(){
            fac[0]=1;
            fac[1]=1;
            finv[0]=1;
            finv[1]=1;
            inv[1]=1;
            for (int i=2;i<MAX;i++){
                fac[i]=fac[i-1]*i%MOD;
                inv[i]=MOD-inv[MOD%i]*(MOD/i)%MOD;
                finv[i]=finv[i-1]*inv[i]%MOD;
            }
        }
        public long COM(int n, int k){
            if (n<k)return 0;
            if (n<0||k<0)return 0;
            return fac[n]*(finv[k]*finv[n-k]%MOD)%MOD;
        }
        public long HCOM(int n, int k){
            return COM(n+k-1,k);
        }
    }
    public static class Queue<T>{
        private final int max = 1000000;
        private final T[] queue = (T[]) new Object[max];
        private int tail = 0; private int head = 0;
        public void init(){this.head = 0; tail = 0;}
        public boolean isEmpty(){return (head==tail);}
        public boolean isFull(){return (head == (tail+1)%max);}
        public void enqueue(T v){
            if (isFull()){
                System.out.println("error: queue is full.");
                return;
            }
            queue[tail++] = v;
            if (tail == max) tail = 0;
        }
        public T dequeue(){
            if (isEmpty()){
                System.out.println("error: queue is empty");
                return null;
            }
            T res = queue[head];
            ++head;
            if (head == max) head = 0;
            return res;
        }
    }
    public static class Stack<T>{
        private final int max = 100000;
        private final T[] stack =(T[]) new Object[max];
        private int top = 0;
        public boolean isEmpty(){return (top==0);}
        public boolean isFull(){return (top==max);}
        public void init(){top=0;}
        public void push(T v){
            if (isFull()){
                System.out.println("error: stack is full.");
                return;
            }
            stack[top++] = v;
        }
        public T pop(){
            if (isEmpty()){
                System.out.println("error: stack is empty");
                return null;
            }
            return stack[--top];
        }
    }
    public static class Pair<T>{
        private T A;
        private T B;
        Pair(T a,T b){
            A=a;
            B=b;
        }
        public void changeA(T a){A=a;}
        public void changeB(T b){B=b;}
        public void changeAB(T a,T b){A=a;B=b;}
        public static Comparator numberSortWithA = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Pair p = (Pair)o1;
                Pair q = (Pair)o2;
                if ((Long)p.A<(Long)q.A)return -1;
                else if ((long)p.A==(long)q.A)return 0;
                else return 1;
            }
        };
        public static Comparator numberSortWithB = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Pair p = (Pair)o1;
                Pair q = (Pair)o2;
                if ((long)p.B<(long)q.B)return -1;
                else if ((long)p.B==(long)q.B)return 0;
                else return 1;
            }
        };
    }
    public static class Graph<T>{
        private final HashMap<T,HashSet<T>> graph = (HashMap<T,HashSet<T>>) new Object();
        private T[] nodeList;
        private HashMap<T,Integer> dictionary = new HashMap<>();
        private int Size;
        private int[] Depth;
        Graph(T[] nodes){
            for (T t : nodes)graph.put(t,new HashSet<>());
            Size = nodes.length;
            nodeList = nodes.clone();
            for (int i=0;i<Size;i++)dictionary.put(nodeList[i],i);
        }
        public void addEdge(T node1,T node2){
            if (graph.containsKey(node1)&&graph.containsKey(node2)){
                graph.get(node1).add(node2);
                graph.get(node2).add(node1);
            }
        }
        public int[] Depth(T root){
            Queue<T> q = new Queue<>();
            q.enqueue(root);
            boolean[] seen = new boolean[Size];
            Arrays.fill(seen, false);
            seen[dictionary.get(root)]=true;
            int[] depth = new int[Size];
            depth[dictionary.get(root)]=0;
            while (!q.isEmpty()){
                T v = q.dequeue();
                int vNum = dictionary.get(v);
                for (T u : graph.get(v)){
                    if (!seen[dictionary.get(u)]){
                        int uNum = dictionary.get(u);
                        seen[uNum]=true;
                        q.enqueue(u);
                        depth[uNum]=depth[vNum]+1;
                    }
                }
            }
            Depth = depth.clone();
            return depth;
        }
    }
}


#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<unordered_map>
#include<stack>
#include<string>
#include<algorithm>
#include<functional>
#include<cstring>
#include<complex>
using namespace std;

/**** Type Define ****/

typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<ll, P> Q;
typedef complex<double> C;

/**** Macro Define ****/

#define cx real()
#define cy imag()

/**** Const List   ****/

const ll INF = 1LL << 60;
const double DINF = 1e30;
const ll mod = 1000000007;
const ll MAX_FLOW_MAX_V = 10000;
const ll MIN_COST_FLOW_MAX_V = 10000;
const ll BIPARTITE_MATCHING_MAX_V = 10000;
const ll dx[4] = {1, 0, -1, 0};
const ll dy[4] = {0, -1, 0, 1};
const C I = C(0, 1);
const double EPS = 1e-10;

/**** General Functions ****/

template <typename T>
T tmin(T a, T b) { return a > b ? b : a; };

template <typename T>
T tmax(T a, T b) { return a > b ? a : b; };

template <typename T>
T tadd(T a, T b) { return a + b; };

template <typename T>
T tmul(T a, T b) { return a * b; };

template <typename T>
T tpow(T a, T b) { return a * b; };

ll gcd(ll a, ll b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

ll extgcd(ll a, ll b, ll& x, ll& y) {
  if (b == 0) {
    x = 1, y = 0; return a;
  }
  ll q = a/b, g = extgcd(b, a - q*b, x, y);
  ll z = x - q * y;
  x = y;
  y = z;
  return g;
}

ll invmod (ll a, ll m) { // a^-1 mod m
  ll x, y;
  extgcd(a, m, x, y);
  x %= m;
  if (x < 0) x += m;
  return x;
}

ll nCk(ll n, ll k, ll mod) {
  ll ans = 1;
  for (ll i = n, j = 1; j <= k; i--, j++) ans = (((ans * i) % mod) * invmod(j, mod)) % mod;
  return ans;
}

ll lmin(ll a, ll b) { return a > b ? b : a; };

ll lmax(ll a, ll b) { return a > b ? a : b; };

ll lsum(ll a, ll b) { return a + b; };

/**** Matrix ****/

template <typename T>
struct Matrix {
  typedef vector<T> vec;
  typedef vector<vec> mat;
  ll x, y; // x: horizon  y: vertical
  mat d;

  Matrix(ll _y, ll _x = -1) {
    if (_x == -1) _x = _y;
    x = _x, y = _y;
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) d[i][j] = 0;
  }
  void unit() {
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) d[i][j] = i == j ? 1 : 0;
  }
  Matrix copy() {
    Matrix m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j];
    return m;
  }
  Matrix<T> operator + (Matrix<T>& t) { // No error check! Don't forget to check Matrix size!!
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j] + t.d[i][j];
    return m;
  }
  Matrix<T> operator - (Matrix<T>& t) {
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j] - t.d[i][j];
    return m;
  }
  Matrix<T> operator * (T t) {
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j] * t;
    return m;
  }
  Matrix<T> det(Matrix<T>& t) { // x need to correspond to t.y
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++)
      for (int j = 0; j < x; j++)
        for (int k = 0; k < t.x; k++) m.d[i][j] += d[i][k] * t.d[k][j]; ////////////// mod???
    return m;
  }
};

/**** Zip ****/

template <typename T>
class Zip {
  vector<T> d;
  bool flag;
public:
  Zip() {
    flag = false;
  }
  void add(T x) {
    d.push_back(x);
    flag = true;
  }
  ll getNum(T x) { // T need to have operator < !!
    if (flag) {
      sort(d.begin(), d.end());
      d.erase(unique(d.begin(), d.end()), d.end());
      flag = false;
    }
    return lower_bound(d.begin(), d.end(), x) - d.begin();
  }
  ll size() {
    if (flag) {
      sort(d.begin(), d.end());
      d.erase(unique(d.begin(), d.end()), d.end());
      flag = false;
    }
    return (ll)d.size();
  }
};

/**** Union Find ****/

class UnionFind {
  vector<ll> par, rank; // par > 0: number, par < 0: -par
public:
  void init(ll n) {
    par.resize(n, 1); rank.resize(n, 0);
  }
  ll getSize(ll x) {
    return par[find(x)];
  }
  ll find(ll x) {
    if (par[x] > 0) return x;
    return -(par[x] = -find(-par[x]));
  }
  void merge(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      par[y] += par[x];
      par[x] = -y;
    } else {
      par[x] += par[y];
      par[y] = -x;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool isSame(ll x, ll y) {
    return find(x) == find(y);
  }
};

template <typename T>
struct UnionFindT {
  vector<ll> par;
  vector<ll> rank;
  vector<T> diff_weight;

  UnionFindT(ll n = 1, T SUM_UNITY = 0) {
    init(n, SUM_UNITY);
  }

  void init(ll n = 1, T SUM_UNITY = 0) {
    par.resize(n); rank.resize(n); diff_weight.resize(n);
    for (ll i = 0; i < n; ++i) par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
  }

  ll find(ll x) {
    if (par[x] == x) {
      return x;
    }
    else {
      ll r = find(par[x]);
        diff_weight[x] += diff_weight[par[x]];
        return par[x] = r;
    }
  }

  T weight(ll x) {
    find(x);
    return diff_weight[x];
  }

  bool isSame(ll x, ll y) {
    return find(x) == find(y);
  }

  bool merge(ll x, ll y, T w) {
    w += weight(x); w -= weight(y);
    x = find(x); y = find(y);
    if (x == y) return false;
    if (rank[x] < rank[y]) swap(x, y), w = -w;
    if (rank[x] == rank[y]) ++rank[x];
    par[y] = x;
    diff_weight[y] = w;
    return true;
  }

  T diff(ll x, ll y) {
    return weight(y) - weight(x);
  }
};

class PersistentUnionFind {
  vector<ll> rank, fin, par;
  ll index;
public:
  void init(ll n) {
    index = 0;
    par.resize(n); rank.resize(n, 1); fin.resize(n, 0);
    for (ll i = 0; i < n; i++) par[i] = i;
  }
  ll find(ll x, ll t) {
    if (t >= fin[x] && par[x] != x) return find(par[x], t);
    return x;
  }
  void merge(ll x, ll y) {
    x = find(x, index);
    y = find(y, index);
    index++;
    if (x == y) return;
    if (rank[x] < rank[y]) par[x] = y, fin[x] = index;
    else {
      par[y] = x, fin[y] = index;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool isSame(ll x, ll y, ll t) { return find(x, t) == find(y, t); }
};

/**** Segment Tree ****/

template <typename T>
class SegmentTree {
  ll n;
  vector<T> node;
  function<T(T, T)> fun, fun2;
  bool customChange;
  T outValue, initValue;
public:
  void init(ll num, function<T(T, T)> resultFunction, T init, T out, function<T(T, T)> changeFunction = NULL) {
    // changeFunction: (input, beforevalue) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    customChange = changeFunction != NULL;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1, init);
    outValue = out;
    initValue = init;
  }
  void valueChange(ll num, T value) {
    num += n-1;
    if (customChange) node[num] = fun2(value, node[num]);
    else node[num] = value;
    while (num > 0) num = (num - 1) / 2, node[num] = fun(node[num * 2 + 1], node[num * 2 + 2]);
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (a <= l && r <= b) return node[k];
    if (b <= l || r <= a) return outValue;
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

template <typename T>
class LazySegmentTree {
  ll n;
  vector<T> node;
  vector<T> lazyNode;
  function<T(T, T)> fun, fun2;
  function<T(T, ll)> fun3;
  T outValue, initValue;
  T substitution(T a, T b) { return a; }
  void eval(ll k, ll l, ll r) {
    if (lazyNode[k] == 0) return;
    node[k] = fun2(fun3(lazyNode[k], r - l), node[k]);
    if (r - l > 1) {
      lazyNode[2 * k + 1] = fun2(lazyNode[k], lazyNode[2 * k + 1]);
      lazyNode[2 * k + 2] = fun2(lazyNode[k], lazyNode[2 * k + 2]);
    }
    lazyNode[k] = initValue;
  }
public:
  void init(ll num, function<T(T, T)> resultFunction, function<T(T, T)> changeFunction, function<T(T, ll)> lazyFunction, T init, T out) {
    // changeFunction: (input, beforevalue) => newvalue
    // lazyFunction: (lazyNode, diff) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    fun3 = lazyFunction;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1, init);
    lazyNode.resize(2 * n - 1, init);
    outValue = out;
    initValue = init;
  }
  void rangeChange(ll a, ll b, T value, ll l = 0, ll r = -1, ll k = 0) {
    if (r == -1) r = n;
    eval(k, l, r);
    if (b <= l || r <= a) return;
    if (a <= l && r <= b) {
      lazyNode[k] = fun2(value, lazyNode[k]);
      eval(k, l, r);
    } else {
      ll mid = (l + r) / 2;
      rangeChange(a, b, value, l, mid, 2*k+1);
      rangeChange(a, b, value, mid, r, 2*k+2);
      node[k] = fun(node[2*k+1], node[2*k+2]);
    }
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (b <= l || r <= a) return outValue;
    eval(k, l, r);
    if (a <= l && r <= b) return node[k];
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

/**** Network Flow ****/

class MaxFlow {
public:
  struct edge { ll to, cap, rev; };

  vector<edge> G[MAX_FLOW_MAX_V];
  bool used[MAX_FLOW_MAX_V];
  ll level[MAX_FLOW_MAX_V];
  ll iter[MAX_FLOW_MAX_V];

  void init() {
    for (ll i = 0; i < MAX_FLOW_MAX_V; i++) {
      G[i].clear();
    }
  }
  void add_edge(ll from, ll to, ll cap) {
    G[from].push_back((edge){to, cap, (ll)G[to].size()});
    G[to].push_back((edge){from, 0, (ll)G[from].size() - 1});
  }
  void add_undirected_edge(ll e1, ll e2, ll cap) {
    G[e1].push_back((edge){e2, cap, (ll)G[e2].size()});
    G[e2].push_back((edge){e1, cap, (ll)G[e1].size() - 1});
  }
  ll dfs(ll v, ll t, ll f) {
    if (v == t) return f;
    used[v] = true;
    for (ll i = 0; i < (ll)G[v].size(); i++) {
      edge &e = G[v][i];
      if (!used[e.to]&& e.cap > 0) {
        ll d = dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  ll max_flow(ll s, ll t) {
    ll flow = 0;
    while (1) {
      memset(used, 0, sizeof(used));
      ll f = dfs(s, t, INF);
      if (f == 0) return flow;
      flow += f;
    }
  }
  void bfs(ll s) {
    memset(level, -1, sizeof(level));
    queue<ll> que;
    level[s] = 0;
    que.push(s);
    while (!que.empty()) {
      ll v = que.front(); que.pop();
      for (ll i = 0; i < (ll)G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[v] + 1;
          que.push(e.to);
        }
      }
    }
  }
  ll dinic_dfs(ll v, ll t, ll f) {
    if (v == t) return f;
    for (ll &i= iter[v]; i < (ll)G[v].size(); i++) {
      edge &e = G[v][i];
      if (e.cap > 0 && level[v] < level[e.to]) {
        ll d = dinic_dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  ll dinic(ll s, ll t) {
    ll flow = 0;
    while (1) {
      bfs(s);
      if (level[t] < 0) return flow;
      memset(iter, 0, sizeof(iter));
      ll f;
      while ((f = dinic_dfs(s, t, INF)) > 0) {
        flow += f;
      }
    }
  }
};

/**** bipartite matching ****/

class BipartiteMatching {
public:
  ll V;
  vector<ll> G[BIPARTITE_MATCHING_MAX_V];
  ll match[BIPARTITE_MATCHING_MAX_V];
  bool used[BIPARTITE_MATCHING_MAX_V];

  BipartiteMatching(ll v) {
    V = v;
  }
  void init(ll v) {
    V = v;
    for (ll i = 0; i < BIPARTITE_MATCHING_MAX_V; i++) {
      G[i].clear();
    }
  }
  void add_edge(ll u, ll v) {
    G[u].push_back(v);
    G[v].push_back(u);
  }
  bool dfs(ll v) {
    used[v] = true;
    for (ll i = 0; i < (ll)G[v].size(); i++) {
      ll u = G[v][i], w = match[u];
      if (w < 0 || !used[w] && dfs(w)) {
        match[v] = u;
        match[u] = v;
        return true;
      }
    }
    return false;
  }
  ll max_matching() {
    ll res = 0;
    memset(match, -1, sizeof(match));
    for (ll v = 0; v < V;v++) {
      if (match[v] < 0) {
        memset(used, 0, sizeof(used));
        if (dfs(v)) {
          res++;
        }
      }
    }
    return res;
  }
};

class MinCostFlow {
public:
  struct edge { ll to, cap, cost, rev; };

  ll V;
  vector<edge> G[MIN_COST_FLOW_MAX_V];
  ll dist[MIN_COST_FLOW_MAX_V];
  ll prevv[MIN_COST_FLOW_MAX_V];
  ll preve[MIN_COST_FLOW_MAX_V];
  ll h[MIN_COST_FLOW_MAX_V];

  MinCostFlow(ll v) {
    V = v;
  }
  void init() {
    for (ll i = 0; i < MAX_FLOW_MAX_V; i++) {
      G[i].clear();
    }
  }
  void add_edge(ll from, ll to, ll cap, ll cost) {
    G[from].push_back((edge){to, cap, cost, (ll)G[to].size()});
    G[to].push_back((edge){from, 0, -cost, (ll)G[from].size() - 1});
  }
  void add_undirected_edge(ll e1, ll e2, ll cap, ll cost) {
    add_edge(e1, e2, cap, cost);
    add_edge(e2, e1, cap, cost);
  }
  ll min_cost_flow(ll s, ll t, ll f) { // minas
    ll res = 0;
    while (f > 0) {
      fill(dist, dist + V, INF);
      dist[s] = 0;
      bool update = true;
      while (update) {
        update = false;
        for (ll v = 0; v < V; v++) {
          if (dist[v] == INF) continue;
          for (ll i = 0; i < (ll)G[v].size(); i++) {
            edge &e = G[v][i];
            if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
              dist[e.to] = dist[v] + e.cost;
              prevv[e.to] = v;
              preve[e.to] = i;
              update = true;
            }
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      ll d = f;
      for (ll v = t; v != s; v = prevv[v]) {
        d = min(d, G[prevv[v]][preve[v]].cap);
      }
      f -= d;
      res += d * dist[t];
      for (ll v = t; v != s; v = prevv[v]) {
        edge &e = G[prevv[v]][preve[v]];
        e.cap -= d;
        G[v][e.rev].cap += d;
      }
    }
    return res;
  }
  ll min_cost_flow_dijkstra(ll s, ll t, ll f) {
    ll res = 0;
    fill(h, h + V, 0);
    while (f > 0) {
      priority_queue<P, vector<P>, greater<P> > que;
      fill(dist, dist + V, 0);
      dist[s] = 0;
      que.push(P(0, s));
      while (!que.empty()) {
        P p = que.top(); que.pop();
        int v = p.second;
        if (dist[v] < p.first) continue;
        for (int i = 0; i < G[v].size(); i++) {
          edge &e = G[v][i];
          if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
            dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
            prevv[e.to] = v;
            preve[e.to] = i;
            que.push(P(dist[e.to], e.to));
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      for (int v = 0; v < V; v++) h[v] += dist[v];
      int d = f;
      for (int v = t; v != s; v = prevv[v]) {
        d = tmin<ll>(d, G[prevv[v]][preve[v]].cap);
      }
      f -= d;
      res += d * h[t];
      for (int v = t; v != s; v = prevv[v]) {
        edge &e = G[prevv[v]][preve[v]];
        e.cap -= d;
        G[v][e.rev].cap += d;
      }
      return res;
    }
    return 0;
  }
};

/**** LIS ****/
ll lis(ll* a, ll n, ll* dp) {
  fill(dp, dp + n, INF);
  for (ll i = 0; i < n; i++) *lower_bound(dp, dp + n, a[i]) = a[i];
  return (ll)(lower_bound(dp, dp + n, INF) - dp);
}

/**** Geometry ****/

bool isEqual(double a, double b) { return abs(a - b) < EPS; }
bool isCEqual(C a, C b) { return isEqual(a.cx, a.cy) && isEqual(a.cy, a.cy); }
bool isZero(double a) { return abs(a) < EPS; } // a == 0
bool isUZero(double a) { return a > EPS; } // a > 0
bool isUEZero(double a) { return a > -EPS; } // a >= 0
bool isLZero(double a) { return a < -EPS; } // a < 0
bool isLEZero(double a) { return a < EPS; } // a <= 0
C getUnitVector(C a) { double len = abs(a); return isZero(len) ? C(0.0, 0.0) : a / len; }
double dot(C a, C b) { return a.cx * b.cx + a.cy * b.cy; } // |a||b|cosθ
double det(C a, C b) { return a.cx * b.cy - a.cy * b.cx; } // |a||b|sinθ
bool isLineOrthogonal(C a1, C a2, C b1, C b2) { return isZero(dot(a1 - a2, b1 - b2)); } // a1-a2, b1-b2
bool isLineParallel(C a1, C a2, C b1, C b2) { return isZero(det(a1 - a2, b1 - b2)); } // a1-a2, b1-b2
bool isPointOnLine(C a, C b, C c) { return isZero(det(b - a, c - a)); } // a-b <- c
/*
bool isPointOnLineSegment(C a, C b, C c) { // a-b <- c
  return isZero(det(b - a, c - a)) && isUEZero(dot(b - a, c - a)) && isUEZero(dot(a - b, c - b));
}
*/
bool isPointOnLineSegment(C a, C b, C c) { return isZero(abs(a-c) + abs(c-b) - abs(a-b)); }
double distanceLineAndPoint(C a, C b, C c) { return abs(det(b-a, c-a)) / abs(b-a); } // a-b <- c
double distanceLineSegmentAndPoint(C a, C b, C c) { // a-b <- c
  if (isLEZero(dot(b-a, c-a))) return abs(c-a);
  if (isLEZero(dot(a-b, c-b))) return abs(c-b);
  return abs(det(b-a, c-a)) / abs(b-a);
}
bool isIntersectedLine(C a1, C a2, C b1, C b2) { // a1-a2, b1-b2
  return !isLineParallel(a1, a2, b1, b2);
}
C intersectionLine(C a1, C a2, C b1, C b2) { // isIntersectedLine-> true
  C a = a2 - a1, b = b2 - b1;
  return a1 + a * det(b, b1 - a1) / det(b, a);
}

/**** NG Words ****/
// cx cy P Q C
// Warning: EPS

/**** main function ****/

ll ans1, n;
char s[100001];

int main() {
  scanf("%s", s);
  for (ll i = 0; s[i] != 0; i++) {
    n++;
    if (i % 2 == 0 && s[i] == '0') ans1++;
    if (i % 2 == 1 && s[i] == '1') ans1++;
  }
  printf("%lld\n", min(ans1, n-ans1));
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x<y?x:y)
#define ABS(x) (x>0?x:-(x))

#define INF 1000000000

int array_min_max(int* p, int n,bool f)  //f: true→min false→max
{
	int tmp;

	if (f)
		tmp = INF;
	else
		tmp = 0;

	for (int i = 0; i < n; i++)
	{
		if (f)
		{
			if (p[i] < tmp)
				tmp = p[i];
		}
		else
		{
			if (p[i] > tmp)
				tmp = p[i];
		}
	}
	return tmp;
}

int main()
{
	char S[100000];
	int count = 0;
	int count2=0;

	scanf("%s", S);

	for (int i = 0; S[i]!=NULL; i++)
	{
		if (i % 2 == 0)
		{
			if (S[i] == '1')
				count++;
		}
		else
		{
			if (S[i] == '0')
				count++;
		}

	}

	for (int i = 0; S[i] != NULL; i++)
	{
		if (i % 2 == 0)
		{
			if (S[i] == '0')
				count2++;
		}
		else
		{
			if (S[i] == '1')
				count2++;
		}

	}

	printf("%d\n", MIN(count, count2));
}


#include <cstdio>
#include <algorithm>

char s[100001];

int count(char d)
{
  const char digit[] = "010";
  const char* check = digit + d;
  int r = 0;
  for (int i = 0; s[i]; ++i)
  {
    if (s[i] != check[i & 1]) ++r;
  }
  return r;
}

int main()
{
  scanf("%s", s);
  printf("%d\n", std::min(count(0), count(1)));
  return 0;
}


#include <iostream>
#include <iomanip>
#include <algorithm>
#include <bitset>
#include <string>
#include <cmath>
#include <complex>
#include <numeric>
#include <cassert>

#include <vector>
#include <array>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <utility>

#define int64 long long
#define uint64 unsigned long long
#define PI 3.1415926535897932384626433832795
#define coutfix(i) cout << fixed << setprecision(i)
using namespace std;

int main()
{
	string ss;
	cin >> ss;
	int64 aa = 0;
	for(int64 ii = 0;ii < ss.length();ii++)
	{
		if((ss[ii] - '0') == ii % 2)
		{
			aa++;
		}
	}
	cout << min(aa, ss.length() - aa) << endl;
}


#include <bits/stdc++.h>
using namespace std;

int chColor(string S) {
    int l = 0, r = 0;
    for (int i = 0; i < (int)S.size(); i++) {
        if (i % 2 != 0 && S.at(i) != '1') {
            S.at(i) = 1; l++;
        }
    }
    for (int i = 0; i < (int)S.size(); i++) {
        if (i % 2 == 0 && S.at(i) != '0') {
            S.at(i) = 0; r++;
        }
    }
    return max(l, r);
}

int main() {
    string S; cin >> S;
    cout << chColor(S) << endl;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
  string S;
  cin>>S;
  long long N=S.size();
  long long zero_even=0,zero_odd=0;
  for(int i=0;i<N;i++){
    if(i%2==0 && S.at(i)=='0){
      zero_even++;
    }
    else if(i%2==1 && S.at(i)=='0){
      zero_odd++;
    }
  }
  long long a_1,a_2;
  a_1=(N+1)/2-zero_even+zero_odd;//010...
  a_2=zero_even+N/2-zero_odd;//101...
  cout<<min(a_1,a_2)<<endl;
}


#include "stdio.h"

int main(void)
{
    char S[100000];
    int count_1 = 0;
    int count_2 = 0;
    int ans;

    scanf("%s", S);
    for(int i = 0 ; i< 50000; ++i){

        /* 左端が１で始まるパターン */

        if(S[2*i] ==  '0'){
            count_1 = count_1 + 1;
        }
        if(S[2*i+1] == '1'){
            count_1 = count_1 + 1;
        }

        /* 左端が０で始まるパターン */
        if(S[2*i] ==  '1'){
            count_2 = count_2 + 1;
        }
        if(S[2*i+1] == '0'){
            count_2 = count_2 + 1;
        }

        if(S[2*i+1] == NULL){
            break;
        }
    }
    if(count_1 < count_2){
        ans = count_1;
    }
    else{
        ans = count_2;
    }

    printf("%d", ans);

    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
	char s[100000];
	scanf("%s", s);
	int i;
	int n = strlen(s);
	char t[n], u[n];
	int countA = 0, countB = 0;
	for (i = 0;i < n; i++) {
		if (i % 2 == 0) {
			t[i] = '1';
			u[i] = '0';
		} else {
			t[i] = '0';
			u[i] = '1';
		}
		if (s[i] != t[i]) {
			countA++;
		}
		if (s[i] != u[i]) {
			countB++;
		}
	}
	/*
	for (i = 0; s[i] != '\0'; i++) {
		if (s[i] == '0' && s[i+1] == '0') {
			s[i+1] = '1';
			count++;
		} else if (s[i] == '1' && s[i+1] == '1'){
			s[i+1] = '0';
			count++;
		}
	}
	*/
	int ans = 0;
	printf("%d\n", ans = ( (countA >= countB) ? countB : countA));
	return 0;
}


#include<stdio.h>
#include<string.h>

int main(){
  int i,j,k;
  char S[1000000];
  j = k = 0;
  scanf("%s",S);

  for(i=0;i<strlen(S);i++){
    if(i%2==0){
      if(S[i]=='0')
        j++;
    }
    else
      if(S[i]=='1')
        j++;
  }

  for(i=0;i<strlen(S);i++){
    if(i%2==0){
      if(S[i]=='1')
        k++;
    }
    else
      if(S[i]=='0')
        k++;
  }

  if(j > k)
    printf("%d\n",k);
  else
    printf("%d\n",j);
  return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef long long ll;
typedef char keytype;

int gcd(int a, int b){ return (a % b) ? gcd(b, a % b) : b;}
int lcm(int a, int b){ return (a / gcd(a, b)) * b;}

/* a[0], ..., a[n-1] の数の最大公約数 */
int ngcd(int n, int a[])
{
    int i, d;

    d = a[0];
    for (i = 1; i < n && d != 1; i++)
        d = gcd(a[i], d);
    return d;
}

void quicksort(keytype a[], int first, int last)
{
    int i, j;
    keytype x, t;

    x = a[(first + last) / 2];
    i = first;  j = last;
    for ( ; ; ) {
        while (a[i] < x) i++;
        while (x < a[j]) j--;
        if (i >= j) break;
        t = a[i];  a[i] = a[j];  a[j] = t;
        i++;  j--;
    }
    if (first  < i - 1) quicksort(a, first , i - 1);
    if (j + 1 < last) quicksort(a, j + 1, last);
}

int is_prime(int x){
    if(x <= 1) return 0;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0) return 0;
    }
    return 1;
}

int is_substr(char s[], char t[], int i){
    int flag = 1;

    if(s[i] == '\0') flag = 0;

    for(int j = 0; j < strlen(t); ++j, ++i){
        if(s[i] != t[j]){
            flag = 0;
            break;
        }
    }
    return flag;
}

// factor list, number of factors, natural number
void factorize(int ftr[], int *num, int n){
    int a = 2, cnt = 0;

    while(n >= a){
        if(n % a == 0){
            n = n / a;
            ftr[cnt++] = a;
        }else{
            a++;
        }
    }
    *num = cnt;
}

//#define N 5
//int p[N + 1];
int nextperm(int p[], int N)  /* 辞書式順序で次の順列 */
{
    int i, j, t;

    i = N - 1;
    p[0] = 0;  /* 番人 */
    while (p[i] >= p[i + 1]) i--;
    if (i == 0) return 0;  /* 完了 */
    j = N;
    while (p[i] >= p[j]) j--;
    t = p[i];  p[i] = p[j];  p[j] = t;
    i++;  j = N;
    while (i < j) {
        t = p[i];  p[i] = p[j];  p[j] = t;  i++;  j--;
    }
    return 1;  /* 未了 */
}

void comb(int size1, int size2, int v[size1][size2]){
  for(int i = 0; i < size1; i++){
    v[i][0] = 1;
    v[i][i] = 1;
  }
  for(int k = 1; k < size1; k++){
    for(int j = 1; j < k; j++){
      v[k][j] = (v[k-1][j-1] + v[k-1][j]);
    }
  }
}

int abs_val(int a, int b){
    if(a > b) return a - b;
    else return b - a;
}

const int inf = 1012345678;
int main(){
    char s[100005], a[100005], b[100005];

    scanf("%s", s);

    int size = (int)strlen(s);
    a[0] = 0;
    b[0] = 1;
    for(int i = 0; i < size; ++i){
        a[i+1] = ~a[i];
        b[i+1] = ~b[i];
    }

    int cnt_a = 0, cnt_b = 0;
    for(int i = 0; i < size; ++i){
        s[i] = s[i] - '0';
        //printf("%d\n", s[i]);
        if(s[i] == a[i]){
            cnt_a++;
        }else{
            cnt_b++;
        }
    }

    if(cnt_a < cnt_b) printf("%d\n", cnt_a);
    else printf("%d\n", cnt_b);

#if 0
    //int i = 0;
    int size = (int)strlen(s);
    //printf("%lu\n", strlen(s));
    for(int i = 0; i < size; ++i){
        s[i] = s[i] - '0';
        t[i] = s[i];
        //printf("%d\n", i);
    }

    if(size == 1){
        puts("0");
        return 0;
    }
    int cnt_w = 0;
    for(int j = 0; j < size; ++j){
        if((s[j] ^ s[j+1]) == 0){
            s[j+1] = ~s[j+1];
            cnt_w++;
            //printf("%d\n", s[i]);
        }
    }
    t[0] = ~t[0];
    int cnt_b = 0;
    for(int j = 0; j < size; ++j){
        if((t[j] ^ t[j+1]) == 0){
            t[j+1] = ~t[j+1];
            cnt_b++;
            //printf("%d\n", s[i]);
        }
    }
#endif

    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef long long ll;
typedef char keytype;

int gcd(int a, int b){ return (a % b) ? gcd(b, a % b) : b;}
int lcm(int a, int b){ return (a / gcd(a, b)) * b;}

/* a[0], ..., a[n-1] の数の最大公約数 */
int ngcd(int n, int a[])
{
    int i, d;

    d = a[0];
    for (i = 1; i < n && d != 1; i++)
        d = gcd(a[i], d);
    return d;
}

void quicksort(keytype a[], int first, int last)
{
    int i, j;
    keytype x, t;

    x = a[(first + last) / 2];
    i = first;  j = last;
    for ( ; ; ) {
        while (a[i] < x) i++;
        while (x < a[j]) j--;
        if (i >= j) break;
        t = a[i];  a[i] = a[j];  a[j] = t;
        i++;  j--;
    }
    if (first  < i - 1) quicksort(a, first , i - 1);
    if (j + 1 < last) quicksort(a, j + 1, last);
}

int is_prime(int x){
    if(x <= 1) return 0;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0) return 0;
    }
    return 1;
}

int is_substr(char s[], char t[], int i){
    int flag = 1;

    if(s[i] == '\0') flag = 0;

    for(int j = 0; j < strlen(t); ++j, ++i){
        if(s[i] != t[j]){
            flag = 0;
            break;
        }
    }
    return flag;
}

// factor list, number of factors, natural number
void factorize(int ftr[], int *num, int n){
    int a = 2, cnt = 0;

    while(n >= a){
        if(n % a == 0){
            n = n / a;
            ftr[cnt++] = a;
        }else{
            a++;
        }
    }
    *num = cnt;
}

//#define N 5
//int p[N + 1];
int nextperm(int p[], int N)  /* 辞書式順序で次の順列 */
{
    int i, j, t;

    i = N - 1;
    p[0] = 0;  /* 番人 */
    while (p[i] >= p[i + 1]) i--;
    if (i == 0) return 0;  /* 完了 */
    j = N;
    while (p[i] >= p[j]) j--;
    t = p[i];  p[i] = p[j];  p[j] = t;
    i++;  j = N;
    while (i < j) {
        t = p[i];  p[i] = p[j];  p[j] = t;  i++;  j--;
    }
    return 1;  /* 未了 */
}

void comb(int size1, int size2, int v[size1][size2]){
  for(int i = 0; i < size1; i++){
    v[i][0] = 1;
    v[i][i] = 1;
  }
  for(int k = 1; k < size1; k++){
    for(int j = 1; j < k; j++){
      v[k][j] = (v[k-1][j-1] + v[k-1][j]);
    }
  }
}

int abs_val(int a, int b){
    if(a > b) return a - b;
    else return b - a;
}

const int inf = 1012345678;
int main(){
    char s[100005], t[100005];

    scanf("%s", s);

    //int i = 0;
    int size = (int)strlen(s);
    //printf("%lu\n", strlen(s));
    for(int i = 0; i < size; ++i){
        s[i] = s[i] - '0';
        t[i] = s[i];
        //printf("%d\n", i);
    }

    if(size == 1){
        puts("0");
        return 0;
    }
    int cnt_w = 0;
    for(int j = 0; j < size; ++j){
        if((s[j] ^ s[j+1]) == 0){
            s[j+1] = ~s[j+1];
            cnt_w++;
            //printf("%d\n", s[i]);
        }
    }
    t[0] = ~t[0];
    int cnt_b = 0;
    for(int j = 0; j < size; ++j){
        if((t[j] ^ t[j+1]) == 0){
            t[j+1] = ~t[j+1];
            cnt_b++;
            //printf("%d\n", s[i]);
        }
    }

    if(cnt_b < cnt_w) printf("%d\n", cnt_b);
    else printf("%d\n", cnt_w);

    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef long long ll;
typedef char keytype;

int gcd(int a, int b){ return (a % b) ? gcd(b, a % b) : b;}
int lcm(int a, int b){ return (a / gcd(a, b)) * b;}

/* a[0], ..., a[n-1] の数の最大公約数 */
int ngcd(int n, int a[])
{
    int i, d;

    d = a[0];
    for (i = 1; i < n && d != 1; i++)
        d = gcd(a[i], d);
    return d;
}

void quicksort(keytype a[], int first, int last)
{
    int i, j;
    keytype x, t;

    x = a[(first + last) / 2];
    i = first;  j = last;
    for ( ; ; ) {
        while (a[i] < x) i++;
        while (x < a[j]) j--;
        if (i >= j) break;
        t = a[i];  a[i] = a[j];  a[j] = t;
        i++;  j--;
    }
    if (first  < i - 1) quicksort(a, first , i - 1);
    if (j + 1 < last) quicksort(a, j + 1, last);
}

int is_prime(int x){
    if(x <= 1) return 0;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0) return 0;
    }
    return 1;
}

int is_substr(char s[], char t[], int i){
    int flag = 1;

    if(s[i] == '\0') flag = 0;

    for(int j = 0; j < strlen(t); ++j, ++i){
        if(s[i] != t[j]){
            flag = 0;
            break;
        }
    }
    return flag;
}

// factor list, number of factors, natural number
void factorize(int ftr[], int *num, int n){
    int a = 2, cnt = 0;

    while(n >= a){
        if(n % a == 0){
            n = n / a;
            ftr[cnt++] = a;
        }else{
            a++;
        }
    }
    *num = cnt;
}

//#define N 5
//int p[N + 1];
int nextperm(int p[], int N)  /* 辞書式順序で次の順列 */
{
    int i, j, t;

    i = N - 1;
    p[0] = 0;  /* 番人 */
    while (p[i] >= p[i + 1]) i--;
    if (i == 0) return 0;  /* 完了 */
    j = N;
    while (p[i] >= p[j]) j--;
    t = p[i];  p[i] = p[j];  p[j] = t;
    i++;  j = N;
    while (i < j) {
        t = p[i];  p[i] = p[j];  p[j] = t;  i++;  j--;
    }
    return 1;  /* 未了 */
}

void comb(int size1, int size2, int v[size1][size2]){
  for(int i = 0; i < size1; i++){
    v[i][0] = 1;
    v[i][i] = 1;
  }
  for(int k = 1; k < size1; k++){
    for(int j = 1; j < k; j++){
      v[k][j] = (v[k-1][j-1] + v[k-1][j]);
    }
  }
}

int abs_val(int a, int b){
    if(a > b) return a - b;
    else return b - a;
}

const int inf = 1012345678;
int main(){
    char s[100005];

    scanf("%s", s);

    //int i = 0;
    int size = (int)strlen(s);
    //printf("%lu\n", strlen(s));
    for(int i = 0; i < size; ++i){
        s[i] = s[i] - '0';
        //printf("%d\n", i);
    }

    if(size == 1){
        puts("0");
        return 0;
    }
    int cnt = 0;
    for(int j = 0; j < size; ++j){
        if((s[j] ^ s[j+1]) == 0){
            s[j+1] = ~s[j+1];
            cnt++;
            //printf("%d\n", s[i]);
        }
    }

    printf("%d\n", cnt);

    return 0;
}


input = require('fs').readFileSync('/dev/stdin', 'utf8')
lines = input.split('\n')
S = lines.shift()

a = 0
b = 0
for (i=0; i<S.length; i++) {
    if (S[i] != (i % 2 == 0 ? '0' : '1')) {
        a++
    }
    if (S[i] != (i % 2 == 1 ? '0' : '1')) {
        b++
    }
}

console.log(Math.min(a, b))


// inputに入力データ全体が入る
function Main(input) {
	// 1行目がinput[0], 2行目がinput[1], …に入る
	input = input.split("");
	//文字列から10進数に変換するときはparseIntを使います
  	var count = 0;
  	if (input.length !== 1) {
      for (var i=0; i<input.length; i++) {
        if (i === input.length - 1) break;
        if (input[i] === input[i + 1]) {
          count++;
          input[i + 1] = (input[i] === "0") ? "1" : "0";
        }
      }
    }

  	//出力
	console.log(count);
}

//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


// inputに入力データ全体が入る
function Main(input) {
	// 1行目がinput[0], 2行目がinput[1], …に入る
    input = input.split("\n");
    // 数値の配列を作る
//    const numList1 = input[0].split(' ').map(x => parseInt(x, 10));
    const strList = input[0].split(' ');
    const SCharList = strList[0];
    const length = SCharList.length;

    var cnt = 0;
    for (var i = 0; i < length; i++) {
        var c = SCharList[i];
        // 010101...の方基準で考える
        if (i % 2 === 0 && c === '0') {
            cnt++;
        } else if (i % 2 === 1 && c === '1') {
            cnt++;
        }
    }

    // 0101010...と10101010...どちらに近いか
    cnt = Math.min(cnt, length - cnt);
    console.log(cnt);
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function Main(input) {
  input = input.split("");
  var a=0;
  for(var i=0;i<input.length;i++){
    if(i%2==0){
      if(input[i]==0){
        a++;
      }
    }else{
      if(input[i]==1){
        a++;
      }
    }
  }
  if(input.length-a<a){
    console.log(input.length-a);
  }else{
    console.log(a);
  }
}Main(require("fs").readFileSync("/dev/stdin", "utf8"));


"use strict"

function Main(input) {
  //input = input.split('\n');
  let odd = 0;
  let even = 0;
  for (let i=0;i<input.length;i++){
    if(i%2){
      if(input.charCodeAt(i) == 0x30){
        even++;
      } else {
        odd++;
      }
    } else {
      if(input.charCodeAt(i) == 0x30){
        odd++;
      } else {
        even++;
      }
    }
  }
  console.log(Math.min(odd, even))
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


"use strict"

function Main(input) {
  //input = input.split('\n');
  let odd = 0;
  let even = 0;
  for (let i=0;i<input.length;i++){
    if(i%2){
      if(input.charAt(i) == '0'){
        even++;
      } else {
        odd++;
      }
    } else {
      if(input.charAt(i) == '0'){
        odd++;
      } else {
        even++;
      }
    }
  }
  console.log(Math.min(odd, even))
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


package main

import (
  "fmt"
  "bufio"
  "os"
)

func main() {
  count := [2] int{0, 0}

  rd := bufio.NewReaderSize(os.Stdin, 100000)
  s := make([]byte, 0, 100000)
  for {
    l, p, _ := rd.ReadLine()
    s = append(s, l...)
    if !p {
      break
    }
  }

  n := len(s)

  for i := 0; i < n; i++ {
    if i % 2 == 0 {
      if s[i] == 48 {
        count[0]++
      } else {
        count[1]++
      }
    } else {
      if s[i] == 48 {
        count[1]++
      } else {
        count[0]++
      }
    }
  }

  if count[0] < count[1] {
    fmt.Println(count[0])
  } else {
    fmt.Println(count[1])
  }
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)
var rdr = bufio.NewReaderSize(os.Stdin, 1000000)

func readLine() string {
	buf := make([]byte, 0, 1000000)
	for {
		l, p, e := rdr.ReadLine()
		if e != nil {
			panic(e)
		}
		buf = append(buf, l...)
		if !p {
			break
		}
	}
	return string(buf)
}

func nextWord() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(nextWord())
	if e != nil {
		panic(e)
	}
	return i
}

func min(lhs, rhs int64) int64 {
	if lhs < rhs {
		return lhs
	}
	return rhs
}

func main() {
	sc.Split(bufio.ScanWords)
	s := readLine()

	var ans int64

	// count 0
	var cnt0 [2]int64
	var cnt1 [2]int64
	for i := 0; i < len(s); i++ {
		if s[i] == '0' {
			cnt0[i%2]++
		} else {
			cnt1[i%2]++
		}
	}
	// 01010...
	ans0 := cnt0[1] + cnt1[0]
	// 10101...
	ans1 := cnt0[0] + cnt1[1]
	ans = min(ans0, ans1)
	fmt.Println(ans)
}


package main
import (
	"fmt"
	"os"
	"bufio"
	"strings"
)

var stdin = bufio.NewScanner(os.Stdin)
var rdr = bufio.NewReaderSize(os.Stdin,1000000)
func readLine() string{
	//長いトークンを読み込みたい場合
	buf := make([]byte,0,1000000)
	for {
		read,isPrefix,error := rdr.ReadLine()
		if error!= nil{
			panic(error)
		}
		buf = append(buf,read...)
		if !isPrefix{
			break
		}
	}
	return string(buf)
}

func Input_Str() string {
	//かんたんに読み込みたい場合
	stdin.Scan()
	stringInput := stdin.Text()
	out := strings.TrimSpace(stringInput)
	return out
}

func main(){
	stdin.Split(bufio.ScanWords)
	s := readLine()
	count_W:=0
	count_B:=0

	for i:=0;i<len(s);i++{
		if i%2==0{
			if s[i]=='0'{
				count_W++
			}else{
				count_B++
			}
		}else{
			if s[i]=='1'{
				count_W++
			}else{
				count_B++
			}
		}
	}

	if count_W < count_B{
		fmt.Println(count_W)
	}else{
		fmt.Println(count_B)
	}
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

func nextStr() string {
	sc.Scan()
	return sc.Text()
}

var sc = bufio.NewScanner(os.Stdin)

func main() {
	// Code for C - Coloring Colorfully
	S := nextStr()

	var A string
	for i := 0; i < len(S); i++ {
		if i%2 == 0 {
			A += string('0')
		} else {
			A += string('1')
		}
	}

	var countA, countB int
	for i := 0; i < len(S); i++ {
		if A[i] != S[i] {
			countB++
		} else {
			countA++
		}
	}

	fmt.Println(math.Min(float64(countA), float64(countB)))
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

func nextStr() string {
	sc.Scan()
	return sc.Text()
}

var sc = bufio.NewScanner(os.Stdin)

func main() {
	// Code for C - Coloring Colorfully
	S := nextStr()
	/*
		var A string
		for i := 0; i < len(S); i++ {
			if i%2 == 0 {
				A += string('0')
			} else {
				A += string('1')
			}
		}
	*/

	var A string
	var countA, countB int
	for i := 0; i < len(S); i++ {

		if i%2 == 0 {
			A = string('0')
		} else {
			A = string('1')
		}

		if A[0] != S[i] {
			countB++
		} else {
			countA++
		}
	}

	fmt.Println(math.Min(float64(countA), float64(countB)))
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

func nextStr() string {
	sc.Scan()
	return sc.Text()
}

var sc = bufio.NewScanner(os.Stdin)

func main() {
	// Code for C - Coloring Colorfully
	S := nextStr()

	var A string
	var countA, countB int
	for i := 0; i < len(S); i++ {
		if i%2 == 0 {
			A = string('0')
		} else {
			A = string('1')
		}

		if A[0] != S[i] {
			countB++
		} else {
			countA++
		}
	}

	fmt.Println(math.Min(float64(countA), float64(countB)))
}


S = gets.chomp
N = S.size

s = S.to_i(2)

a = "#{ '01' * (N / 2) }#{ '0' if N.odd? }".to_i(2)
b = "#{ '10' * (N / 2) }#{ '1' if N.odd? }".to_i(2)

puts [a, b].map {|i| (i ^ s).to_s(2).count('1') }.min


s = gets.chomp!
n = s.size
q, r = n.divmod(2)
ans = "10" * q + "1" * r
cnt = (ans.to_i(2)^s.to_i(2)).to_s(2).count("1")
puts cnt > (n-cnt) ? n-cnt : cnt


io = STDIN

s=io.gets.chomp
len=s.size
x='01'*(len/2)
y='10'*(len/2)
if len.odd?
  x=x+"0"
  y=y+"1"
end
bins=s.to_i(2)
binx=x.to_i(2)
biny=y.to_i(2)
def popcount(x)
  x.to_s(2).count("1")
end
puts [popcount(bins^binx),popcount(bins^biny)].min


p`dd`.chop.bytes.map{1.&_1^$.+=1}.tally.values.min


s = gets.chomp.map(&:to_i)
ans = [0,0]
s.each.with_index{|c,i|ans[i%2^s[i]] += 1}
p ans.min


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	sc.Split(bufio.ScanWords)
	s := nextMega()
	col := []int{0, 1}
	cnt := []int{0, 0}
	for i := range s {
		for j := 0; j < 2; j++ {
			if col[j] != int(s[i]-'0') {
				cnt[j]++
			}
		}
		col[0], col[1] = col[1], col[0]
	}

	puts(min(cnt[0], cnt[1]))
	wt.Flush()
}

var (
	sc  = bufio.NewScanner(os.Stdin)
	rdr = bufio.NewReaderSize(os.Stdin, 1000000)
	wt  = bufio.NewWriter(os.Stdout)
)

func next() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	i, _ := strconv.Atoi(next())
	return i
}

func nextFloat64() float64 {
	f, _ := strconv.ParseFloat(next(), 64)
	return f
}

func nextInts(n int) []int {
	slice := make([]int, n)
	for i := 0; i < n; i++ {
		slice[i] = nextInt()
	}
	return slice
}

func nextFloat64s(n int) []float64 {
	slice := make([]float64, n)
	for i := 0; i < n; i++ {
		slice[i] = nextFloat64()
	}
	return slice
}

func nextMega() string {
	buf := make([]byte, 0, 1000000)
	for {
		l, p, _ := rdr.ReadLine()
		buf = append(buf, l...)
		if !p {
			break
		}
	}
	return string(buf)
}

func putf(format string, a ...interface{}) {
	fmt.Fprintf(wt, format, a...)
}

func puts(a ...interface{}) {
	fmt.Fprintln(wt, a...)
}

func min(nums ...int) int {
	ret := nums[0]
	for _, v := range nums {
		if v < ret {
			ret = v
		}
	}
	return ret
}


use std::cmp::min;

fn main() {
    let mut buf = String::new();
    std::io::stdin().read_line(&mut buf).ok();
    let s = buf.trim().chars().collect::<Vec<char>>();
    let n = s.len();
    let s1 = (0..n).map(|x| if x % 2 == 0 {'1'} else {'0'}).collect::<Vec<_>>();
    let s2 = (0..n).map(|x| if x % 2 == 0 {'0'} else {'1'}).collect::<Vec<_>>();
    let (mut c1, mut c2) = (0, 0);
    for i in 0..n {
        if s1[i] != s[i] {c1 += 1}
        if s2[i] != s[i] {c2 += 1}
    }
    let ans = min(c1, c2);
    println!("{}", ans);
}


fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn main() {
    let s = read::<String>();
    let cs = s.chars().collect::<Vec<_>>();
    let mut count_a = 0;
    let mut count_b = 0;
    for (i, c) in cs.iter().map(|&c| ((c as u8) - b'0') as usize).enumerate() {
        if i % 2 != c {
            count_a += 1;
        }
        if (i + 1) % 2 != c {
            count_b += 1;
        }
    }

    let ans = std::cmp::min(count_a, count_b);
    println!("{}", ans);
}


use std::io;
use std::str::FromStr;
use std::cmp::min;

fn input_char_vec() -> Vec<char> {
    let mut line: String = String::new();
    io::stdin().read_line(&mut line);
    line.trim().chars().collect()
}

fn main() {
    let s = input_char_vec();
    let mut s1 = vec!['0'; s.len()];
    let mut s2 = vec!['0'; s.len()];
    for i in 0..s.len() {
        if i % 2 == 0 {
            s1[i] = '1';
        } else {
            s2[i] = '1';
        }
    }
    let mut c1 = 0;
    let mut c2 = 0;
    for i in 0..s.len() {
        if s[i] != s1[i] {
            c1 += 1;
        }
        if s[i] != s2[i] {
            c2 += 1;
        }
    }
    // println!("{}, {}", c1, c2);
    println!("{}", min(c1, c2));
}