Go: package main

import (
	"bufio"
	_ "container/heap"
	"fmt"
	"os"
	_ "sort"
	"strconv"
)

// I/O
type Scanner struct {
	sc *bufio.Scanner
}

func NewScanner() *Scanner {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 1024), int(1e+9))
	return &Scanner{sc}
}

func (s *Scanner) nextStr() string {
	s.sc.Scan()
	return s.sc.Text()
}

func (s *Scanner) nextInt() int {
	i, e := strconv.Atoi(s.nextStr())
	if e != nil {
		panic(e)
	}
	return i
}

func (s *Scanner) nextFloat() float64 {
	f, e := strconv.ParseFloat(s.nextStr(), 64)
	if e != nil {
		panic(e)
	}
	return f
}

func (s *Scanner) nextRuneSlice() []rune {
	return []rune(s.nextStr())
}

func (s *Scanner) nextIntSlice(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ {
		res[i] = s.nextInt()
	}
	return res
}

func (s *Scanner) nextFloatSlice(n int) []float64 {
	res := make([]float64, n)
	for i := 0; i < n; i++ {
		res[i] = s.nextFloat()
	}
	return res
}

// Arithmetic
func max(nums ...int) int {
	m := nums[0]
	for _, i := range nums {
		if m < i {
			m = i
		}
	}
	return m
}

func min(nums ...int) int {
	m := nums[0]
	for _, i := range nums {
		if m > i {
			m = i
		}
	}
	return m
}

func abs(x int) int {
	if x > 0 {
		return x
	}
	return -x
}

func pow(x, y int) int {
	res := 1
	for i := 0; i < y; i++ {
		res *= x
	}
	return res
}

func ceil(a, b int) int {
	if a%b == 0 {
		return a / b
	} else {
		return a/b + 1
	}
}

func gcd(a, b int) int {
	if b == 0 {
		return a
	}
	return gcd(b, a%b)
}

func lcm(a, b int) int {
	return a / gcd(a, b) * b
}

// Sort
type RuneSlice []rune

func (a RuneSlice) Len() int           { return len(a) }
func (a RuneSlice) Less(i, j int) bool { return a[i] < a[j] }
func (a RuneSlice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

// Main
const MOD = int(1e+9) + 7
const INF = 1 << 60

func main() {
	sc := NewScanner()
	wtr := bufio.NewWriter(os.Stdout)
	defer wtr.Flush()
	var nums []int
	for i := 1; i < 2*100+1; i++ {
		nums = append(nums, i*(i+1)*(i+2)/6)
	}
	var ins []int
	N := 0
	for true {
		n := sc.nextInt()
		if n == 0 {
			break
		}
		ins = append(ins, n)
		N = max(N, n)
	}
	dp := make([]int, N+1)
	dp2 := make([]int, N+1)
	for i := 1; i < N+1; i++ {
		dp[i] = INF
		dp2[i] = INF
	}
	for i := 0; i < len(nums); i++ {
		n := nums[i]
		if n > N {
			break
		}
		for j := 0; j < N+1; j++ {
			if j >= n {
				dp[j] = min(dp[j], dp[j-n]+1)
				if n%2 != 0 {
					dp2[j] = min(dp2[j], dp2[j-n]+1)
				}
			}
		}
	}
	for i := 0; i < len(ins); i++ {
		fmt.Fprintln(wtr, dp[ins[i]], dp2[ins[i]])
	}
}

Python: N = 10**6

N1 = [i for i in range(N+40)]
N2 = [i for i in range(N+40)]

#N1[0] = 0
#N2[0] = 0

p = [n*(n+1)*(n+2)//6 for n in range(1,200) if n *(n+1)*(n+2)//6< N+1]
p2 = [n*(n+1)*(n+2)//6 for n in range(1,200) if n *(n+1)*(n+2)//6< N+1 and n *(n+1)*(n+2)//6 % 2 ==1 ]
#print(p2)
for p_ in p:
    if p_ > N +1:
        continue
    n = min(p_*5,10**6)
    for j in range(p_,n):
#        print(j)
        if N1[j] > N1[j-p_] +1:
            N1[j] = N1[j-p_]+1
for p_ in p2:
    if p_ > N +1 :
        continue
    for j in range(p_,N +1):
        if N2[j] > N2[j-p_]+1:
            N2[j] = N2[j -p_]+1
print('a')
while True:
    n = int(input())
    if n == 0:
        break
    print(N1[n],N2[n])

Python: def main():
  INIT = 100
  
  query = []
  ans = []
  while True:
    q = int(input())
    if q == 0:
      break
    query.append(q)
  MAX = max(query)
  
  table = [INIT] * (MAX + 1)
  table[0] = 0
  all_item = [i * (i + 1) * (i + 2) // 6 for i in range(1, 181)]
  odd_item = [i for i in all_item if i % 2]
  eve_item = [i for i in all_item if not i % 2]
  
  for v in odd_item:
    for j in range(v, MAX + 1):
      tjv = table[j - v]
      if table[j] > tjv + 1:
        table[j] = tjv + 1
  
  for q in query:
    ans.append(table[q])
  
  for v in eve_item:
    for j in range(v, MAX + 1):
      tjv = table[j - v]
      if table[j] > tjv + 1:
        table[j] = tjv + 1
  
  for i, q in enumerate(query):
    print(table[q], ans[i])

main()

Python: N = 10**6

N1 = [i for i in range(N+40)]
N2 = [i for i in range(N+40)]

N1[0] = 0
N2[0] = 0

p = [n*(n+1)*(n+2)//6 for n in range(1,200) if n *(n+1)*(n+2)//6< N+1]
p2 = [n*(n+1)*(n+2)//6 for n in range(1,200) if n *(n+1)*(n+2)//6< N+1 and n *(n+1)*(n+2)//6 % 2 ==1 ]
#print(p2)
for p_ in p:
    if p_ > N +1:
        continue
    for j in range(p_,N+1):
#        print(j)
        N1[j] = min(N1[j],N1[j-p_]+1)

for p_ in p2:
    if p_ > N +1 :
        continue
    for j in range(p_,N +1):
        N2[j] = min(N2[j],N2[j-p_]+1)
#print('a')
while True:
    n = int(input())
    if n == 0:
        break
    print(N1[n],N2[n])

Python: 

def calc():
    n = 10**6

    dataset = [t * (t + 1) * (t + 2) // 6 for t in range(1, 181)]

    dp = [1000] * (n+1)
    dp_odd = dp.copy()
    dp[0] = 0
    dp_odd[0] = 0
    for j in range(n):
        for d in dataset:
            if j + d > n:
                break
            if dp[j + d] > dp[j] + 1:
                dp[j + d] = dp[j] + 1
            if d%2:
                if dp_odd[j + d] > dp_odd[j] + 1:
                    dp_odd[j + d] = dp_odd[j] + 1

    return dp, dp_odd


all, odd = calc()

while True:
    n = int(input())
    if n == 0:
        break

    a = all[n]
    o = odd[n]

    print(a, o)

Python: INF = 1000000

while True:
    n = input()
    n = int(n)

    if n == 0:
        break

    i = 1
    tetra = []
    while True:
        t = i*(1+i)*(2+i)/6
        if t <= n:
            tetra.append(int(t))
            i += 1
        else:
            break

    dp = [[INF for _ in range(n+1)] for _ in range(len(tetra)+1)]
    for i in range(len(tetra)+1):
        dp[i][0] = 0

    for i in range(len(tetra)):
        for j in range(n):
            if j + tetra[i] <= n:
                m = INF
                for k in range(i+1):
                    if dp[k+1][j] < m:
                        m = dp[k+1][j]
                dp[i+1][j+tetra[i]] = m+1

    output = INF
    for i in range(len(tetra)+1):
        if dp[i][n] < output:
            output = dp[i][n]

    print(output)

Python: INF = 10**20
MAX_INT = 10**6
a = [INF] * MAX_INT
b = [INF] * MAX_INT
a[0],b[0] = 0,0
for i in range(1, 200):
  t = i*(i+1)*(i+2)//6
  mm = min(t*5, MAX_INT)
  for j in range(t, mm):
    if a[j] > a[j-t]+1:
      a[j] = a[j-t]+1

  if t%2==0: continue

  for j in range(t, MAX_INT):
    if b[j] > b[j-t]+1:
      b[j] = b[j-t]+1

while True:
  N = int(input())
  if N==0: exit()
  print(a[N], b[N])

Python: def solve():
    rec = [5] * 1000000
    rec[0] = 0
    
    tetra_num = [i * (i + 1) * (i + 2) // 6 for i in range(1, 181)]
    
    for i, a in enumerate(tetra_num):
        for j, b in enumerate(tetra_num[i:], start=i):
            if a + b >= 1000000:
                break
            for c in tetra_num[j:]:
                if a + b + c >= 1000000:
                    break
                rec[a + b + c] = 3
    
    for i, a in enumerate(tetra_num, start=0):
        for b in tetra_num[i:]:
            if a + b >= 1000000:
                break
            rec[a + b] = 2
    
    for n in tetra_num:
        rec[n] = 1
    
    for i, n in enumerate(rec[1:], start=1):
        if n == 3:
            for t in tetra_num:
                if i + t >= 1000000:
                    break
                if rec[i + t] == 5:
                    rec[i + t] = 4
    
    odd_rec = [1000000] * 1000000
    odd_rec[0] = 0
    
    odd_tetra_num = tetra_num[::4]
    
    for odd_t in odd_tetra_num:
        for i, tpl in enumerate(zip(odd_rec[odd_t:], odd_rec), start=odd_t):
            a, b = tpl
            b += 1
            if b < a:
                odd_rec[i] = b
    
    import sys
    file_input = sys.stdin
    n = int(file_input.readline())
    while n:
        print(rec[n], odd_rec[n])
        n = int(file_input.readline())

solve()

Python: print("")