/* merge-sort-number.c */

#include <stdio.h>
#define ARRAY_MAX 65536

/* ソート対象配列へのデータの読み込み関数 */
int input_data(int array[]) {
  int i, d;

  for( i = 0; i < ARRAY_MAX; i++ ) {
    if ( scanf("%d", &d) == EOF ) {
      return i;
    } else {
      array[i] = d;
    }
  }
  fprintf(stderr, "Out of maximum amount(%d).", 65536);
  return i;
}

/* マージソート関数 array[]: ソート対象配列, left: 左端, right: 右端 */
void merge_sort(int array[], int left, int right) {
  int reserve[ARRAY_MAX / 2 + 1]; /* 前半部退避用の配列 */
  int mid; /* 左端と右端の中間位置を示す変数 */
  int i; /* 退避用配列の添え字のカウンタ */
  int reserve_end; /* 退避用配列の右端 */
  int j; /* ソート対象配列の後半部の添え字のカウンタ */
  int k; /* ソート対象配列の添え字のカウンタ */

  if ( left == right ) return; /* 配列の要素が空であれば何もせず戻る */
  mid = (left + right) / 2; /* 配列の中間位置を求める */
  merge_sort(array, left, mid); /* 再帰呼び出しにより前半部をソート */
  merge_sort(array, mid + 1, right); /* 再帰呼び出しにより後半部をソート */

  for( i = 0, k = left; k <= mid; i++, k++ ) { /* 前半部を退避 */
    reserve[i] = array[k];
  }

  i = 0; /* 退避された前半部の比較位置の初期値を設定 */
  j = mid + 1; /* 後半部の比較位置の初期値を設定 */
  reserve_end = mid - left; /* 退避された前半部の右端を設定 */
  k = left; /* マージした結果の格納位置の初期値を設定 */

  /* 退避された前半部、および後半部が残っている間、マージ */
  while( i <= reserve_end && j <= right ) {
    if ( reserve[i] >= array[j] ) {
      array[k] = reserve[i]; /* 退避された前半部からマージ */
      i++;
    } else {
      array[k] = array[j]; /* 後半部からマージ */
      j++;
    }
    k++; /* マージ位置を右に移動 */
  }

  /* 比較によるマージ後、退避された前半部が残っていれば無条件にマージ */
  while( i <= reserve_end ) {
    array[k] = reserve[i];
    i++;
    k++;
  }
}

int main(int argc, char **argv) {
  int array[ARRAY_MAX]; /* ソート対象配列の用意 */
  int amount; /* ソート対象配列の要素数 */
  int i;

  amount = input_data(array); /* データ読み込み関数呼び出し */

  merge_sort(array, 0, amount - 1); /* マージソート関数呼び出し */

  for( i = 0; i < amount; i++ ) { /* 結果出力 */
    printf("%d ", array[i] );
  }
  printf("\n");
}