标签:c c++ mathematica csdn博客 设计图
这个问题的来源另外一篇博客里面已经提到过,stackexchange上一个有趣的C++代码竞赛的博客,它的来源是:StackExchange上的原始问题及答案
比赛基于下面的代码:基础代码链接 ,这个在博文我的另一CSDN博客中也已经给出,如果原始链接无法访问可以备用。
已经提到,我感兴趣的是基于这个代码如何生成一面五星红旗。红旗的设计图如下,也在我的上一篇博客搜索给出过。
首先,五星红旗颜色简单,只有红色黄色两种。从减法色(RGB)的角度看,黄色就是白色光中减去红色和绿色。所以,背景是红色很单一,关键就是如何减掉五角星区域内的绿色,即改写unsigned char GR(int i,int j)函数。
考虑到问题不是那么简单直接,先不考虑字符数仅为140个(一twitter)的限制,先做出来再说。
我打算用Mathematica完成逻辑部分。代码如下:
ClearAll["Global`*"];
sol = Solve[{(x - x0)^2 + (y - y0)^2 ==
r^2, (y - y0) (x1 - x0) == (x - x0) (y1 - y0)}, {x, y}] //
FullSimplify;
p1 = {x, y} /. sol[[2]] // Simplify;
a = {x0, y0};
p2 = RotationTransform[2 Pi/5, a][p1] // Simplify;
p3 = RotationTransform[2 Pi/5, a][p2] // Simplify;
p4 = RotationTransform[2 Pi/5, a][p3] // Simplify;
p5 = RotationTransform[2 Pi/5, a][p4] // Simplify;
q1 = {x, y} /. sol[[1]] // Simplify;
q2 = RotationTransform[2 Pi/5, a][q1] // Simplify;
q3 = RotationTransform[2 Pi/5, a][q2] // Simplify;
q4 = RotationTransform[2 Pi/5, a][q3] // Simplify;
q5 = RotationTransform[2 Pi/5, a][q4] // Simplify;
(P1 = Limit[
Limit[{p1, p2, p3, p4, p5} /. {x1 -> 100, y1 -> 200, r -> 60},
x0 -> 100], y0 -> 100] // Simplify // N // Round);
(P2 = Limit[
Limit[{q1, q2, q3, q4, q5} /. {x1 -> 100, y1 -> 100, r -> 20},
x0 -> 200], y0 -> 180] // Simplify // N // Round);
(P3 = Limit[
Limit[{q1, q2, q3, q4, q5} /. {x1 -> 100, y1 -> 100, r -> 20},
x0 -> 200], y0 -> 40] // Simplify // N // Round);
(P4 = Limit[
Limit[{q1, q2, q3, q4, q5} /. {x1 -> 100, y1 -> 100, r -> 20},
x0 -> 240], y0 -> 140] // Simplify // N // Round);
(P5 = Limit[
Limit[{q1, q2, q3, q4, q5} /. {x1 -> 100, y1 -> 100, r -> 20},
x0 -> 240], y0 -> 80] // Simplify // N // Round);
line[P_] := (P[[1, 1]] - P[[2, 1]]) y + P[[2, 1]] P[[1, 2]] -
P[[1, 1]] P[[2, 2]] + x (P[[2, 2]] - P[[1, 2]])
lines[P_] := {line@P[[{1, 3}]], line@P[[{3, 5}]], line@P[[{5, 2}]],
line@P[[{2, 4}]], line@P[[{4, 1}]]}
pc01 = lines[P1];
pc02 = lines[P2];
pc03 = lines[P3];
pc04 = lines[P4];
pc05 = lines[P5];
innerQ[rp_, pc_] :=
Not[(pc[[1]] /. rp) >= 0 && (pc[[3]] /. rp) >= 0] &&
Not[(pc[[1]] /. rp) >= 0 && (pc[[4]] /. rp) >= 0] &&
Not[(pc[[2]] /. rp) >= 0 && (pc[[4]] /. rp) >= 0] &&
Not[(pc[[2]] /. rp) >= 0 && (pc[[5]] /. rp) >= 0] &&
Not[(pc[[3]] /. rp) >= 0 && (pc[[5]] /. rp) >= 0]
testQ[pc01_] :=
Not[(pc01[[1]]) >= 0 && (pc01[[3]]) >= 0] &&
Not[(pc01[[1]]) >= 0 && (pc01[[4]]) >= 0] &&
Not[(pc01[[2]]) >= 0 && (pc01[[4]]) >= 0] &&
Not[(pc01[[2]]) >= 0 && (pc01[[5]]) >= 0] &&
Not[(pc01[[3]]) >= 0 && (pc01[[5]]) >= 0]
Print[testQ@pc01 // CForm]
Print[""]
Print[testQ@pc02 // CForm]
Print[""]
Print[testQ@pc03 // CForm]
Print[""]
Print[testQ@pc04 // CForm]
Print[""]
Print[testQ@pc05 // CForm]
上面这段代码直接输出五个五角星区域的逻辑判断为C/C++代码形式,几乎不用什么修改。唯一的缺点是太长了。把它们OR(||)起来就是GR函数中需要的部分。
修改好的完整的C++代码我是这样弄的:
// NOTE: compile with g++ filename.cpp -std=c++11
#include <iostream>
#include <cmath>
#include <cstdlib>
#define DIM1 600
#define DIM2 400
#define DM1 (DIM1-1)
#define DM2 (DIM2-1)
#define _sq(x) ((x)*(x)) // square
#define _cb(x) abs((x)*(x)*(x)) // absolute value of cube
#define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root
unsigned char GR(int,int);
unsigned char BL(int,int);
unsigned char RD(int i,int j){
// YOUR CODE HERE
return 255;
}
unsigned char GR(int i,int j){
int x=i,y=j;
// YOUR CODE HERE
return (!(-9500+109*x-35*y>=0&&9234-114*y>=0)&&!(-9500+109*x-35*y>=0&&-18128+68*x+92*y>=0)&&!(-4528-68*x+92*y>=0&&-18128+68*x+92*y>=0)&&!(-4528-68*x+92*y>=0&&12300-109*x-35*y>=0)&&!(9234-114*y>=0&&12300-109*x-35*y>=0))||(!(3656+13*x-36*y>=0&&10074-30*x-24*y>=0)&&!(3656+13*x-36*y>=0&&-8188+38*x+2*y>=0)&&!(-8897+10*x+37*y>=0&&-8188+38*x+2*y>=0)&&!(-8897+10*x+37*y>=0&&2176-31*x+21*y>=0)&&!(10074-30*x-24*y>=0&&2176-31*x+21*y>=0))||(!(6374-28*x-25*y>=0&&5407-32*x+19*y>=0)&&!(6374-28*x-25*y>=0&&-1830+15*x-35*y>=0)&&!(-7784+37*x+4*y>=0&&-1830+15*x-35*y>=0)&&!(-7784+37*x+4*y>=0&&-3314+8*x+37*y>=0)&&!(5407-32*x+19*y>=0&&-3314+8*x+37*y>=0))||(!(5572-2*x-38*y>=0&&10043-37*x-10*y>=0)&&!(5572-2*x-38*y>=0&&-7044+36*x-13*y>=0)&&!(-10206+24*x+30*y>=0&&-7044+36*x-13*y>=0)&&!(-10206+24*x+30*y>=0&&456-21*x+31*y>=0)&&!(10043-37*x-10*y>=0&&456-21*x+31*y>=0))||(!(6562-17*x-34*y>=0&&8406-38*x+6*y>=0)&&!(6562-17*x-34*y>=0&&-4563+27*x-27*y>=0)&&!(-9758+34*x+17*y>=0&&-4563+27*x-27*y>=0)&&!(-9758+34*x+17*y>=0&&-1834-6*x+38*y>=0)&&!(8406-38*x+6*y>=0&&-1834-6*x+38*y>=0))?255:0;
}
unsigned char BL(int i,int j){
// YOUR CODE HERE
return 0;
}
void pixel_write(int,int);
FILE *fp;
int main(){
fp = fopen("MathPic.ppm","wb");
fprintf(fp, "P6\n%d %d\n255\n", DIM1, DIM2);
for(int j=0;j<DIM2;j++)
for(int i=0;i<DIM1;i++)
pixel_write(i,j);
fclose(fp);
return 0;
}
void pixel_write(int i, int j){
static unsigned char color[3];
color[0] = RD(i,j)&255;
color[1] = GR(i,j)&255;
color[2] = BL(i,j)&255;
fwrite(color, 1, 3, fp);
}
它的输出已经是一面五星红旗了。用XnView转ppm为png格式如下:
遗憾的是,我所修改的GR函数中的逻辑判断太长,远超一个twitter和140字符的要求。需要一些特殊技巧来压缩,目前我还做不到。
所以,我是来征集一个代码压缩技巧的。
……
问谁又能做到?
……
——Beyond
标签:c c++ mathematica csdn博客 设计图
原文地址:http://blog.csdn.net/stereohomology/article/details/46290597