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 <cstdio>
#include <algorithm> // sort, max

using namespace std;

#define MAX_N 1001

int N;			// 的の部分の個数 (1≦N≦1000)
int M;			// 得点上限(1 ≦ M ≦ 200000000 = 2 × 10^8)
int P[MAX_N];	// 得点(1 ≦ Pi ≦ 100000000 = 10^8)
int Q[MAX_N * MAX_N];	// 2回投げた時の可能な得点
 
int main() {

	// 読込み
	scanf("%d%d", &N, &M);

	while(N > 0 && M > 0) {
		// 得点の読み込み
		P[0] = 0;
		for(int i = 1; i <= N; i++) scanf("%d", &P[i]);

		// 2回合計
		int cnt = 0;
		for(int i = 0; i <= N; i++) 
			for(int j = 0; j <= N; j++) 
				Q[cnt ++] = P[i] + P[j];

		// 昇順並べ替え O(N^2log N)
		sort(Q, Q + cnt);
		
		int s, t = cnt - 1;
		int Max = 0;

		// 探索 O(N^2)
		for(s = 0; s < cnt; s++) {
			// 
			while(Q[s] + Q[t] > M) t--;
			// 候補なし
			if(t < 0) break;
			// 最大値更新
			Max = max(Max, Q[s] + Q[t]);
		}
		// 最大値出力
		printf("%d\n", Max);
		// 
		scanf("%d%d", &N, &M);
	}
	return 0;
}

C++: #include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long int ll;

int main(){
  while(1){
    int n,m; cin >> n >> m;
    if(n==0&&m==0)break;
    vector<int> a(n);
    for(int i=0;i<n;i++){
        cin >> a[i];
    }
    a.push_back(0);
    vector<ll> v;
    for(int i=0;i<=n;i++){
      for(int j=0;j<=n;j++){
        v.push_back(a[i]+a[j]);
      }
    }
    sort(v.begin(),v.end());
    ll ans=0;
    for(int i=0;i<v.size();i++){
        if(m-v[i]>=0){
            int left=-1,right=v.size();
            while(right-left>1){
                int mid=(right+left)/2;
                if(v[mid]<=m-v[i]){
                    left=mid;
                }
                else{
                    right=mid;
                }
            }
            ans=max(ans,v[i]+v[left]);
        }
    }
    cout << ans << endl;
  }
  return 0;
}

C++: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>

#define EPS 1e-9
#define INF 1070000000LL
#define MOD 1000000007LL
#define fir first
#define foreach(it,X) for(auto it=(X).begin();it!=(X).end();it++)
#define ite iterator
#define mp make_pair
#define mt make_tuple
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<(n);i++)
#define pb push_back
#define sec second
#define sz(x) ((int)(x).size())

using namespace std;

struct timer{
	time_t start;
	timer(){start=clock();}
	~timer(){cerr<<1.*(clock()-start)/CLOCKS_PER_SEC<<" secs"<<endl;}
};

typedef istringstream iss;
typedef long long ll;
typedef pair<ll,ll> pi;
typedef stringstream sst;
typedef vector<ll> vi;

ll N,M,P[1010],a[1100000];

int main2(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);
	
	if(cin>>N>>M,!N)return 1;
	rep(i,N)cin>>P[i];
	P[N++]=0;
	rep(i,N)rep(j,N)a[i*N+j]=-(P[i]+P[j]);
	sort(a,a+N*N);
	ll ans=0;
	rep(i,N*N){
		ll b=-a[i];
		int id=lower_bound(a,a+N*N,-(M-b))-a;
		if(id==N*N)continue;
		ans=max(ans,b-a[id]);
	}
	cout<<ans<<endl;
	return 0;
}

int main(){
	while(!main2());
}

C++: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

int n;
long m, p[1100];
long dp[6][1100];

long rec(int a, int b){ //a本目，最後に当てた位置b
	if(dp[a][b]>=0) return dp[a][b];
	
	long ret=0;
	
	if(a==4) ret=0;
	else{
		for(int i=b; i<=n; ++i){
			long tmp=rec(a+1, i)+p[i];
			if(tmp>m) tmp=0;	
			
			if(ret<tmp) ret=tmp;
		}		
	}
	
	return dp[a][b]=ret;
}

int main(){
	while(1){
		scanf(" %d %ld", &n, &m);
		if(n==0) break;
		p[0]=0; //投げない選択肢
		for(int i=1; i<=n; ++i) scanf(" %ld", &p[i]);
		sort(p, p+n);
		
		memset(dp, -1, sizeof(dp));
		printf("%ld\n", rec(0,0));
	}
}

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

using namespace std;


int a[1000*1001];

int main(){
	int n,m;
	int i,j,k;
	int *p;
	int r,rr;

	while(true){

		//memset(a,0,sizeof(a));
		scanf("%d%d",&n,&m);
		if(n==0&&m==0) break;

		for(i=0;i<n;i++){
			scanf("%d",&a[i]);
		}

		k=n;
		for(i=0;i<n;i++){
			for(j=i;j<n;j++){
				a[k++]=a[i]+a[j];
				}
		}
		sort(a,a+n*(n+1)/2+n);

	/*
		for(i=0;i<n*(n+1)/2+n;i++){
			printf("%d\n",a[i]);
		}
		*/
		rr=0;
		for(i=0;i<n*(n+1)/2+n;i++){
			p=lower_bound(a+i,a+n*(n+1)/2+n,m-a[i]);
			r=*(p-1)+a[i];
			if((*(p-1)<=m-a[i])&&(r>rr)) rr=r;
			}

		printf("%d\n",rr);

		}

	return 0;
	}

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

using namespace std;


int P[1001];
int twice[1002010];
vector<int> vi;


int main(void){
	int N,M;
	
	while(scanf("%d%d", &N, &M) && N != 0 && M != 0 ){
		int ans = 0;
		
		P[0] = 0;
		
		for(int i = 1; i <= N; i++){
			scanf("%d", &P[i]);
		}
		
		for(int i = 0; i <= N; i++){
			for(int j = 0; j <= N; j++){
				vi.push_back( P[i]+P[j] );
			}
		}
		
		sort(vi.begin(),vi.end());
		
		twice[0] = vi[0];
		int c = 1;
		
		for(int i = 1; i < vi.size(); i++){
			if(vi[i] != vi[i-1]){
				twice[c] = vi[i];
				c++;
			}
		}
		/*
		for(int i = 0; i < c; i++){
			printf("%d\n",twice[i]);
		}
		*/
		//cツ古つづ荊wice
		
		for(int i = 0; i < c; i++){
			int *p = upper_bound(twice,twice+c,M-twice[i]);
			int u = p - twice;
			int t = u-1;
			if(twice[i]+twice[u]<=M)ans = max(ans,twice[i]+twice[u]);
			if(t != -1 &&twice[i]+twice[t]<=M)ans = max(ans,twice[i]+twice[t]);
		}
		
		printf("%d\n",ans);
		vi.clear();
		
	}
	
	return 0;
}

C++: #include <iostream>
#include <algorithm>
#include <functional>
#include <queue>

using namespace std;

struct data {
	int num;
	char count;
};

int main( void )
{
	int n, m, input[1000];
	while(cin >> n >> m, n | m) {
		for(int i=0; i < n; ++i) cin >> input[i];
		queue<data> q; data a;
		a.num = m; a.count = 0;
		q.push(a);
		sort(input, input+n, greater<int>());
		//for(int i=0; i < n; ++i) cout << input[i] << ' ';
		//cout << endl;
		int Min = m;
		while(!q.empty()) {
			data tmp = q.front(); q.pop();
			for(int i=0; i < n; ++i) {
				int bb = tmp.num - input[i];
				if(bb >= 0 && tmp.count < 4) {
					Min = min(Min, bb);
					data x = { bb, tmp.count + 1 };
					q.push(x);
					if(!Min) break;
				}
			}
			if(!Min) break;
		}
		cout << m - Min << endl;
	}
	return 0;
}

C++: #import<iostream>
#import<algorithm>
using namespace std;int*p,P[1001],*q,Q[1<<20],n,m,v,*i,*j;main(){for(;cin>>n>>m,n;cout<<v<<endl){for(p=P+1;n--;v=0)cin>>*p++;sort(P,p);p=unique(i=P,p);for(q=Q;i-p;++i)for(j=P;j<i+1;)*q++=*j+++*i;sort(Q,q);q=unique(i=Q,q);for(*q++=m+1;*i<=m;++i)v=max(v,*i+upper_bound(Q+1,q,m-*i)[-1]);}}