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

C++: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <climits>
#include <cassert>
using namespace std;

#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define INF INT_MAX/3
#define LINF LLONG_MAX/3
#define MP make_pair
#define PB push_back
#define EB emplace_back
#define ALL(v) (v).begin(),(v).end()
#define debug(x) cout<<#x<<":"<<x<<endl
#define debug2(x,y) cout<<#x","<<#y":"<<x<<","<<y<<endl

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;

vi num;
vi num_odd;
int N;
int N_odd;

void init(){
    int t=1;
    int i=1;
    while(t<1000000){
        num.EB(t);
        i++;
        t = i*(i+1)*(i+2)/6;
    }
    N = num.size();

    for(i=0;i<N;i++){
        if(num[i]%2==1) num_odd.emplace_back(num[i]);
    }
    N_odd = num_odd.size();
}

void solve(int n){
    vi dp(n+10,INF);
    dp[0]=0;
    for(int i=0;i<N;i++){
        for(int j=num[i];j<=n;j++){
            dp[j] = min(dp[j],dp[j-num[i]]+1);
        }
    }

    cout << dp[n] << " ";

    dp = vector<int>(n+10,INF);
    dp[0] = 0;
    for(int i=0;i<N_odd;i++){
        for(int j=num_odd[i];j<=n;j++){
            dp[j] = min(dp[j],dp[j-num_odd[i]]+1);
        }
    }
    cout << dp[n] << endl;
}

int main(){
    init();
    int n;


    while(cin>>n){
        if(n==0) break;
        solve(n);
    }
}

C++: #include<algorithm>
#include<bitset>
#include<iostream>
#include<iomanip>
#include<set>
#include<string>
#include<math.h>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long int ll;
typedef pair<int, ll> P;

//--------------
///#define DEBUG
//--------------

#ifdef DEBUG
	#define debugprint(x) cout<<x<<" "
	#define debugendl cout<<endl
	#define debug(x) x
#else
	#define debugprint(x)
	#define debugendl
	#define debug(x)
#endif

class zahyo{
	public:
	int x;
	int y;
	zahyo(){
		x=0;
		y=0;
	}
	zahyo(int x_,int y_){
		x=x_;
		y=y_;
	}
	void print(){
		cout<<x<<" "<<y;
	}
	zahyo operator+(zahyo add){
		add.x=this->x+add.x;
		add.y=this->y+add.y;
		return add;
	}
	zahyo operator-(zahyo add){
		add.x=this->x-add.x;
		add.y=this->y-add.y;
		return add;
	}
	zahyo operator*(int t){
		zahyo temp;
		temp.x=this->x*t;
		temp.y=this->y*t;
		return temp;
	}
	zahyo operator%(int t){
		zahyo temp(this->x%t,this->y%t);
		return temp;
	}
	zahyo operator/(int t){
		zahyo temp(this->x/t,this->y/t);
		return temp;
	}
	bool operator==(const zahyo add) const{
		if(add.x==this->x and add.y==this->y){return true;}
		else{return false;}
	}
	bool operator!=(const zahyo add) const{
		if(add.x==this->x or add.y==this->y){return false;}
		else{return true;}
	}
	bool operator<(const zahyo add) const{
		if(this->x<add.x){return true;}
		else if(this->x==add.x and this->y<add.y){return true;}
		else{return false;}
	}
	bool operator>(const zahyo add) const{
		if(this->x>add.x){return true;}
		else if(this->x==add.x and this->y>add.y){return true;}
		else{return false;}
	}
	void input(){
		cin>>x>>y;
	}
};

bool IsInBoard(int x,int maxx, int y,int maxy){
	if(x>=0 and x<maxx and y>=0 and y<maxy){
		return true;
	}
	else{
		return false;
	}
}

int dpall[1000001];
int dpodd[1000001];

int sqnum(int n){
	return (n*(n+1)*(n+2))/6;
}

int main(){
	int n;
	dpall[0]=0;dpodd[0]=0;
	for(int i=1;i<1000000;i++){
		dpall[i]=i;
		dpodd[i]=i;
	}
	for(int i=1;i<=1000000;i++){
		for(int j=1;j<200;j++){
			if(sqnum(j)>i){break;}
			else{
				dpall[i]=min(dpall[i],dpall[i-sqnum(j)]+1);
				if(sqnum(j)%2==1){
					dpodd[i]=min(dpodd[i],dpodd[i-sqnum(j)]+1);
				}
			}
		}
	}
	while(1){
		cin>>n;
		if(n==0){break;}
		cout<<dpall[n]<<" "<<dpodd[n]<<endl;
	}
	return 0;
}

C++: #include<stdio.h>
#include<string.h>

char table[1000000][1],tablek[1000000];
int po[182];

int main(){
	int i,j,k,n;
	
	memset(po,0,sizeof(po));
	memset(table,0,sizeof(table));
	memset(tablek,0,sizeof(tablek));
	
	for(i=1;i<182;i++){
		po[i]=i*(i+1)*(i+2)/6;
		if(po[i]<1000000)table[po[i]][0]=1;
	}
	
	for(i=1;i<5;i++){
		for(j=1;j<1000000;j++){
			if(table[j][0]==i){
				for(k=1;k<182;k++){
					if(j+po[k]>=1000000)break;
					if(table[j+po[k]][0]==0)table[j+po[k]][0]=i+1;
				}
			}
		}
	}
	
	n=1000000-1;
	
	for(i=1;i<182;i++){
		if(po[i]<1000000 && po[i]%2==1){
			tablek[po[i]]=1;
			--n;
		}
	}
	printf("a\n");
	for(i=1;n>0;i++){
		for(j=1;j<1000000;j++){
			if(tablek[j]==i){
				for(k=1;k<182;k++){
					if(j+po[k]>=1000000)break;
					if(tablek[j+po[k]]==0 && po[k]%2==1){
						tablek[j+po[k]]=i+1;
						--n;
					}
				}
			}
		}
	}
	for(i=1;i<36;i++)printf("%d\n",tablek[i]);
	
	while(scanf("%d",&n)>=0){
		if(n==0)break;
		printf("%d %d\n",table[n][0],tablek[n]);
	}
	
	
	return 0;
}