#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MM 32 // こんなには要らない（動作確認のためには 16 くらいが見やすい）

int height[MM][MM]; // 高さ（初期値 0 ）
int tops[MM][MM]; // 上面の値（初期値 0 ）

int diceDir; // dice の向き（テーブル上のインデックスに同じ）
typedef struct _Dice {
	int T; // Top    各面の数字
    int F; // Front
    int S; // Side
    int _T; // Top の反対側
    int _F; // Front の反対側
    int _S; // Side の反対側
} Dice;

Dice diceTable[24]; // 24 通りの状態テーブル
int diceTableCnt=0; // テーブルに格納されている数

// 裏側の値を出す ( 単に 7 から引くだけ）
int backNum( int num ) 
{
	return 7 - num;
}

// diceTable に値を設定する
void setDiceTable(Dice dice)
{
    diceTable[diceTableCnt]=dice;
	diceTableCnt++;
}
// diceTable の内容をダンプする（動作状況確認用）
void printDiceTable()
{
	int i;
	for(i=0; i<diceTableCnt; i++) {
		printf("%2d: %d,%d,%d (%d,%d,%d)\n", i, 
               diceTable[i].T, diceTable[i].F, diceTable[i].S,  
               diceTable[i]._T, diceTable[i]._F, diceTable[i]._S);
	}
}

// オリジナル dice の状態を作る
void initDice(Dice *dice)
{
    dice->T = 1;
    dice->F = 3;
    dice->S = 5;
	dice->_T = backNum(dice->T);
	dice->_F = backNum(dice->F);
	dice->_S = backNum(dice->S);
}
// dice を回転する（一応右回転気分）
void rotateDice(Dice *dice)
{
    dice->F = dice->S;
    dice->S = dice->_F;
	dice->_F = backNum(dice->F);
	dice->_S = backNum(dice->S);
}
// dice を倒す - Front 側
void turnDiceF(Dice *dice)
{
	Dice _dice; // 一時的にダイスの状態を保持する変数
	
    _dice = *dice; // 元の値を保持
	dice->T = _dice._F;
	dice->F = _dice.T;
	dice->S = _dice.S; // 実は変化が無い（Side を軸にして回転）のでやらなくて良い
	dice->_T = backNum(dice->T);
	dice->_F = backNum(dice->F);
	dice->_S = backNum(dice->S); // 当然これもやらなくて良い
}
// dice を倒す - Front 反対側（ Front 側に三回倒した結果に同じはず）
void turnDiceF_(Dice *dice)
{    
    turnDiceF(dice);
    turnDiceF(dice);
    turnDiceF(dice);
}
// dice を倒す - Side 側
void turnDiceS(Dice *dice)
{
	Dice _dice; // 一時的にダイスの状態を保持する変数
	
    _dice = *dice; // 元の値を保持
	dice->T = _dice._S;
	dice->F = _dice.F; // 実は変化が無い（Front を軸にして回転）のでやらなくて良い
	dice->S = _dice.T;
	dice->_T = backNum(dice->T);
	dice->_F = backNum(dice->F); // 当然これもやらなくて良い
	dice->_S = backNum(dice->S);
}
// dice を倒す - Side 反対側（ Side 側に三回倒した結果に同じはず）
void turnDiceS_(Dice *dice)
{
    turnDiceS(dice); 
    turnDiceS(dice); 
    turnDiceS(dice); 
}
// diceTable を初期化する
void initDiceTable()
{
    Dice dice;
	int i;
	initDice(&dice);	setDiceTable(dice); // 初期状態をまず登録
	for(i=0; i<3; i++) { rotateDice(&dice); setDiceTable(dice); } // 三回回してバリエーションを登録

	initDice(&dice); // 初期状態に戻して、
	turnDiceF(&dice); setDiceTable(dice); // Front 側に倒してそれをまず登録
	for(i=0; i<3; i++) { rotateDice(&dice); setDiceTable(dice); } // 三回回してバリエーションを登録
	
	initDice(&dice); // 初期状態に戻して、
	turnDiceF_(&dice); setDiceTable(dice); // Front 反対側に倒してそれをまず登録
	for(i=0; i<3; i++) { rotateDice(&dice); setDiceTable(dice); } // 三回回してバリエーションを登録

	initDice(&dice); // 初期状態に戻して、
	turnDiceS(&dice); setDiceTable(dice); // Side 側に倒してそれをまず登録
	for(i=0; i<3; i++) { rotateDice(&dice); setDiceTable(dice); } // 三回回してバリエーションを登録

	initDice(&dice); // 初期状態に戻して、
	turnDiceS_(&dice); setDiceTable(dice); // Side 反対側に倒してそれをまず登録
	for(i=0; i<3; i++) { rotateDice(&dice); setDiceTable(dice); } // 三回回してバリエーションを登録

	initDice(&dice); // 初期状態に戻して、
	turnDiceF(&dice); turnDiceF(&dice); setDiceTable(dice); // 二回 Front 側に倒してそれを登録
	for(i=0; i<3; i++) { rotateDice(&dice); setDiceTable(dice); } // 三回回してバリエーションを登録
	
}

// =============================================================

// 初期化処理
void doInit()
{
	int x, y;
	for(x=0; x<MM; x++) {
		for(y=0; y<MM; y++) {
			height[x][y]=0;
			tops[x][y]=0;
		}
	}
}

// 盤面出力（動作状況確認用）
void printMap()
{
	int x, y;
	printf("          height             tops\n");
	for (y=0; y<MM; y++) {
		printf("%2d:", y);
		for(x=0; x<MM; x++) if(height[x][y]==0) printf(" "); else printf("%1d", height[x][y]);
		printf("  %2d   ", y);
		for(x=0; x<MM; x++) if(tops[x][y]==0) printf(" "); else printf("%1d", tops[x][y]);
		printf("  %2d\n", y);
	}
}

// 結果出力（上面ばかりを数えて出す）
void countMap()
{
	int x, y, top, i, count[6];
	
	for(i=0; i<6; i++) count[i]=0;
	
	for (y=0; y<MM; y++) {
		for (x=0; x<MM; x++) {
			top=tops[x][y];
			if(top != 0) count[top-1]++;
		}
	}
	printf("%d %d %d %d %d %d\n", 
		count[0], count[1], count[2], count[3], count[4], count[5]);
}

// ダイスの向きをテーブルから発見する t, f は Top, Front 面の数字。
// 発見した場合はそのテーブルの行位置を返す（発見できないことはありえない）
int checkDiceDir(int t, int f)
{
	int i;
	for(i=0; i<diceTableCnt; i++) {
		if((t == diceTable[i].T)&&
		   (f == diceTable[i].F)) return i; // パターンに合致するものを発見した
	}
	fprintf(stderr, "checkDiceDir() - didn't match any pattern. what? t=%d, f=%d\n", t, f);
	exit(1);
}

// サイコロをこの状態で、この位置に落としたよ！
void doDrop(int t, int f, int x, int y)
{
	Dice dice; // 一時利用的ダイス
	int maxNum, dir; // 倒れる方向を調べるときの為の一時変数
    enum DIRECTION {F, _F, S, _S}; // ダイスの方向について定数を定義しておく
	
	diceDir = checkDiceDir(t, f); // ダイスの向きをテーブルから捜して確保
	dice = diceTable[diceDir];
    
	while(1) { // 落ち着くまで何度でもやるぞ
		// printf("t=%d, f=%d, (%d,%d)\n", t, f, x, y);
		// 倒れるものがあったか（あったとしたら最も優先度の高いところがどれか）調べる
		// 着地予定位置の周辺四方向の高さを見る
		// 隣が一つ以上低い位置にあり、その方向は落下可能面であり、過去最大の優先度なら
		maxNum=0; dir=99;
		if((height[x][y]>height[x-1][y  ])&&(dice.F  >3)&&(dice.F  >maxNum)) { maxNum=dice.F;  dir=F; }
		if((height[x][y]>height[x+1][y  ])&&(dice._F >3)&&(dice._F >maxNum)) { maxNum=dice._F; dir=_F; }
		if((height[x][y]>height[x  ][y+1])&&(dice.S  >3)&&(dice.S  >maxNum)) { maxNum=dice.S;  dir=S; }
		if((height[x][y]>height[x  ][y-1])&&(dice._S >3)&&(dice._S >maxNum)) { maxNum=dice._S; dir=_S; }
		
		// printf("maxNum=%d, dir=%d\n", maxNum, dir);
		switch (dir) {
			case F:  turnDiceF(&dice);  x=x-1; // Front 側に倒して、そちらにずれたところから再落下
				break;
			case _F: turnDiceF_(&dice); x=x+1; // Front 反対側に倒して、そちらにずれたところから再落下
				break;
			case S:  turnDiceS(&dice);  y=y+1; // Side 側に倒して、そちらにずれたところから再落下
				break;
			case _S: turnDiceS_(&dice); y=y-1; // Side 反対側に倒して、そちらにずれたところから再落下
				break;
			default: // これでどこにも倒れるところはない、ので、ここに設置して return
				height[x][y]++; // 高さを +1 する
				tops[x][y]=dice.T; // 上面の値を記録
				return; // この関数から脱出
		}
	}
}

// ==============================================

int main()
{
	int n, i, t, f;

	initDiceTable();
	// printDiceTable();

	while(1) {
		// printf("======================\n");
		scanf("%d", &n);
		if(n==0) break;
		doInit();
		for(i=0; i<n; i++) {
			scanf("%d %d", &t, &f);
			doDrop(t, f, MM/2, MM/2);
		}
		// printMap();
		countMap();
	}
	
	return 0;
}

