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)
	}
}

Python: from time import perf_counter
from itertools import combinations_with_replacement
from bisect import bisect_right
from functools import lru_cache


def solve1(darts, scores, point, target):
    if darts == 3 or point > target:
        if point > target:
            return 0
        else:
            pos = bisect_right(scores, target-point)
            return point + scores[pos-1]

    max_score = 0
    for s in scores:
        result1 = solve1(darts + 1, scores, point + s, target)  # ???????????´???
        # result2 = solve1(darts + 1, scores, point, target)      # ?????°????????£?????´???
        max_score = max(max_score, result1)
    return max_score


def solve2(darts, scores, point, target):
    """ ???????????? """
    combi = combinations_with_replacement(scores, 4)
    max_score = 0
    max_combi = []
    for s in combi:
        score = sum(s)
        if score <= target and score > max_score:
            max_score = score
            max_combi = s
    print('max_combi: {0}'.format(max_combi))
    return max_score


Target = 0
def solve3(darts, scores, point, target):
    """ ?????£???????????°??????????????¢??? """
    global Target
    Target = target
    return cache_solve3(darts, tuple(scores), point)


@lru_cache(maxsize=None)
def cache_solve3(darts, scores, point):
    if darts == 4 or point > Target:
        if point > Target:
            return 0
        else:
            pos = bisect_right(scores, Target-point)
            return point + scores[pos-1]

    max_score = 0
    for s in scores:
        result1 = cache_solve3(darts + 1, scores, point + s)
        max_score = max(max_score, result1)
    return max_score


def solve4(darts, scores, point, target):
    if darts == 3 or point > target:
        if point > target:
            return 0
        else:
            pos = bisect_right(scores, target-point)
            return point + scores[pos-1]

    max_score = 0
    t = (target - point) // (4 - darts)
    min_lim = bisect_right(scores, t)
    for s in range(min_lim-1, len(scores)):
        result1 = solve4(darts + 1, scores, point + scores[s], target)  # ???????????´???
        max_score = max(max_score, result1)
    return max_score


def solve5(darts, scores, point, target):
    combi = combinations_with_replacement(scores, 2)
    i_scores = [sum(x) for x in combi if sum(x) < target]
    i_scores.sort()

    results = [x + find_le(i_scores, target-x) for x in i_scores]
    return max(results)


def find_le(a, x):
    'Find rightmost value less than or equal to x'
    i = bisect_right(a, x)
    if i:
        return a[i-1]
    raise ValueError


if __name__ == '__main__':
    # ??????????????\???
    while True:
        N, M = [int(x) for x in input().split(' ')]
        scores = [int(input()) for _ in range(N)]

        if N == 0 and M == 0:
            break

        # ???????????????????????????????¨????
        scores.append(0)  # ??????????????????????????????????????¨??????????????¢???????????????????????????=0????????????
        scores.sort()  # ???????????°??????????????????????????????

        # start_time = perf_counter()
        # ans = solve1(0, scores, 0, M)
        # end_time = perf_counter()
        # print('solve1, elapsed: {0}'.format(end_time - start_time))
        # print(ans)

        # start_time = perf_counter()
        # ans = solve2(0, scores, 0, M)
        # end_time = perf_counter()
        # print('solve2, elapsed: {0}'.format(end_time - start_time))
        # print(ans)

        # start_time = perf_counter()
        # ans = solve4(0, scores, 0, M)
        # end_time = perf_counter()
        # print('solve4, elapsed: {0}'.format(end_time - start_time))
        # print(ans)

        #start_time = perf_counter()
        ans = solve5(0, scores, 0, M)
        #end_time = perf_counter()
        #print('solve5, elapsed: {0}'.format(end_time - start_time))
        print(ans)

        # ???????????¨???
        # print(ans)

Python: import bisect

while 1:
    n,m=map(int,raw_input().split())
    if n==m==0:break
    p=[0]+[int(raw_input()) for _ in xrange(n)]
    com=[None]*((n+1)**2)
    for i in xrange(n+1):
        for j in xrange(n+1):
            com[(n+1)*i+j]=p[i]+p[j]
    com.sort()
    ans=0
    for i in xrange(n+1):
        for j in xrange(n+1):
            tmp=m-com[(n+1)*i+j]
            if tmp<0:continue
            index=bisect.bisect_left(com,tmp)
            if index==(n+1)**2:continue
            if com[index]>tmp:
                if index==0:continue
                else:
                    index-=1
            ans=max(ans,com[(n+1)*i+j]+com[index])
        if ans==m:
            break
    print(ans)

Python: import bisect
# python template for atcoder1
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline


def solve():
    N, M = map(int, input().split())
    if N*M == 0:
        return False
    P = [0]+[int(input()) for _ in range(N)]
    # solve
    k = [P[i]+P[j] for i in range(N) for j in range(i, N)]
    k = sorted(k)

    ret = 0
    for tmp in k:
        if tmp > M:
            break
        else:
            r = M-tmp
            l = bisect.bisect_right(k, r)
            if l >= len(k):
                tmp += k[-1]
            elif l != 0:
                tmp += k[l-1]
            ret = max(ret, tmp)
    return ret


ans = []
while True:
    ret = solve()
    if ret:
        ans.append(ret)
    else:
        break
print("\n".join(map(str, ans)))

Python: import bisect
while 1:
    n,m=map(int,input().split())
    if n==0:break
    s=[]
    a=[0]+sorted([int(input()) for _ in range(n)])
    for i in range(n+1):
        for j in a[i:]:
            if a[i]+j>m:break
            s+=[a[i]+j]
    s.sort()
    print(max(i+s[bisect.bisect_right(s,m-i)-1]for i in s))

Python: while 1:
    n,m=map(int,raw_input().split())
    if n==m==0:break
    p=[int(raw_input()) for _ in xrange(n)]
    dp=[[0]*5 for _ in xrange(n+1)]
    for i in xrange(n):
        for j in xrange(1,5):
            for k in xrange(1,5):
                if j<k:
                    continue
                else:
                    if dp[i][j-k]+k*p[i]>m:continue
                    dp[i+1][j]=max(dp[i][j],dp[i+1][j],dp[i][j-k]+k*p[i])
    print(max(dp[n]))

Python: import sys

file_input = sys.stdin

NM = file_input.readline()

import itertools, bisect

while NM != '0 0\n':
    N, M = map(int, NM.split())
    P = [int(file_input.readline()) for i in range(N)]
    P.append(0)
    scores = map(sum, itertools.combinations_with_replacement(P, 2))
    scores = list(set(scores))
    scores.sort()
    ans = []
    for s1 in scores:
        rest = M - s1
        i = bisect.bisect_right(scores, rest)
        if i:
            ans.append(s1 + scores[i - 1])
    print(max(ans))
    NM = file_input.readline()