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>

#define mp       make_pair
#define mt	 make_tuple
#define pb       push_back
#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

typedef    long long          ll;
typedef    unsigned long long ull;
typedef    pair<int,int>      pii;
typedef    pair<long,long>    pll;

const int INF=1<<29;
const double EPS=1e-9;
const int MOD = 100000007;

const int dx[]={1,0,-1,0},dy[]={0,-1,0,1};
int N,M;

int main(){
  while (cin >> N >> M){
    if (N == 0 and M == 0)break;
    vector<int> darts;
    vector<int> d_darts;
    for (int i = 0; i < N; i++){
      int x;
      cin >> x;
      darts.push_back(x);
    }
    darts.push_back(0);
    for (int i = 0; i < darts.size(); i++){
      for (int j = i + 1; j < darts.size(); j++){
	d_darts.push_back(darts[i] + darts[j]);
      }
    }
    sort(d_darts.begin(), d_darts.end());
    int res = 0;
    for (int i = 0; i <d_darts.size(); i++){
      int query = M - d_darts[i];
      int index = (lower_bound(d_darts.begin(), d_darts.end(), query) - d_darts.begin());
      if (index - 1 >= 0){

	res = max(res, d_darts[index - 1] + d_darts[i]);
      }
    }
    cout << res << endl;
  }
}

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

using namespace std;

int N;
int M;
vector<int>P;
int ans=0;

/*
int binarySearch(int t){
    int lo=0,hi=N-1;
    int te;
    while(true){
        int m=(lo+hi)/2;
        if(P[m]<t){
            hi=(m-1)<=1?0:m-1;
        }else if(P[m]>t){
            lo=m+1;
        }
        if(lo>=hi){
            te=hi;
        }
    }
    return te;
}*/



void func(int dart,int sum){
    ans=max(ans,sum);
    if(dart==4)return ;
    int s=M-sum;
    auto it = upper_bound(P.begin(),P.end(),s);
    it = prev(it);
    for(auto i=it;i!=P.begin();i--){
        func(dart+1,sum+*it);
    }
    
    
    /*
    if(sum+P[n]<=M){
        func(n-1,dart+1,sum+P[n]);
        func(n,1+dart,sum+P[n]);
        func(n-1,dart,sum);
    }
    else {
        func(n-1,dart,sum);
    }
     */
    
    return ;
}
int main(){
    while(cin>>N>>M,N,M){
        P = vector<int>(N+1,0);
        for(int i=0;i<N;i++){
            cin>>P[i];
        }
        sort(P.begin(),P.end());
        func(0,0);
        cout<<ans<<endl;
        ans=0;
    }
    
    
}

C++: #include <bits/stdc++.h>
using namespace std;
#define FOR(i,k,n) for(int i = (k); i < (n); i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(a) begin(a),end(a)
#define MS(m,v) memset(m,v,sizeof(m))
#define D10  fixed<<setprecision(5)
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<short, short> P;
typedef complex<double> Point;
typedef long long ll;
const int INF = 114514810;
const int MOD = 100000007;
const double EPS = 1e-10;
const double PI = acos(-1.0);
struct edge
{
	int from, to, cost;
	bool operator < (const edge& e) const { return cost < e.cost; }
	bool operator >(const edge& e) const { return cost > e.cost; }
};
///*************************************************************************************///
///*************************************************************************************///
///*************************************************************************************///

int n, m;
int main()
{
	while (cin >> n >> m, n)
	{
		vector<int> v, w;
		REP(i, n)
		{
			int a;
			cin >> a;
			w.push_back(a);
		}
		w.push_back(0);
		REP(i, w.size())REP(j, w.size())
		{
			int t = w[i] + w[j];
			v.push_back(w[i] + w[j]);
			
		}
		sort(ALL(v));
		int ans = 0;
		int i = 0;
		int j = v.size() - 1;
		while (i<=j)
		{
			if (v[i] + v[j] <= m)
			{
				ans = max(ans, v[i] + v[j]);
				i++;
			}
			else
			{
				j--;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

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

typedef long long INT;
typedef vector <INT> VI;
typedef set <INT> SI;

INT solve( VI Q, INT M ) {
    INT answer = 0;
    int n = Q.size();
    for ( int i = 0; i < n; ++ i ) {
        int q = Q[i];
        int L = 0;
        int R = n;
        INT m = M - q;
        while ( L < R ) {
            int p = ( R - L ) / 2 + L;
            INT t = q + Q[p];
            if ( t > M ) t = 0;
            answer = max( answer, t );
            if ( Q[p] > m ) {
                R = p;
            } else {
                L = p + 1;
            }
        }
    }
    return answer;
}

int main() {
    int n, m;
    while ( cin >> n >> m ) {
        if ( n == 0 && m == 0 ) break;
        VI P;
        for ( int i = 0; i < n; ++ i ) {
            INT p;
            cin >> p;
            P.push_back( p );
        }
        P.push_back( 0 );
        VI Q;
        for ( int i = 0; i < n + 1; ++ i ) {
            for ( int j = 0; j < n + 1; ++ j ) {
                Q.push_back( P[i] + P[j] );
            }
        }
        sort( Q.begin(), Q.end() );
        unique( Q.begin(), Q.end() );
        cout << solve( Q, m ) << endl;
    }
    return 0;
}

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

int solve(int*, int, int);
int main(){
  int n, points;
  while(cin>>n>>points, n!=0 && points!=0){
    int darts[n+1]; //投げない場合を考えるため、1つだけ多く取っておく
    darts[0]=0; //投げない場合
    for(int i=1; i<=n; i++) cin >> darts[i];


    //ダーツを2回投げた時の場合を考える
    //ループを抜けた後に cnt=(n+1)*(n+1)
    int cnt=0;
    int set[(n+1)*(n+1)];
    for(int i=0; i<=n; i++){
      for(int j=0; j<=n; j++){
        set[cnt++]=darts[i]+darts[j];
      }
    }

    //upper_boundを使うためソート
    sort(set, set+(n+1)*(n+1));

    int ans=0;
    for(int i=0; i<(n+1)*(n+1); i++){
      int aim = points-set[i];//目標
      if(aim<0) continue;
      int last = *(upper_bound(set, set+(n+1)*(n+1), aim)-1);
      if(set[i]+aim <= points) ans=max(ans, set[i]+last);
    }


    printf("%d\n", solve(darts, n+1, points));
  }

  return 0;
}

/*
int solve(int* darts, int size, int point){
  int temp[size*size];
  int k=0;
  //2本投げ終わった後の合計点数を探索
  for(int i=0; i<size; i++){
    for(int j=0; j<size; j++){
      temp[k++]= darts[i]+darts[j];
    }
  }

  sort(temp, temp+size*size);

  int ans=0;
  for(int i=0; i<size*size; i++){
    int aim = point-temp[i];
    if(aim<0) continue;
    int last = *(upper_bound(temp, temp+size*size, aim)-1);
    if(temp[i]+last<=point) ans=max(ans, temp[i]+last);
  }

  return ans;
}
*/


int solve(int* darts, int size, int points){
  //ダーツを2回投げた時の場合を考える
  //ループを抜けた後に cnt=(n+1)*(n+1)
  int cnt=0;
  int set[size*size];
  for(int i=0; i<size; i++){
    for(int j=0; j<size; j++){
      set[cnt++]=darts[i]+darts[j];
    }
  }

  //upper_boundを使うためソート
  sort(set, set+size*size);

  int ans=0;
  for(int i=0; i<size*size; i++){
    int aim = points-set[i];//目標
    if(aim<0) continue;
    int last = *(upper_bound(set, set+size*size, aim)-1);
    if(set[i]+aim <= points) ans = max(ans, set[i]+last);
  }
  return ans;
}