//directory=0 file=1
#include <iostream>
#include <string>
#include <vector>
using namespace std;

struct Node {
	int type;
	string name;
	Node *next;
	Node *parent;
	Node *child;
	Node(string myname="/",Node *myparent=NULL,int mytype=0,Node *mynext=NULL) {
		name=myname; type=mytype; next=mynext; parent=myparent; child=NULL;	}
};

class Tree {
	struct Node *root;
	struct Node *currentnode;
public:
	Tree(struct Node *arg) {root=currentnode=arg;}
	void Setcurrentpointer(Node *tmpnode) {currentnode=tmpnode;}
	Node *Getroot() {return root;}
	Node *Getcurrentnode() {return currentnode;}
};

string genstring[100];
int flag,rootflag;

int Getcommandtype(string st)
{
	if(st=="cd") return 1;
	if(st=="md") return 2;
	if(st=="mf") return 3;
	if(st=="rd") return 4;
	if(st=="rf") return 5;
	if(st=="find") return 6;
	if(st=="ls") return 7;
	if(st=="lsR") return 8;
	if(st=="diff") return 9;
	if(st=="exit") return 10;
	return 0;
}

Node *Getnewtempdir(Tree &mytree,Node *currenttempdir,string st)
{
	if(st=="/")
		return mytree.Getroot();
	if(st==".")
		return currenttempdir;
	if(st=="..")
		if(currenttempdir==mytree.Getroot())
		{
			rootflag=1;
			return NULL;
		}
		else
			return currenttempdir->parent;
	Node *temp;
	temp=currenttempdir->child;
	while(temp->next)
		if(temp->next->name==st && !temp->next->type)
			return temp->next;
		else
			temp=temp->next;
		return NULL;
}

void Change_Directory(Tree &mytree,string st)
{
	Node *tempdir;
	string tmpstring;
	tempdir=mytree.Getcurrentnode();
	tmpstring="";
	rootflag=0;
	for(int i=0;i<st.length();i++)
	{
		if(st[i]=='/' || i==st.length()-1)
		{
			if(i==st.length()-1)
				tmpstring+=st[i];
			if(tmpstring=="")
				tmpstring="/";
			tempdir=Getnewtempdir(mytree,tempdir,tmpstring);
			tmpstring="";
			if(!tempdir)
			{
				if(!rootflag)
				cout<<"directory "<<st<<" not found"<<endl;
				goto functionend;
			}
		}
		else
			tmpstring+=st[i];
	}
	mytree.Setcurrentpointer(tempdir);
functionend:;
}

void Makenewdirectory(Tree &mytree,string st)
{
	Node *mycurrentdir,*tempdir,*aranode;
	mycurrentdir=mytree.Getcurrentnode();
	tempdir=mycurrentdir->child;
	while(tempdir->next && st>tempdir->next->name)
		tempdir=tempdir->next;
	if(!tempdir->next)
	{
		tempdir->next=new Node(st,mycurrentdir);
		tempdir->next->child=new Node("myfirstchild");		
	}
	else if(st<tempdir->next->name)
	{
		aranode=new Node(st,mycurrentdir);
		aranode->child=new Node("myfirstchild");
		aranode->next=tempdir->next;
		tempdir->next=aranode;
	}
	else
		cout<<"directory "<<st<<" already exists"<<endl;
}

void Makenewfile(Tree &mytree,string st)
{
	Node *mycurrentdir,*tempdir,*aranode;
	mycurrentdir=mytree.Getcurrentnode();
	tempdir=mycurrentdir->child;
	while(tempdir->next && st>tempdir->next->name)
		tempdir=tempdir->next;
	if(!tempdir->next)
		tempdir->next=new Node(st,mycurrentdir,1);
	else if(st<tempdir->next->name)
	{
		aranode=new Node(st,mycurrentdir,1);
		aranode->next=tempdir->next;
		tempdir->next=aranode;
	}
	else
		cout<<"file "<<st<<" already exists"<<endl;
}

void Deldirectory(Tree &mytree,string st)
{
	Node *mycurrentdir,*aranode;
	mycurrentdir=mytree.Getcurrentnode();
	mycurrentdir=mycurrentdir->child;
	while(mycurrentdir->next && mycurrentdir->next->name!=st)
		mycurrentdir=mycurrentdir->next;
	if(!mycurrentdir->next || mycurrentdir->next->type)
		cout<<"directory "<<st<<" does not exist";
	else
	{
		aranode=mycurrentdir->next;
		mycurrentdir->next=mycurrentdir->next->next;
		delete aranode;
		aranode=NULL;
	}
}

void Removefile(Tree &mytree,string st)
{
	Node *mycurrentdir,*aranode;
	mycurrentdir=mytree.Getcurrentnode();
	mycurrentdir=mycurrentdir->child;
	while(mycurrentdir->next && mycurrentdir->next->name!=st)
		mycurrentdir=mycurrentdir->next;
	if(!mycurrentdir->next || !mycurrentdir->next->type)
		cout<<"file "<<st<<" does not exist";
	else
	{
		aranode=mycurrentdir->next;
		mycurrentdir->next=mycurrentdir->next->next;
		delete aranode;
		aranode=NULL;
	}
}

void Writefounds(Node *currentdir,string st,int depth)
{
	Node *tempnode;
	tempnode=currentdir->child->next;
	while(tempnode)
	{
		if(tempnode->name==st)
		{
			for(int i=0;i<depth;i++)
				cout<<genstring[i]<<"/";
			cout<<st<<endl;
			flag=1;
		}
		if(!tempnode->type)
		{
			genstring[depth]=tempnode->name;
			Writefounds(tempnode,st,depth+1);
		}
		tempnode=tempnode->next;
	}
}

void Findargument(Tree &mytree,string st)
{
	Node *mycurrentdir;
	mycurrentdir=mytree.Getcurrentnode();
	flag=0;
	Writefounds(mycurrentdir,st,0);
	if(!flag)
		cout<<"no such file/directory exists"<<endl;
}

void Ls(Tree &mytree)
{
	Node *mycurrentdir;
	mycurrentdir=mytree.Getcurrentnode();
	mycurrentdir=mycurrentdir->child->next;
	while(mycurrentdir)
	{
		cout<<mycurrentdir->name;
		if(!mycurrentdir->type)
			cout<<"/";
		cout<<endl;
		mycurrentdir=mycurrentdir->next;
	}
}

void Listdown(Node *currentdir,int depth)
{
	Node *tempnode;
	if(depth)
	{
		cout<<endl;
		for(int i=0;i<depth-1;i++)
			cout<<genstring[i]<<"/";
		cout<<currentdir->name<<":"<<endl;
	}
	
	tempnode=currentdir->child->next;
	while(tempnode)
	{
		cout<<tempnode->name;
		if(!tempnode->type)
			cout<<"/";
		cout<<endl;
		tempnode=tempnode->next;
	}

	tempnode=currentdir->child->next;
	while(tempnode)
	{
		if(!tempnode->type)
		{
			genstring[depth]=tempnode->name;
			Listdown(tempnode,depth+1);
		}
		tempnode=tempnode->next;
	}
}

void LsR(Tree &mytree)
{
	Node *mycurrentdir;
	mycurrentdir=mytree.Getcurrentnode();
	Listdown(mycurrentdir,0);
	cout<<endl;
}

Node *Getpointer(Tree &mytree,Node *currentdir,string st)
{
	Node *tempdir;
	string tmpstring;
	tmpstring="";
	rootflag=0;
	tempdir=currentdir;
	for(int i=0;i<st.length();i++)
	{
		if(st[i]=='/' || i==st.length()-1)
		{
			if(i==st.length()-1)
				tmpstring+=st[i];
			if(tmpstring=="")
				tmpstring="/";
			tempdir=Getnewtempdir(mytree,tempdir,tmpstring);
			tmpstring="";
			if(!tempdir)
				return NULL;
		}
		else
			tmpstring+=st[i];
	}
	return tempdir;
}

void Diffhelper(Node *ptr1,Node *ptr2,int depth)
{
	Node *ara1,*ara2;
	ara1=ptr1->child->next;
	ara2=ptr2->child->next;
	while(ara1)
	{
		ara2=ptr2->child->next;
		while(ara2 && ara2->name!=ara1->name)
			ara2=ara2->next;
		if(!ara2 || ara1->type!=ara2->type)
		{
			for(int i=0;i<depth;i++)
				cout<<genstring[i]<<"/";
			cout<<ara1->name<<endl;
		}
		ara1=ara1->next;
	}

	ara1=ptr1->child->next;
	ara2=ptr2->child->next;
	while(ara1)
	{
		ara2=ptr2->child->next;
		while(ara2 && ara1->name!=ara2->name)
			ara2=ara2->next;
		if(ara2 && !ara1->type && !ara2->type)
		{
			genstring[depth]=ara1->name;
			Diffhelper(ara1,ara2,depth+1);
		}
		ara1=ara1->next;
	}
}

void Diff(Tree &mytree,string arg1,string arg2)
{
	Node *mycurrentdir,*ptr1,*ptr2;
	mycurrentdir=mytree.Getcurrentnode();
	ptr1=Getpointer(mytree,mycurrentdir,arg1);
	ptr2=Getpointer(mytree,mycurrentdir,arg2);
	Diffhelper(ptr1,ptr2,0);		
}

void Parse_Command(Tree &mytree)
{
	string st,arg1,arg2;
	char ch;
	int commandtype;
	cin>>st;
	commandtype=Getcommandtype(st);
	switch(commandtype) {
	case 1:
		cin>>arg1;
		Change_Directory(mytree,arg1);
		break;
	case 2:
		cin>>arg1;
		Makenewdirectory(mytree,arg1);
		break;
	case 3:
		cin>>arg1;
		Makenewfile(mytree,arg1);
		break;
	case 4:
		cin>>arg1;
		Deldirectory(mytree,arg1);
		break;
	case 5:
		cin>>arg1;
		Removefile(mytree,arg1);
		break;
	case 6:
		cin>>arg1;
		Findargument(mytree,arg1);
		break;
	case 7:
		Ls(mytree);
		break;
	case 8:
		LsR(mytree);
		break;
	case 9:
		cin>>arg1>>arg2;
		Diff(mytree,arg1,arg2);
		break;
	case 10:
		exit(0);
		break;
	case 0:
		do
		cin.get(ch);
		while(ch!='\n');
		cout<<"command not found"<<endl;
		break;	
	}
}

int main()
{
	Node rootnode;
	rootnode.child=new Node("myfirstchild");
	Tree mytree(&rootnode);
	while(1)
	Parse_Command(mytree);
	return 0;
}
