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

import (
	"fmt"
	"sort"
)

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

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

		arr := make([]int64, N+1)
		for i := 1; i <= N; i++ {
			fmt.Scan(&arr[i])
		}
		sort.Slice(arr, func(i, j int) bool { return arr[i] < arr[j] })

		sums := make([]int64, 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.Slice(sums, func(i, j int) bool { return sums[i] < sums[j] })

		var m int64 = 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 <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
	int n,m;
	while(cin>>n>>m){
		int ans=0;
		vector<int> a,sum;
		a.push_back(0);
		for(int i=1;i<=n;i++){
			int s;
			cin>>s;
			a.push_back(s);
		}
		sort(a.begin(),a.end());
		for(int i=0;i<=n;i++){
			for(int j=i;j<=n;j++){
				if(a[i]+a[j]<=m)sum.push_back(a[i]+a[j]);
			}
		}
		sort(sum.begin(),sum.end());
		int suml=sum.size()-1;
		for(int i=0;i<=suml;i++){
			while(sum[i]+sum[suml]>m)suml--;
			if(ans<sum[i]+sum[suml])ans=sum[i]+sum[suml];
		}
		cout<<ans<<endl;
	}
}

C++: #include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<ctime>
using namespace std;
#define INF (1<<30)
typedef pair<int,int> Pa;
inline int mmin(int a,int b){ return a>b?b:a;}
inline int mmax(int a,int b){ return a>b?a:b;}
int N,M;
int P[1111];
struct Segment{
  Pa T[(1<<21)+1];
  int p[1001*1001+1];
  map<int,bool> f;
  int n;

  //節点の番号、追加する要素の区間[fi、se)
  void update(int k,int fi,int se){
    k=k+(n/2)-1;
    T[k].first=mmin(fi,T[k].first);
    T[k].second=mmax(se,T[k].second);
    while(k>0){//登りながら更新
      k=(k-1)/2;
      T[k].first=mmin(fi,T[k].first);
      T[k].second=mmax(se,T[k].second);
    }
  }

  void init(){//ツリー構築

    int ind=0;
    //P[i]+P[j]の足し算の結果を格納
    for(int i=0;i<N;i++){
      for(int j=0;j<N;j++){
	p[ind++]=P[i]+P[j];
      }
    }
    //最後にINFを付加
    p[N*N]=INF;

    //昇順ソート
    sort(p,p+N*N+1);
    unique(p,p+N*N+1);

    int _n;
    for(int i=0;i<N*N+1;i++){
      if(p[i]==INF){ _n=i+1; break;}
    }

    //nを2^mに
    n=1;
    while( n < _n*2 ) n*=2;
    
    //木を全て(INF~0)に初期化
    for(int i=0;i<n;i++){
      T[i]=Pa(INF,0);
    }

    //葉を追加
    for(int i=0;i<_n-1;i++){
      update(i,p[i],p[i+1]);
    }  
  }

  //値aより小さくもっと大きい数字は何か探す
  int search(int a){
    return query(0,a);
  }

  //区間[T[k].first,T[k].second)にaあるか否か
  int query(int k,int a){
    if(k>=n/2-1)
      return T[k].first;
    if(T[k].first<=a && a<T[k].second){
      int v=query(k*2+1,a);//左の葉
      if(v==-1)
	v=query(k*2+2,a);//右の葉
      return v;
    }
    return -1;
  }
  int size(){ return n;}
  void view(){
    printf("size=%d\n",this->size());
    int r=1;
    for(int i=0;i<n;i++){
      if(i==r){puts(""); r=(r+1)*2-1;}
      printf(" [%2d,%2d) ",T[i].first,T[i].second);
    }
  }

};

Segment S;

main(){

  /*   clock_t start,end;
       start=clock();//計測*/
  while(1){
    scanf("%d %d",&N,&M);
    if(!N && !M) break;
    for(int i=0;i<N;i++){
      scanf("%d",&P[i]);
    }
    P[N]=0;
    ++N;
    S.init();
    //    S.view();
    //    printf("%d=size\n",S.size());
    


    int res=0;
    for(int i=0;i<N;i++){
      for(int j=0;j<N;j++){
	int m=M-P[i]-P[j];
	if(m<0) continue;
	m-=S.search(m);
	res = max(res,M-m);
      }
    }
    /*   //時間を図り終える
	 end=clock();
	 printf("%.2f秒かかりました\n",(double)(end-start)/CLOCKS_PER_SEC);
    */

    printf("%d\n",res);
  }
}

C++: // AOJ 0529 (http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0529)
#include<cstdio>
#include<algorithm>
#define rep(i,a) for(int i=0;i<(a);++i)

const int MAX_N = 1001;

int N, M;
int P[MAX_N], S[MAX_N*MAX_N];

int main()
{
	while( scanf( "%d%d", &N, &M ), N|M )
	{
		rep( i, N )
			scanf( "%d", P+i+1 );
		++N;

		rep( i, N ) rep( j, N )
			S[i*N+j] = P[i]+P[j];

		std::sort( S, S+N*N );

		int ans = 0;
		rep( i, N*N )
		{
			int t = S[i]+*(std::upper_bound( S, S+N*N, M-S[i] )-1);

			if( t <= M )
				ans = std::max( ans, t );
		}

		printf( "%d\n", ans );
	}

	return 0;
}

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

using namespace std;

void darts();

int main()
{
  darts();
}


void darts()
{
  while (true)
  {
    int n, m;
    cin >> n >> m;

    // stop cond
    if (n == 0) break;

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

    // 2 darts combination
    // p = q, 0, p + q
    vector<int> q = p;
    q.push_back(0);
    for (int i = 0; i < n; ++i)
    {
      for (int j = 0; j <= i; ++j)
      {
        q.push_back(p[i] + p[j]);
      }
    }

    sort(q.begin(), q.end());

    // q's size = 1 + n + n(n + 1) / 2
    //cout << q.size() << "\n";
    //for (auto x : q) cout << x << " ";

    int ret = 0;
    int j = q.size() - 1;
    //i:q linear scan
    for (int i = 0; i < q.size(); ++i)
    {
      if (q[i] > m) break;
      while (q[i] + q[j] > m) --j;
      ret = max(ret, q[i] + q[j]);
    }

    cout << ret << "\n";
  }
}

C++: #include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;

ll n, m, p[1000], d[600000];

int main() {
  while (scanf("%lld%lld", &n, &m), n) {
    for (ll i = 0; i < n; i++) scanf("%lld", &p[i]);
    ll counter = 0;
    for (ll i = 0; i < n; i++) for (ll j = 0; j <= i; j++) d[counter++] = p[i] + p[j];
    for (ll i = 0; i < n; i++) d[counter++] = p[i];
    sort(d, d + counter);
    ll ans = 0;
    for (ll i = 0, j = counter - 1; i < counter; i++) {
      while (d[i] + d[j] > m) j--;
      if (i > j) break;
      if (ans < d[i] + d[j]) ans = d[i] + d[j];
    }
    printf("%lld\n", ans);
  }
}

C++: #include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <utility>
#include <iomanip>

#define ll long long int
#define pb push_back
#define mk make_pair
#define pq priority_queue

using namespace std;
typedef pair<int, int> P;
typedef pair<ll, int> Pl;
const int inf = 1e9;
const ll linf = 1LL << 50;

int n, m;
int p[1001];
int arr[1000001];

int main(int argc, char const* argv[])
{
	while(true){
			cin >> n >> m;
			if(n == 0)break;
			for(int i = 0; i < n; i++){
					cin >> p[i];
			}
			vector<int> vec;
			vec.pb(0);
			for(int i = 0; i < n - 1; i++){
					if(p[i] <= m)vec.pb(p[i]);
					else continue;
					for(int j = i; j < n; j++){
							if(p[i] + p[j] <= m)vec.pb(p[i] + p[j]);
					}
			}
			sort(vec.begin(), vec.end());
			int ind = 1;
			for(auto itr = vec.begin(); itr != vec.end(); ++itr){
					arr[vec.size() - ind] = *itr;
					ind++;
			}
			int res = 0;
			for(auto itr = vec.begin(); itr != vec.end(); ++itr){
					int index = lower_bound(arr, arr+vec.size(), m-*itr, greater<int>()) - arr;
					if(index >= 0 && index < vec.size()){
							res = max(res, arr[index] + *itr);
					}
			}
			cout << res << endl;
	}
	return 0;
}

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

int main(){
  long n,m,p[1001];
  while(cin>>n>>m,n||m){
    for(int i=1;i<=n;++i) cin>>p[i];
    p[0]=0;
    vector<long> s(0);
    for(int i=0;i<=n;++i){
      for(int j=0;j<=n;++j) s.push_back(p[i]+p[j]);
    }
    sort(s.begin(),s.end());
    long a=0;
    for(vector<long>::iterator it=s.begin();it!=s.end();++it){
      if(*it>m/2) break;
      a=max(a,*it+*(upper_bound(s.begin(),s.end(),m-*it)-1));
    }
    cout<<a<<endl;
  }
  return 0;
}