//#include "pch.h"
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <limits.h>
#include <string>
#include <cmath>

using namespace std;

#define rip(i, n, s) for (int i = (s);i < (int)( n ); i++)
#define mp make_pair
#define all(a) (a).begin(), (a).end()
typedef long long ll;
typedef pair<int, int> P;

template<int Size>
struct Largenum{
    vector<long long> num;
    long long p;
    int sign;
    Largenum(){
        num = vector<long long>(Size,0);
        p = 1000000000;
        sign = 0;
    }
    Largenum<Size>(long long _num){
        num = vector<long long>(Size,0);
        p = 1000000000;
        if(_num){
            if(_num > 0){
                sign = 1;
            }
            else{
                sign = -1;
            }
        }
        else{
            sign = 0;
        }
        num[0] = _num % p;
        num[1] = _num /p;
    }
    Largenum(string _num){
        num = vector<long long> (Size,0);
        int base = 0;
        p = 1000000000;
        if(_num == "0"){
            sign = 0;
        }
        else if(_num[0] == '-'){
            base = 1;
            sign = -1;
        }
        else{
            sign = 1;
        }
        int size = _num.size();
        for(int i = base;i < size;i++){
            num[(size - i - 1)/9] *= 10;
            num[(size - i - 1)/9] += _num[i] - '0';
        }
    }
    void output(){
        if(sign == 0){
            printf("0");
            return;
        }
        if (sign == -1){
            printf("-");
        }
        int lim = Size - 1;
        while(lim > -1){
            if(num[lim] != 0){
                break;
            }
            lim--;
        }
        printf("%lld",num[lim]);
        for(int i = lim - 1;i >= 0;i--){
            printf("%09lld",num[i]);
        }
    }
    bool compa(const vector<long long> &left, const vector<long long> &right){
        for(int i = Size - 1;i >= 0;i--){
            if(left[i] != right[i]){
                return (left[i] > right[i]);
            }
        }
        return false;
    }
    bool operator>(const Largenum<Size> &other){
        if(sign != other.sign){
            return sign > other.sign;
        }
        return compa(num, other.num);
    }
    bool operator<(const Largenum<Size> &other){
        if(sign != other.sign){
            return sign < other.sign;
        }
        return compa(other.num, num);
    }
    bool operator<=(const Largenum<Size> &other){
        if(sign != other.sign){
            return sign <= other.sign;
        }
        return !compa(num, other.num);
    }
    bool operator>=(const Largenum<Size> &other){
        if(sign != other.sign){
            return sign >= other.sign;
        }
        return !compa(other.num, num);
    }
    void add(const vector<long long> &left, const vector<long long> &right){
        vector<long long> ret(Size, 0);
        for(int i = 0;i < Size;i ++){
            if(i){
                ret[i] += ret[i - 1] / p;
                ret[i - 1] %= p;
            }
            ret[i] += left[i] + right[i];
        }
        num = ret;
    }
    void dif(const vector<long long> &left, const vector<long long> &right){
        vector<long long> ret(Size, 0);
        int base = 0;
        for(int i = 0;i < Size;i++){
            ret[i] = (left[i] - right[i] -base + p) % p;
            if(left[i] - base < right[i]){
                base = 1;
            }
            else{
                base = 0;
            }
        }
        num = ret;
    }
    Largenum<Size> operator+(const Largenum<Size> &other){
        Largenum<Size> ret;
        if(sign == 0 && other.sign == 0){
            return ret;
        }
        else if(sign == 0 || other.sign == 0){
            ret.sign = sign + other.sign;
            ret.add(num, other.num);
        }
        else if(sign == other.sign){
            ret.sign = sign;
            ret.add(num, other.num);
        }
        else if(num == other.num){
            return ret;
        }
        else if(compa(num, other.num)){
            ret.sign = sign;
            ret.dif(num, other.num);
        }
        else{
            ret.sign = other.sign;
            ret.dif(other.num, num);
        }
        return ret;
    }
    Largenum<Size> operator-(const Largenum<Size> &other){
        Largenum<Size> ret;
        if(sign == 0 && other.sign == 0){
            return ret;
        }
        else if(sign == 0 || other.sign == 0){
            ret.sign = sign - other.sign;
            ret.add(num, other.num);
        }
        else if(sign + other.sign == 0){
            ret.sign = sign;
            ret.add(num, other.num);
        }
        else if(num == other.num){
            return ret;
        }
        else if(compa(num, other.num)){
            ret.sign = sign;
            ret.dif(num, other.num);
        }
        else{
            ret.sign = -other.sign;
            ret.dif(other.num, num);
        }
        return ret;
    }
    Largenum<Size> operator*(const Largenum<Size> &other){
        Largenum ret;
        if(sign == 0 || other.sign == 0){
            return ret;
        }
        
    }
};

struct complex{ //except for (0,0)
    double real;
    double imag;
    complex (double x,double y){
        real=x;
        imag=y;
    }
    double dist(){
        return sqrt(real*real+imag*imag);
    }
};
complex operator+(const complex &x,const complex &y){
    return complex(x.real+y.real,x.imag+y.imag);
}
complex operator-(const complex &x,const complex &y){
    return complex(x.real-y.real,x.imag-y.imag);
}
complex operator*(const complex &x,const complex &y){
    return complex(x.real*y.real-x.imag*y.imag,x.real*y.imag+x.imag*y.imag);
}
complex operator*(const complex &x,const double y){
    return complex(x.real*y,x.imag*y);
}
complex operator/(const complex &x,const double &y){
    return x*(1/y);
}
complex operator/(const complex &x,const complex &y){
    complex ret(y.real,-y.imag);
    double div=ret.dist();
    ret=x*ret;
    return ret/div;
}
bool operator>(const complex &x,const complex &y){//偏角、絶対値の順で
    if (x.imag==0 && y.imag==0){
        return x.real<y.real;
    }
    else if (x.imag==0 && y.imag>0){
        return x.real<0;
    }
    else if (x.imag==0 && y.imag<0){
        return false;
    }
    else if (x.imag>0 && y.imag==0){
        return y.real > 0;
    }
    else if (x.imag<0 && y.imag==0){
        return true;
    }
    else if(x.imag*y.imag>0){
        return y.real/y.imag > x.real/x.imag;
    }
    else if(x.imag*y.imag<0){
        return x.imag<y.imag;
    }
}
bool operator<(const complex &x,const complex &y){
    return (y>x);
}
bool operator>=(const complex &x,const complex &y){
    return !(y>x);
}
bool operator<=(const complex &x,const complex &y){
    return !(x>y);
}

long long pow(long long n, long long p, long long k) {//n^k(mod p)
	if (!k) return 1;
	long long a = pow(n,p, k>>1);
	a = a * a%p;
	if (k & 1) a = a * n%p;
	return a;
}
void euclid(long long &a, long long &b, long long p) { // a>=b A*b+B*(a-a/b*b)=1
	if (a == 1) {
		a = 1;
	}
	else {
		long long A = b, B = a % b;
		euclid(A, B, p);
		b = (A - (p + a / b) % p * B % p + p) % p;
		a = B;
	}
}
long long rev(long long n, long long p) {//nの逆元 n*x-p*y=1
	//long long q = p;
	//euclid(p, n, p);
	//return n % q;
    return pow(n,p,p-2);
}
long long bino(long long n, long long m, long long p) {//nCm(mod p)
	long long me = 1;
	long long ans = 1;
	for (int i = 0;i < n + m;i++) {
		me = (long long)(i + 1) * ans % p;
		if (i == m - 1) {
			ans = (long long)rev(me, p) * ans%p;
		}
		if (i == m - n - 1) {
			ans = (long long)(rev(me, p))*ans%p;
		}
	}
	ans = (long long)(ans*me%p);
	return ans;
}
struct modint {
	long long num;
	long long p;
	modint() {
		num = 0;
		p = 1000000007;
	}
	modint(int x) {
		p = 1000000007;
		num = (long long)x%p;
	}
	modint(long long x) {
		p = 1000000007;
		num = x % p;
	}
	modint operator+(const modint &other) {
		modint ret;
		ret.p = p;
		ret.num = (num + other.num) % p;
		return ret;
	}
	modint operator+(const long long &other) {
		modint ret;
		ret.p = p;
		ret.num = (num + (other%p)) % p;
		return ret;
	}
	modint operator-(const modint &other) {
		modint ret;
		ret.p = p;
		ret.num = (num - other.num + p) % p;
		return ret;
	}
	modint operator-(const long long &other) {
		modint ret;
		ret.p = p;
		ret.num = (num - (other%p) + p) % p;
		return ret;
	}
	modint operator*(const modint &other) {
		modint ret;
		ret.p = p;
		ret.num = (num*other.num) % p;
		return ret;
	}
	modint operator*(const long long &other) {
		modint ret;
		ret.p = p;
		ret.num = (num*(other%p)) % p;
		return ret;
	}
	modint operator/(const modint &other) {
		modint ret;
		ret.p = p;
		ret.num = (num*rev(other.num, p)) % p;
		return ret;
	}
	modint operator/(const long long &other) {
		modint ret;
		ret.p = p;
		ret.num = (num*rev(other%p, p)) % p;
		return ret;
	}
	void operator+=(const long long &other) {
		num = (num + other) % p;
	}
	void operator+=(const modint &other) {
		num = (num + other.num) % p;
	}
	void operator-=(const long long &other) {
		num = (num - other + p) % p;
	}
	void operator-=(const modint &other) {
		num = (num - other.num + p) % p;
	}
	void operator*=(const long long &other) {
		num = (num*other) % p;
	}
	void operator*=(const modint &other) {
		num = (num*other.num) % p;
	}
};

template<typename T>
struct matrix{
	int size;
	vector<vector<T> > table;
	matrix(int n){
		size=n;
		table=vector<vector<T> >(n,vector<T>(n));
	}
	matrix<T> operator*(const matrix<T> &othor){
		matrix<T> ret(size);
		for(int i=0;i<size;i++){
			for(int j=0;j<size;j++){
				for(int k=0;k<size;k++){
					ret.table[i][j]+=table[i][k]*othor.table[k][j];
				}
			}
		}
		return ret;
	}
	matrix<T> operator+(const matrix<T> &other){
		matrix<T> ret(size);
		for(int i=0;i<size;i++){
			for(int j=0;j<size;j++){
				ret[i][j] = table[i][j] + other.table[i][j];
			}
		}
		return ret;
	}
	
	matrix<T> operator-(const matrix<T> &other){
		matrix<T> ret(size);
		for(int i=0;i<size;i++){
			for(int j=0;j<size;j++){
				ret[i][j] = table[i][j] - other.table[i][j];
			}
		}
		return ret;
	}
	T trace(T num){
		T ret = num;
		for(int i=0;i<size;i++){
			ret += table[i][i];
		}
		return ret;
	}
	T all_sum(){
		T ret = table[0][0];
		for(int i=1;i<size;i++){
			ret+=table[0][i];
		}
		for(int i=1;i<size;i++){
			for(int j=0;j<size;j++){
				ret+=table[i][j];
			}
		}
		return ret;
	}
};

template<typename T>
struct BIT{
    vector<T> li;
    int size;
    BIT (int n){
        li=vector<T>(n+1,0);
        size=n;
    }
    T sum (int i){
        int s=0;
        while(i>0){
            s+=li[i];
            i-=i & -i;
        }
        return s;
    }
    void add(int i,T x){
        while(i<=size){
            li[i]+=x;
            i+=i & -i;
        }
    }
};

struct SegTree{ //0indexed
    vector<int> nod;
    int size;
    SegTree(int x){
        size=1;
        while(x>size){
            size*=2;
        }
        nod=vector<int>(size*2-1,0);
    }
    void update(int k,int a){
        k+=size-1;
        nod[k]+=a;//最下の処理
        while(k>0){
            k=(k-1)/2;
            nod[k]+=a; //下から上へ 
        }
    }
    void Update(int a,int b,int k,int l,int r,int x){
        //[a,b)について
        //kは節点の番号,[l,r)はその節点がカバーする範囲
        if(r<=a||b<=l){ //[a,b)と[l,r)が重なって無いとき
            return;
        }
        if(a<=l && r<=b){ //[a,b)が[l,r)を完全に含んでいるとき
            nod[k] = max(x,nod[k]);
            return;
        }
        else{
            Update(a,b,k*2+1,l,(l+r)/2,x);
            Update(a,b,k*2+2,(l+r)/2,r,x);
            return;
        }
    }
    int query(int a,int b,int k,int l,int r){
        //[a,b)について
        //kは節点の番号,[l,r)はその節点がカバーする範囲
        if(r<=a||b<=l){ //[a,b)と[l,r)が重なって無いとき
            return 0;
        }
        if(a<=l && r<=b){ //[a,b)が[l,r)を完全に含んでいるとき
            return nod[k];
        }
        else{
            return query(a,b,k*2+1,l,(l+r)/2)+query(a,b,k*2+2,(l+r)/2,r);
        }
    }
    void deb(){ //全ノードの出力
		for(int i=0;i<size*2-1;i++){
			if(i==size*2-2){
				cout << nod[i] << endl;
			}
			else{
				cout << nod[i] << ' ';
			}
		}
		return;
	}
};

struct UnionFind{
    int size;
    vector<int> par;
    vector<int> rank;
    UnionFind(int x){
        size=x;
        par=vector<int> (x);
        rank=vector<int> (x,1);
        for (int i=0;i<x;i++){
            par[i]=i;
        }
    }
    int root(int x){
        if(par[x]==x){
            return x;
        }
        else{
            return par[x]=root(par[x]);
        }
    }
    void unite(int x,int y){
        x=root(x);y=root(y);
        if(x==y){
            return;
        }
        if(rank[x]<rank[y]){
            par[x]=y;
        }
        else{
            par[y]=x;
        }
        if(rank[x]==rank[y]){
            rank[x]++;
        }
    }
    bool check(int x,int y){
        return root(x)==root(y);
    }
    void initialize(){
        for (int i=0;i<size;i++){
            par[i]=i;
            rank[i]=1;
        }
    }
};

template<typename T>
void vdeb(vector<T> &da){
    int size=da.size();
    for(int i=0;i<size;i++){
        if(i==size-1){
            cout << da[i] << endl;
        }
        else{
            cout << da[i] << ' ';
        }
    }
}
template<typename T>
void vvdeb(vector<T> &da){
    int size=da.size();
    for(int i=0;i<size;i++){
        vdeb(da[i]);
    }
}

template<typename T, typename S>
struct Mypair{
    T first;
    S second;
    Mypair(){
        first = 0;
        second = 0;
    }
    Mypair(T _first, S _second){
        first = _first;
        second = _second;
    }
};
template<typename T, typename S>
bool operator<(const Mypair<T, S> &left, const Mypair<T, S> &right){
    if(left.first == right.first){
        return left.second > right.second;
    }
    else{
        return left.first < right.first;
    }
}
template<typename T, typename S> bool operator>(const Mypair<T, S> &left, const Mypair<T,S> &right){return right < left;}
template<typename T, typename S> bool operator>=(const Mypair<T, S> &left, const Mypair<T,S> &right){return !(left < right);}
template<typename T, typename S> bool operator<=(const Mypair<T, S> &left, const Mypair<T,S> &right){return !(right < left);}

int main(){
    int n,m;
    cin >> n >> m;
    if(n == 0){
        if(m==0){
            printf("0 0\n");
        }
        else{
            printf("-1\n");
        }
    }
    else if(n == 1){
        if(m){
            printf("-1\n");
        }
        else{
            printf("0 0 1 1\n");
        }
    }
    else{
        int x = 1 << n;
        if(m < x){
            vector<int> ans(x*2,m);
            int now= 0;
            for(int i = 0;i < x ;i++){
                if(i == m){
                    continue;
                }
                ans[now] = i;
                ans[x*2 - 2 - now] = i;
                now++;
            }
            vdeb(ans);
        }
        else{
            printf("-1\n");
        }
    }
}

Measured memory_bytes: 2816