import std.stdio, std.string, std.conv, std.array, std.algorithm;

ulong[] getArray() {
  auto ary = appender( new ulong[]( 0 ) );
  foreach ( n; 1 .. 1000 ) {
	immutable ulong val = n * ( n + 1 ) * ( n + 2 ) / 6;
	if ( val >= 10 ^^ 6 ) {
	  break;
	} else {
	  ary.put( val );
	}
  }
  return ary.data;
}

ulong[] getOddArray() {
  immutable auto s = getArray().length;
  auto ary = appender( new ulong[]( 0 ) );
  foreach ( n; 1 .. s + 1 ) {
	immutable auto val = n * ( n + 1 ) * ( n + 2 ) / 6;
	if ( val % 2 == 1 ) {
	  ary.put( val );
	}
  }
  return ary.data;
}

void main()
{
  const ulong[] array = getArray();
  const ulong[] oddArray = getOddArray();

  ulong[] answer = new ulong[]( 100_0001 );
  answer[] = 100_0000;
  answer[ 0 ] = 0;
  ulong[] oddAnswer = new ulong[]( 100_0001 );
  oddAnswer[] = 100_0000;
  oddAnswer[ 0 ] = 0;
  
  foreach ( i; 0 .. 100_0001 ) {
	foreach ( v; array ) {
	  if ( i + v <= 100_0000 ) {
		answer[ i + v ] = min( answer[ i + v ], answer[ i ] + 1 );
	  }
	}
	foreach ( v; oddArray ) {
	  if ( i + v <= 100_0000 ) {
		oddAnswer[ i + v ] = min( oddAnswer[ i + v ], oddAnswer[ i ] + 1 );
	  }
	}
  }

  while ( true ) {
	immutable int n = to!int( strip( readln ) );
	if ( n == 0 ) break;
	writeln( answer[ n ], " ", oddAnswer[ n ] );
  }  
}