#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll int64_t
#define ld long double
#define ull unsigned long long
#define pi pair<int,int>
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define mod 1000000007
#define IMAX INT64_MAX
#define IMIN INT64_MIN
#define ends string::npos


bool isPrime(int n)
{
    if (n <= 1)  return false;
    if (n <= 3)  return true;

    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;
}


ll max(ll a,ll b)
{
    if(a>b)
    {
        return a;
    }
    return b;
}

ll min(ll a,ll b)
{
    if(a<b)
    {
        return a;
    }
    return b;
}

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

ll lcm(ll a, ll b)
{
    return (a*b)/gcd(a, b);
}


ll fact(ll n)
{
    ll res = 1;
    for (ll i = 2; i <= n; i++)
        res = res * i;
    return res;
}

ll nCr(ll n, ll r)
{
    return fact(n) / (fact(r) * fact(n - r));
}

ll fpow(ll base,ll exp)
{
    base%=1000000000000000007;
    ll ans=1;
    while(exp)
    {
        if(exp&1) {ans*=base; ans%=1000000000000000007;}
        exp/=2;
        base*=base;
        base%=1000000000000000007;
    }
    return ans;
}

class DSU {
public:
    int n;
    vector<int> parent,size;

    DSU(int a) {
        n = a;
        parent.assign(n,0);
        size.assign(n,0);
        for(int i=0 ; i<n ; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }

    void makeSets(int k) {
        for(int i=0 ; i<n ; i++) {
            if(find(i) != i) {
                size[i] = 0;
            }
        }
    }

    int find(int a) {
        int root = a;
        while(root != parent[root]) {
            root = parent[root];
        }
        while(root != a) {
            int temp = parent[a];
            parent[a] = root;
            a = temp;
        }
        return root;
    }

    void unionSet(int a, int b) {
        int root_a = find(a);
        int root_b = find(b);
        if(root_a == root_b) return;
        if(size[a] < size[b]) {
            parent[root_a] = root_b;
            size[root_b] += size[root_a];
        }
        else {
            parent[root_b] = root_a;
            size[root_a] += size[root_b];
        }
    }
};


set<ll> intersection(set<ll> s1,set<ll> s2)
{
    set<ll> intersect;
    set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(), inserter(intersect,intersect.begin()));
    return intersect;
}




class unionFind
{
public:
    vector<int> rank,p;
    int noc;
public:
    unionFind(int n)
    {
        rank.assign(n,0);
        p.assign(n,0);
        noc=n;
        for(int i=0;i<n;i++)
        {
            p[i]=i;
        }
    }
    int find(int i)
    {
        return (p[i] == i) ? i : (p[i] = find(p[i]));
    }
    bool isSameSet(int i,int j)
    {
        return find(i)==find(j);
    }
    void unionSet(int i,int j)
    {
        if(!isSameSet(i,j))
        {
            int x=find(i);
            int y=find(j);
            noc--;
            if(rank[x]>rank[y])
            {
                p[y]=x;
            } else{
                p[x]=y;
            }
            if(rank[x]==rank[y])
            {
                rank[y]++;
            }
        }
    }
    int getNoc()
    {
        return noc;
    }

};

//unordered_map<ll,vector<ll>> v,ch;
//unordered_map<ll,ll> par;
//unordered_map<ll,ll> vis;
//unordered_map<ll,ll> dep,dep1;
//unordered_set<ll> leaves;
//ll ed=0;
//ll ve=0;
//void dfs(ll x)
//{
//    vis[x]=1;
//    //dep1[x]=1;
//    if(v[x].size()==1)
//    {
//        leaves.insert(x);
//    }
//    ed+=v[x].size();
//    ve++;
//
//    for(auto&i:v[x])
//    {
//        if(vis[i]==0)
//        {
//
//            dep[i] = dep[x] + 1;
//            par[i]=x;
//            ch[x].push_back(i);
//            dfs(i);
//            if(leaves.find(i)!=leaves.end())
//            {
//                dep1[i]=1;
//            }
//            dep1[par[i]]=max(dep1[i]+1,dep1[par[i]]);
//        }
//    }
//
//}

struct safe_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

struct tri
{
    unordered_map<char,tri*> child;
    bool end;
    tri()
    {
        for(char i='a';i<='z';i++)
        {
            child[i]=NULL;
        }
        end=false;
    }
};


int main() {

    ios_base::sync_with_stdio(false);
    cin.tie(NULL);



      string n;
      cin>>n;
      ll c=0;
      for(auto&i:n)
      {
          c+=(i-48);
      }
      if(c%9==0)
      {
          cout<<"Yes"<<endl;
      }
      else
      {
          cout<<"No"<<endl;
      }



}

Measured memory_bytes: 3716