欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Week2 作业&实验

程序员文章站 2022-07-12 14:58:48
...

作业题部分

A - Maze

东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。
Input
  输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。
Output
  输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)
Hint
坐标(x, y)表示第x行第y列,行、列的编号从0开始,且以左上角为原点。
另外注意,输出中分隔坐标的逗号后面应当有一个空格。

解析:

本题为经典的迷宫的问题,寻找从左上角到右下角的路径。总体的思路是通过BFS的方法来求路径。BFS的方法则是采用队列,通过两个偏移量数组实现上下左右。而路径,则是由最初声明的point类的一个二维数组path保存。Path[x][y](point类型)里存的是它的前一个点的坐标,这样就可以依次找到它的路径。输出时,从终点(4,4)开始,将到达的点入栈,然后将这个点对应的path[][](即它的前一个点)入栈,循环这个过程,到(0,0)为止,即可将完整路径倒序入栈。输出即可。

源码:

#include<iostream>
#include<queue>
#include<stack>
using namespace std;
// 基本操作 
struct point
{
    int x;
	int y;
    point(int x, int y) : x(x), y(y){}
    point(){}
}path[10][10];

bool vis[10][10];
int a[10][10], dis[10][10];
int sx, sy, tx, ty;
queue<point> Q;
stack<point> s;
int dy[] = {-1, 1, 0, 0};
int dx[] = {0, 0, -1, 1};


// BFS,通过队列和偏移量数组实现 
int bfs()
{
    Q.push(point(sx, sy));
    vis[sx][sy] = true;
    dis[sx][sy] = 0;
    while(!Q.empty())
    {
        point now = Q.front();
		Q.pop();
        // 上下左右寻找可到达的点 
		for(int i = 0 ; i < 4 ; ++i)
        {
            int x = now.x + dx[i], y = now.y + dy[i];
            if(x >= 0 && x < 5 && y >= 0 && y < 5 && vis[x][y] == 0 && a[x][y] == 0)
            {
                dis[x][y] = dis[now.x][now.y] + 1;
				vis[x][y] = 1;
                Q.push(point(x, y));
                // 用path[][]记录前一个点坐标 
                path[x][y] = point(now.x, now.y);
            }
        }
    }
    return 0;
}
int main()
{
    for(int i = 0 ; i < 5 ; i++)
		for(int j = 0 ; j < 5 ; j++)
			vis[i][j] = 0;
	for(int i = 0 ; i < 5 ; i++)
        for(int j = 0 ; j < 5 ; j++)
            cin >> a[i][j];
    bfs();
    
    // 入栈,寻找路径 
    int px = 4, py = 4;
    while(true)
    {
        s.push(point(px, py));
    	
		int b = px, c = py; 
		px = path[b][c].x;
        py = path[b][c].y;
        if(px == 0 && py == 0) 
			break;
    }
    
    // 输出路径
	cout << "(0, 0)" << endl; 
	point step;
	while(!s.empty())
    {
        step = s.top(); 
		s.pop();
        cout << "(" << step.x << ", " << step.y << ")" << endl;
    }
    return 0;
}

B - Pour Water

倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。
Input
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。
Output
你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。
Sample Input
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
Notes
如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。

解析:

这是一个隐式图问题。类似于迷宫问题,以最终水量4为例,这道题等价于从(0,0)的初始状态到终点(4,n)或者(m,4)的迷宫。因此我们用BFS的做法来实现。为了便于输出,我们在结构体status中加入一个字符串变量string s,用来存放“fill A”、“pour A B”等句子。

源码:

#include<queue>
#include<iostream>
#include<string>
#define maxn 1000
using namespace std;

int vis[maxn][maxn];

// 隐式图的节点 
struct status
{
    int a;  // A杯水量 
	int b;  // B杯水量 
	int step;  // 步数 
    string s[maxn];  // 操作名 
}form;

// BFS 
int bfs(int A, int B, int C)
{
    status node;
    // 初始化(0,0),也是最初的状态 
	node.a = 0;
	node.b = 0;
	node.step = 0;
	
    queue<status> q;
    q.push(node);
    
	while(!q.empty())
    {
        // 取队首元素top
		status t = q.front();
        q.pop();
        
        // 结束的标志 
        if(t.a == C || t.b == C)
        {
            form = t;
            return 1;
        }
        // vis[A][t.b]代表b杯不动,a杯加满 
        // 当vis[A][t.b]为0时,代表这个点未到达过,执行下面操作 
		if(!vis[A][t.b])
        {
			status p;
			p = t;
            p.a = A;   // 将A加满
			vis[p.a][p.b] = 1; // 标记已到达 
			p.step++;  // 步数加一 
            p.s[p.step] = "fill A"; // 记录操作名 
            q.push(p); // 入队 
        }
        
        //下面的几种情况类似,不再详细注释 
        
        // vis[t.a][B]代表a杯不动,b杯加满 
        if(!vis[t.a][B])
        {
            status p;
			p = t;
            p.b = B;
			vis[p.a][p.b] = 1;
			p.step++;
            p.s[p.step] = "fill B";  
            q.push(p);
        }
        // vis[0][t.b]代表b杯不动,a杯倒空 
        if(!vis[0][t.b])
        {
            status p;
			p = t;
            p.a = 0;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "empty A";
            q.push(p);
        }
        // vis[t.a][B]代表a杯不动,b杯倒空 
        if(!vis[t.a][0])
        {
            status p;
			p = t;
            p.b = 0;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "empty B";
            q.push(p);
        }
        // A中水全倒入B中,如果A中剩余的水不足以使B满,则A变为0,B变为a + b
		// 如果能使B满还有溢出,则B满,A为a + b - B 
        if(!vis[(B - t.b >= t.a) ? 0 : t.a - B + t.b][(B - t.b >= t.a) ? t.a + t.b : B])
        {
            status p;
			p = t;
            p.a = (B - t.b >= t.a) ? 0 : t.a - B + t.b;
            p.b = (B - t.b >= t.a) ? t.a + t.b : B;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "pour A B";
            q.push(p);
        }
        // B中水全倒入A中,如果B中剩余的水不足以使A满,则B变为0,A变为a + b
		// 如果能使A满还有溢出,则A满,B为a + b - A 
		if(!vis[(A - t.a >= t.b) ? t.a + t.b : A][(A - t.a >= t.b) ? 0 : t.b - A + t.a])
        {
            status p;
			p = t;
            p.a = (A - t.a >= t.b) ? t.a + t.b : A;
            p.b = (A - t.a >= t.b) ? 0 : t.b - A + t.a;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "pour B A";
            q.push(p);
        }
    }
    return 0;2 
}

int main()
{
    int A, B, C;
	
    while(cin >> A >> B >> C)
    {
    	int m = max(A, B);
		for(int i = 0 ; i < m ; i++)
    		for(int j = 0 ; j < m ; j++)
    			vis[i][j] = 0;
		bfs(A, B, C);
		// 输出s[],即为操作名。注意这个解不是唯一的。 
        for(int i = 1 ; i <= form.step ; i++)
            cout << form.s[i] << endl;
        cout << "success" << endl;
	}
}

回顾:

在VJ上测试这道题时,刚开始发生了CE的错误。后经分析发现,代码里没有引用头文件导致cout无法直接输出string类型。仔细了解后发现不同编译器对cout的输出不一样,C++的编译器没有时无法cout string类型,而G++则可以。

实验部分

A - 化学 (编译器选 GNU G++)

化学很神奇,以下是烷烃基。
Week2 作业&实验
假设如上图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基
你的任务是甄别烷烃基的类别。
原子没有编号方法,比如
1 2
2 3
3 4
4 5
5 6

1 3
2 3
2 4
4 5
5 6
是同一种,本质上就是一条链,编号其实是没有关系的,可以在纸上画画就懂了
Input
输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)
数据保证,输入的烷烃基是以上5种之一
Output
每组数据,输出一行,代表烷烃基的英文名
Example
Input
2
1 2
2 3
3 4
4 5
5 6
1 4
2 3
3 4
4 5
5 6
Output
n-hexane
3-methylpentane

解析:

仔细观察图发现,以树的角度看待图中的五种烷烃基:
(1) n-hexane有两个叶子节点;
(2)2,3-dimethylbutane和2,2-dimethylbutane都有4个叶子节点,可是2,2-dimethylbutane中有一个节点度为4(即与其它4个点连接)而2,3没有这种节点。
(3)3-methylpentane与2-methylpentane,度为3的点连接的叶子数分别为1和2。
这样我们就确定了5种不同的烷烃基。我们可以通过记录叶节点数n、度为4的节点数r以及关注度为3的点所连接的叶子数即可区分五种烷烃基。
建立一个数组c[7]用来储存每个节点的度。

源码:

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

struct graph
{
	int a[5];
	int b[5];
};
 
int creatg(graph gra){
	// c[7]数组用于储存每个点的度 ,c[0]不用 
	int c[7] = {0,0,0,0,0,0,0};
	for(int i = 0 ; i < 5 ; i++){
		if(gra.a[i] == 1 || gra.b[i] == 1)
			c[1]++;
		if(gra.a[i] == 2 || gra.b[i] == 2)
			c[2]++;
		if(gra.a[i] == 3 || gra.b[i] == 3)
			c[3]++;
		if(gra.a[i] == 4 || gra.b[i] == 4)
			c[4]++;
		if(gra.a[i] == 5 || gra.b[i] == 5)
			c[5]++;
		if(gra.a[i] == 6 || gra.b[i] == 6)
			c[6]++;
	}
	
	// 统计叶节点数n、度为4的节点数r,记录度为3的节点p 
	int n = 0, r = 0, p = 0;
	for(int i = 1 ; i < 7 ; i++){
		if(c[i] == 1)
			n++;
		if(c[i] == 4)
			r++;
		if(c[i] == 3)
			p = i;
	}
	// 先找出3种	
	if(n == 2)
		cout << "n-hexane" << endl;
	if(n == 4 && r == 0)
		cout << "2,3-dimethylbutane" << endl;
	if(n == 4 && r == 1)
		cout << "2,2-dimethylbutane" << endl;
	//  区分另外两种 
	if(n == 3)
	{
		// 用d[3]来记录度为3的节点的三个邻接节点 
		int d[3]; 
		int tag = 0;
		for(int i = 0 ; i < 5 ; i++){
			if(gra.a[i] == p)
			{
				d[tag] = gra.b[i];
				tag++;
			}	
			if(gra.b[i] == p)
			{
				d[tag] = gra.a[i];
				tag++;
			}
		};
		
		int u = 0; // u代表邻接节点中叶子的数目 
		
		for(int i = 0 ; i < 3 ; i++)
		{
			// 邻接节点是叶子: 
			if(c[d[i]] == 1)
				u++;	
		}
		// 区分剩下两个 
		if(u == 1)
			cout << "3-methylpentane" << endl;
		else
			cout << "2-methylpentane" << endl;
	}
	
		
}

int main(){
	graph gra;
	int n;
	cin >> n;
	for(int j = 0 ; j < n ; j++)
	{
		for(int i = 0 ; i < 5 ; i++)
		{
			cin >> gra.a[i] >> gra.b[i];
		}
		creatg(gra);
	}
	
}

B - 爆零(×)大力出奇迹(√)

程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回AC,要么是返回各种其他的错误,不论是怎样的错法,它总会给你记上一笔,表明你曾经在这儿被坑过,而当你历经千辛终将它AC之后,它便会和你算笔总账,表明这题共错误提交了几次。
在岁月的长河中,你通过的题数虽然越来越多,但通过每题时你所共花去的时间(从最开始算起,直至通过题目时的这段时间)都会被记录下来,作为你曾经奋斗的痕迹。特别的,对于你通过的题目,你曾经的关于这题的每次错误提交都会被算上一定的单位时间罚时,这样一来,你在做出的题数上,可能领先别人很多,但是在做出同样题数的人中,你可能会因为罚时过高而处于排名上的劣势。
例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分。
Input
输入数据包含多行,第一行是共有的题数n(1≤n≤12)以及单位罚时m(10≤m≤20),之后的每行数据描述一个学生的信息,首先是学生的用户名(不多于10个字符的字串)其次是所有n道题的得分现状,其描述采用问题描述中的数量标记的格式,见上面的表格。
Output
根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。
Sample Input
8 20
GuGuDong 96 -3 40(3) 0 0 1 -8 0
hrz 107 67 -3 0 0 82 0 0
TT 120(3) 30 10(1) -3 0 47 21(2) -2
OMRailgun 0 -99 -8 0 -666 -10086 0 -9999996
yjq -2 37(2) 13 -1 0 113(2) 79(1) -1
Zjm 0 0 57(5) 0 0 99(3) -7 0
Sample Output
TT 5 348
yjq 4 342
GuGuDong 3 197
hrz 3 256
Zjm 2 316
OMRailgun 0 0

解析:

这个题类似第一周的长方形排序题,是一种多条件的排序。其优先级依次为:
(1)做出来的题目 降序
(2)花费时间(含罚时) 升序
(3)名字的字典序 升序
通过排序函数compare来实现排序。

源码:

#include<iostream>
#include<cstring>
using namespace std;

struct student
{
    char name[10];  // ID 
    int solved;     // A掉的题数 
    int timescore;  // 耗时 
}stu[1000];

// 用于排序的比较函数 
int cmp(int j, int i)
{
    // 第一优先级,解决问题数 
	if(stu[j].solved < stu[i].solved)
    	return 1;
    else 
        if(stu[j].solved == stu[i].solved)
        	// 第二优先级,耗时 
			if(stu[j].timescore > stu[i].timescore)
        		return 1;
        	else
				if(stu[j].timescore == stu[i].timescore)
            		// 第三优先级,姓名字典序 
					if(strcmp(stu[j].name, stu[i].name) > 0)
        				return 1; 
    return 0;
}

// 计算乘以10的n次方的函数,便于将字符串保存的数转化为int 
int e10(int n){
	int a = 1;
	for(int i = 0 ; i < n ; i++)
	{
		a *= 10;
	}
	return a;
}

int main()
{
	int n, m;
	cin >> n >> m;
	int i = 1;
	while(cin >> stu[i].name)
	{
        char a[100]; // 用字符串保存 
        stu[i].solved = 0; 
        stu[i].timescore = 0;
        // 循环求n道题的结果 
		for(int j = 1 ; j <= n ; j++)
        {
            cin >> a;
            if(a[0] != '-' && a[0] > '0')
            {
                // 问题解决 
				int tag = 0; 
                int flags = 0;
                stu[i].solved ++;
                
                // 求输入的第一个数据的长度length 
                int length = strlen(a);
                // 利用length求第一个数据 ,倒序处理 
				for(int j = length - 1 ; j >= 0 ; j--)
                {
                    // 数据部分转化 
					if(a[j] != ')' && a[j] != '(')
                    {
						// 计算时间 
						int times = a[j] - '0';
                        stu[i].timescore += times * e10(tag);
						// 如果flag是true,则说明这个数据是未通过次数,应该*20记罚时,由于前面已经加了1,只需再乘(m-1) 
						if(flags)
                        	stu[i].timescore += times * e10(tag) * (m - 1);
                        tag++;	
                	}
					// 如果存在后括号,代表下次处理的数字是未通过的次数,flag变为1 
					if(a[j] == ')')
                    {
                        flags = 1;
                        tag = 0;
                	} 
					// flag变0,代表下一个数据是正常时间 
					if(a[j] == '(')
                    {
                        flags = 0;
                        tag = 0;
                	} 
            	}
        	}
    	}
    	// 插入排序,找到适合输入数据的位置插入 
    	if(i >= 2)
    	{
			for(int j = i - 1 ; j > 0 ; j--)
    		{
            	if(cmp(j, i) && !cmp(j - 1 , i))
            	{
					student tmp = stu[i];
            		for(int k = i - 1 ; k >= j ; k--)
                		stu[k + 1] = stu[k];
            		stu[j] = tmp;
            		break;
            	}
        	} 
     	}
     	i++;
	}
	// 格式化输出 
	for(int j = 1 ; j < i ; j++)
	{
		printf("%-10s ", stu[j].name);
		printf("%2d ", stu[j].solved);
		printf("%4d\n", stu[j].timescore);
	}  
}

C - 瑞神打牌 (不支持C++11,G++和C++编译器都试试提交哈)

瑞神HRZ因为疫情在家闲得无聊,同时他又非常厉害,所有的课对他来说都是水一水就能拿A+,所以他无聊,找来了另外三个人:咕咕东,腾神以及zjm来打牌(天下苦瑞神久矣)。
显然,牌局由四个人构成,围成一圈。我们称四个方向为北 东 南 西。对应的英文是North,East,South,West。游戏一共由一副扑克,也就是52张构成。开始,我们指定一位发牌员(东南西北中的一个,用英文首字母标识)开始发牌,发牌顺序为顺时针,发牌员第一个不发自己,而是发他的下一个人(顺时针的下一个人)。这样,每个人都会拿到13张牌。
现在我们定义牌的顺序,首先,花色是(梅花)<(方片)<(黑桃)<(红桃),(输入时,我们用C,D,S,H分别表示梅花,方片,黑桃,红桃,即其单词首字母)。对于牌面的值,我们规定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。
现在你作为上帝,你要从小到大排序每个人手中的牌,并按照给定格式输出。(具体格式见输出描述和样例输出)。
Input
输入包含多组数据
每组数据的第一行包含一个大写字符,表示发牌员是谁。如果该字符为‘#’则表示输入结束。
接下来有两行,每行有52个字符,表示了26张牌,两行加起来一共52张牌。每张牌都由两个字符组成,第一个字符表示花色,第二个字符表示数值。
Output
输出多组数据发牌的结果,每组数据之后需要额外多输出一个空行!!!!!
每组数据应该由24行的组成,输出按照顺时针方向,始终先输出South Player的结果,每位玩家先输出一行即玩家名称(东南西北),接下来五行,第一行和第五行输出固定格式(见样例),第二行和第四行按顺序和格式输出数值(见样例),第三行按顺序和格式输出花色(见样例)。
Sample Input
N
CTCAH8CJD4C6D9SQC7S5HAD2HJH9CKD3H6D6D7H3HQH4C5DKHKS9
SJDTS3S7S4C4CQHTSAH2D8DJSTSKS2H5D5DQDAH7C9S8C8S6C2C3

Sample Output
South player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T|
| C | C | D | D | S | S | S | S | H | H | H | H | H |
|6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
West player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|2 2|5 5|9 9|K K|5 5|7 7|9 9|4 4|T T|J J|A A|8 8|A A|
| C | C | C | C | D | D | D | S | S | S | S | H | H |
|2 2|5 5|9 9|K K|5 5|7 7|9 9|4 4|T T|J J|A A|8 8|A A|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
North player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|3 3|4 4|J J|2 2|3 3|T T|Q Q|K K|8 8|Q Q|K K|2 2|3 3|
| C | C | C | D | D | D | D | D | S | S | S | H | H |
|3 3|4 4|J J|2 2|3 3|T T|Q Q|K K|8 8|Q Q|K K|2 2|3 3|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
East player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|7 7|8 8|T T|Q Q|4 4|8 8|A A|2 2|3 3|6 6|J J|Q Q|K K|
| C | C | C | C | D | D | D | S | S | H | H | H | H |
|7 7|8 8|T T|Q Q|4 4|8 8|A A|2 2|3 3|6 6|J J|Q Q|K K|
±–±--±–±--±–±--±–±--±–±--±–±--±–+

解析:

我们可以把扑克牌playing cards想象成一个结构体card,包含pattern(花色)、figure(点数)。为了方便本题操作,我们还给它加了belong(持有者,0、1、2、3代表4位玩家),再定义一个realnum把figure的字符表示的点数转化为方便比较的int型数据,其中A用14表示。
解决这题的思路为:用deck[52]依次序记录52张牌,这部分的重点是记录好每张牌的belong(持有者)。之后,我们把这52张牌按花色分到card club[13],diamond[13],spade[13], heart[13]四种花色中。然后每个花色进行排序。
输出时,因为花色间的大小关系已经确定,对于每个玩家,依次输出梅花、方片、黑桃、红桃,因为在上一步中每个花色已经排好,所以直接输出即可。
这种思路针对特定的题,没有按照多条件排序的做法做。

回顾:

本地样例过了之后,VJ上一直是WA。经过研究,发现了错误所在。在输入两个长为52的字符数组(char b1[52], b2[52])时,我刚开始直接采用了cin >> b1 >> b2的写法,而这种写法会导致部分编译器将其视为字符串,然后在最后一位加\0,这样最后一位就丢失了。解决的办法是把数组开大或者采用下面代码中的逐个输入的方法。

源码:

#include<iostream>
using namespace std;

//(梅花C)<(方片D)<(黑桃S)<(红桃H)
// 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A
//North,East,South,West

struct card{
	char pattern; // 花色 
	char figure;  // 点数 
	int belong;   // 持有者 
	int realnum;  // 真值(把figure转化为int型) 
	
};

int main(){
	char a; // 发牌者 
	while(cin >> a)
	{
		if(a - '#' == 0)
			return 0;
		else
		{
			// 把52张牌写进deck[52]里
			char b1[52];
			char b2[52];
			
			for(int i = 0 ; i < 52 ; i++)
			{
				cin >> b1[i];
			 } 
			for(int i = 0 ; i < 52 ; i++)
			{
				cin >> b2[i];
			 } 
			
			int tag;
			if(a == 'N')
				tag = 0;
			if(a == 'E')
				tag = 1;
			if(a == 'S')
				tag = 2;
			if(a == 'W')
				tag = 3;
			
			// 声明deck[52]保存输入的五张牌 
			card deck[52];
			for(int i = 0 ; i < 26 ; i++)
			{
				deck[i].pattern = b1[2 * i];
				deck[i].figure = b1[2 * i + 1];
				deck[i].belong = (i + tag) % 4;
			}
			
			for(int i = 0 ; i < 26 ; i++)
			{
				deck[i + 26].pattern = b2[2 * i];
				deck[i + 26].figure = b2[2 * i + 1];
				deck[i + 26].belong = (i + 2 + tag) % 4;	
			}
			
			for(int i = 0 ; i < 52 ; i++)
			{
				if(deck[i].figure - '2' <= 7)
					deck[i].realnum = deck[i].figure - '0';
				else
				{
					if(deck[i].figure - 'T' == 0)
						deck[i].realnum = 10;
					if(deck[i].figure - 'J' == 0)
						deck[i].realnum = 11;
					if(deck[i].figure - 'Q' == 0)
						deck[i].realnum = 12;
					if(deck[i].figure - 'K' == 0)
						deck[i].realnum = 13;
					if(deck[i].figure - 'A' == 0)
						deck[i].realnum = 14;
				}
			}
			
			// 按花色分出来然后同一花色按大小排序,因为card类型里有belong表示牌的所属
			// 最后直接按belong的值就能取出来输出 
			card club[13];
			card diamond[13];
			card spade[13];
			card heart[13];
			
			int tag1 = 0, tag2 = 0, tag3 = 0, tag4 = 0;
			for(int i = 0 ; i < 52 ; i++)
			{
				
				if(deck[i].pattern - 'C' == 0)
				{
					club[tag1] = deck[i];
					tag1++;
				}
				if(deck[i].pattern - 'D' == 0)
				{
					diamond[tag2] = deck[i];
					tag2++;
				}
				if(deck[i].pattern - 'S' == 0)
				{
					spade[tag3] = deck[i];
					tag3++;
				}
				if(deck[i].pattern - 'H' == 0)
				{
					heart[tag4] = deck[i];
					tag4++;
				}
			}
			
			// 冒泡排序,把每个花色的牌按点数大小排序 
			for(int i = 0 ; i < 12 ; i++)
			{
				for(int j = 0 ; j < 12 ; j++)
				{
					if(club[j].realnum > club[j + 1].realnum)
					{
						card tmp;
						tmp = club[j];
						club[j] = club[j + 1];
						club[j + 1] = tmp;
					}
				}
				for(int j = 0 ; j < 12 ; j++)
				{
					if(diamond[j].realnum > diamond[j + 1].realnum)
					{
						card tmp;
						tmp = diamond[j];
						diamond[j] = diamond[j + 1];
						diamond[j + 1] = tmp;
					}
				}
				for(int j = 0 ; j < 12 ; j++)
				{
					if(spade[j].realnum > spade[j + 1].realnum)
					{
						card tmp;
						tmp = spade[j];
						spade[j] = spade[j + 1];
						spade[j + 1] = tmp;
					}
				}
				for(int j = 0 ; j < 12 ; j++)
				{
					if(heart[j].realnum > heart[j + 1].realnum)
					{
						card tmp;
						tmp = heart[j];
						heart[j] = heart[j + 1];
						heart[j + 1] = tmp;
					}
				}
			}
			
			// 剩下的就是输出部分了 各种重复 原理是遍历四个花色的数组,找出belong是0/1/2/3的分别输出 
			cout << "South player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 1)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 1)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 1)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 1)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 1)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 1)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 1)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 1)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 1)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 1)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 1)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 1)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
			// 
			cout << "West player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 2)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 2)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 2)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 2)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 2)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 2)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 2)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 2)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 2)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 2)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 2)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 2)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
			//
			cout << "North player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 3)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 3)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 3)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 3)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 3)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 3)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 3)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 3)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 3)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 3)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 3)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 3)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
			//
			cout << "East player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 0)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 0)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 0)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 0)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 0)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 0)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 0)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 0)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 0)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 0)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 0)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 0)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
		}
		cout << endl;
	}
}