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

Python: def solve():
  while True:
    n,m = map(int,input().split())
    if not n and not m: break
    lst = []
    lst2 = []
    for i in range(n):
      lst.append(int(input()))
    for i in lst:
      for j in lst:
        lst2.append(i + j)
    lst2 = lst2 + lst
    lst2.sort()
    ans = 0
    def search(x, l, r):
      y = len(l)
      if y == 0:
        return r
      elif y == 1:
        if x >= l[0]:
          return l[0]
        else:
          return r
      elif l[y//2] == x:
        return x
      elif l[y//2] > x:
        return search(x, l[:y//2], r)
      elif l[y//2] < x:
        r = l[y//2]
        return search(x, l[y//2 + 1:], r)
    for i in lst2:
      if i <= m:
        ans = max(ans, i + search(m - i, lst2, 0))
      else:
        break
    print(ans)
solve()

Python: import bisect,sys
input = sys.stdin.readline
 
while True :
    n,m = map(int , input().split())
    p = [0]
 
    if (n == 0) : break
     
    for i in range(n):
        pp = int(input())
        p.append(pp)
 
    pt1 = []
    for i,ii in enumerate(p):
        for jj in p[i:]:
            pt1.append(ii+jj)
 
    pt1.sort()
 
    ans = 0
    for i in pt1:
        if (i > m) : break
        amari = m - i
        ans = max(ans , i+ pt1[bisect.bisect_right(pt1,amari)-1])
 
    print(ans)

Python: import bisect
def main():
	while True:
		n,m=map(int,input().split())
		if n==0 and m==0:
			break
		p=list()
		for i in range(n):
			p.append(int(input()))
		p.append(0)
		ls=list()
		for i in p:
			for j in p:
				if i+j<=m:
					ls.append(i+j)
		ans=0
		for x in ls:
			idx=bisect.bisect_right(ls,m-x)
			if idx==0:
				continue
			idx-=1
			ans=max(ans,x+ls[idx])

		print(ans)

if __name__=="__main__":
	main()

Python: def solve():
  while True:
    n,m = map(int,input().split())
    if not n and not m: break
    lst = []
    lst2 = []
    lst = [int(input()) for _ in range(n)]
    lst.append(0)
    lst2 = [i + j for i in lst for j in lst if i <= j]
    #for i in lst:
    #  for j in lst:
    #    if i + j <= m:
    #      lst2.append(i + j)
    #lst2 = list(set(lst2 + lst))
    lst2.sort()
    def binary(x, left, right):
      center = (left + right) // 2
      length = right - left + 1
      v = lst2[center]
      if length == 1 or length == 2:
        if v > x:
          return center - 1
        else:
          return center
      elif v == x: return x
      elif v < x: return binary(x, center, right)
      elif v > x: return binary(x, left, center)
    A = []
    #ans = 0
    for i in lst2:
      if i + lst2[-1] <= m:
        A.append(i + lst2[-1])
        #ans = max(ans, i + lst2[-1])
      elif i <= m:
        A.append(i + lst2[binary(m - i, 0 , len(lst2) - 1)])
        #ans = max(ans, i + lst2[binary(m - i, 0, len(lst2) - 1)])
      else:
        break
    print(max(A))
    #print(ans)
solve()

Python: import bisect

def solve(n,m):
    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
    return ans

while 1:
    n,m=map(int,raw_input().split())
    if n==m==0:break
    print(solve(n,m))

Python: import bisect

while True:
    max_S = 0
    p = [0]
    pp = []
    n, m = map(int, input().split())
    if n == 0 and m == 0:
        break

    for _ in range(n):
        p.append(int(input())) 

    # 最初にダーツ2本を投げた状態にする
    for i in range(n+1):
        for j in range(i, n+1):
            pp.append(p[i] + p[j])
    
    pp.sort()
    # t: ppの中でm以下の数字の位置
    t = bisect.bisect_left(pp, m)
    # h: ppの中でm/2以下の数字の位置
    h = bisect.bisect_left(pp, m//2, 0, t)

    if t < len(pp):
        if pp[t] == m:
            print(m)
            continue
        pp = pp[:t]
    max_S = 0

    for i in range(len(pp)):
        t = bisect.bisect_left(pp, m-pp[i])
        if pp[i] + pp[t-1] > max_S:
            max_S = pp[i] + pp[t-1]

    print(max_S)

Python: import bisect

while True:
  max_S = 0
  p = [0]
  pp = []

  n, m = map(int, input().split())
  if n == 0 and m == 0:
    break

  for _ in range(n):
    p.append(int(input()))

  for c in range(n + 1):
    for d in range(c, n + 1):
      pp.append(p[c] + p[d])

  pp.sort()

  # ppの中でm以下の数字の位置
  t = bisect.bisect_left(pp, m)
  ## ppの中でm/2以下の数字の位置
  h = bisect.bisect_left(pp, m//2 , 0, t)

  if t < len(pp):
    if pp[t] == m:
      print(m)
      continue
    pp = pp[:t]
  max_S = 0

  for i in range(0, len(pp)):
    t = bisect.bisect_left(pp, m - pp[i])
    if pp[i] + pp[t - 1] > max_S:
      max_S = pp[i] + pp[t - 1]
  print(max_S)

Python: def input_score(N):
    score = []  # 的の配点をいれる配列、投げないときの点も入れておく
    score.append(0)
    for i in range(N):
        score.append(int(input()))
    return score


def cal_four_sum_score(two_score, M):
    left = 0
    right = len(two_score) - 1
    max_score = 0
    while left != right:
        now_score = two_score[left] + two_score[right]
        if now_score < M:
            # scoreの和がMより小さい時、解の候補である
            max_score = max(max_score, now_score)
            left += 1
        elif now_score > M:
            # scoreの和がMより大きい時、解の候補ではない
            right -= 1
        else:
            # scoreの和がちょうどMになるとき、解である
            max_score = M
            break

    return max_score


def cal_two_sum_score(score):
    two_score = []  # 二回投げた時に取りうる範囲を入れる配列
    contain_sum = {}  # 二回投げたときにその値はすでに存在するか判断する配列
    for i in range(len(score)):
        for j in range(len(score)):
            now_score = score[i] + score[j]
            if not contain_sum.get(now_score):
                contain_sum[now_score] = True
                two_score.append(now_score)

    two_score.sort()  # 尺取り法を用いるためsortしておく
    return two_score


def main():
    while True:
        N, M = map(int, input().split())
        if N == 0 and M == 0:
            break
        score = input_score(N)  # 的の配点の入力
        two_score = cal_two_sum_score(score)  # 二回投げた時に取りうる点の範囲を計算
        max_score = cal_four_sum_score(two_score, M)  # 四回投げたときに取りうる点の範囲を計算
        print(max_score)


if __name__ == "__main__":
    main()

Python: from bisect import bisect_right

while True:
    n, m = map(int, input().split())
    if not n:
        break

    ps = [0] + sorted(int(input()) for _ in range(n))

    p2 = set()
    for i, pi in enumerate(ps):
        for pj in ps[i:]:
            if pi + pj > m:
                break
            p2.add(pi + pj)

    p2 = sorted(p2)

    print(max(pi + p2[bisect_right(p2, m - pi) - 1] for pi in p2))