#include <iostream>
#include <cmath>
using namespace std;
struct POINT
{
int x, y;
int flag; // 表示是否在连线内部,在为0
};
POINT list[500], pk;
int stack[500], top, k, rightnum;
void swap(POINT &a, POINT &b)
{
POINT t;
t = a;
a = b;
b = t;
}
int CrossProd(POINT p0, POINT p1, POINT p2)
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
int comp(const void *pp1, const void *pp2)
{
//int t;
POINT *p1 = (POINT*)pp1, *p2 = (POINT*)pp2;
return CrossProd(list[0], *p1, *p2)*(-1);
}
void select(int n, int &num)
{
POINT p1, p2;
int t, i, j, f;
for (i = 1; i < n; i++)
{
f = 0;
p1 = list[i];
if (p1.flag)
{
for (j = i + 1; j < n; j++)
{
p2 = list[j];
if (p2.flag)
{
t = CrossProd(list[0], p1, p2);
if (t == 0)
{
if ((p1.x - list[0].x) * (p1.x - list[0].x) + (p1.y - list[0].y) *(p1.y - list[0].y) \
< (p2.x - list[0].x) * (p2.x - list[0].x) + (p2.y - list[0].y) *(p2.y - list[0].y))
{
list[i].flag = 0;
}
else list[j].flag = 0;
}
}
}
}
}
i = 1;
for (j = 1; j < n; j++)
{
if (list[j].flag == 1)
{
list[i] = list[j];
i++;
}
}
num = i - 1;
qsort(list + 1, num, sizeof(POINT), comp);
}
int init(int n)
{
int i, num;
for (i = 0; i < n; i++)
{
cin >> list[i].x >> list[i].y;
list[i].flag = 1;
if ((list[i].y < list[0].y) || (list[i].y == list[0].y) && (list[i].x < list[0].x))
{
swap(list[0], list[i]);
}
}
select(n, num);
return num + 1;
}
void graham(int n)
{
int i;
if (n == 1) cout << "(" << list[0].x << ", " << list[0].y << ")" << endl;
if (n == 2) cout << "(" << list[0].x << ", " << list[0].y << ")" \
"(" << list[1].x << ", " << list[1].y << ")" << endl;
if (n > 2)
{
for (i = 0; i <= 2; i++) stack[i] = i;
top = 2;
for (i = 3; i <= n-1; i++)
{
while (CrossProd(list[stack[top-1]], list[stack[top]], list[i]) <= 0)
top--;
top++;
stack[top] = i;
}
for (i = 0; i <= top; i++) cout << "(" << list[stack[i]].x << ", " << list[stack[i]].y << ")";
cout << endl;
}
}
void Chain(int n, int LR) // LR=1生成右链,LR=0生成左链
{
int m = 0, i, t;
POINT pm;
stack[0] = 0;
top = 0;
while (m != k)
{
pm = pk;
m = k;
for (i = 1; i < n; i++)
{
t = CrossProd(list[stack[top]], list[i], pm);
if ((t > 0 && LR==1) || (t < 0 && LR == 0) ||\
(t == 0) && ((list[i].x - list[stack[top]].x) * (list[i].x - list[stack[top]].x) \
+ (list[i].y - list[stack[top]].y)*(list[i].y - list[stack[top]].y)
> (pm.x - list[stack[top]].x) * (pm.x - list[stack[top]].x) \
+ (pm.y - list[stack[top]].y) * (pm.y - list[stack[top]].y)))
{
pm = list[i];
m = i;
}
}
top ++;
stack[top] = m;
}
if (LR == 1)
{
for (i = 0; i <= top; i++)
{
cout << "(" <<list[stack[i]].x << ", " << list[stack[i]].y << ")";
}
}
else
{
for (i = top - 1; i > 0; i--)
{
cout << "(" <<list[stack[i]].x << ", " << list[stack[i]].y << ")";
}
cout << endl;
}
}
void init2(int n)
{
int i;
for (i = 0; i < n; i++)
{
cin >> list[i].x >> list[i].y;
if (i == 0)
{
pk = list[0];
k = 0;
}
if ((list[i].y < list[0].y) || (list[i].y == list[0].y) && (list[i].x < list[0].x))
swap(list[0], list[i]);
if ((list[i].y > pk.y) || (list[i].y == pk.y) && (list[i].x > pk.x))
{
pk = list[i];
k = i;
}
}
}
void Jarvis(int n)
{
if (n == 1) cout << "(" << list[0].x << ", " << list[0].y << ")" << endl;
if (n == 2) cout << "(" << list[0].x << ", " << list[0].y << ")" \
"(" << list[1].x << ", " << list[1].y << ")" << endl;
if (n > 2)
{
Chain(n, 1);
Chain(n, 0);
}
}
int main()
{
int count = 0, n, num;
while (cin >> n)
{
if (n == 0) break;
count++;
cout << "set" << count << ":\n";
cout << "graham...(\n)";
num = init(n);
graham(num);
cout << "Jarvis...(\n)";
init2(n);
Jarvis(n);
}
return 0;
}