import java.io.*;
import java.util.*;
public class tr1 {
	static PrintWriter out;
	static StringBuilder sb;
	static int inf = (int) 1e9;
	static int mod = (int) 1e9 + 7;
	static int[] si;
	static ArrayList<Integer> primes;
	static HashSet<Integer> pr;
	static int n;
	static boolean[] in;
	static HashMap<Integer, Integer> factors;
	static HashSet<Integer> f;
    static long []fac;
    static int []l,r;
    static short [][][]memo;
    static int []a;
    static HashMap<Integer,Integer> hm;
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		String s=sc.nextLine();
		n=s.length();
		a=new int [s.length()];
		for(int i=0;i<s.length();i++)
			a[i]=Integer.parseInt(""+s.charAt(i));
		memo=new short [n][2][3];
		for(short [][]memo1:memo)
		for(short []aa:memo1)
			Arrays.fill(aa, (short)-1);
		out.println(dp(0,0,1));
//		for(int []aa:memo)
	//		System.out.println(Arrays.toString(aa));
		out.flush();
	}
	public static int dp(int i,int val,int st) {
		if(i==n-1) {
			int y=0;
			if((val+a[i])%3==0)
				y++;
			return y;
		}
		if(memo[i][st][val]!=-1) {
	 	return memo[i][st][val];
		}
		int y=0;
		if(val==0)
			y++;
		int take= y+dp(i+1,0,1);
		int leave=dp(i+1,(val+a[i])%3,0);
		//System.out.println(i+" "+st+" "+take+" "+leave);
		return memo[i][st][val]=(short)Math.max(take, leave);
	}
	public int [] merge(int []d,int st,int e) {
		if(st>e)
			return null;
		if(e==st) {
			int []ans= {d[e]};
			return ans;
		}
		int mid=(st+e)/2;
		int []ans=new int[e-st+1];
		int []ll=merge(d,st,mid);
		int []rr=merge(d,mid+1,e);
		if(ll==null)
			return rr;
		if(rr==null)
			return ll;
		int iver=0;
		int idxl=0;
		int idxr=0;
		for(int i=st;i<=e;i++) {
		    if(ll[idxl]<rr[idxr]) {

		    }
		}
		return ans;
	}
	public static class pair1 implements Comparable<pair1>{
		int a;
		int idx;
		pair1(int a,int i){
			this.a=a;
			idx=i;
		}
		public String toString() {
			return a+" "+idx;
		}
		@Override
		public int compareTo(pair1 o) {
			return o.a-a;
		}
	}
	public static class pair2 implements Comparable<pair2>{
		int a;
		int idx;
		pair2(int a,int i){
			this.a=a;
			idx=i;
		}
		public String toString() {
			return a+" "+idx;
		}
		@Override
		public int compareTo(pair2 o) {
			// TODO Auto-generated method stub
			return idx-o.idx;
		}
	}
	static int inver(long x) {
		int a = (int) x;
		int e = (mod - 2);
		int res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				// System.out.println(res*a);
				res = (int) ((1l * res * a) % mod);
			}
			a = (int) ((1l * a * a) % mod);
			e >>= 1;
		}
		// out.println(res+" "+x);
		return res % mod;
	}
	static int atMostSum(int arr[], int n, int k)
	{
	    int sum = 0;
	    int cnt = 0, maxcnt = 0;

	    for (int i = 0; i < n; i++) {

	        // If adding current element doesn't
	        // cross limit add it to current window
	        if ((sum + arr[i]) <= k) {
	            sum += arr[i];
	            cnt++;
	        }

	        // Else, remove first element of current
	        // window and add the current element
	        else if(sum!=0)
	        {
	            sum = sum - arr[i - cnt] + arr[i];
	        }

	        // keep track of max length.
	        maxcnt = Math.max(cnt, maxcnt);
	    }
	    return maxcnt;
	}
	public static int[] longestSubarray(int[] inp) {
		// array containing prefix sums up to a certain index i
		int[] p = new int[inp.length];
		p[0] = inp[0];
		for (int i = 1; i < inp.length; i++) {
			p[i] = p[i - 1] + inp[i];
		}

		// array Q from the description below
		int[] q = new int[inp.length];
		q[inp.length - 1] = p[inp.length - 1];
		for (int i = inp.length - 2; i >= 0; i--) {
			q[i] = Math.max(q[i + 1], p[i]);
		}
		int a = 0;
		int b = 0;
		int maxLen = 0;
		int curr;
		int[] res = new int[] { -1, -1 };
		while (b < inp.length) {
			curr = a > 0 ? q[b] - p[a - 1] : q[b];
			if (curr >= 0) {
				if (b - a > maxLen) {
					maxLen = b - a;
					res = new int[] { a, b };
				}
				b++;
			} else {
				a++;
			}
		}
		return res;
	}

	static void factor(int n) {
		if (si[n] == n) {
			f.add(n);
			return;
		}
		f.add(si[n]);
		factor(n / si[n]);
	}

	static void seive() {
		si = new int[1000001];
		primes = new ArrayList<>();
		int N = 1000001;
		pr = new HashSet<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
				pr.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);

		}
	}

	static public class SegmentTree { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		int[] array, sTree, lazy;

		SegmentTree(int[] in) {
			array = in;
			N = in.length - 1;
			sTree = new int[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[N << 1];
			build(1, 1, N);
		}
         public String toString() {
        	 return Arrays.toString(sTree);
         }
		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = gcd(sTree[node << 1] , sTree[node << 1 | 1]);
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = sTree[index << 1] + sTree[index << 1 | 1];
			}
		}

		void update_range(int i, int j, int val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, int val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		int query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		int query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return 0;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			//propagate(node, b, mid, e);
			int q1 = query(node << 1, b, mid, i, j);
			int q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return gcd(q1 , q2);
		}
	}

	static int gcd(int a, int b) {

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

	static class unionfind {
		int[] p;
		int[] size;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];

			for (int i = 0; i < n; i++) {
				p[i] = i;
			}
			Arrays.fill(size, 1);
		}

		int findSet(int v) {
			if (v == p[v])
				return v;
			return p[v] = findSet(p[v]);
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		void combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return;
			if (size[a] > size[b]) {
				p[b] = a;
				size[a] += size[b];

			} else {
				p[a] = b;
				size[b] += size[a];
			}
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.io.*;
import java.util.*;
public class tr1 {
	static PrintWriter out;
	static StringBuilder sb;
	static int inf = (int) 1e9;
	static int mod = (int) 1e9 + 7;
	static int[] si;
	static ArrayList<Integer> primes;
	static HashSet<Integer> pr;
	static int n;
	static boolean[] in;
	static HashMap<Integer, Integer> factors;
	static HashSet<Integer> f;
    static long []fac;
    static int []l,r;
    static int [][][]memo;
    static int []a;
    static HashMap<Integer,Integer> hm;
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		String s=sc.nextLine();
		n=s.length();
		a=new int [s.length()];
		for(int i=0;i<s.length();i++)
			a[i]=Integer.parseInt(""+s.charAt(i));
		memo=new int [n][2][101];
		for(int [][]memo1:memo)
		for(int []aa:memo1)
			Arrays.fill(aa, -1);
		out.println(dp(0,0,1));
//		for(int []aa:memo)
	//		System.out.println(Arrays.toString(aa));
		out.flush();
	}
	public static int dp(int i,int val,int st) {
		if(i==n-1) {
			int y=0;
			if((val+a[i])%3==0)
				y++;
			return y;
		}
		if(memo[i][st][val]!=-1) {
	 	return memo[i][st][val];
		}
		int y=0;
		if((val+a[i])%3==0)
			y++;
		int take= y+dp(i+1,0,1);
		int leave=dp(i+1,val+a[i],0);
		//System.out.println(i+" "+st+" "+take+" "+leave);
		return memo[i][st][val]=Math.max(take, leave);
	}
	public int [] merge(int []d,int st,int e) {
		if(st>e)
			return null;
		if(e==st) {
			int []ans= {d[e]};
			return ans;
		}
		int mid=(st+e)/2;
		int []ans=new int[e-st+1];
		int []ll=merge(d,st,mid);
		int []rr=merge(d,mid+1,e);
		if(ll==null)
			return rr;
		if(rr==null)
			return ll;
		int iver=0;
		int idxl=0;
		int idxr=0;
		for(int i=st;i<=e;i++) {
		    if(ll[idxl]<rr[idxr]) {

		    }
		}
		return ans;
	}
	public static class pair1 implements Comparable<pair1>{
		int a;
		int idx;
		pair1(int a,int i){
			this.a=a;
			idx=i;
		}
		public String toString() {
			return a+" "+idx;
		}
		@Override
		public int compareTo(pair1 o) {
			return o.a-a;
		}
	}
	public static class pair2 implements Comparable<pair2>{
		int a;
		int idx;
		pair2(int a,int i){
			this.a=a;
			idx=i;
		}
		public String toString() {
			return a+" "+idx;
		}
		@Override
		public int compareTo(pair2 o) {
			// TODO Auto-generated method stub
			return idx-o.idx;
		}
	}
	static int inver(long x) {
		int a = (int) x;
		int e = (mod - 2);
		int res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				// System.out.println(res*a);
				res = (int) ((1l * res * a) % mod);
			}
			a = (int) ((1l * a * a) % mod);
			e >>= 1;
		}
		// out.println(res+" "+x);
		return res % mod;
	}
	static int atMostSum(int arr[], int n, int k)
	{
	    int sum = 0;
	    int cnt = 0, maxcnt = 0;

	    for (int i = 0; i < n; i++) {

	        // If adding current element doesn't
	        // cross limit add it to current window
	        if ((sum + arr[i]) <= k) {
	            sum += arr[i];
	            cnt++;
	        }

	        // Else, remove first element of current
	        // window and add the current element
	        else if(sum!=0)
	        {
	            sum = sum - arr[i - cnt] + arr[i];
	        }

	        // keep track of max length.
	        maxcnt = Math.max(cnt, maxcnt);
	    }
	    return maxcnt;
	}
	public static int[] longestSubarray(int[] inp) {
		// array containing prefix sums up to a certain index i
		int[] p = new int[inp.length];
		p[0] = inp[0];
		for (int i = 1; i < inp.length; i++) {
			p[i] = p[i - 1] + inp[i];
		}

		// array Q from the description below
		int[] q = new int[inp.length];
		q[inp.length - 1] = p[inp.length - 1];
		for (int i = inp.length - 2; i >= 0; i--) {
			q[i] = Math.max(q[i + 1], p[i]);
		}
		int a = 0;
		int b = 0;
		int maxLen = 0;
		int curr;
		int[] res = new int[] { -1, -1 };
		while (b < inp.length) {
			curr = a > 0 ? q[b] - p[a - 1] : q[b];
			if (curr >= 0) {
				if (b - a > maxLen) {
					maxLen = b - a;
					res = new int[] { a, b };
				}
				b++;
			} else {
				a++;
			}
		}
		return res;
	}

	static void factor(int n) {
		if (si[n] == n) {
			f.add(n);
			return;
		}
		f.add(si[n]);
		factor(n / si[n]);
	}

	static void seive() {
		si = new int[1000001];
		primes = new ArrayList<>();
		int N = 1000001;
		pr = new HashSet<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
				pr.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);

		}
	}

	static public class SegmentTree { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		int[] array, sTree, lazy;

		SegmentTree(int[] in) {
			array = in;
			N = in.length - 1;
			sTree = new int[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[N << 1];
			build(1, 1, N);
		}
         public String toString() {
        	 return Arrays.toString(sTree);
         }
		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = gcd(sTree[node << 1] , sTree[node << 1 | 1]);
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = sTree[index << 1] + sTree[index << 1 | 1];
			}
		}

		void update_range(int i, int j, int val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, int val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		int query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		int query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return 0;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			//propagate(node, b, mid, e);
			int q1 = query(node << 1, b, mid, i, j);
			int q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return gcd(q1 , q2);
		}
	}

	static int gcd(int a, int b) {

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

	static class unionfind {
		int[] p;
		int[] size;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];

			for (int i = 0; i < n; i++) {
				p[i] = i;
			}
			Arrays.fill(size, 1);
		}

		int findSet(int v) {
			if (v == p[v])
				return v;
			return p[v] = findSet(p[v]);
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		void combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return;
			if (size[a] > size[b]) {
				p[b] = a;
				size[a] += size[b];

			} else {
				p[a] = b;
				size[b] += size[a];
			}
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.io.*;
import java.util.*;
public class tr1 {
	static PrintWriter out;
	static StringBuilder sb;
	static int inf = (int) 1e9;
	static int mod = (int) 1e9 + 7;
	static int[] si;
	static ArrayList<Integer> primes;
	static HashSet<Integer> pr;
	static int n;
	static boolean[] in;
	static HashMap<Integer, Integer> factors;
	static HashSet<Integer> f;
    static long []fac;
    static int []l,r;
    static short [][][]memo;
    static int []a;
    static HashMap<Integer,Integer> hm;
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		String s=sc.nextLine();
		n=s.length();
		a=new int [s.length()];
		for(int i=0;i<s.length();i++)
			a[i]=Integer.parseInt(""+s.charAt(i));
		memo=new short [n][2][1001];
		for(short [][]memo1:memo)
		for(short []aa:memo1)
			Arrays.fill(aa, (short)-1);
		out.println(dp(0,0,1));
//		for(int []aa:memo)
	//		System.out.println(Arrays.toString(aa));
		out.flush();
	}
	public static int dp(int i,int val,int st) {
		if(i==n-1) {
			int y=0;
			if((val+a[i])%3==0)
				y++;
			return y;
		}
		if(memo[i][st][val]!=-1) {
	 	return memo[i][st][val];
		}
		int y=0;
		if((val+a[i])%3==0)
			y++;
		int take= y+dp(i+1,0,1);
		int leave=dp(i+1,val+a[i],0);
		//System.out.println(i+" "+st+" "+take+" "+leave);
		return memo[i][st][val]=(short)Math.max(take, leave);
	}
	public int [] merge(int []d,int st,int e) {
		if(st>e)
			return null;
		if(e==st) {
			int []ans= {d[e]};
			return ans;
		}
		int mid=(st+e)/2;
		int []ans=new int[e-st+1];
		int []ll=merge(d,st,mid);
		int []rr=merge(d,mid+1,e);
		if(ll==null)
			return rr;
		if(rr==null)
			return ll;
		int iver=0;
		int idxl=0;
		int idxr=0;
		for(int i=st;i<=e;i++) {
		    if(ll[idxl]<rr[idxr]) {

		    }
		}
		return ans;
	}
	public static class pair1 implements Comparable<pair1>{
		int a;
		int idx;
		pair1(int a,int i){
			this.a=a;
			idx=i;
		}
		public String toString() {
			return a+" "+idx;
		}
		@Override
		public int compareTo(pair1 o) {
			return o.a-a;
		}
	}
	public static class pair2 implements Comparable<pair2>{
		int a;
		int idx;
		pair2(int a,int i){
			this.a=a;
			idx=i;
		}
		public String toString() {
			return a+" "+idx;
		}
		@Override
		public int compareTo(pair2 o) {
			// TODO Auto-generated method stub
			return idx-o.idx;
		}
	}
	static int inver(long x) {
		int a = (int) x;
		int e = (mod - 2);
		int res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				// System.out.println(res*a);
				res = (int) ((1l * res * a) % mod);
			}
			a = (int) ((1l * a * a) % mod);
			e >>= 1;
		}
		// out.println(res+" "+x);
		return res % mod;
	}
	static int atMostSum(int arr[], int n, int k)
	{
	    int sum = 0;
	    int cnt = 0, maxcnt = 0;

	    for (int i = 0; i < n; i++) {

	        // If adding current element doesn't
	        // cross limit add it to current window
	        if ((sum + arr[i]) <= k) {
	            sum += arr[i];
	            cnt++;
	        }

	        // Else, remove first element of current
	        // window and add the current element
	        else if(sum!=0)
	        {
	            sum = sum - arr[i - cnt] + arr[i];
	        }

	        // keep track of max length.
	        maxcnt = Math.max(cnt, maxcnt);
	    }
	    return maxcnt;
	}
	public static int[] longestSubarray(int[] inp) {
		// array containing prefix sums up to a certain index i
		int[] p = new int[inp.length];
		p[0] = inp[0];
		for (int i = 1; i < inp.length; i++) {
			p[i] = p[i - 1] + inp[i];
		}

		// array Q from the description below
		int[] q = new int[inp.length];
		q[inp.length - 1] = p[inp.length - 1];
		for (int i = inp.length - 2; i >= 0; i--) {
			q[i] = Math.max(q[i + 1], p[i]);
		}
		int a = 0;
		int b = 0;
		int maxLen = 0;
		int curr;
		int[] res = new int[] { -1, -1 };
		while (b < inp.length) {
			curr = a > 0 ? q[b] - p[a - 1] : q[b];
			if (curr >= 0) {
				if (b - a > maxLen) {
					maxLen = b - a;
					res = new int[] { a, b };
				}
				b++;
			} else {
				a++;
			}
		}
		return res;
	}

	static void factor(int n) {
		if (si[n] == n) {
			f.add(n);
			return;
		}
		f.add(si[n]);
		factor(n / si[n]);
	}

	static void seive() {
		si = new int[1000001];
		primes = new ArrayList<>();
		int N = 1000001;
		pr = new HashSet<>();
		si[1] = 1;
		for (int i = 2; i < N; i++) {
			if (si[i] == 0) {
				si[i] = i;
				primes.add(i);
				pr.add(i);
			}
			for (int j = 0; j < primes.size() && primes.get(j) <= si[i] && (i * primes.get(j)) < N; j++)
				si[primes.get(j) * i] = primes.get(j);

		}
	}

	static public class SegmentTree { // 1-based DS, OOP

		int N; // the number of elements in the array as a power of 2 (i.e. after padding)
		int[] array, sTree, lazy;

		SegmentTree(int[] in) {
			array = in;
			N = in.length - 1;
			sTree = new int[N << 1]; // no. of nodes = 2*N - 1, we add one to cross out index zero
			lazy = new int[N << 1];
			build(1, 1, N);
		}
         public String toString() {
        	 return Arrays.toString(sTree);
         }
		void build(int node, int b, int e) // O(n)
		{
			if (b == e)
				sTree[node] = array[b];
			else {
				int mid = b + e >> 1;
				build(node << 1, b, mid);
				build(node << 1 | 1, mid + 1, e);
				sTree[node] = gcd(sTree[node << 1] , sTree[node << 1 | 1]);
			}
		}

		void update_point(int index, int val) // O(log n)
		{
			index += N - 1;
			sTree[index] += val;
			while (index > 1) {
				index >>= 1;
				sTree[index] = sTree[index << 1] + sTree[index << 1 | 1];
			}
		}

		void update_range(int i, int j, int val) // O(log n)
		{
			update_range(1, 1, N, i, j, val);
		}

		void update_range(int node, int b, int e, int i, int j, int val) {
			if (i > e || j < b)
				return;
			if (b >= i && e <= j) {
				sTree[node] += (e - b + 1) * val;
				lazy[node] += val;
			} else {
				int mid = b + e >> 1;
				propagate(node, b, mid, e);
				update_range(node << 1, b, mid, i, j, val);
				update_range(node << 1 | 1, mid + 1, e, i, j, val);
				sTree[node] = sTree[node << 1] + sTree[node << 1 | 1];
			}

		}

		void propagate(int node, int b, int mid, int e) {
			lazy[node << 1] += lazy[node];
			lazy[node << 1 | 1] += lazy[node];
			sTree[node << 1] += (mid - b + 1) * lazy[node];
			sTree[node << 1 | 1] += (e - mid) * lazy[node];
			lazy[node] = 0;
		}

		int query(int i, int j) {
			return query(1, 1, N, i, j);
		}

		int query(int node, int b, int e, int i, int j) // O(log n)
		{
			if (i > e || j < b)
				return 0;
			if (b >= i && e <= j)
				return sTree[node];
			int mid = b + e >> 1;
			//propagate(node, b, mid, e);
			int q1 = query(node << 1, b, mid, i, j);
			int q2 = query(node << 1 | 1, mid + 1, e, i, j);
			return gcd(q1 , q2);
		}
	}

	static int gcd(int a, int b) {

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

	static class unionfind {
		int[] p;
		int[] size;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];

			for (int i = 0; i < n; i++) {
				p[i] = i;
			}
			Arrays.fill(size, 1);
		}

		int findSet(int v) {
			if (v == p[v])
				return v;
			return p[v] = findSet(p[v]);
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		void combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return;
			if (size[a] > size[b]) {
				p[b] = a;
				size[a] += size[b];

			} else {
				p[a] = b;
				size[b] += size[a];
			}
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class temp
{
	void solve()
	{
		FastReader sc =new FastReader();
		String s = sc.next();

		int n = s.length();
		int sum[] = new int[n];

		for(int i=0;i<n;i++)
		{
			int number = s.charAt(i)%48;
			if(i==0)
				sum[i] = number;
			else
				sum[i] = sum[i-1] + number;
		}

		int dp[] = new int[n];

		dp[0] = (sum[0]%3==0?1:0);

		for(int i=1;i<n;i++)
		{
			dp[i] = Math.max(dp[i-1],(sum[i]%3==0?1:0));
			for(int j=0;j<i;j++)
				dp[i] = Math.max(dp[i],(sum[i]-sum[j])%3 == 0 ? dp[j]+1:0);
		}

		System.out.println(dp[n-1]);
	}

    public static void main(String[] args)
    {
        new temp().solve();
    }

    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class temp
{

	void solve()
	{
		FastReader sc =new FastReader();
		String s = sc.next();

		long ans = 0;
		int sum = 0;

		for(int i=0;i<s.length();i++)
		{
			int number = s.charAt(i)%48;

			if(number%3==0)
			{
				ans++;
				sum=0;
			}
			else
			{
				sum+=number;
				if(sum%3==0)
				{
					ans++;
					sum=0;
				}
			}
		}

		System.out.println(ans);
	}

    public static void main(String[] args)
    {
        new temp().solve();
    }

    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class temp
{
	void solve()
	{
		FastReader sc =new FastReader();
		String s = sc.next();

		int n = s.length();
		int sum[] = new int[n];

		for(int i=0;i<n;i++)
		{
			int number = s.charAt(i)%48;
			if(i==0)
				sum[i] = number;
			else
				sum[i] = sum[i-1] + number;
		}

		int dp[] = new int[n];

		dp[0] = (sum[0]%3==0?1:0);

		for(int i=1;i<n;i++)
		{
			dp[i] = Math.max(dp[i-1],(sum[i]%3==0?1:0));
			for(int j=i-1;j>=0;j--)
			{
				if((sum[i]-sum[j])%3 == 0)
				{
					dp[i] = Math.max(dp[i],dp[j]+1);
					break;
				}
			}
		}

		System.out.println(dp[n-1]);
	}

    public static void main(String[] args)
    {
        new temp().solve();
    }

    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.io.*;
import java.util.stream.Collectors.*;
import java.lang.*;
import static java.util.stream.Collectors.*;
import static java.util.Map.Entry.*;
public class Ideo
{
    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }

static int power(int x,int y)
{
    int res = 1;      // Initialize result

      // Update x if it is more than or
                // equal to p

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y%2==1)
            res = (res*x);

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x);
    }
    return res;
}

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

  static boolean compareSeq(char[] S, int x, int y, int n)
    {
        for (int i = 0; i < n; i++)
         {

            if (S[x] < S[y])
               return true;
            else if (S[x] > S[y])
                return false;
            x = (x + 1) % n;
            y = (y + 1) % n;
        }
        return true;
    }

    static void build(long[] sum,int[] arr,int n)
    {
      for(int i=0;i<(1<<n);i++)
      {
        long total=0;
        for(int j=0;j<n;j++)
        {
          if((i & (1 << j)) > 0)
            total+=arr[j];
        }

        sum[i]=total;
      }
    }

     static int count(long arr[], long x, int n)
       {

        int l=0;
        int h=n-1;

        int res=-1;
        int mid=-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res=mid;
            h=mid-1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res==-1)
          return 0;

        //res is first index and res1 is last index of an element in a sorted array total number of occurences is (res1-res+1)

        int res1=-1;
        l=0;
        h=n-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res1=mid;
            l=mid+1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res1==-1)
          return 0;
        if(res!=-1 && res1!=-1)
          return (res1-res+1);

        return 0;

       }

       static int parity(int a)
       {
    a^=a>>16;
    a^=a>>8;
    a^=a>>4;
    a^=a>>2;
    a^=a>>1;
    return a&1;
  }
/*
  PriorityQueue<aksh> pq = new PriorityQueue<>((o1, o2) -> {
            if (o1.p < o2.p)
                return 1;
            else if (o1.p > o2.p)
                return -1;
            else
                return 0;

        });//decreasing order acc to p*/
static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }
static int modinv(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return 0;
        else
        {
           return power(a, m - 2, m);
        }
        //return 0;
    }

static int[] product(int[] nums) {
    int[] result = new int[nums.length];

    int[] t1 = new int[nums.length];
    int[] t2 = new int[nums.length];

    t1[0]=1;
    t2[nums.length-1]=1;

    //scan from left to right
    for(int i=0; i<nums.length-1; i++){
        t1[i+1] = nums[i] * t1[i];
    }

    //scan from right to left
    for(int i=nums.length-1; i>0; i--){
        t2[i-1] = t2[i] * nums[i];
    }

    for(int i=0;i<nums.length;i++)
      {
        System.out.print(t1[i]+" "+t2[i]);
        System.out.println();
      }

    //multiply
    for(int i=0; i<nums.length; i++){
        result[i] = t1[i] * t2[i];
    }

    return result;
}

static int getsum(int[] bit,int ind)
{
  int sum=0;
  while(ind>0)
  {
    sum+=bit[ind];
    ind-= ind & (-ind);
  }

  return sum;
}

static void update(int[] bit,int max,int ind,int val)
{
  while(ind<=max)
  {
    bit[ind]+=val;
    ind+= ind & (-ind);
  }
}

    //static ArrayList<Integer>[] adj;

    static boolean check(long mid,long a,long b)
    {
      long count=1;
      while(count<=mid)
      {
        count++;
        if(a<b)
          a+=count;
        else
          b+=count;

        if(a==b)
          return true;
      }
        return false;
    }

    static class a1 implements Comparable<a1>
    {
      int p;
      int q;

      public a1(int p,int q)
      {
        this.p=p;
        this.q=q;
      }

      public int compareTo(a1 o)
      {
        return p-o.p;
      }
    }
    static int get(int arr[], int n)
    {
        int result = 0;
        int x, sum;

        // Iterate through every bit
        for(int i=0; i<32; i++)
        {
            // Find sum of set bits at ith position in all
            // array elements
            sum = 0;
            x = (1 << i);
            for(int j=0; j<n; j++)
            {
                if((arr[j] & x)!=0)
                sum++;
            }
            // The bits with sum not multiple of 3, are the
            // bits of element with single occurrence.
            if ((sum % 3)!=0)
            result |= x;
        }
        return result;
    }
    /*        Collections.sort(orders, new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if (o1.diff < o2.diff) {
                    return -1;
                } else if (o1.diff > o2.diff) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });  */

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1) return false;
        if (n <= 3) return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0) return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
            return false;

        return true;
    }

    static int nextPrime(int N)
    {

        // Base case
        if (N <= 1)
            return (2-N);

        int prime = N;
        boolean found = false;

        // Loop continuously until isPrime returns
        // true for a number greater than n
        while (!found)
        {
            if (isPrime(prime))
                {
                  found = true;
                  break;
                }

            prime++;
        }

        return (prime-N);
    }

    static long product(long x)
{
    long prod = 1;
    while (x > 0)
    {
        prod *= (x % 10);
        x /= 10;
    }
    return prod;
}

// This function returns the number having
// maximum product of the digits
static long findNumber(long l, long r)
{
    // Converting both integers to strings
    //string a = l.ToString();
    String b = Long.toString(r);

    // Let the current answer be r
    long ans = r;
    for (int i = 0; i < b.length(); i++)
    {
        if (b.charAt(i) == '0')
            continue;

        // Stores the current number having
        // current digit one less than current
        // digit in b
        char[] curr = b.toCharArray();
        curr[i] = (char)(((int)(curr[i] -
                    (int)'0') - 1) + (int)('0'));

        // Replace all following digits with 9
        // to maximise the product
        for (int j = i + 1; j < curr.length; j++)
            curr[j] = '9';

        // Convert string to number
        int num = 0;
        for (int j = 0; j < curr.length; j++)
            num = num * 10 + (curr[j] - '0');

        // Check if it lies in range and its product
        // is greater than max product
        if (num >= l && product(ans) < product(num))
            ans = num;
    }

    return product(ans);
}

static long mod=998244353;

static long pow(long in, long pow) {
    if(pow == 0) return 1;
    long out = pow(in, pow / 2);
    out = (out * out) % mod;
    if(pow % 2 == 1) out = (out * in) % mod;
    return out;
  }
  static long inv(long in) {
    return pow(in, mod - 2);
  }

  static void swap(int x,int y)
  {
    int temp=x;
    x=y;
    y=temp;
  }

  static int[] par;
  static int[] size;
  static int find(int i)
  {
     if (par[i] == i)
      return i;

    return par[i] = find(par[par[i]]);
  }

  static void union(int x, int y)
  {
      x = find(x);
      y = find(y);
      if (x == y)
        return;
      if (size[x] < size[y])
        swap(x, y);

      par[y] = x;
      size[x] += size[y];
    }

    static void multisourcebfs(long[] arr,int n,int m)
    {
      //HashSet<Long> vis=new HashSet<>();
      HashMap<Long,Long> dis=new HashMap<>();
      Queue<Long> q=new LinkedList<>();

      for(int i=0;i<arr.length;i++)
      {
        dis.put(arr[i],(long)0);
        q.add(arr[i]);
        //vis.add(arr[i]);
      }

      long[] res=new long[m];
      long ans=0;
      int k=0;
      while(!q.isEmpty())
      {
        if(k==m)
          break;
        long x=q.remove();
        if(dis.get(x)!=0)
        {
          ans+=dis.get(x);
          res[k]=x;
          k++;
        }

        if(dis.get(x-1)==null)
        {
          dis.put(x-1, dis.get(x)+1);
          q.add(x-1);
          //vis.add(x-1);
        }

        if(dis.get(x+1)==null)
        {
          dis.put(x+1, dis.get(x)+1);
          q.add(x+1);
          //vis.add(x+1);
        }
      }

      System.out.println(ans);

      for(int i=0;i<m;i++)
        System.out.print(res[i]+" ");

    }

    static final long INF = Long.MAX_VALUE/5;
    static ArrayList<Integer>[] adj;
    public static void main(String args[] ) throws Exception
    {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT */

        FastReader sc=new FastReader();
        String s=sc.next();
        int n=s.length();
        char[] ch=s.toCharArray();

        int sum=0;
        int ans=0;
        int c=0;

        for(int i=0;i<n;i++)
        {
          sum+=(ch[i]-'0')%3;
          if(((ch[i]-'0')%3==0)||(sum%3==0))
            {
              sum=0;
              ans++;
            }
        }

        System.out.println(ans);

      }

    }


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.io.*;
import java.util.stream.Collectors.*;
import java.lang.*;
import static java.util.stream.Collectors.*;
import static java.util.Map.Entry.*;
public class Ideo
{
    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }

static int power(int x,int y)
{
    int res = 1;      // Initialize result

      // Update x if it is more than or
                // equal to p

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y%2==1)
            res = (res*x);

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x);
    }
    return res;
}

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

  static boolean compareSeq(char[] S, int x, int y, int n)
    {
        for (int i = 0; i < n; i++)
         {

            if (S[x] < S[y])
               return true;
            else if (S[x] > S[y])
                return false;
            x = (x + 1) % n;
            y = (y + 1) % n;
        }
        return true;
    }

    static void build(long[] sum,int[] arr,int n)
    {
      for(int i=0;i<(1<<n);i++)
      {
        long total=0;
        for(int j=0;j<n;j++)
        {
          if((i & (1 << j)) > 0)
            total+=arr[j];
        }

        sum[i]=total;
      }
    }

     static int count(long arr[], long x, int n)
       {

        int l=0;
        int h=n-1;

        int res=-1;
        int mid=-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res=mid;
            h=mid-1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res==-1)
          return 0;

        //res is first index and res1 is last index of an element in a sorted array total number of occurences is (res1-res+1)

        int res1=-1;
        l=0;
        h=n-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res1=mid;
            l=mid+1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res1==-1)
          return 0;
        if(res!=-1 && res1!=-1)
          return (res1-res+1);

        return 0;

       }

       static int parity(int a)
       {
    a^=a>>16;
    a^=a>>8;
    a^=a>>4;
    a^=a>>2;
    a^=a>>1;
    return a&1;
  }
/*
  PriorityQueue<aksh> pq = new PriorityQueue<>((o1, o2) -> {
            if (o1.p < o2.p)
                return 1;
            else if (o1.p > o2.p)
                return -1;
            else
                return 0;

        });//decreasing order acc to p*/
static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }
static int modinv(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return 0;
        else
        {
           return power(a, m - 2, m);
        }
        //return 0;
    }

static int[] product(int[] nums) {
    int[] result = new int[nums.length];

    int[] t1 = new int[nums.length];
    int[] t2 = new int[nums.length];

    t1[0]=1;
    t2[nums.length-1]=1;

    //scan from left to right
    for(int i=0; i<nums.length-1; i++){
        t1[i+1] = nums[i] * t1[i];
    }

    //scan from right to left
    for(int i=nums.length-1; i>0; i--){
        t2[i-1] = t2[i] * nums[i];
    }

    for(int i=0;i<nums.length;i++)
      {
        System.out.print(t1[i]+" "+t2[i]);
        System.out.println();
      }

    //multiply
    for(int i=0; i<nums.length; i++){
        result[i] = t1[i] * t2[i];
    }

    return result;
}

static int getsum(int[] bit,int ind)
{
  int sum=0;
  while(ind>0)
  {
    sum+=bit[ind];
    ind-= ind & (-ind);
  }

  return sum;
}

static void update(int[] bit,int max,int ind,int val)
{
  while(ind<=max)
  {
    bit[ind]+=val;
    ind+= ind & (-ind);
  }
}

    //static ArrayList<Integer>[] adj;

    static boolean check(long mid,long a,long b)
    {
      long count=1;
      while(count<=mid)
      {
        count++;
        if(a<b)
          a+=count;
        else
          b+=count;

        if(a==b)
          return true;
      }
        return false;
    }

    static class a1 implements Comparable<a1>
    {
      int p;
      int q;

      public a1(int p,int q)
      {
        this.p=p;
        this.q=q;
      }

      public int compareTo(a1 o)
      {
        return p-o.p;
      }
    }
    static int get(int arr[], int n)
    {
        int result = 0;
        int x, sum;

        // Iterate through every bit
        for(int i=0; i<32; i++)
        {
            // Find sum of set bits at ith position in all
            // array elements
            sum = 0;
            x = (1 << i);
            for(int j=0; j<n; j++)
            {
                if((arr[j] & x)!=0)
                sum++;
            }
            // The bits with sum not multiple of 3, are the
            // bits of element with single occurrence.
            if ((sum % 3)!=0)
            result |= x;
        }
        return result;
    }
    /*        Collections.sort(orders, new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if (o1.diff < o2.diff) {
                    return -1;
                } else if (o1.diff > o2.diff) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });  */

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1) return false;
        if (n <= 3) return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0) return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
            return false;

        return true;
    }

    static int nextPrime(int N)
    {

        // Base case
        if (N <= 1)
            return (2-N);

        int prime = N;
        boolean found = false;

        // Loop continuously until isPrime returns
        // true for a number greater than n
        while (!found)
        {
            if (isPrime(prime))
                {
                  found = true;
                  break;
                }

            prime++;
        }

        return (prime-N);
    }

    static long product(long x)
{
    long prod = 1;
    while (x > 0)
    {
        prod *= (x % 10);
        x /= 10;
    }
    return prod;
}

// This function returns the number having
// maximum product of the digits
static long findNumber(long l, long r)
{
    // Converting both integers to strings
    //string a = l.ToString();
    String b = Long.toString(r);

    // Let the current answer be r
    long ans = r;
    for (int i = 0; i < b.length(); i++)
    {
        if (b.charAt(i) == '0')
            continue;

        // Stores the current number having
        // current digit one less than current
        // digit in b
        char[] curr = b.toCharArray();
        curr[i] = (char)(((int)(curr[i] -
                    (int)'0') - 1) + (int)('0'));

        // Replace all following digits with 9
        // to maximise the product
        for (int j = i + 1; j < curr.length; j++)
            curr[j] = '9';

        // Convert string to number
        int num = 0;
        for (int j = 0; j < curr.length; j++)
            num = num * 10 + (curr[j] - '0');

        // Check if it lies in range and its product
        // is greater than max product
        if (num >= l && product(ans) < product(num))
            ans = num;
    }

    return product(ans);
}

static long mod=998244353;

static long pow(long in, long pow) {
    if(pow == 0) return 1;
    long out = pow(in, pow / 2);
    out = (out * out) % mod;
    if(pow % 2 == 1) out = (out * in) % mod;
    return out;
  }
  static long inv(long in) {
    return pow(in, mod - 2);
  }

  static void swap(int x,int y)
  {
    int temp=x;
    x=y;
    y=temp;
  }

  static int[] par;
  static int[] size;
  static int find(int i)
  {
     if (par[i] == i)
      return i;

    return par[i] = find(par[par[i]]);
  }

  static void union(int x, int y)
  {
      x = find(x);
      y = find(y);
      if (x == y)
        return;
      if (size[x] < size[y])
        swap(x, y);

      par[y] = x;
      size[x] += size[y];
    }

    static void multisourcebfs(long[] arr,int n,int m)
    {
      //HashSet<Long> vis=new HashSet<>();
      HashMap<Long,Long> dis=new HashMap<>();
      Queue<Long> q=new LinkedList<>();

      for(int i=0;i<arr.length;i++)
      {
        dis.put(arr[i],(long)0);
        q.add(arr[i]);
        //vis.add(arr[i]);
      }

      long[] res=new long[m];
      long ans=0;
      int k=0;
      while(!q.isEmpty())
      {
        if(k==m)
          break;
        long x=q.remove();
        if(dis.get(x)!=0)
        {
          ans+=dis.get(x);
          res[k]=x;
          k++;
        }

        if(dis.get(x-1)==null)
        {
          dis.put(x-1, dis.get(x)+1);
          q.add(x-1);
          //vis.add(x-1);
        }

        if(dis.get(x+1)==null)
        {
          dis.put(x+1, dis.get(x)+1);
          q.add(x+1);
          //vis.add(x+1);
        }
      }

      System.out.println(ans);

      for(int i=0;i<m;i++)
        System.out.print(res[i]+" ");

    }

    static final long INF = Long.MAX_VALUE/5;
    static ArrayList<Integer>[] adj;
    public static void main(String args[] ) throws Exception
    {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT */

        FastReader sc=new FastReader();
        String s=sc.next();
        int n=s.length();
        char[] ch=s.toCharArray();

        int sum=0;
        int ans=0;
        int c=0;

        for(int i=0;i<n;i++)
        {
          sum+=(ch[i]-'0');
          if(((ch[i]-'0')%3==0)||(sum%3==0))
            {
              sum=0;
              ans++;
            }
        }

        System.out.println(ans);

      }

    }


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.io.*;
import java.util.stream.Collectors.*;
import java.lang.*;
import static java.util.stream.Collectors.*;
import static java.util.Map.Entry.*;
public class Ideo
{
    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }

static int power(int x,int y)
{
    int res = 1;      // Initialize result

      // Update x if it is more than or
                // equal to p

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y%2==1)
            res = (res*x);

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x);
    }
    return res;
}

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

  static boolean compareSeq(char[] S, int x, int y, int n)
    {
        for (int i = 0; i < n; i++)
         {

            if (S[x] < S[y])
               return true;
            else if (S[x] > S[y])
                return false;
            x = (x + 1) % n;
            y = (y + 1) % n;
        }
        return true;
    }

    static void build(long[] sum,int[] arr,int n)
    {
      for(int i=0;i<(1<<n);i++)
      {
        long total=0;
        for(int j=0;j<n;j++)
        {
          if((i & (1 << j)) > 0)
            total+=arr[j];
        }

        sum[i]=total;
      }
    }

     static int count(long arr[], long x, int n)
       {

        int l=0;
        int h=n-1;

        int res=-1;
        int mid=-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res=mid;
            h=mid-1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res==-1)
          return 0;

        //res is first index and res1 is last index of an element in a sorted array total number of occurences is (res1-res+1)

        int res1=-1;
        l=0;
        h=n-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res1=mid;
            l=mid+1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res1==-1)
          return 0;
        if(res!=-1 && res1!=-1)
          return (res1-res+1);

        return 0;

       }

       static int parity(int a)
       {
    a^=a>>16;
    a^=a>>8;
    a^=a>>4;
    a^=a>>2;
    a^=a>>1;
    return a&1;
  }
/*
  PriorityQueue<aksh> pq = new PriorityQueue<>((o1, o2) -> {
            if (o1.p < o2.p)
                return 1;
            else if (o1.p > o2.p)
                return -1;
            else
                return 0;

        });//decreasing order acc to p*/
static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }
static int modinv(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return 0;
        else
        {
           return power(a, m - 2, m);
        }
        //return 0;
    }

static int[] product(int[] nums) {
    int[] result = new int[nums.length];

    int[] t1 = new int[nums.length];
    int[] t2 = new int[nums.length];

    t1[0]=1;
    t2[nums.length-1]=1;

    //scan from left to right
    for(int i=0; i<nums.length-1; i++){
        t1[i+1] = nums[i] * t1[i];
    }

    //scan from right to left
    for(int i=nums.length-1; i>0; i--){
        t2[i-1] = t2[i] * nums[i];
    }

    for(int i=0;i<nums.length;i++)
      {
        System.out.print(t1[i]+" "+t2[i]);
        System.out.println();
      }

    //multiply
    for(int i=0; i<nums.length; i++){
        result[i] = t1[i] * t2[i];
    }

    return result;
}

static int getsum(int[] bit,int ind)
{
  int sum=0;
  while(ind>0)
  {
    sum+=bit[ind];
    ind-= ind & (-ind);
  }

  return sum;
}

static void update(int[] bit,int max,int ind,int val)
{
  while(ind<=max)
  {
    bit[ind]+=val;
    ind+= ind & (-ind);
  }
}

    //static ArrayList<Integer>[] adj;

    static boolean check(long mid,long a,long b)
    {
      long count=1;
      while(count<=mid)
      {
        count++;
        if(a<b)
          a+=count;
        else
          b+=count;

        if(a==b)
          return true;
      }
        return false;
    }

    static class a1 implements Comparable<a1>
    {
      int p;
      int q;

      public a1(int p,int q)
      {
        this.p=p;
        this.q=q;
      }

      public int compareTo(a1 o)
      {
        return p-o.p;
      }
    }
    static int get(int arr[], int n)
    {
        int result = 0;
        int x, sum;

        // Iterate through every bit
        for(int i=0; i<32; i++)
        {
            // Find sum of set bits at ith position in all
            // array elements
            sum = 0;
            x = (1 << i);
            for(int j=0; j<n; j++)
            {
                if((arr[j] & x)!=0)
                sum++;
            }
            // The bits with sum not multiple of 3, are the
            // bits of element with single occurrence.
            if ((sum % 3)!=0)
            result |= x;
        }
        return result;
    }
    /*        Collections.sort(orders, new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if (o1.diff < o2.diff) {
                    return -1;
                } else if (o1.diff > o2.diff) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });  */

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1) return false;
        if (n <= 3) return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0) return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
            return false;

        return true;
    }

    static int nextPrime(int N)
    {

        // Base case
        if (N <= 1)
            return (2-N);

        int prime = N;
        boolean found = false;

        // Loop continuously until isPrime returns
        // true for a number greater than n
        while (!found)
        {
            if (isPrime(prime))
                {
                  found = true;
                  break;
                }

            prime++;
        }

        return (prime-N);
    }

    static long product(long x)
{
    long prod = 1;
    while (x > 0)
    {
        prod *= (x % 10);
        x /= 10;
    }
    return prod;
}

// This function returns the number having
// maximum product of the digits
static long findNumber(long l, long r)
{
    // Converting both integers to strings
    //string a = l.ToString();
    String b = Long.toString(r);

    // Let the current answer be r
    long ans = r;
    for (int i = 0; i < b.length(); i++)
    {
        if (b.charAt(i) == '0')
            continue;

        // Stores the current number having
        // current digit one less than current
        // digit in b
        char[] curr = b.toCharArray();
        curr[i] = (char)(((int)(curr[i] -
                    (int)'0') - 1) + (int)('0'));

        // Replace all following digits with 9
        // to maximise the product
        for (int j = i + 1; j < curr.length; j++)
            curr[j] = '9';

        // Convert string to number
        int num = 0;
        for (int j = 0; j < curr.length; j++)
            num = num * 10 + (curr[j] - '0');

        // Check if it lies in range and its product
        // is greater than max product
        if (num >= l && product(ans) < product(num))
            ans = num;
    }

    return product(ans);
}

static long mod=998244353;

static long pow(long in, long pow) {
    if(pow == 0) return 1;
    long out = pow(in, pow / 2);
    out = (out * out) % mod;
    if(pow % 2 == 1) out = (out * in) % mod;
    return out;
  }
  static long inv(long in) {
    return pow(in, mod - 2);
  }

  static void swap(int x,int y)
  {
    int temp=x;
    x=y;
    y=temp;
  }

  static int[] par;
  static int[] size;
  static int find(int i)
  {
     if (par[i] == i)
      return i;

    return par[i] = find(par[par[i]]);
  }

  static void union(int x, int y)
  {
      x = find(x);
      y = find(y);
      if (x == y)
        return;
      if (size[x] < size[y])
        swap(x, y);

      par[y] = x;
      size[x] += size[y];
    }

    static void multisourcebfs(long[] arr,int n,int m)
    {
      //HashSet<Long> vis=new HashSet<>();
      HashMap<Long,Long> dis=new HashMap<>();
      Queue<Long> q=new LinkedList<>();

      for(int i=0;i<arr.length;i++)
      {
        dis.put(arr[i],(long)0);
        q.add(arr[i]);
        //vis.add(arr[i]);
      }

      long[] res=new long[m];
      long ans=0;
      int k=0;
      while(!q.isEmpty())
      {
        if(k==m)
          break;
        long x=q.remove();
        if(dis.get(x)!=0)
        {
          ans+=dis.get(x);
          res[k]=x;
          k++;
        }

        if(dis.get(x-1)==null)
        {
          dis.put(x-1, dis.get(x)+1);
          q.add(x-1);
          //vis.add(x-1);
        }

        if(dis.get(x+1)==null)
        {
          dis.put(x+1, dis.get(x)+1);
          q.add(x+1);
          //vis.add(x+1);
        }
      }

      System.out.println(ans);

      for(int i=0;i<m;i++)
        System.out.print(res[i]+" ");

    }

    static final long INF = Long.MAX_VALUE/5;
    static ArrayList<Integer>[] adj;
    public static void main(String args[] ) throws Exception
    {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT */

        FastReader sc=new FastReader();
        String s=sc.next();
        int n=s.length();
        int[] pref=new int[n];
        char[] ch=s.toCharArray();

        for(int i=0;i<n;i++)
        {
          if(i==0)
            pref[i]=ch[i]-'0';
          else
            pref[i]=pref[i-1]+(ch[i]-'0');
        }

        for(int i=0;i<n;i++)
          pref[i]=pref[i]%3;

        int[] rem=new int[3];
        Arrays.fill(rem,-1);

        int[] dp=new int[n];

        int ans=0;
        for(int i=0;i<n;i++)
        {
          int prev = rem[pref[i]];
          if((int)(ch[i]-'0')%3==0)
          {
            if(i==0)
              dp[i]=1;
            else
              dp[i]=dp[i-1]+1;
          }
          else if(prev!=-1)
          {
            if(i==0)
              {
                rem[pref[i]]=i;
                continue;
              }
            else
              dp[i]=Math.max(dp[i-1],dp[prev]+1);
          }

          rem[pref[i]]=i;
        }

        System.out.println(dp[n-1]);

      }

    }


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.StringTokenizer;
import java.io.PrintWriter;
import java.io.*;
import java.util.stream.Collectors.*;
import java.lang.*;
import static java.util.stream.Collectors.*;
import static java.util.Map.Entry.*;
public class Ideo
{
    static class FastReader
    {
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

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

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }

static int power(int x,int y)
{
    int res = 1;      // Initialize result

      // Update x if it is more than or
                // equal to p

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y%2==1)
            res = (res*x);

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x);
    }
    return res;
}

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

  static boolean compareSeq(char[] S, int x, int y, int n)
    {
        for (int i = 0; i < n; i++)
         {

            if (S[x] < S[y])
               return true;
            else if (S[x] > S[y])
                return false;
            x = (x + 1) % n;
            y = (y + 1) % n;
        }
        return true;
    }

    static void build(long[] sum,int[] arr,int n)
    {
      for(int i=0;i<(1<<n);i++)
      {
        long total=0;
        for(int j=0;j<n;j++)
        {
          if((i & (1 << j)) > 0)
            total+=arr[j];
        }

        sum[i]=total;
      }
    }

     static int count(long arr[], long x, int n)
       {

        int l=0;
        int h=n-1;

        int res=-1;
        int mid=-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res=mid;
            h=mid-1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res==-1)
          return 0;

        //res is first index and res1 is last index of an element in a sorted array total number of occurences is (res1-res+1)

        int res1=-1;
        l=0;
        h=n-1;
        while(l<=h)
        {
          mid=l+(h-l)/2;
          if(x==arr[mid])
          {
            res1=mid;
            l=mid+1;
          }
          else if(x<arr[mid])
            h=mid-1;
          else
            l=mid+1;
        }

        if(res1==-1)
          return 0;
        if(res!=-1 && res1!=-1)
          return (res1-res+1);

        return 0;

       }

       static int parity(int a)
       {
    a^=a>>16;
    a^=a>>8;
    a^=a>>4;
    a^=a>>2;
    a^=a>>1;
    return a&1;
  }
/*
  PriorityQueue<aksh> pq = new PriorityQueue<>((o1, o2) -> {
            if (o1.p < o2.p)
                return 1;
            else if (o1.p > o2.p)
                return -1;
            else
                return 0;

        });//decreasing order acc to p*/
static int power(int x, int y, int m)
    {
        if (y == 0)
            return 1;

        int p = power(x, y / 2, m) % m;
        p = (p * p) % m;

        if (y % 2 == 0)
            return p;
        else
            return (x * p) % m;
    }
static int modinv(int a, int m)
    {
        int g = gcd(a, m);
        if (g != 1)
            return 0;
        else
        {
           return power(a, m - 2, m);
        }
        //return 0;
    }

static int[] product(int[] nums) {
    int[] result = new int[nums.length];

    int[] t1 = new int[nums.length];
    int[] t2 = new int[nums.length];

    t1[0]=1;
    t2[nums.length-1]=1;

    //scan from left to right
    for(int i=0; i<nums.length-1; i++){
        t1[i+1] = nums[i] * t1[i];
    }

    //scan from right to left
    for(int i=nums.length-1; i>0; i--){
        t2[i-1] = t2[i] * nums[i];
    }

    for(int i=0;i<nums.length;i++)
      {
        System.out.print(t1[i]+" "+t2[i]);
        System.out.println();
      }

    //multiply
    for(int i=0; i<nums.length; i++){
        result[i] = t1[i] * t2[i];
    }

    return result;
}

static int getsum(int[] bit,int ind)
{
  int sum=0;
  while(ind>0)
  {
    sum+=bit[ind];
    ind-= ind & (-ind);
  }

  return sum;
}

static void update(int[] bit,int max,int ind,int val)
{
  while(ind<=max)
  {
    bit[ind]+=val;
    ind+= ind & (-ind);
  }
}

    //static ArrayList<Integer>[] adj;

    static boolean check(long mid,long a,long b)
    {
      long count=1;
      while(count<=mid)
      {
        count++;
        if(a<b)
          a+=count;
        else
          b+=count;

        if(a==b)
          return true;
      }
        return false;
    }

    static class a1 implements Comparable<a1>
    {
      int p;
      int q;

      public a1(int p,int q)
      {
        this.p=p;
        this.q=q;
      }

      public int compareTo(a1 o)
      {
        return p-o.p;
      }
    }
    static int get(int arr[], int n)
    {
        int result = 0;
        int x, sum;

        // Iterate through every bit
        for(int i=0; i<32; i++)
        {
            // Find sum of set bits at ith position in all
            // array elements
            sum = 0;
            x = (1 << i);
            for(int j=0; j<n; j++)
            {
                if((arr[j] & x)!=0)
                sum++;
            }
            // The bits with sum not multiple of 3, are the
            // bits of element with single occurrence.
            if ((sum % 3)!=0)
            result |= x;
        }
        return result;
    }
    /*        Collections.sort(orders, new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if (o1.diff < o2.diff) {
                    return -1;
                } else if (o1.diff > o2.diff) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });  */

    static boolean isPrime(int n)
    {
        // Corner cases
        if (n <= 1) return false;
        if (n <= 3) return true;

        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0) return false;

        for (int i = 5; i * i <= n; i = i + 6)
            if (n % i == 0 || n % (i + 2) == 0)
            return false;

        return true;
    }

    static int nextPrime(int N)
    {

        // Base case
        if (N <= 1)
            return (2-N);

        int prime = N;
        boolean found = false;

        // Loop continuously until isPrime returns
        // true for a number greater than n
        while (!found)
        {
            if (isPrime(prime))
                {
                  found = true;
                  break;
                }

            prime++;
        }

        return (prime-N);
    }

    static long product(long x)
{
    long prod = 1;
    while (x > 0)
    {
        prod *= (x % 10);
        x /= 10;
    }
    return prod;
}

// This function returns the number having
// maximum product of the digits
static long findNumber(long l, long r)
{
    // Converting both integers to strings
    //string a = l.ToString();
    String b = Long.toString(r);

    // Let the current answer be r
    long ans = r;
    for (int i = 0; i < b.length(); i++)
    {
        if (b.charAt(i) == '0')
            continue;

        // Stores the current number having
        // current digit one less than current
        // digit in b
        char[] curr = b.toCharArray();
        curr[i] = (char)(((int)(curr[i] -
                    (int)'0') - 1) + (int)('0'));

        // Replace all following digits with 9
        // to maximise the product
        for (int j = i + 1; j < curr.length; j++)
            curr[j] = '9';

        // Convert string to number
        int num = 0;
        for (int j = 0; j < curr.length; j++)
            num = num * 10 + (curr[j] - '0');

        // Check if it lies in range and its product
        // is greater than max product
        if (num >= l && product(ans) < product(num))
            ans = num;
    }

    return product(ans);
}

static long mod=998244353;

static long pow(long in, long pow) {
    if(pow == 0) return 1;
    long out = pow(in, pow / 2);
    out = (out * out) % mod;
    if(pow % 2 == 1) out = (out * in) % mod;
    return out;
  }
  static long inv(long in) {
    return pow(in, mod - 2);
  }

  static void swap(int x,int y)
  {
    int temp=x;
    x=y;
    y=temp;
  }

  static int[] par;
  static int[] size;
  static int find(int i)
  {
     if (par[i] == i)
      return i;

    return par[i] = find(par[par[i]]);
  }

  static void union(int x, int y)
  {
      x = find(x);
      y = find(y);
      if (x == y)
        return;
      if (size[x] < size[y])
        swap(x, y);

      par[y] = x;
      size[x] += size[y];
    }

    static void multisourcebfs(long[] arr,int n,int m)
    {
      //HashSet<Long> vis=new HashSet<>();
      HashMap<Long,Long> dis=new HashMap<>();
      Queue<Long> q=new LinkedList<>();

      for(int i=0;i<arr.length;i++)
      {
        dis.put(arr[i],(long)0);
        q.add(arr[i]);
        //vis.add(arr[i]);
      }

      long[] res=new long[m];
      long ans=0;
      int k=0;
      while(!q.isEmpty())
      {
        if(k==m)
          break;
        long x=q.remove();
        if(dis.get(x)!=0)
        {
          ans+=dis.get(x);
          res[k]=x;
          k++;
        }

        if(dis.get(x-1)==null)
        {
          dis.put(x-1, dis.get(x)+1);
          q.add(x-1);
          //vis.add(x-1);
        }

        if(dis.get(x+1)==null)
        {
          dis.put(x+1, dis.get(x)+1);
          q.add(x+1);
          //vis.add(x+1);
        }
      }

      System.out.println(ans);

      for(int i=0;i<m;i++)
        System.out.print(res[i]+" ");

    }

    static final long INF = Long.MAX_VALUE/5;
    static ArrayList<Integer>[] adj;
    public static void main(String args[] ) throws Exception
    {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT */

        FastReader sc=new FastReader();
        String s=sc.next();
        int n=s.length();
        char[] ch=s.toCharArray();

        int sum=0;
        int ans=0;
        int c=0;

        for(int i=0;i<n;i++)
        {
          sum+=(ch[i]-'0');
          if(((ch[i]-'0')%3==0)||(c==2)||(sum%3==0))
            {
              c=0;
              sum=0;
              ans++;
            }
          else
            {
              c++;
            }
        }

        System.out.println(ans);

      }

    }


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

		public class temp
		{
			static TreeSet<pair>[] adj;
			static int v;
			static int e;
			static int ans = 0;

			public static void main(String[] args)
			{
				InputReader in = new InputReader(System.in);
				PrintWriter pw = new PrintWriter(System.out);

				String s = in.nextLine();
				int n = s.length();
				int[] a = new int[n];

				int mod = 0, ans = 0, sum = 0;

				for(int i=0;i<n;i++)
					a[i] = s.charAt(i) - '0';

				for(int i=0;i<n;i++)
				{
					mod = a[i]%3;

					if(mod == 0)
					{
						ans++;
						sum = 0;
					}
					else
					{
						sum += mod;
						sum %= 3;

						if(sum == 0)
							ans++;
					}
				}

				pw.println(ans);

				pw.flush();
				pw.close();
			}

			static class pair implements Comparable<pair>
			{
				Integer x, y;
				pair(int x,int y)
				{
					this.x=x;
					this.y=y;
				}

				public int compareTo(pair o) {
					int result = x.compareTo(o.x);
					if(result==0)
						result = y.compareTo(o.y);

					return result;
				}

				public String toString()
				{
					return x+" "+y;
				}

				public boolean equals(Object o)
				{
					if (o instanceof pair)
				    {
						pair p = (pair)o;
						return p.x - x == 0 && p.y - y == 0 ;
					}
					return false;
				}

				public int hashCode()
				{
					return new Long(x).hashCode()*31 + new Long(y).hashCode();
				}
			}

			static class InputReader
			{

				private final InputStream stream;
				private final byte[] buf = new byte[8192];
				private int curChar, snumChars;
				private SpaceCharFilter filter;

				public InputReader(InputStream stream)
				{
					this.stream = stream;
				}

				public int snext()
				{
					if (snumChars == -1)
						throw new InputMismatchException();
					if (curChar >= snumChars)
					{
						curChar = 0;
						try
						{
							snumChars = stream.read(buf);
						}
						catch (IOException e)
						{
							throw new InputMismatchException();
						}
						if (snumChars <= 0)
							return -1;
					}
					return buf[curChar++];
				}

				public int nextInt()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					int sgn = 1;
					if (c == '-')
				    {
						sgn = -1;
						c = snext();
					}
					int res = 0;
					do
					{
						if (c < '0' || c > '9')
							throw new InputMismatchException();
						res *= 10;
						res += c - '0';
						c = snext();
					} while (!isSpaceChar(c));
					return res * sgn;
				}

				public long nextLong()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					int sgn = 1;
					if (c == '-')
					{
						sgn = -1;
						c = snext();
					}
					long res = 0;
					do
					{
						if (c < '0' || c > '9')
							throw new InputMismatchException();
						res *= 10;
						res += c - '0';
						c = snext();
					} while (!isSpaceChar(c));
					return res * sgn;
				}

				public int[] nextIntArray(int n)
				{
					int a[] = new int[n];
					for (int i = 0; i < n; i++)
					{
						a[i] = nextInt();
					}
					return a;
				}

				public String readString()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					StringBuilder res = new StringBuilder();
					do
					{
						res.appendCodePoint(c);
						c = snext();
					} while (!isSpaceChar(c));
					return res.toString();
				}

				public String nextLine()
				{
					int c = snext();
					while (isSpaceChar(c))
						c = snext();
					StringBuilder res = new StringBuilder();
					do
					{
						res.appendCodePoint(c);
						c = snext();
					} while (!isEndOfLine(c));
					return res.toString();
				}

				public boolean isSpaceChar(int c)
				{
					if (filter != null)
						return filter.isSpaceChar(c);
					return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
				}

				private boolean isEndOfLine(int c)
				{
					return c == '\n' || c == '\r' || c == -1;
				}

				public interface SpaceCharFilter
			    {
					public boolean isSpaceChar(int ch);
				}
			}

			static class CodeX {
	        public static void sort(long arr[]) {
	            merge_sort(arr, 0, arr.length - 1);
	        }

	        private static void merge_sort(long A[], long start, long end) {
	            if (start < end) {
	                long mid = (start + end) / 2;
	                merge_sort(A, start, mid);
	                merge_sort(A, mid + 1, end);
	                merge(A, start, mid, end);
	            }

	        }

	        private static void merge(long A[], long start,long mid, long end) {
	            long p = start, q = mid + 1;
	            long Arr[] = new long[(int)(end - start + 1)];
	            long k = 0;

	            for (int i = (int)start; i <= end; i++) {
	                if (p > mid)
	                    Arr[(int)k++] = A[(int)q++];

	                else if (q > end)
	                    Arr[(int)k++] = A[(int)p++];

	                else if (A[(int)p] < A[(int)q])
	                    Arr[(int)k++] = A[(int)p++];

	                else
	                    Arr[(int)k++] = A[(int)q++];
	            }
	            for (int i = 0; i < k; i++) {
	                A[(int)start++] = Arr[i];
	            }

	        }

	    }
		}


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

		public class temp
		{
			public static void main(String[] args)
			{
				InputReader in = new InputReader(System.in);
				PrintWriter pw = new PrintWriter(System.out);

				String s = in.nextLine();
				int n = s.length();
				int[] a = new int[n];
				int[] ans = new int[6];
				int count = 0;

				for(int i=0;i<n;i++)
					a[i] = s.charAt(i) - '0';

				int i = 0, j = 0;

				while(i + 2 < n)
				{
					for(j=i;j<i+3;j++)
						ans[j-i] = a[j]%3;

					ans[3] = ans[2];
					ans[2] = (ans[0] + ans[1])%3;
					ans[4] = (ans[1] + ans[3])%3;
					ans[5] = (ans[0] + ans[1] + ans[3])%3;

					for(int k=0;k<6;k++)
					{
						if(ans[k]%3 == 0)
						{
							count++;

							if(k < 2)
								i += k + 1;
							else if(k < 4)
								i += k;
							else if(k == 4)
								i += k - 1;
							else
								i += k - 2;

							break;
						}
					}
				}

				if(i < n)
				{
					if(a[i]%3 == 0)
						count++;

					i++;

					if(i < n)
					{
						if(a[i]%3 == 0)
							count++;
						else if((a[i-1] + a[i])%3 == 0)
							count++;
					}
				}

				pw.println(count);

				pw.flush();
				pw.close();
			}

			static class pair implements Comparable<pair>
			{
				Integer x, y;
				pair(int x,int y)
				{
					this.x=x;
					this.y=y;
				}

				public int compareTo(pair o) {
					int result = x.compareTo(o.x);
					if(result==0)
						result = y.compareTo(o.y);

					return result;
				}

				public String toString()
				{
					return x+" "+y;
				}

				public boolean equals(Object o)
				{
					if (o instanceof pair)
				    {
						pair p = (pair)o;
						return p.x - x == 0 && p.y - y == 0 ;
					}
					return false;
				}

				public int hashCode()
				{
					return new Long(x).hashCode()*31 + new Long(y).hashCode();
				}
			}

			static class InputReader
			{

				private final InputStream stream;
				private final byte[] buf = new byte[8192];
				private int curChar, snumChars;
				private SpaceCharFilter filter;

				public InputReader(InputStream stream)
				{
					this.stream = stream;
				}

				public int snext()
				{
					if (snumChars == -1)
						throw new InputMismatchException();
					if (curChar >= snumChars)
					{
						curChar = 0;
						try
						{
							snumChars = stream.read(buf);
						}
						catch (IOException e)
						{
							throw new InputMismatchException();
						}
						if (snumChars <= 0)
							return -1;
					}
					return buf[curChar++];
				}

				public int nextInt()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					int sgn = 1;
					if (c == '-')
				    {
						sgn = -1;
						c = snext();
					}
					int res = 0;
					do
					{
						if (c < '0' || c > '9')
							throw new InputMismatchException();
						res *= 10;
						res += c - '0';
						c = snext();
					} while (!isSpaceChar(c));
					return res * sgn;
				}

				public long nextLong()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					int sgn = 1;
					if (c == '-')
					{
						sgn = -1;
						c = snext();
					}
					long res = 0;
					do
					{
						if (c < '0' || c > '9')
							throw new InputMismatchException();
						res *= 10;
						res += c - '0';
						c = snext();
					} while (!isSpaceChar(c));
					return res * sgn;
				}

				public int[] nextIntArray(int n)
				{
					int a[] = new int[n];
					for (int i = 0; i < n; i++)
					{
						a[i] = nextInt();
					}
					return a;
				}

				public String readString()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					StringBuilder res = new StringBuilder();
					do
					{
						res.appendCodePoint(c);
						c = snext();
					} while (!isSpaceChar(c));
					return res.toString();
				}

				public String nextLine()
				{
					int c = snext();
					while (isSpaceChar(c))
						c = snext();
					StringBuilder res = new StringBuilder();
					do
					{
						res.appendCodePoint(c);
						c = snext();
					} while (!isEndOfLine(c));
					return res.toString();
				}

				public boolean isSpaceChar(int c)
				{
					if (filter != null)
						return filter.isSpaceChar(c);
					return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
				}

				private boolean isEndOfLine(int c)
				{
					return c == '\n' || c == '\r' || c == -1;
				}

				public interface SpaceCharFilter
			    {
					public boolean isSpaceChar(int ch);
				}
			}

			static class CodeX {
	        public static void sort(long arr[]) {
	            merge_sort(arr, 0, arr.length - 1);
	        }

	        private static void merge_sort(long A[], long start, long end) {
	            if (start < end) {
	                long mid = (start + end) / 2;
	                merge_sort(A, start, mid);
	                merge_sort(A, mid + 1, end);
	                merge(A, start, mid, end);
	            }

	        }

	        private static void merge(long A[], long start,long mid, long end) {
	            long p = start, q = mid + 1;
	            long Arr[] = new long[(int)(end - start + 1)];
	            long k = 0;

	            for (int i = (int)start; i <= end; i++) {
	                if (p > mid)
	                    Arr[(int)k++] = A[(int)q++];

	                else if (q > end)
	                    Arr[(int)k++] = A[(int)p++];

	                else if (A[(int)p] < A[(int)q])
	                    Arr[(int)k++] = A[(int)p++];

	                else
	                    Arr[(int)k++] = A[(int)q++];
	            }
	            for (int i = 0; i < k; i++) {
	                A[(int)start++] = Arr[i];
	            }

	        }

	    }
		}


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

		public class temp
		{
			public static void main(String[] args)
			{
				InputReader in = new InputReader(System.in);
				PrintWriter pw = new PrintWriter(System.out);

				String s = in.nextLine();
				int n = s.length();
				int[] a = new int[n];
				int[] ans = new int[6];
				int count = 0;

				for(int i=0;i<n;i++)
					a[i] = s.charAt(i) - '0';

				int i = 0, j = 0;

				while(i + 2 < n)
				{
					for(j=i;j<i+3;j++)
						ans[j-i] = a[j]%3;

					ans[3] = (ans[0] + ans[1])%3;
					ans[4] = (ans[1] + ans[2])%3;
					ans[5] = (ans[0] + ans[1] + ans[2])%3;

					for(int k=0;k<6;k++)
					{
						if(ans[k]%3 == 0)
						{
							count++;

							if(k < 3)
								i += k + 1;
							else if(k < 5)
								i += k - 1;
							else
								i += k - 2;

							break;
						}
					}
				}

				if(i < n)
				{
					if(a[i]%3 == 0)
						count++;

					i++;

					if(i < n)
					{
						if(a[i]%3 == 0)
							count++;
						else if((a[i-1] + a[i])%3 == 0)
							count++;
					}
				}

				pw.println(count);

				pw.flush();
				pw.close();
			}

			static class pair implements Comparable<pair>
			{
				Integer x, y;
				pair(int x,int y)
				{
					this.x=x;
					this.y=y;
				}

				public int compareTo(pair o) {
					int result = x.compareTo(o.x);
					if(result==0)
						result = y.compareTo(o.y);

					return result;
				}

				public String toString()
				{
					return x+" "+y;
				}

				public boolean equals(Object o)
				{
					if (o instanceof pair)
				    {
						pair p = (pair)o;
						return p.x - x == 0 && p.y - y == 0 ;
					}
					return false;
				}

				public int hashCode()
				{
					return new Long(x).hashCode()*31 + new Long(y).hashCode();
				}
			}

			static class InputReader
			{

				private final InputStream stream;
				private final byte[] buf = new byte[8192];
				private int curChar, snumChars;
				private SpaceCharFilter filter;

				public InputReader(InputStream stream)
				{
					this.stream = stream;
				}

				public int snext()
				{
					if (snumChars == -1)
						throw new InputMismatchException();
					if (curChar >= snumChars)
					{
						curChar = 0;
						try
						{
							snumChars = stream.read(buf);
						}
						catch (IOException e)
						{
							throw new InputMismatchException();
						}
						if (snumChars <= 0)
							return -1;
					}
					return buf[curChar++];
				}

				public int nextInt()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					int sgn = 1;
					if (c == '-')
				    {
						sgn = -1;
						c = snext();
					}
					int res = 0;
					do
					{
						if (c < '0' || c > '9')
							throw new InputMismatchException();
						res *= 10;
						res += c - '0';
						c = snext();
					} while (!isSpaceChar(c));
					return res * sgn;
				}

				public long nextLong()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					int sgn = 1;
					if (c == '-')
					{
						sgn = -1;
						c = snext();
					}
					long res = 0;
					do
					{
						if (c < '0' || c > '9')
							throw new InputMismatchException();
						res *= 10;
						res += c - '0';
						c = snext();
					} while (!isSpaceChar(c));
					return res * sgn;
				}

				public int[] nextIntArray(int n)
				{
					int a[] = new int[n];
					for (int i = 0; i < n; i++)
					{
						a[i] = nextInt();
					}
					return a;
				}

				public String readString()
			    {
					int c = snext();
					while (isSpaceChar(c))
					{
						c = snext();
					}
					StringBuilder res = new StringBuilder();
					do
					{
						res.appendCodePoint(c);
						c = snext();
					} while (!isSpaceChar(c));
					return res.toString();
				}

				public String nextLine()
				{
					int c = snext();
					while (isSpaceChar(c))
						c = snext();
					StringBuilder res = new StringBuilder();
					do
					{
						res.appendCodePoint(c);
						c = snext();
					} while (!isEndOfLine(c));
					return res.toString();
				}

				public boolean isSpaceChar(int c)
				{
					if (filter != null)
						return filter.isSpaceChar(c);
					return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
				}

				private boolean isEndOfLine(int c)
				{
					return c == '\n' || c == '\r' || c == -1;
				}

				public interface SpaceCharFilter
			    {
					public boolean isSpaceChar(int ch);
				}
			}

			static class CodeX {
	        public static void sort(long arr[]) {
	            merge_sort(arr, 0, arr.length - 1);
	        }

	        private static void merge_sort(long A[], long start, long end) {
	            if (start < end) {
	                long mid = (start + end) / 2;
	                merge_sort(A, start, mid);
	                merge_sort(A, mid + 1, end);
	                merge(A, start, mid, end);
	            }

	        }

	        private static void merge(long A[], long start,long mid, long end) {
	            long p = start, q = mid + 1;
	            long Arr[] = new long[(int)(end - start + 1)];
	            long k = 0;

	            for (int i = (int)start; i <= end; i++) {
	                if (p > mid)
	                    Arr[(int)k++] = A[(int)q++];

	                else if (q > end)
	                    Arr[(int)k++] = A[(int)p++];

	                else if (A[(int)p] < A[(int)q])
	                    Arr[(int)k++] = A[(int)p++];

	                else
	                    Arr[(int)k++] = A[(int)q++];
	            }
	            for (int i = 0; i < k; i++) {
	                A[(int)start++] = Arr[i];
	            }

	        }

	    }
		}


import java.util.*;
import java.io.*;

public class D7
{
	public static void main(String[] args)
	{
		Scanner in = new Scanner(System.in);

		String s = in.nextLine();
		int[] a = new int[s.length()];
		int i=0,count=0;

		for(int j=0;j<s.length();j++)
			a[j] = s.charAt(j) - '0';

		long sum=a[i];

		while(i<s.length())
		{
			if(sum%3==0)
			{
				i++;
				count++;

				//System.out.println(sum);
				if(i<s.length())
					sum = a[i];
			}
			else
			{
				i++;

				if(i<s.length())
					sum = sum*10 + a[i];

				if(i<s.length() && a[i]==0)
					sum = 0;
			}
		}

		System.out.println(count);
	}

}