#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T, class U>
using P = pair<T, U>;
template <class T>
using Heap = priority_queue<T>;
template <class T>
using heaP = priority_queue<T, vector<T>, greater<T>>;
template <class T, class U>
using umap = unordered_map<T, U>;
template <class T>
using uset = unordered_set<T>;
template <class T>
bool ChangeMax(T& a, const T& b) {
  if (a >= b) return false;
  a = b;
  return true;
}
template <class T>
bool ChangeMin(T& a, const T& b) {
  if (a <= b) return false;
  a = b;
  return true;
}
template <class T, size_t N, class U>
void Fill(T (&a)[N], const U& v) {
  fill((U*)a, (U*)(a + N), v);
}
template <class T>
istream& operator>>(istream& is, vector<T>& v) {
  for (auto& e : v) is >> e;
  return is;
}
string s;
int len;
int Rec(int i, int vmax, int vmin, int v) {
  static map<tuple<int, int, int, int>, int> mp;
  if (mp.count({i, vmax, vmin, v}) > 0) return mp[{i, vmax, vmin, v}];
  vmax = max(vmax, v);
  vmin = min(vmin, v);
  if (i >= len) {
    return mp[{i, vmax, vmin, v}] = vmax - vmin;
  }
  if (s[i] == '0') {
    return mp[{i, vmax, vmin, v}] = Rec(i + 1, vmax, vmin, v - 1);
  } else if (s[i] == '1') {
    return mp[{i, vmax, vmin, v}] = Rec(i + 1, vmax, vmin, v + 1);
  }
  return mp[{i, vmax, vmin, v}] =
             min(Rec(i + 1, vmax, vmin, v + 1), Rec(i + 1, vmax, vmin, v - 1));
}
int main() {
  cin >> s;
  len = (int)s.size();
  cout << Rec(0, 0, 0, 0) << endl;
  return 0;
}
