# include <iostream>
# include <conio.h>
using namespace std;
int h = 0;
class date
{
public:
	date(int day=1, int month=1, int year = 1);
	friend bool operator > (const date a, const date b);
	friend bool operator == (const date a, const date b);
	friend istream& operator >> (istream& in,date& a);
	friend ostream& operator << (ostream& out, date& a);
	~date();
private:
	int day;
	int month;
	int year;
};

date::date(int d, int m, int y)
{
	day = d; month = m; year = y;
}

bool operator > (date a1, date b1){
    if(a1.year > b1.year)
        return 1;
    else if((a1.year==b1.year)&&(a1.month>b1.month))
        return 1;
    else if((a1.year==b1.year)&&(a1.month==b1.month)&&(a1.day>b1.day))
        return 1;
    else return 0;
}
bool operator == (const date a, const date b){
    return ((a.day==b.day)&&(a.month==b.month)&&(a.year==b.year));
}

istream & operator>>(istream &in, date &a){
	int d, m, y;
	char c;
	in >> d >> c >> m >> c >> y;
	a = date(d, m, y);
	return in;
}

ostream & operator<<(ostream &out, date &a){
    if(a.day<10)
        out << '0' << a.day << '.';
    else
        out << a.day << '.';
    if(a.month<10)
        out << '0' << a.month << '.';
    else
        out << a.month << '.';
	out  << a.year;
	return out;
}

date::~date(){
}





//Наша структура
struct node
{
    date info; //Информационное поле
    node *l, *r, *p;//Левая и Правая часть дерева
};

node * tree=NULL; //Объявляем переменную, тип которой структура Дерево

/*ФУНКЦИЯ ЗАПИСИ ЭЛЕМЕНТА В БИНАРНОЕ ДЕРЕВО*/
void push(date a,node **t)
{
    if ((*t)==NULL) //Если дерева не существует
    {
        (*t)=new node; //Выделяем память
        (*t)->info=a; //Кладем в выделенное место аргумент a
        (*t)->l=(*t)->r=NULL; //Очищаем память для следующего роста
        return; //Заложили семечко, выходим
    }
       //Дерево есть
        if (a>(*t)->info) push(a,&(*t)->r); //Если аргумент а больше чем текущий элемент, кладем его вправо
        else push(a,&(*t)->l); //Иначе кладем его влево
}

void minElement(node*t){
    while(t->l)
        t = t->l;
    cout << t->info;
}

void secondElement(node*t, int i){
    if(!(t->l)&&!(t->r)){
        cout << "00.00.0000" << endl; return;
        }
    while(t->r->r){
        t=t->r;
    }
    if(t->r->l){
        cout << t->r->l->info << endl; return;
    }
    if(t->l)
        cout <<t->l->info << endl; return;
}



int Node_Height(const node* p){
    int l, r, h = 0;
    if(p != NULL){
        l = Node_Height(p->l);
        r = Node_Height(p->r);
        h = ((l > r) ? l : r) + 1;
    }
    return h;
}

void postOrderTravers(node* root) {
    if (root) {
        postOrderTravers(root->l);
        postOrderTravers(root->r);
        cout << root->info << ' ';
    }
}

void growingPrint(node*Root){
    if(Root->l)
        growingPrint(Root->l);
    cout << Root->info << ' ';
    if(Root->r)
        growingPrint(Root->r);

}

void outLeaves(node*Root){
    if(Root->l)
        outLeaves(Root->l);
    if(!(Root->l)&& !(Root->r))
        cout << Root->info << ' ';
    if(Root->r)
        outLeaves(Root->r);

}

int maxDepth(node* root) {
    if (!root) {
        return 0;
    }
    return  max(maxDepth(root->l), maxDepth(root->r))+1;
}

int minDepth(node* root) {
    if (!root) {
        return 0;
    }
    return  min(minDepth(root->l), minDepth(root->r))+1;
}

void isBalanced(node* root) {
    if (maxDepth(root) - minDepth(root) <= 1)
        cout << "YES";
    else
        cout << "NO";

}

int main ()
{
    date d;
    date end(00, 00, 0000);
    while(1){
        cin >> d;
        if(d==end)
            break;
        else
            push(d, &tree);
    }
    h=Node_Height(tree);
    cout << h << endl;//1
    minElement(tree);//2
    cout << endl;
    secondElement(tree, 0);//3 кажется, норм
   // cout << endl;
    growingPrint(tree);//4
    cout << endl;
    postOrderTravers(tree);//5
    cout << endl;
    outLeaves(tree);//6
    cout << endl;
    isBalanced(tree);//7, не работает

}