Go: ///
// File:  0529.go
// Author: ymiyamoto
//
// Created on Wed Feb 28 20:39:28 2018
//
package main

import (
	"fmt"
	"sort"
)

func max(n, m int) int {
	if n < m {
		return m
	} else {
		return n
	}
}

func main() {
	for {
		var N, M int
		fmt.Scan(&N, &M)
		if N == 0 && M == 0 {
			break
		}

		arr := make([]int, N+1)
		for i := 1; i <= N; i++ {
			fmt.Scan(&arr[i])
		}
		sort.Ints(arr)

		sums := make([]int, len(arr)*len(arr))
		for i := 0; i < len(arr); i++ {
			for j := 0; j < len(arr); j++ {
				sums[i+j] = arr[i] + arr[j]
			}
		}
		sort.Ints(sums)

		m := 0
		for i := 0; i < len(sums); i++ {
			rem := M - sums[i]
			if rem >= 0 {
				index := sort.Search(len(sums), func(i int) bool { return sums[i] > rem }) - 1
				if index >= 0 {
					m = max(m, sums[i]+sums[index])
				}
			}
		}
		fmt.Println(m)
	}
}

C++: #include<bits/stdc++.h>
using namespace std;
vector<long int> po;
long int n,a,low,m,lastans,memo[1005],ss;
void solve(int dp,long int sum);

int main(){
    while(1){
        ss=0;
        lastans=0;
        po.clear();
        low=100000000;
        for(int i=0;i<1005;i++)memo[i]=0;

        cin >> n >> m;
        if(n==0&&m==0)break;
        for(int i=0;i<n;i++){
            cin >> a;
            po.push_back(a);
            low=min(low,a);
        }
        sort(po.begin(),po.end());
        solve(0,0);
        cout << lastans << endl;
        //cout <<"ss=" << ss << endl;
    }

    return 0;
}

void solve(int dp,long int sum){
    //long int ans=0;
    ss++;
    //cout <<"ss=" << ss << endl;
    if(dp==n)return ;
    else{
    // memo[dp]=max(sum,memo[dp]);

     for(int i=0;i<n;i++){
        if(sum+po[i]<m){
            lastans=max(lastans,sum+po[i]);
            //ans=max(ans,sum+po[i]);
            solve(dp+1,sum+po[i]);
            }else break;
        }
    }
    return;
}

C++: #include <bits/stdc++.h>
using namespace std;

#define rep(i,s,n) for (int i = (int)s; i < (int)n; i++)
#define ll long long
#define pb push_back
#define eb emplace_back
#define All(x) x.begin(), x.end()
#define Range(x, i, j) x.begin() + i, x.begin() + j
#define lbidx(x, y) lower_bound(x.begin(), x.end(), y) - x.begin()
#define ubidx(x, y) upper_bound(x.begin(), x.end(), y) - x.begin()
#define llbidx(x, y, z) lower_bound(x.begin(), x.end(), z) - lower_bound(x.begin(), x.end(), y) // 二要素間の距離
#define deg2rad(deg) ((((double)deg)/((double)360)*2*M_PI))
#define rad2deg(rad) ((((double)rad)/(double)2/M_PI)*(double)360)
#define Find(set, element) set.find(element) != set.end()
#define Decimal(x) printf("%.10f\n", x) // 小数点を10桁まで表示
// debug用
#define PrintVec(x) for (auto elementPrintVec: x) { cout << elementPrintVec << " "; } cout << endl;

typedef pair<int, int> PI;
typedef pair<ll, ll> PLL;

int POWINT(int x, int n) {
  int ret = 1;
  rep(i, 0, n) ret *= x;
  return ret;
};

ll POWLL(int x, int n) {
  ll ret = 1;
  rep(i, 0, n) ret *= x;
  return ret;
};

template<class T>
inline bool chmax(T &a, T b) {
  if(a < b) {
    a = b;
    return true;
  }
  return false;
};

template<class T>
inline bool chmin(T &a, T b) {
  if(a > b) {
    a = b;
    return true;
  }
  return false;
};

bool check(ll x, set<ll> &s) { // x以上が作れるかどうか
  bool ret = false;
  for (auto it: s) {
    if (Find(s, x - it)) {
      ret = true;
      break;
    }
  }

  return ret;
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  int m;
  while (cin >> n >> m, n) {
    set<int> s;
    vector<int> P(n+1, 0);
    rep(i, 1, n+1) {
      cin >> P[i];
    }

    sort(All(P));

    rep(i, 0, n+1) {
      rep(j, i, n+1) {
        s.insert(P[i]+P[j]);
      }
    }

    vector<int> possible; // 二本の矢での取り得る点数
    for (auto it: s) {
      possible.pb(it);
    }
    sort(All(possible)); // (N^2long(N^2))

    int ans = 0;

    rep(i, 0, n+1) {
      int a = P[i];
      rep(j, i, n+1) {
        int b = P[j];
        int ab = a+b;
        if (ab > m) break;

        int ng = possible.size();
        int ok = 0;
        while (abs(ng - ok) > 1) {
          ll mid = (ok + ng) / 2;
          if (possible[mid] <= (m - ab)) {
            ok = mid;
          } else {
            ng = mid;
          }
        }

        ans = max(ans, possible[ok] + ab);
      }
    }

    cout << ans << endl;
  }


  return 0;
};

C++: #include <bits/stdc++.h>
using namespace std;
#define Rep(i, N) for(int i = 0; i < N; i++)
 
int main()
{
  int N, M;
  int A[1005] = {0};
  vector<int>sum;
  int maxv = 0;
  
  cin >> N >> M;
  sum.push_back(0);
  for(int i = 1; i <= N; i++) {
    cin >> A[i];
    Rep(j, i + 1) {
      if(A[i] + A[j] <= M) sum.push_back(A[i] + A[j]);
    }
  }
  sort(sum.begin(), sum.end());
  Rep(i, sum.size()) {
    maxv = max(maxv, sum[i] + *(upper_bound(sum.begin(), sum.end(), M - sum[i]) - 1));
  }
  cout << maxv << endl;
    
  return 0;
}

C++: #include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

int main()
{
    for(;;){
        int n, m;
        cin >> n >> m;
        if(n == 0)
            return 0;

        vector<int> p(n);
        for(int i=0; i<n; ++i)
            cin >> p[i];

        vector<int> num = p;
        num.push_back(0);
        for(int i=0; i<n; ++i){
            for(int j=0; j<=i; ++j){
                num.push_back(p[i] + p[j]);
            }
        }
        sort(num.begin(), num.end());

        int ret = 0;
        unsigned j = num.size() - 1;
        for(unsigned i=0; i<num.size(); ++i){
            if(num[i] > m)
                break;
            while(num[i] + num[j] > m)
                -- j;
            ret = max(ret, num[i] + num[j]);
        }
        cout << ret << endl;
    }
}

C++: #include<bits/stdc++.h>
using namespace std;
static const int MAX_N = 100;
int main(){
	int N, M;
	int point[MAX_N + 1];
	int a[(MAX_N + 1) * (MAX_N + 1)];
	for(;;){
		scanf("%d %d", &N, &M);
		if(N == 0 && M == 0) break;
		point[0] = 0;
		for(int i = 1; i <= N; i++) scanf("%d", &point[i]);
		int index = 0;
		for(int i = 0; i < N + 1; i++){
			for(int j = 0; j < N + 1; j++){
				a[index] = point[i] + point[j];
				index++;
			}
		}
		sort(a, a + (N + 1) * (N + 1));
		int num_a = (N + 1) * (N + 1);
		int ans = 0;
		for(int i = 0; i < num_a; i++){
			if(a[i] > M) break;
			int lb = 0, ub = num_a - 1;
			int mid;
			while(ub - lb > 1){
				mid = (lb + ub) / 2;
				if(a[i] + a[mid] > M) ub = mid;
				else lb = mid;
			}
			mid = (lb + ub) / 2;
			if(a[i] + a[mid] > ans){
				ans = a[i] + a[mid];
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

C++: #include <iostream>
#include <vector>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <cstdio>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
#include <functional>
#include <cstring>
#include <tuple>
#include <utility>
#include <list>
#include <cmath>

using namespace std;

typedef long long LL;
typedef vector<int> Array;
typedef pair<int, int> P;

const LL LINF = 1LL << 60;
const LL MOD = 100000;
#define rep(i,n) for(int i=0;i<(int)n;++i)
#define all(c) (c).begin(), (c).end()

struct edge{ LL to, cost; edge(int t, LL c) :to(t), cost(c){} };

int dxk[] = { 1, 1, 1, 0, -1, 0 };
int dxg[] = { 0, 1, 0, -1, -1, -1 };
int dy[] = { -1, 0, 1, 1, 0, -1 };

int main()
{
	int n;
	LL m;
	while (cin >> n >> m && n)
	{
		vector<LL> nums(n);
		rep(i, n) cin >> nums[i];
		vector<LL> arr(n*n + n);
		rep(i, n) rep(j, n)
		{
			arr[i * n + j] = nums[i] + nums[j];
		}
		rep(i, n) arr[n*n + i] = nums[i];
		sort(all(arr));

		LL ans = 0;
		for (auto x : arr)
		{
			LL rem = m - x;
			auto it = upper_bound(all(arr), rem);
			if (it != arr.begin())
			{
				LL num = *(--it);
				ans = max(ans, num + x);
			}
		}
		cout << ans << endl;
	}
	return 0;
}