#include <iostream>
#include <queue>
#include <map>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;
#define INF 2e9 + 9
#define ALL(v) v.begin() , v.end()
#define Int int_fast64_t
#define pll pair<Int,Int>
template<class T> using pql = priority_queue<T,vector<T>>;
template<class T> using pq = priority_queue<T,vector<T>,greater<T>>;
#define ll(n) Int n; cin >> n;
#define LL(...) Int __VA_ARGS___; cin >> __VA_ARGS___;
#define OUT(...) cout << __VA_ARGS___;
#define RP(n,i,s) for(Int i = s ;i < n ;i++)
#define REP(n,i) for (Int i = 0; i < n; i++)
#define REPe(n,i) for (Int i = 1; i <= n; i++)
#define RPe(n,i,s) for (Int i = s; i <= n; i++)

struct node{
    Int to;
    Int length;
};

class Graph {
protected:
    int n;
    vector<Int> prev;
    vector<Int> minD;
    vector<vector<node>> ker;
public:
    Graph(Int N) : n(N) , prev(N) , minD(N) , ker(N) {}
    void addEdge(Int from, Int next, Int cost) {
        ker.at(from).push_back({next, cost});
        ker.at(next).push_back({from, cost});
    }
    void addDirectedEdge(Int from, Int next, Int cost){
        ker.at(from).push_back({next,cost});
    }
    void dijkstra(Int s) {
        REP(n,i) {
            minD.at(i) = INF;
        }
        minD.at(s) = 0;
        priority_queue<pll,vector<pll>,greater<>> que;
        que.push({0,s});
        while(!que.empty()){
            auto z = que.top();
            que.pop();
            int v = z.second;
            if (minD[v] < z.first) continue;
            REP(ker.at(v).size(),i){
                node n = ker.at(v).at(i);
                if (minD[n.to] > minD[v] + n.length) {
                    minD[n.to] = minD[v] + n.length;
                    que.push({minD[n.to],n.to});
                }
            }
        }
    }

    bool bellmanford(Int s){
        bool flag = false;
        REP(n,i) {
            minD.at(i) = INF;
        }
        minD.at(s) = 0;
        REP(n-1,i) {
            REP(n, k) {
                for (auto z: ker.at(k)) {
                    if (minD[k] != INF && minD[z.to] > minD[k] + z.length) {
                        minD[z.to] = minD[k] + z.length;
                    }
                }
            }
        }

        REP(n, k) {
            for (auto z: ker.at(k)) {
                if (minD[k] != INF && minD[z.to] > minD[k] + z.length) {
                    minD[z.to] = minD[k] + z.length;
                    flag = true;
                }
            }
        }
        return flag;
    }

    Int getD(Int x){
        return minD[x];
    }

    Int putD(Int x, string sep = "\n"){
        if (minD[x] == INF) {
            cout << "INF" << sep;
        }else{
            cout << minD[x] << sep;
        }
        return minD[x];
    }
};


vector<vector<int>> to;
vector<int> flag;
vector<int> c;

Int dfs(int from, int mae){
    flag[from] = 1;
    Int mini = 0;
    for (auto next : to[from]){
        if (next == mae) continue;
        if (flag[next] == 1){
            return -1;
        }else{
            mini = min(mini,dfs(next,from));
        }
    }
    return mini;
}

vector<string> dt;
int tox[4] = {-1,0,1,0};
int toy[4] = {0,-1,0,1};

int main(void) {
    while(true){
        Int n, x;
        cin >> n >> x;
        if (n == 0 && x == 0) break;
        Int ans = 0;
        REPe(n,i1){
            RPe(n,i2,i1){
                RPe(n,i3,i2){
                    if (i1 != i2 && i2 != i3 && i3 != i1){
                        if (i1 + i2 + i3 == x) ans++;
                    }
                }
            }
        }
        cout << ans << endl;
    }
}


Measured memory_bytes: 3104