笔试被虐惨,选择题一半多的概率题,每道题差不多3、5分钟,so,最后好几个没有算。
附加两个大题,一个是编写魔方,另一个是机器学习的分布不均衡问题和SVM。魔方题没有写完,机器学习的题目也只答了一问...
当天晚上把魔方的代码完善了下,没有找到好的解法,硬写的,麻烦的要死。
晚上的时候网上已经有题目了,详情如下,最后结果的输出其实不一定要与题目一致,因为每一面的方向没有明确定义,颜色对了即可,比如本文的程序里,Y面与题目的Y面相差180度:
一个三阶魔方由六个面组成,颜色分别是白色(W)、对面为黄色(Y)、红色(R)、对面为橙色(O)、绿色(G)、对面为蓝色(B)。如果手持魔方,白色向上,红色朝向自己,则绿色在左手侧。
请写一个程序,对一个处于还原状态(各面各块同色)的魔方,进行操作,打印操作后的魔方状态。操作指令为单个操作指令组成的字符串。单个操作指令包括:
1)U:白色面顺时针旋转90度
2)D:黄色面顺时针旋转90度
3)F:红色面顺时针旋转90度
4)B:橙色面顺时针旋转90度
5)L:绿色面顺时针旋转90度
6)R:蓝色面顺时针旋转90度
其中顺时针旋转定义为将该面朝向自己时的顺时针方向。
按WYROGB的顺序输出经过操作后6个面的状态。每个面首先输出中心块颜色,然后从此面面向自己时的左下角块开始,顺时针顺出每块的颜色。输出一面后换行。
请设计一个数据结构表示魔方,并基于该数据结构完成功能。
请用C/C++,Java或Python语言实现。请注意尽量以可成功编译或可直接运行为标准来编写代码。
示例:
输入:
LR
输出:
WOOOWRRRW
YRRRYOOOY
RWWWRYYYR
OYYYOWWWO
GGGGGGGGG
BBBBBBBBB
代码如下:
#include <stdio.h> #include <stdlib.h> struct panel { //暴力解法,每个面的面板颜色和四个接触的边 int a[3][3]; //每个面的颜色 char status; //本面的颜色符号 struct panel *u; //四个相邻的面 int ul; //相邻的边是相应面的那一条1-6表示1-3行+1-3列,-号表示逆序 struct panel *r; int rl; struct panel *d; int dl; struct panel *l; int ll; }; typedef struct panel PP; void initPanel(PP *p, int color); void changePanel(PP *p, PP *u, PP *r, PP *d, PP *l); void rot(PP *p); void getLine(PP *p,int line,int b[]); void setLine(PP *p,int line ,int b[]); int abValue(int x); void printPanel(PP *p, int check); char intTochar(int i); void printA(int a[]); int main(int argc, char **argv) { char c; PP Wp; PP Op; PP Bp; PP Rp; PP Gp; PP Yp; //定义每个面的颜色 initPanel(&Wp,1); initPanel(&Op,2); initPanel(&Bp,3); initPanel(&Rp,4); initPanel(&Gp,5); initPanel(&Yp,6); /*给白色面定义四个临边,尼玛太麻烦了,有好一点的算法没? 以这个方向定义,输出也是用的这个方向 --- | O | --- --- --- --- | G | W | B | Y | --- --- --- --- | R | --- */ Wp.status = 'W'; Wp.u = &Op; Wp.ul = 3; Wp.r = &Bp; Wp.rl = 4; Wp.d = &Rp; Wp.dl = 1; Wp.l = &Gp; Wp.ll = 6; //橘色定义 Op.status = 'O'; Op.u = &Yp; Op.ul = -1; Op.r = &Bp; Op.rl = -1; Op.d = &Wp; Op.dl = 1; Op.l = &Gp; Op.ll = 1; //蓝色定义 Bp.status = 'B'; Bp.u = &Op; Bp.ul = -6; Bp.r = &Yp; Bp.rl = 4; Bp.d = &Rp; Bp.dl = 6; Bp.l = &Wp; Bp.ll = 6; //红色定义 Rp.status = 'R'; Rp.u = &Wp; Rp.ul = 3; Rp.r = &Bp; Rp.rl = 3; Rp.d =&Yp; Rp.dl = -3; Rp.l = &Gp; Rp.ll = -3; //绿色定义 Gp.status = 'G'; Gp.u = &Op; Gp.ul = 4; Gp.r = &Wp; Gp.rl = 4; Gp.d = &Rp; Gp.dl = -4; Gp.l = &Yp; Gp.ll = 6; //黄色定义 Yp.status = 'Y'; Yp.u = &Op; Yp.ul = -1; Yp.r = &Gp; Yp.rl = 4; Yp.d = &Rp; Yp.dl = -3; Yp.l = &Bp; Yp.ll = 6; while((c = getchar()) != '\n'){ if(c == 'U') changePanel(&Wp, Wp.u, Wp.r, Wp.d, Wp.l); //改变本面和相邻的四个面 if(c == 'D') changePanel(&Yp, Yp.u, Yp.r, Yp.d, Yp.l); if(c == 'F') changePanel(&Rp, Rp.u, Rp.r, Rp.d, Rp.l); if(c == 'B') changePanel(&Op, Op.u, Op.r, Op.d, Op.l); if(c == 'L') changePanel(&Gp, Gp.u, Gp.r, Gp.d, Gp.l); if(c == 'R') changePanel(&Bp, Bp.u, Bp.r, Bp.d, Bp.l); } //输出每一个面,注意输出的顺序,1代表与定义顺序一致,0代表翻转180 printPanel(&Wp, 1); printPanel(&Yp, 0); printPanel(&Rp, 1); printPanel(&Op, 1); printPanel(&Gp, 1); printPanel(&Bp, 1); return 0; } //初始每个面的颜色 void initPanel(PP *p, int color){ int i,j; for(i = 0;i < 3;i++) for(j = 0;j < 3;j++) p->a[i][j] = color; } //旋转 void changePanel(PP *p, PP *u, PP *r, PP *d, PP *l){ //旋转本面二维数组 rot(p); //旋转四个边 int ua[3],ra[3],da[3],la[3]; int i,j; getLine(p->u,p->ul,ua); getLine(p->r,p->rl,ra); getLine(p->d,p->dl,da); getLine(p->l,p->ll,la); //输出本面的当前四个边 printf("%c %dth is\n",p->u->status,p->ul); printA(ua); printf("%c %dth is\n",p->r->status,p->rl); printA(ra); printf("%c %dth is\n",p->d->status,p->dl); printA(da); printf("%c %dth is\n",p->l->status,p->ll); printA(la); printf("\n"); //转换4条边,由于下边和左边的定义顺序是左到右、上到下排列,与顺时针方向相反,在转换时要注意 for(i = 0;i < 3;i++){ j = ua[i]; ua[i] = la[2-i]; la[2-i] = da[2-i]; da[2-i] = ra[i]; ra[i] = j; } //输出旋转后本面的当前四个边 printf("%c %d th is\n",p->u->status,p->ul); printA(ua); printf("%c %d th is\n",p->r->status,p->rl); printA(ra); printf("%c %d th is\n",p->d->status,p->dl); printA(da); printf("%c %d th is\n",p->l->status,p->ll); printA(la); printf("\n"); //将旋转后的4个边赋值给相应的临面 setLine(p->u,p->ul,ua); setLine(p->r,p->rl,ra); setLine(p->d,p->dl,da); setLine(p->l,p->ll,la); } //旋转二维数组,注意每一行交换两个 void rot(PP *p){ int i,j; for(i = 0; i < 2; i++){ j = p->a[0][i]; p->a[0][i] = p->a[2-i][0]; p->a[2-i][0] = p->a[2][2-i]; p->a[2][2-i] = p->a[i][2]; p->a[i][2] = j; } } //获取面的某条边数据 void getLine(PP *p,int line,int b[]){ int i; if(abValue(line) < 4){ for(i = 0;i < 3;i++){ if(line < 0) b[i] = p->a[abValue(line) - 1][2-i]; if(line > 0) b[i] = p->a[line - 1][i]; } } else if(abValue(line) >= 4){ for(i = 0;i < 3;i++){ if(line < 0) b[i] = p->a[2-i][abValue(line) - 4]; if(line > 0) b[i] = p->a[i][line - 4]; } } } //赋值面的某条边 void setLine(PP *p,int line ,int b[]){ int i; if(abValue(line) < 4){ for(i = 0;i < 3;i++){ if(line < 0) p->a[abValue(line) - 1][2-i] = b[i]; if(line > 0) p->a[line - 1][i] = b[i]; } } else if(abValue(line) >= 4){ for(i = 0;i < 3;i++){ if(line < 0) p->a[2-i][abValue(line) - 4] = b[i]; if(line > 0) p->a[i][line - 4] = b[i]; } } } //取绝对值 int abValue(int x){ if(x < 0) return 0-x; else return x; } //check为定义如何输出,定义每一面时是按照正方体展开的方向,最下面的Y貌似与定义顺序不同 void printPanel(PP *p, int check){ int i,j,k; if(check == 1){ //正序,j+k*正序下标,无变化 j = 0; k = 1; } else if(check == 0){ //逆序下标=2-正序下标 j+k*正序下标 j = 2; k = -1; } //输出二维数组,先输出中心点,再输出4个边,左下开始顺时针 printf("%c",intTochar(p->a[1][1])); for(i = 0;i < 2;i++) printf("%c",intTochar(p->a[j+k*(2-i)][j+k*0])); for(i = 0;i < 2;i++) printf("%c",intTochar(p->a[j+k*0][j+k*i])); for(i = 0;i < 2;i++) printf("%c",intTochar(p->a[j+k*i][j+k*2])); for(i = 0;i < 2;i++) printf("%c",intTochar(p->a[j+k*2][j+k*(2-i)])); printf("\n"); } //由数字颜色转为字符 char intTochar(int i){ switch(i){ case 1: return 'W'; break; case 2: return 'O'; break; case 3: return 'B'; break; case 4: return 'R'; break; case 5: return 'G'; break; case 6: return 'Y'; break; default: return 'N'; break; } } //输出暂存数组 void printA(int a[]){ printf("%c",intTochar(a[0])); printf("%c",intTochar(a[1])); printf("%c",intTochar(a[2])); printf("\n"); }