/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author aryssoncf
 */



// Taken from: https://github.com/bqi343/USACO/blob/master/Implementations/content/contest/templateShort.cpp

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<ull> vul;
typedef vector<ll> vl;
typedef vector<pii> vpii;

#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i,0,a)
#define ROF(i, a, b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i, a) ROF(i,0,a)
#define trav(a, x) for (auto& a: x)

#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rsz resize

#define mp make_pair
#define pb push_back
#define f first
#define s second

const int MOD = 1e9 + 7; // 998244353; // = (119<<23)+1
const int MX = 2e5 + 5;

template<class T>
bool ckmin(T &a, const T &b) {
    return a > b ? a = b, 1 : 0;
}

template<class T>
bool ckmax(T &a, const T &b) {
    return a < b ? a = b, 1 : 0;
}

mt19937 rng((uint32_t) chrono::steady_clock::now().time_since_epoch().count());


//
// Created by aryssoncf on 28/10/2019.
//

#include <type_traits>


#include <iterator>
#include <utility>

template<typename T>
constexpr auto hasBegin(int) -> decltype(std::begin(std::declval<T>()), true) {
    return true;
}

constexpr bool hasBegin(...) {
    return false;
}

template<typename T>
using IsContainer = std::integral_constant<bool, hasBegin<T>(0)>;


#ifndef JHELPER_EXAMPLE_PROJECT_IO_HPP
#define JHELPER_EXAMPLE_PROJECT_IO_HPP

#endif //JHELPER_EXAMPLE_PROJECT_IO_HPP

template<typename T>
std::istream &operator>>(std::istream &is, std::vector<T> &vec) {
    for (T &element: vec) {
        is >> element;
    }
    return is;
}

template<typename T, typename U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    is >> p.first;
    is >> p.second;
    return is;
}

template<class X, class Y>
std::ostream &operator<<(std::ostream &os, std::pair<X, Y> const &p) {
    return os << p.first << " " << p.second;
}

template<class Ch, class Tr, class Container>
std::basic_ostream<Ch, Tr> &operator<<(std::basic_ostream<Ch, Tr> &os, Container const &x) {
    bool first = true;
    for (auto &y : x) {
        if (first) {
            first = false;
        } else {
            os << " ";
        }
        os << y;
    }
    return os;
}


#include <vector>
#include <limits>
#include <functional>

#include <queue>


#include <string>
#include <stdexcept>

#ifndef SPCPPL_ASSERT
#ifdef SPCPPL_DEBUG
#define SPCPPL_ASSERT(condition) \
        if(!(condition)) { \
            throw std::runtime_error(std::string() + #condition + " in line " + std::to_string(__LINE__) + " in " + __PRETTY_FUNCTION__); \
        }
#else
#define SPCPPL_ASSERT(condition)
#endif
#endif


template<typename FlowSize, typename CostSize>
struct CostFlow {
    FlowSize flow;
    CostSize cost;
};

template<typename FlowSize, typename CostSize>
class MinCostFlow {
    struct Edge {
        std::size_t from, to;
        FlowSize cap;
        FlowSize flow;
        CostSize cost;
    };
public:
    explicit MinCostFlow(std::size_t n) : g(n) {

    }

    void addEdge(std::size_t from, std::size_t to, FlowSize capacity, CostSize cost) {
        SPCPPL_ASSERT(from < g.size() && to < g.size());
        Edge edge = {from, to, capacity, 0, cost};
        g[from].push_back(edges.size());
        edges.push_back(edge);

        Edge backwardEdge = {to, from, 0, 0, -cost};
        g[to].push_back(edges.size());
        edges.push_back(backwardEdge);
    }

    Edge getEdge(std::size_t id) {
        SPCPPL_ASSERT(id < edges.size());
        return edges[id];
    }

    std::size_t edgesCount() const {
        return edges.size();
    }

    template<typename Strategy>
    CostFlow<FlowSize, CostSize> findFlow(std::size_t s, std::size_t t, Strategy strategy) {
        SPCPPL_ASSERT(s < g.size());
        SPCPPL_ASSERT(t < g.size());
        SPCPPL_ASSERT(s != t);
        CostSize cost = 0;
        FlowSize flow = 0;
        std::size_t n = g.size();
        std::vector<CostSize> potential(n);
        const std::size_t NO_PARENT = std::numeric_limits<std::size_t>::max();
        {
            std::vector<std::size_t> p(n, NO_PARENT);
            std::vector<CostSize> d(n);
            d[s] = 0;
            p[s] = s;
            bool changed = true;
            while (changed) {
                changed = false;
                for (auto i = 0; i < edges.size(); ++i) {
                    Edge &e = edges[i];
                    if (e.cap == e.flow || p[e.from] == -1) {
                        continue;
                    }
                    if (p[e.to] == -1 || d[e.to] > d[e.from] + e.cost) {
                        d[e.to] = d[e.from] + e.cost;
                        p[e.to] = i;
                        changed = true;
                    }
                }
            }
            potential = std::move(d);
        }
        while (true) {
            std::vector<CostSize> d(n);
            std::vector<std::size_t> p(n, NO_PARENT);

            using QueueType = std::pair<CostSize, std::size_t>;
            std::priority_queue<QueueType, std::vector<QueueType>, std::greater<QueueType>> q;

            q.push(std::make_pair(0, s));

            while (!q.empty()) {
                std::size_t v = q.top().second;
                CostSize oldD = q.top().first;
                q.pop();
                if (oldD != d[v]) {
                    continue;
                }
                for (std::size_t id: g[v]) {
                    Edge &e = edges[id];
                    if (e.to == s) {
                        continue;
                    }
                    if (e.cap > e.flow) {
                        SPCPPL_ASSERT(e.cost + potential[e.from] - potential[e.to] >= 0);
                        CostSize newd = d[v] + e.cost + potential[e.from] - potential[e.to];
                        if (p[e.to] == NO_PARENT || d[e.to] > newd) {
                            d[e.to] = newd;
                            p[e.to] = id;
                            q.push(std::make_pair(d[e.to], e.to));
                        }
                    }
                }
            }

            if (p[t] == NO_PARENT) {
                break;
            }

            std::size_t cur = t;
            FlowSize maxAdd = strategy.maximalAdditionFlow(flow, cost, potential[t] + d[t]);

            if (maxAdd == 0) {
                break;
            }

            while (cur != s) {
                Edge &e = edges[p[cur]];
                cur = e.from;
                maxAdd = std::min(maxAdd, e.cap - e.flow);
            }

            flow += maxAdd;
            cost += (potential[t] + d[t]) * maxAdd;
            cur = t;
            while (cur != s) {
                std::size_t id = p[cur];
                edges[id].flow += maxAdd;
                edges[id ^ 1].flow -= maxAdd;
                cur = edges[id].from;
            }

            for (auto i = 0; i < n; ++i) {
                if (p[i] != NO_PARENT) {
                    potential[i] = potential[i] + d[i];
                }
            }
        }

        return {flow, cost};

    }

private:
    std::vector<std::vector<std::size_t>> g;
    std::vector<Edge> edges;
};


template<typename CostSize>
struct FixedCostMaxFlowStrategy {
    explicit FixedCostMaxFlowStrategy(CostSize maxCost) : maxCost(maxCost) {

    }

    template<typename FlowSize>
    FlowSize maximalAdditionFlow(const FlowSize &, const CostSize &currentCost, const CostSize &additionalCost) {
        if (additionalCost <= 0) {
            return std::numeric_limits<FlowSize>::max();
        }
        return (maxCost - currentCost) / additionalCost;
    }

private:
    CostSize maxCost;
};


using namespace std;

class ACandyDistributionAgain {
public:
    void solve(std::istream &in, std::ostream &out) {
        int n, x;
        in >> n >> x;
        vi A(n);
        in >> A;
        sort(all(A));
        int res = 0;
        trav(k, A) {
            if (x >= k) {
                x -= k;
                res++;
            } else {
                break;
            }
        }
        int source = n, sink = n + 1, N = sink + 1;
        MinCostFlow<int, ll> graph(N);
        FOR(i, 0, n) {
            if (i < res) {
                graph.addEdge(source, i, 1, 0);
            } else {
                graph.addEdge(i, sink, 1, 0);
            }
        }
        FOR(i, 0, res) {
            FOR(j, res, n) {
                graph.addEdge(i, j, INT_MAX, A[j] - A[i]);
            }
        }
        ll cost = graph.findFlow(source, sink, FixedCostMaxFlowStrategy(x)).cost;
        if (res and cost != x) {
            res--;
        }
        out << res << '\n';
    }

    void setup() {}
};


int main() {
    std::ios_base::sync_with_stdio(false);
    ACandyDistributionAgain solver;
    solver.setup();
    std::istream &in(std::cin);
    std::ostream &out(std::cout);
    in.tie(nullptr);
    out << std::fixed;
    out.precision(20);
    solver.solve(in, out);
    return 0;
}
