#include <bits/stdc++.h>
using namespace std;
template <typename T>
using reversed_priority_queue =
    std::priority_queue<T, std::vector<T>, std::greater<T>>;
const int dy[] = {-1, 0, 1, 0};
const int dx[] = {0, 1, 0, -1};
long long int mpow(long long int x, long long int y, long long int m) {
  x %= m;
  long long int result = 1;
  while (y > 0) {
    if (y & 1) result = (result * x) % m;
    x = (x * x) % m;
    y >>= 1;
  }
  return result;
}
unsigned long long int minverse(unsigned long long int x,
                                unsigned long long int m) {
  return mpow(x, m - 2, m);
}
long long int modpowsum(long long int a, long long int n, long long int m) {
  if (n == 0) {
    return 0;
  } else if (n % 2 == 1) {
    return (1 + modpowsum(a, n - 1, m) * a) % m;
  } else {
    long long int t = modpowsum(a, n / 2, m);
    return (t + t * mpow(a, n / 2, m)) % m;
  }
}
long long int strmod(const string s, const long long int m) {
  if (m == 1) return 0;
  long long int len = s.size(), res = 0;
  long long int t = 1;
  for (long long int i = (0); i < (len); i++) {
    int x = s[len - i - 1] - '0';
    res = (res + x * t) % m;
    t = (t * 10) % m;
  }
  return res;
}
long long int c(long long int n, long long int k, long long int m) {
  static long long int memo[1000][1000];
  if (memo[n][k] != 0)
    return memo[n][k];
  else if (n == k)
    return memo[n][k] = 1;
  else if (k == 0)
    return memo[n][k] = 1;
  else
    return memo[n][k] = (c(n - 1, k - 1, m) + c(n - 1, k, m)) % m;
}
long long int c2(long long int n, long long int k, long long int m) {
  if (n == 0 && k == 0) return 1;
  if (k > n) return 0;
  if (n <= 0) return 0;
  if (n == k) return 1;
  long long int res = 1;
  for (long long int x = n - k + 1; x <= n; x++) {
    res = res * x;
    if (m != -1) res %= m;
  }
  for (long long int x = 1; x <= k; x++) {
    if (m == -1)
      res = res / x;
    else
      res = (res * minverse(x, m)) % m;
  }
  return res;
}
long long int fact[400000];
long long int rfact[400000];
void c3_init(long long int m) {
  fact[0] = rfact[0] = 1;
  for (int i = 1; i < 400000; i++) {
    fact[i] = (fact[i - 1] * i) % m;
    rfact[i] = minverse(fact[i], m);
  }
}
long long int c3(long long int n, long long int k, long long int m) {
  return (((fact[n] * rfact[k]) % m) * rfact[n - k]) % m;
}
long long int hcomp(long long int n, long long int k, long long int m) {
  return c(k + n - 1, k, m);
}
long long int hcomp2(long long int n, long long int k, long long int m) {
  long long int res = 1;
  for (long long int j = 1; j < n; j++) {
    res = (res * (k + j)) % m;
    res = (res * minverse(j, m)) % m;
  }
  return res;
}
template <class BidirectionalIterator>
bool next_combination(BidirectionalIterator first1, BidirectionalIterator last1,
                      BidirectionalIterator first2,
                      BidirectionalIterator last2) {
  if ((first1 == last1) || (first2 == last2)) {
    return false;
  }
  BidirectionalIterator m1 = last1;
  BidirectionalIterator m2 = last2;
  --m2;
  while (--m1 != first1 && !(*m1 < *m2)) {
  }
  bool result = (m1 == first1) && !(*first1 < *m2);
  if (!result) {
    while (first2 != m2 && !(*m1 < *first2)) {
      ++first2;
    }
    first1 = m1;
    std ::iter_swap(first1, first2);
    ++first1;
    ++first2;
  }
  if ((first1 != last1) && (first2 != last2)) {
    m1 = last1;
    m2 = first2;
    while ((m1 != first1) && (m2 != last2)) {
      std ::iter_swap(--m1, m2);
      ++m2;
    }
    std ::reverse(first1, m1);
    std ::reverse(first1, last1);
    std ::reverse(m2, last2);
    std ::reverse(first2, last2);
  }
  return !result;
}
template <class BidirectionalIterator>
bool next_combination(BidirectionalIterator first, BidirectionalIterator middle,
                      BidirectionalIterator last) {
  return next_combination(first, middle, middle, last);
}
class UnionFind {
 public:
  int n;
  vector<int> par;
  vector<int> num;
  UnionFind(int n) {
    this->n = n;
    this->par.resize(n);
    this->num.resize(n, 1);
    for (int i = 0; i < n; i++) {
      this->par[i] = i;
    }
  }
  int root(int i) {
    if (par[i] == i)
      return i;
    else
      return par[i] = root(par[i]);
  }
  bool same(int i, int j) { return root(i) == root(j); }
  void unite(int i, int j) {
    int t = root(i);
    int k = root(j);
    if (t == k) return;
    par[t] = k;
    num[k] += num[t];
  }
  int size(int i) { return num[root(i)]; }
};
template <typename T>
class SegTree {
 private:
  int _n;
  T _init_val;
  vector<T> _data;
  function<T(T, T)> _f;
  T _query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) return _init_val;
    if (a <= l && r <= b) return _data[k];
    T vl = _query(a, b, k * 2 + 1, l, (l + r) / 2);
    T vr = _query(a, b, k * 2 + 2, (l + r) / 2, r);
    return _f(vl, vr);
  }

 public:
  SegTree(int n, T init_val, function<T(T, T)> f) {
    _init_val = init_val;
    _n = 1;
    _f = f;
    while (_n < n) _n *= 2;
    _data.resize(2 * _n, init_val);
  }
  T get(int k) { return _data[k + _n - 1]; }
  void update(int k, T a) {
    k += _n - 1;
    _data[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      _data[k] = _f(_data[k * 2 + 1], _data[k * 2 + 2]);
    }
  }
  T query(int a, int b) { return _query(a, b, 0, 0, _n); }
  int lower_bound(T x) { return _lower_bound(x, 0); }
  int _lower_bound(T x, int k) {
    if (k >= _n - 1) {
      return k - (_n - 1);
    } else if (_data[k] < x) {
      return _n;
    } else if (x <= _data[k * 2 + 1]) {
      return _lower_bound(x, k * 2 + 1);
    } else {
      return _lower_bound(x - _data[k * 2 + 1], k * 2 + 2);
    }
  }
};
class Block {
 public:
  vector<pair<int, int>> block;
  void add(int l, int r) {
    auto it =
        lower_bound(begin(this->block), end(this->block), make_pair(l, r));
    auto jt = it;
    jt--;
    if (it != block.end() && r >= it->first) {
      it->first = min(l, it->first);
      it->second = max(r, it->second);
      auto jt = it;
      jt--;
      if (it != block.begin() && jt->second >= it->first) {
        it->first = min(it->first, jt->first);
        it->second = max(it->second, jt->second);
        this->block.erase(jt);
      }
    } else if (it != block.begin() && jt->second >= l) {
      jt->first = min(jt->first, l);
      jt->second = max(jt->second, r);
    } else {
      block.insert(it, make_pair(l, r));
    }
  }
};
long long bit_count(unsigned long long i) {
  i = i - ((i >> 1) & 0x5555555555555555);
  i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333);
  return (((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101) >> 56;
}
class SuffixArray {
 public:
  string s;
  vector<int> sa;
  vector<int> rsa;
  vector<int> lcp;
  SegTree<int> st_lcp;
  SuffixArray(string s)
      : s(s),
        st_lcp(s.size() + 1, 1 << 29, [](int a, int b) { return min(a, b); }) {
    sa = construct_sa();
    lcp = construct_lcp();
    rsa = vector<int>(s.size() + 1, 0);
    for (int i = 0; i < sa.size(); i++) {
      rsa[sa[i]] = i;
    }
    for (int i = 0; i < lcp.size(); i++) {
      st_lcp.update(i, lcp[i]);
    }
  }
  bool compare_sa(int i, int j, int k, int n, vector<int> &rank) {
    if (rank[i] != rank[j]) {
      return rank[i] < rank[j];
    } else {
      int ri = i + k <= n ? rank[i + k] : -1;
      int rj = j + k <= n ? rank[j + k] : -1;
      return ri < rj;
    }
  }
  vector<int> construct_sa() {
    int n = s.size();
    vector<int> res(n + 1, 0);
    vector<int> rank(n + 1, 0);
    vector<int> tmp(n + 1, 0);
    for (int i = 0; i <= n; i++) {
      res[i] = i;
      rank[res[i]] = i < n ? s[i] : -1;
    }
    for (int k = 1; k <= n; k *= 2) {
      auto f = [&](int i, int j) { return this->compare_sa(i, j, k, n, rank); };
      sort(begin(res), end(res), f);
      tmp[res[0]] = 0;
      for (int i = 1; i <= n; i++) {
        tmp[res[i]] = tmp[res[i - 1]] + (f(res[i - 1], res[i]) ? 1 : 0);
      }
      rank = tmp;
    }
    return res;
  }
  vector<int> construct_lcp() {
    int n = s.size();
    vector<int> rank(n + 1, 0);
    vector<int> res(n + 1, 0);
    for (int i = 0; i <= n; i++) rank[sa[i]] = i;
    int h = 0;
    res[0] = 0;
    for (int i = 0; i < n; i++) {
      int j = sa[rank[i] - 1];
      if (h > 0) h--;
      for (; j + h < n && i + h < n; h++) {
        if (s[j + h] != s[i + h]) break;
      }
      res[rank[i] - 1] = h;
    }
    return res;
  }
  void dump() {
    int n = s.size();
    cout << "# SuffixArray dump" << endl;
    cout << "s = " << s << endl;
    cout << "----------------------" << endl;
    cout << " i sa[i] lcp[i]  s[sa[i]...]" << endl;
    for (int i = 0; i <= n; i++) {
      printf("%2d%6d%7d  %s\n", i, sa[i], lcp[i], s.substr(sa[i]).c_str());
    }
  }
  int getRank(int i) { return rsa[i]; }
  int find(const string &pat) {
    int a = 0, b = s.size();
    while (b - a > 1) {
      int c = (a + b) / 2;
      if (s.compare(sa[c], pat.size(), pat) < 0)
        a = c;
      else
        b = c;
    }
    if (s.compare(sa[b], pat.size(), pat) == 0) {
      return sa[b];
    } else {
      return -1;
    }
  }
  int prefixCommonLength(int i, int j) {
    if (i == j) return s.size() - i;
    i = rsa[i];
    j = rsa[j];
    return st_lcp.query(min(i, j), max(i, j));
  }
};
long long int LCS(string s, string t) {
  long long int s_len = s.size();
  long long int t_len = t.size();
  long long int table[s_len + 1][t_len + 1];
  for (long long int i = (0); i < (s_len + 1); i++) table[i][0] = 0;
  for (long long int j = (0); j < (t_len + 1); j++) table[0][j] = 0;
  for (long long int i = (0); i < (s_len); i++)
    for (long long int j = (0); j < (t_len); j++)
      if (s[i] == t[j]) {
        table[i + 1][j + 1] =
            max(max(table[i + 1][j], table[i][j + 1]), table[i][j] + 1);
      } else {
        table[i + 1][j + 1] =
            max(max(table[i + 1][j], table[i][j + 1]), table[i][j]);
      }
  return table[s_len][t_len];
}
bool _visit(long long int n, vector<long long int> &marks,
            vector<vector<long long int>> &edges, vector<long long int> &res) {
  if (marks[n] == 1) {
    return false;
  } else if (marks[n] == 0) {
    marks[n] = 1;
    for (long long int nxt : edges[n]) {
      if (!_visit(nxt, marks, edges, res)) {
        return false;
      }
    }
    marks[n] = 2;
    res.push_back(n);
  }
  return true;
}
vector<long long int> topologicalSort(vector<vector<long long int>> edges) {
  long long int N = edges.size();
  vector<long long int> res;
  vector<long long int> marks(N, 0);
  bool ok = true;
  for (long long int i = 0; i < N; i++)
    if (marks[i] == 0)
      if (!_visit(i, marks, edges, res)) {
        ok = false;
        break;
      }
  reverse(begin(res), end(res));
  return (ok ? res : vector<long long int>());
}
signed main() {
  string s;
  cin >> s;
  long long int x = 0;
  for (int i = 0; i < s.length(); i++) {
    x *= 4;
    if (s[i] >= '7') {
      x += 3;
    } else if (s[i] >= '5') {
      x += 2;
    } else {
      x += 1;
    }
  }
  long long int ans = 0;
  for (int k = 1; k <= x; k++) {
    int t = k;
    bool p, q, r;
    p = q = r = false;
    while (t != 0) {
      if (t % 4 == 3) {
        p = true;
      } else if (t % 4 == 2) {
        q = true;
      } else if (t % 4 == 1) {
        r = true;
      } else {
        p = q = r = false;
        break;
      }
      t /= 4;
    }
    if (p && q && r) {
      ans++;
    }
  }
  cout << ans << endl;
  return 0;
}
