#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;

struct Point
{
      int x,y;
      friend std::ostream &operator << (std::ostream &output,const Point &p);
      friend std::istream &operator >> (std::istream &input,Point &p);
};

bool operator == (Point a,Point b)
{
     return (a.x == b.x && a.y == b.y); 
}

std::ostream &operator << (std::ostream &output,const Point &p)
{
        output<<"( "<<p.x<<" , "<<p.y<<" ) ";
        return output;
}



std::istream &operator >> (std::istream &input,Point &p)
{
        input>>p.x>>p.y;; 
        return input;
}


template<class T>
class Link
{
      private:
              T data;
              Link<T> *next;
              Link<T> *previous;
      public:
             Link(T data);
             void displayLink();
             T getData();
             void setData(T data);
             Link<T> *getNext();
             void setNext(Link<T> *next);
             Link<T> *getPrevious();
             void setPrevious(Link<T> *previous);
             template<class U> friend std::ostream& operator<< (std::ostream& print, Link<U>& obj);

};

template<class T>
Link<T>::Link(T data)
{
     setData(data);
     setNext(NULL);
     setPrevious(NULL);
                
}

template<class T>
void Link<T>::displayLink()
{
     std::cout<<getData()<<" ";
}

template<class T>
T Link<T>::getData()
{
     return data;               
}

template<class T>
void Link<T>::setData(T data)
{
     this->data = data;               
}

template<class T>
Link<T> *Link<T>::getNext()
{
      return next;  
}

template<class T>
void Link<T>::setNext(Link<T> *next)
{
      this->next = next; 
}

template<class T>
Link<T> *Link<T>::getPrevious()
{
      return previous;  
}

template<class T>
void Link<T>::setPrevious(Link<T> *previous)
{
      this->previous = previous; 
}


template <class U>  
std::ostream& operator<<(std::ostream& print, Link<U> & L)
{
        print << L.getData();
        return print;
}

template<class T>
class DoublyLinkedList
{
      private:
              Link<T> *first;
              Link<T> *last;
      public:
             DoublyLinkedList();
             ~DoublyLinkedList();
             Link<T> *getFirst();
             void setFirst(Link<T> *first);
             Link<T> *getLast();
             void setLast(Link<T> *first);
             bool isEmpty();
             Link<T> *find(T key);
             void insertFirst(T dd);
             void insertLast(T dd);
             void deleteFirst();
             void deleteLast();
             bool insertAfter(T key,T dd);
             void deleteKey(T key);
             void displayForward();
             void displayBackward();
};

template<class T>
DoublyLinkedList<T>::DoublyLinkedList()
{
    setFirst(NULL);
    setLast(NULL);                                   
}

template<class T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
    while(!isEmpty())
    {
        deleteFirst();             
    }                                   
}

template<class T>
Link<T> *DoublyLinkedList<T>::getFirst()
{
       return first; 
}

template<class T>
void DoublyLinkedList<T>::setFirst(Link<T> *first)
{
     this->first = first;
}

template<class T>
Link<T> *DoublyLinkedList<T>::getLast()
{
       return last; 
}

template<class T>
void DoublyLinkedList<T>::setLast(Link<T> *last)
{
     this->last = last;
}

template<class T>
bool DoublyLinkedList<T>::isEmpty()
{
     return getFirst()==NULL;
}

template<class T>
 Link<T> *DoublyLinkedList<T>::find(T key)
 {
         Link<T> *current = getFirst();
         while(current != NULL && !(current->getData == key))
               current = current->getNext();
         return current;        
 }
 
 template<class T>
 void DoublyLinkedList<T>::insertFirst(T dd)
 {
      Link<T> *newLink = new Link<T>(dd);
      if(isEmpty())
           setLast(newLink);
      else
          getFirst()->setPrevious(newLink);
      newLink->setNext(getFirst());
      setFirst(newLink);        
 }
 
 template<class T>
 void DoublyLinkedList<T>::insertLast(T dd)
 {
      Link<T> *newLink = new Link<T>(dd);
      if(isEmpty())
      {
          setFirst(newLink);         
      }
      else
      {
          getLast()->setNext(newLink);
          newLink->setPrevious(getLast());
      }
      setLast(newLink);
 }
 
 template<class T>
 void DoublyLinkedList<T>::deleteFirst()
 {
      if(isEmpty())
           return;
      Link<T> *temp = getFirst();
      if(getFirst()->getNext() == NULL)
            setLast(NULL);
      else
         getFirst()->getNext()->setPrevious(NULL);
      setFirst(getFirst()->getNext());
      delete temp;                            
 }
 
 template<class T> 
 void DoublyLinkedList<T>::deleteLast()
 {
      if(isEmpty())
         return;
      Link<T> *temp = getLast();
      if(getFirst()->getNext() == NULL)
             setFirst(NULL);
      else
          getLast()->getPrevious()->setNext(NULL);
      setLast(getLast()->getPrevious());
      delete temp;                  
 }
 
 template<class T>
 bool DoublyLinkedList<T>::insertAfter(T key,T dd)
 {
      Link<T> *current = find(key);
      if(current == NULL)
             return false;
      Link<T> *newLink = new Link<T>(dd); 
      if(current->getNext() == NULL)
      {
           newLink->setNext(NULL);
           setLast(newLink);                 
      }
      else
      {
          newLink->setNext(current->getNext());
          current->getNext()->setPrevious(newLink);
      }
      newLink->setPrevious(current);
      current->setNext(newLink);
      return true;    
 }
 
 template<class T>
 void DoublyLinkedList<T>::deleteKey(T key)
 {
      Link<T> *current = find(key);
      if(current==NULL)
           return;
      if(current->getPrevious() == NULL)
             setFirst(current->getNext());
      else
             current->getPrevious()->setNext(current->getNext());
      if(current->getNext() == NULL)
             setLast(current->getPrevious());
      else
             current->getNext()->setPrevious(current->getPrevious());
      delete current;
 }
 
 template<class T>
 void DoublyLinkedList<T>::displayForward()
 {
      std::cout<<"List (first-->last): ";
      Link<T> *current = getFirst();
      while(current != NULL)
      {
         current->displayLink();
         current = current->getNext();   
      }
      std::cout<<"\n";
 }
 
 template<class T>
 void DoublyLinkedList<T>::displayBackward()
 {
      std::cout<<"List (last-->first): ";
      Link<T> *current = getLast();
      while(current != NULL)
      {
         current->displayLink();
         current = current->getPrevious();   
      }
      std::cout<<"\n";
 }

int ScaledDistance(Point u,Point v,Point p)
{
    return (p.x - v.x) * (u.y - v.y) - (p.y - v.y) * (u.x - v.x);
}

int Direction(Point u,Point v, Point p)
{
    return (p.x - v.x) * (u.y - v.y) - (p.y - v.y) * (u.x - v.x);
}

int Projection(Point u,Point v,Point p)
{
    return (p.x - v.x) * (u.x - v.x) + (p.y - v.y) *(u.y - v.y);
}

void Select(Point &p,Point &q, DoublyLinkedList<Point> &S)
{
    Point pt;
    Link<Point> *element = S.getFirst();
    q = element->getData();
    p = q;
    element = element->getNext();
    while(element != NULL)
    {
        pt = element->getData();
        if((pt.y < q.y) || (pt.y == q.y && pt.x < q.x)) q = pt;
        if((pt.y > p.y) || (pt.y == p.y && pt.x > p.x)) p = pt;
        element = element->getNext();
    }
}

void Split(Point p, Point q, DoublyLinkedList<Point> &S, DoublyLinkedList<Point> &R, DoublyLinkedList<Point> &L)
{
    int dir;
    Point pt;
    while(!S.isEmpty())
    {
        pt = S.getFirst()->getData();
        S.deleteFirst();
        dir = Direction(p,q,pt);
        if(dir > 0) R.insertLast(pt);
        if(dir < 0) L.insertLast(pt);
    }
}

void PruneAndSplit(Point p, Point q,Point r, DoublyLinkedList<Point> &S, DoublyLinkedList<Point> &U, DoublyLinkedList<Point> &L)
{
    DoublyLinkedList<Point> internal1,internal2;
    Split(p,r,S,U,internal1);
    Split(r,q,internal1,L,internal2);
    while(!internal2.isEmpty())
        internal2.deleteFirst();
}

Point FarthestPoint(Point p,Point q,DoublyLinkedList<Point> &S)
{
    int maxdist,dist;
    Point r,pt;
    maxdist = 0;
    Link<Point> *element = S.getFirst();
    while(element != NULL)
    {
        pt = element->getData();
        dist = ScaledDistance(p,q,pt);
        if(dist > maxdist)
        {
            maxdist = dist;
            r = pt;
        }
        else if(dist == maxdist)
        {
            if(Projection(p,q,pt) > Projection(p,q,r))
            {
                maxdist = dist;
                r = pt;
            }
        }
        element = element->getNext();
        
    }
    return r;
}

void QuickHull(Point p,Point q,DoublyLinkedList<Point> &S,DoublyLinkedList<Point> &CH)
{
    Point r;
    DoublyLinkedList<Point> U,L;
    if(!S.isEmpty())
    {
        r = FarthestPoint(p,q,S);
        PruneAndSplit(p,q,r,S,U,L);
        QuickHull(p,r,U,CH);
        CH.insertLast(r);
        QuickHull(r,q,L,CH);
    }
}

void Solve(DoublyLinkedList<Point> &A,DoublyLinkedList<Point> &CH)
{
    DoublyLinkedList<Point> S,L,R;
    Point p,q;
    Link<Point> *element = A.getFirst();
    while(element != NULL)
    {
        S.insertLast(element->getData());
        element = element->getNext();
    }
    Select(p,q,S);
    Split(p,q,S,R,L);
    CH.insertLast(p);
    QuickHull(p,q,R,CH);
    CH.insertLast(q);
    QuickHull(q,p,L,CH);
}

int main(int argc, char *argv[])
{
    DoublyLinkedList<Point> A;
    DoublyLinkedList<Point> B;
    stringstream ss;
    Point p;
    string line;
    int counter;
    while(getline(cin,line))
    {
       ss.clear();
       ss.str(line);
       counter = 1;
       while(ss)
       {
           try
           {
               switch(counter)
               {
                   case 1:
                   {
                       ss>>p.x;
                       break;
                   }
                   case 0:
                   {
                       ss>>p.y;
                       A.insertLast(p);
                       break;
                   }
               }
           }
           catch(...)
           {
               
           }
           counter = (counter + 1)%2;
       }
        Solve(A,B);
        cout<<"List A \n";
        A.displayForward();
        A.displayBackward();
        cout<<"List B \n";
        B.displayForward();
        B.displayBackward();
        while(!A.isEmpty())
            A.deleteFirst();
        while(!B.isEmpty())
            B.deleteFirst();
    }    
    return EXIT_SUCCESS;
}
