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 <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int N, M;
int a[1005];
vector<int> vec;

int main(void)
{
	while(1){
		cin >> N >> M;
		if(N == 0 && M == 0) break;
		for(int i = 0; i < N; i++) cin >> a[i];
		a[N] = 0;
		
		vec.clear();
		for(int i = 0; i <= N; i++){
			for(int j = 0; j <= N; j++){
				vec.push_back(a[i] + a[j]);
			}
		}
		sort(vec.begin(), vec.end());
		
		int ans = 0;
		for(int i = 0; i < vec.size(); i++){
			auto p = upper_bound(vec.begin(), vec.end(), M-vec[i]);
			if(p == vec.begin()) continue;
			ans = max(ans, vec[i] + *(--p));
		}
		cout << ans << endl;
	}
	
	return 0;
}

C++: #include<algorithm>

#define MAX_N 1001

using namespace std;

int BinSearch(int v[], int vsize, int search){
	int l = 0;
	int r = vsize;
	int m = 0;
	if( v[r - 1] < search )
		return r - 1;
	else if(v[1] > search )
		return 0;

	while( r - 1 > l ){
		m = (r + l) / 2;

		if( v[m] > search )
			r = m;
		else if(v[m] == search)
			return m;
		else
			l = m;
	}
	return m;
}

int main(void){
	while( true ){
		int prevQ = -1;
		int index = 0;
		int Max = 0;
		int N, M;
		int *Q;
		int V[MAX_N];

		cin >> N >> M;
		
		if( N == 0 && M == 0 ) break;

		for(int i = 0; i < N; i++)
			cin >> V[i];
		
		V[N] = 0;
		N++;

		Q = new int[N*N];

		for(int i = 0; i < N; i++)
			for(int j = 0; j < N; j++)
				Q[i * N + j] = V[i] + V[j];

		sort(Q, Q+N*N);

		for(int i = 0; i < N * N; i++){
			int optim;
			
			if( prevQ == Q[i] )
				continue;
			else
				prevQ = Q[i];

			optim = BinSearch(Q, N*N, M - Q[i]);
			if( optim > 0 && Q[i] + Q[optim] > M)
				optim--;
			Max = max( Max , Q[i] + Q[optim] > M ? 0 : Q[i] + Q[optim]);
		}

		delete[] Q;
		cout << Max << '\n';
	}
	return 0;
}

C++: #include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
	int a,b,mato[1000];
	vector<int> nums;
	while(scanf("%d%d",&a,&b),a,b){
		int res=0;
		for(int i=0;i<a;i++){scanf("%d",mato+i);}
		nums.clear();
		for(int i=0;i<=a;i++){
			for(int j=0;j<=a;j++){
				int r=0;
				if(i!=a)r+=mato[i];
				if(j!=a)r+=mato[j];
				nums.push_back(r);
			}
		}
		sort(nums.begin(),nums.end());
		vector<int>::iterator it=nums.begin();
		while(it!=nums.end()){
			if(b-*it<0)break;
			vector<int>::iterator itt=upper_bound(nums.begin(),nums.end(),b-*it);
			itt--;
			res=max(res,*it+*itt);
			it++;
		}
		printf("%d\n",res);
	}
	return 0;
}

C++: #include <iostream>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <vector>
#include <utility>
#include <numeric>
#include <string>
#include <set>
#include <map>
#include <tuple>
#include <queue>
#include <stack>
#include <deque>
#define rep(i, a, n) for(int (i) = (int)(a);(i) < (int)(n);++(i))
#define repe(i, a, n) for(int (i) = (int)(a);(i) <= (int)(n);++(i))
#define repif(i, a, x) for(int (i) = (int)(a);(x);++(i))
#define repr(i, a, n) for(int (i) = (int)(a);(i) > (int)(n);--(i))
#define reper(i, a, n) for(int (i) = (int)(a);(i) >= (int)(n);--(i))
#define SIZE(x) ((int)(x).size())
#define ALL(x) (x).begin(), (x).end()
#define RNG(x, n) &((x)[0]), &((x)[n])
#define ADD(a, b) ((((a)%MOD)+((b)%MOD))%MOD)
#define MUL(a, b) ((((a)%MOD)*((b)%MOD))%MOD)
#define FLOOR(x) ((int)floor(((double)x)))
#define CEIL(x) ((int)ceil(((double)x)))
#define UNIQUE(x) (x).erase(unique(ALL((x))), (x).end())
#define YES cout << "YES" << endl
#define NO cout << "NO" << endl
#define Yes cout << "Yes" << endl
#define No cout << "No" << endl
#define yes cout << "yes" << endl;
#define no cout << "no" << endl;
#define fcout cout << fixed << setprecision(10)
#define pb push_back
#define pf push_front
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define EPS (1e-20)
#define INF 2147483647
#define MOD 1000000007
using llint = long long;
using VI = std::vector<int>;
using PII = std::pair<int, int>;
using SI = std::set<int>;
using MII = std::map<int, int>;
using TIII = std::tuple<int, int, int>;
using VLL = std::vector<llint>;
using MCI = std::map<char, int>;
using namespace std;


int N, M;
int P[1010];
VI enum1, enum2;


void makeEnum(){
	enum1.pb(0);
	rep(i, 0, N) enum1.pb(P[i]);
	rep(i, 0, N)
		rep(j, 0, N) enum1.pb(P[i]+P[j]);
	sort(ALL(enum1));
	UNIQUE(enum1);
	enum2 = enum1;
}


void clear(){
	enum1.clear();
	enum2.clear();
}


int solve(){
	int ans = 0;
	for(int x : enum1){
		if(x > M) continue;
		auto it = ub(ALL(enum2), M-x);
		if(it == enum2.begin()) continue;
		ans = max(ans, *(it-1)+x);
	}
	return ans;
}


signed main(){
	while(cin >> N >> M, N || M){
		rep(i, 0, N) cin >> P[i];
		
		makeEnum();
		
		cout << solve() << endl;
		
		clear();
	}
	
	return 0;
}

C++: #include<iostream>
#include<vector>
#include<map>
#include<cassert>
#include<algorithm>
using namespace std;

int main(){
  int N,M;
  vector<int> vec[5];
 
  while(true){
  cin >> N >> M;
  if(N+M == 0)break;
  int val[N];
  for(int i=0;i<5;i++)vec[i].clear();
  
  int mex = -1;
  int master = -1;
  
  for(int i=0;i<N;i++){
    cin >> val[i];    
    mex = max(mex,val[i]);
    vec[1].push_back(val[i]);
  }
  master = mex;
  if(mex == M){
    cout << M << endl;
    continue;
  }
  bool fin = false;
  for(int i=2;i<=4;i++){       
    if(i > 2)vec[i-2].clear();
      for(int j=0;j<vec[i-1].size();j++){
	if(vec[i-1][j]+master <= mex)continue;
	for(int k=0;k<N;k++){
	  if(val[k] >= M)continue;
	 
	  if(i == 4 && vec[i-1][j]+val[k] <= mex)continue;
	 
	  vec[i].push_back(vec[i-1][j]+val[k]);
	

	if(M >= vec[i-1][j]+val[k])mex = max(mex,vec[i-1][j]+val[k]);

	if(mex == M){
	  fin = true;
	  break;
	}
      }
      if(fin)break;
    }
    if(fin)break;
 
  }
  assert(mex != -1);
  cout << mex << endl;	
  }
  return 0;
}

C++: #include<algorithm>
#include<vector>

#define MAX_N 1001

using namespace std;

int main(void){
	while( 1 ){
		int n, m;
		int V[MAX_N] = {0,};
		int D[MAX_N][4] = {{0,},};
		int Max = 0;

		cin >> n >> m;

		if( n == 0 && m == 0 ){
			break;
		}

		for(int i = 0; i < n; i++){
			cin >> V[i];
		}
		V[n] = 0;
		n++;

		sort(V, V + n);
		reverse(V, V + n);

		for(int i = 0; i < n; i++){
			for(int j = 0; j < 4; j++){
				if( j == 0 ){
					D[i][j] = V[i] > m ? -1 : V[i];
				}else{
					int thisMax = 0;

					if( D[i][j - 1] < 0 ){
						D[i][j] = -1;
						continue;
					}
					
					for(int k = 0; k <= i; k++){
						int tmp = V[i] + D[k][j - 1];
						if( D[k][j - 1] < 0 ){
							continue;
						}
						if( tmp > m ){
							continue;
						}
						thisMax = max(thisMax, tmp);
					}
					
					if( thisMax > V[i] ){
						D[i][j] = thisMax > m ? -1 : thisMax;
					}
				}
			}
		}

		for(int i = 0; i < n; i++){
			for(int j = 0; j < 4; j++){
				//cout << D[i][j] << ' ';
				if( D[i][j] <= m ){
					if( Max < D[i][j] ){
						Max = D[i][j];
					}
				}
			}
			//cout << '\n';
		}

		cout << Max << '\n';
	}
	return 0;
}