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*len(arr)+j] = arr[i] + arr[j]
			}
		}

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

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

using namespace std;

vector<int>arr;
bool IsOK(int index, int key)
{
    if (arr[index] <= key) return true;
    else return false;
}
static int Binary_search(int key)
{
    int ok = -1;
    int ng = arr.size();
    while (abs(ok - ng) > 1)
    {
        int mid = ng + (ok - ng) / 2;

        if (IsOK(mid, key)) ok = mid;
        else ng = mid;
    }

    return ok;
}

int main() {
    while (true) {
        int n, m;
        cin >> n >> m;
        if (n == 0 && m == 0)break;
        vector<int> p(n);
        arr=vector<int>(0);
        for (int i = 0; i < n; i++)cin >> p[i];
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= n; j++) {
                arr.push_back((i != n ? p[i] : 0) + (j != n ? p[j] : 0));
            }
        }
        sort(arr.begin(), arr.end());
        int ret = 0;
        for (int i = 0; i < arr.size() && arr[i] <= m; i++) {
            ret = max(ret, arr[i] + arr[Binary_search(m - arr[i])]);
        }
        cout << ret << endl;
    }
    return 0;
}

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

vector<long long>F1;
vector<long long>F2;

long long n,m;
long long a[10000];
long long maxn;
long long l,r,M;

int main(){
	while(true){
		maxn=0;
		cin>>n>>m;
		if(n==0 && m==0){break;}
		for(int i=0;i<n;i++){
			cin>>a[i];
		}
		F1.clear();
		F2.clear();
		for(int i=0;i<=n;i++){
			for(int j=0;j<=n;j++){
				F1.push_back(a[i]+a[j]);
			}
		}
		for(int i=0;i<=n;i++){
			for(int j=0;j<=n;j++){
				F2.push_back(a[i]+a[j]);
			}
		}
		sort(F2.begin(),F2.end());
		for(int i=0;i<F1.size();i++){
			if(F1[i]<=m){
				l=0;r=F2.size();
				for(int j=0;j<21;j++){
					M=(l+r)/2;
					if(F1[i]+F2[M]>m){
						r=M;
					}
					else if(M==F1.size()-1){
						l=M;
					}
					else if(F1[i]+F2[M+1]<=m){
						l=M;
					}
				}
				if(F1[i]+F2[M]<=m){
				maxn=max(maxn,F1[i]+F2[M]);
				}
			}
		}
		cout<<maxn<<endl;
	}
	return 0;
}

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

int main(int argc, char *argv[]){
  int n, m;
  while(cin >> n >> m, n){
    int point[n + 1];
    point[0] = 0;
    set<int> a, b;
    for (int i = 1; i <= n; i++) {
      cin >> point[i];
    }
    for (int i = 0; i <= n; i++) {
      for (int j = 0; j <= n; j++) {
        a.insert(point[i] + point[j]);
      }
    }
    int ans = 0;
    for (int i: a) {
      ans = max(ans, i + *(--a.upper_bound(m - i)));
    }
    std::cout << ans << std::endl;
  }
  return 0;
}

C++: #include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
typedef double db;

#define fr first
#define sc second
#define pb push_back
#define rep(i,x) for(ll i=0;i<x;i++)
#define rep1(i,x) for(ll i=1;i<=x;i++)
#define rrep(i,x) for(ll i=x-1;i>=0;i--)
#define rrep1(i,x) for(ll i=x;i>0;i--)

ll n,m;
ll p[1000];
vector<ll> v;
int main()
{while(1){
	v.clear();
	cin>>n>>m;
	if(!n) break;
	p[0]=0;
	rep1(i,n) cin>>p[i];
	rep(i,n+1) rep(j,n+1){
		v.pb(p[i]+p[j]);
	}
	sort(v.begin(),v.end());
	ll ans;
	ans=0;
	//ans=v[upper_bound(v.begin(),v.end(),m)-v.begin()-1];
	rep(i,n+1) rep(j,n+1){
		if(p[i]+p[j]<=m) ans=max(ans,v[upper_bound(v.begin(),v.end(),m-p[i]-p[j])-v.begin()-1]+p[i]+p[j]);
	}
	//for(ll i=n/2;i<n;i++) if(p[i]<=m) ans=max(ans,v[upper_bound(v.begin(),v.end(),m-p[i])-v.begin()-1]+p[i]);
	//for(ll i=n/2;i<n;i++) for(ll j=i+1;j<n;j++) if(p[i]+p[j]<=m) ans=max(ans,v[upper_bound(v.begin(),v.end(),m-p[i]-p[j])-v.begin()-1]+p[i]+p[j]);
	cout<<ans<<endl;
}}

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

using namespace std;

int main() {
    while(true) {
        int N, M;
        cin >> N >> M;
        if(!N && !M) break;

        vector<int> points;
        set<int> points_of_two;
        for(int i = 0; i < N; ++i) {
            int p;
            cin >> p;
            points.push_back(p);
        }
        for(int i = 0; i < N; ++i) {
            if(points[i] <= M) points_of_two.insert(points[i]);
            for(int j = 0; j < i; ++j) {
                int sum = points[i] + points[j];
                if(sum <= M) points_of_two.insert(sum);
            }
        }
        points_of_two.insert(0);

        int ans = 0;
        for(set<int>::iterator it = points_of_two.begin(); it != points_of_two.end(); ++it) {
            int rem = M - *it;
            set<int>::iterator bound = points_of_two.upper_bound(rem);
            if(bound != points_of_two.begin()) --bound;
            int score = *it + *bound;
            if(score > ans) ans = score;
        }
        cout << ans << endl;
    }
    return 0;
}

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

using namespace std ;

int main()
{
	int n ;
	long int m ;
	while( cin >> n >> m ,1 )
	{
		if( !n && !m )
			return 0 ;

		vector< long int > p ,ans ;
		p.push_back( 0 ) ;
		long int a ;
		for( int i = 1 ; i <= n ; i++ )
			cin >> a ,p.push_back( a ) ;

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

		for( int i = 0 ; i <= n ; i++ )
		{
			for( int j = i ; j <= n ; j++ )
			{
				if( p[ i ] + p[ j ] <= m )
					ans.push_back( p[ i ] + p[ j  ] ) ;
			}
		}

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

		long int lp = ans.size() - 1 ,Im_home = 0 ;
		for( int i = 0 ;  i < ans.size() ; i++ )
		{
			while( ans[ i ] + ans[ lp ] > m )
				lp-- ;
			if( ans[ i ] + ans[ lp ] <= m )
				Im_home = max( Im_home ,ans[ i ] + ans[ lp ] ) ;
		}

		cout << Im_home << endl ;
	}
}

C++: #include<cstdio>
#include<math.h>
#include<algorithm>
#include<string.h>

using namespace std;
const int INF =1001001001;
#define rep(i,n) for(int i=0;i<n;i++)
const int MAX_T = 1002*1002;
int M;



int main(){
	while(1){
		int N,M;
		int P[1002];
		scanf("%d %d",&N,&M);
		if(N==0&&M==0)return 0;
		rep(i,N)scanf("%d",&P[i]);
		P[N]=0;//投げない場合
		//2回の合計の場合をだす
		int P2[MAX_T];
		int T=-1;
		rep(i,N+1)rep(j,N+1)P2[++T]=P[i]+P[j];
		sort(P2,P2+T+1);
		//二分探索
		int ans=0;
		rep(i,T+1){
			int q=M-P2[i];
			int a=0,b=T+1;
			if(q<0)continue;
			else{
				do{
				int c=(b+a)/2;
				if(P2[c]>q){b=c;}
				else if(P2[c]==q){a=c;break;}
				else{a=c;}
				}while(b-a>1);
				ans=max(P2[i]+P2[a],ans);					
			}
		}
		printf("%d\n",ans);
	}
return 0;	
}