1. 程式人生 > >用C++程式碼生成一面五星紅旗

用C++程式碼生成一面五星紅旗

原始問題的背景和描述

比賽基於下面的基礎程式碼 ,如果原始連結無法訪問,可以備用我的另一CSDN部落格中引用給出的程式碼。已提到,感興趣的是基於這個程式碼如何生成一面五星紅旗。

紅旗的設計圖如下,也在我的上一篇部落格搜尋給出過。
五星紅旗設計圖

計算和程式碼

首先,五星紅旗顏色簡單,只有紅色黃色兩種。從加法色(RGB)1的角度看,黃色就是紅色加綠色。所以,背景是紅色很單一,關鍵就是如何填充五角星區域內的綠色,即改寫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_] := {[email protected][[{1, 3}]], [email protected][[{3, 5}]], [email protected][[{5, 2}]], [email protected][[{2, 4}]], [email protected][[{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[[email protected] // CForm] Print[""] Print[[email protected] // CForm] Print[""] Print[[email protected] // CForm] Print[""] Print[[email protected] // CForm] Print[""] Print[[email protected] // CForm]

上面這段程式碼直接輸出五個五角星區域的邏輯判斷為C/C++程式碼形式,幾乎不用什麼修改。唯一的缺點是太長了。把它們邏輯並(OR,|| )起來就是GR函式中需要的部分2現在回頭再看上面這些Mathematica程式碼,感覺不但冗餘,而且拙劣;不過也能實現功能

修改好的完整的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);
}

它的輸出已經是一面五星紅旗了。用XnViewConvert.ppm.png格式如下:
final picture

遺憾的是,我所修改的GR函式中的邏輯判斷太長,遠超一個twitter和140字元的要求。單純把一些長的表示式用巨集定義的方式來壓縮,可行性很差:

unsigned char GR(int i,int j){
// YOUR CODE HERE
#define A 6562-17*i-34*j>=0
#define B 8406-38*i+6*j>=0
#define C -4563+27*i-27*j>=0
#define D -9758+34*i+17*j>=0
#define E -1834-6*i+38*j>=0
#define F -10206+24*i+30*j>=0
#define G 456-21*i+31*j>=0
#define H -10206+24*i+30*j>=0
#define I -7044+36*i-13*j>=0
#define J 10043-37*i-10*j>=0
#define K 5572-2*i-38*j>=0
#define L -9500+109*i-35*j>=0
#define M 9234-114*j>=0
#define N -18128+68*i+92*j>=0
#define O -4528-68*i+92*j>=0
#define P 12300-109*i-35*j>=0
#define Q 3656+13*i-36*j>=0
#define R 10074-30*i-24*j>=0
#define S -8188+38*i+2*j>=0
#define T -8897+10*i+37*j>=0
#define U 2176-31*i+21*j>=0
#define V 6374-28*i-25*j>=0
#define W 5407-32*i+19*j>=0
#define X -1830+15*i-35*j>=0
#define Y -7784+37*i+4*j>=0
#define Z -3314+8*i+37*j>=0
return (!(L&&M)&&!(L&&N)&&!(O&&N)&&!(O&&P)&&!(M&&P))||(!(Q&&R)&&!(Q&&S)&&!(T&&S)&&!(T&&U)&&!(R&&U))||(!(V&&W)&&!(V&&X)&&!(Y&&X)&&!(Y&&Z)&&!(W&&Z))||(!(K&&J)&&!(K&&I)&&!(F&&I)&&!(H&&G)&&!(J&&G))||(!(A&&B)&&!(A&&C)&&!(D&&C)&&!(D&&E)&&!(B&&E))?255:0;
}

需要一些特殊技巧來壓縮,目前我還做不到。或者能證明無法實現?

本來我還指望對五角星的邊界作一些近似和優化或者能夠把邏輯表示式簡化,從而實現”140”字元以內表達,後來做了些功課,發現非凸多邊形的情況下,進行邏輯判斷本來就是一個比較難的問題. 所以, 除非有超出當前這些限制的極其冷門的技巧,否則只能望推興嘆了.

現在我想到的基於凹多邊形卷繞數的演算法可以把字元進一步壓縮,但仍大於140*3,而且不容易剛好填入三個函式內

// NOTE: compile with g++ filename.cpp -std=c++11
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <vector>
//#include <functional>
#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

#define pi 3.14159
#define eps 2.02e-16
double arct(double x,double y){
    return abs(x)>eps?(x>eps?atan(y/x):(y>0?atan(y/x)+pi:atan(y/x)-pi)):(y>0?pi/2:-pi/2);
}

bool inQ(int i,int j,int* px){
    double art[5],aro[5];
    for(int k=0;k<5;k++){
        art[k]=arct((double)(px[k]-i),(double)(px[k+5]-j));//
    }
    double total=0.;
    for(int k=0;k<5;k++){
    aro[k]=art[(k+1)%5]-art[k];
        while(aro[k]<-pi) aro[k]+=pi;
        while(aro[k]>pi) aro[k]-=pi;
    total+=aro[k];
    }
    return abs(total)>0.5;
    };

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){
// YOUR CODE HERE
            int p1[10]={100, 135, 43, 157, 65, 40, 149, 81, 81, 149},
        p2[10]={184, 220, 183, 207, 205, 168, 181, 191, 161, 199},
        p3[10]={183, 208, 204, 185, 220, 50, 22, 59, 27, 42},
        p4[10]={221, 259, 229, 239, 252, 135, 133, 157, 120, 156},
        p5[10]={220, 254, 237, 231, 258,83, 66, 100, 62, 89};
    return inQ(i,j,p1)||inQ(i,j,p2)||inQ(i,j,p3)||inQ(i,j,p4)||inQ(i,j,p5)?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);
system("pause");
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);
}

所以,我是來徵集一個程式碼壓縮技巧的。

……
問誰又能做到?
……
——Beyond

  1. 【如果對“加法色”和“減法色”不瞭解也沒啥,直接查不同顏色對應的RGB值即可,黃色就是0xFFFF00;我寫這篇部落格犯的兩個錯誤之一就是把加減法搞錯,不過這個不影響結果】
  2. 【我寫這段部落格犯的兩個錯誤之二是,因為影象的座標y軸方向與五星紅旗通常的座標方向相反,進行座標變換時不小心,導致四個小五星都有一個角正背對著大五星!這是一個嚴重的錯誤,驚出了我一身冷汗。】來見識下我不小心弄出來的這種罕見的紅旗,不仔細看還真發現不了問題,慚愧這裡寫圖片描述

相關推薦

C++程式碼生成一面五星紅旗

原始問題的背景和描述 比賽基於下面的基礎程式碼 ,如果原始連結無法訪問,可以備用我的另一CSDN部落格中引用給出的程式碼。已提到,感興趣的是基於這個程式碼如何生成一面五星紅旗。 紅旗的設計圖如下,也在我的上一篇部落格搜尋給出過。 計算和程式碼

C#程式碼生成一個簡單的PDF檔案(轉)

using System; using System.IO; using System.Text; using System.Collections; namespace PDFGenerator { /// /// Application : Generation of PDF file from

C++程式碼代替記事本

新人第一次發文,請多多關照。(●'◡'●)   先說說這個程式的由來吧。 上學期做了C++的大作業,在其中用到了檔案流(讀檔案和寫檔案),當時的讀取方式是格式化讀取(從一個空格讀到下一空格,然後儲存讀到的資料),而且是對txt文件讀取,我便想到能否寫個程式來讀取文件中的全部內容

gsoap入門:C/C++程式碼生成及編譯--包含soapcpp2 -qname新增名稱空間後報錯的解決方法--可用

gsoap是什麼 先來一段百度百科,說說gsoap是什麼: gSOAP一種跨平臺的開源的C/C++軟體開發工具包。生成C/C++的RPC程式碼,XML資料繫結,對SOAP Web服務和其他應用形成高效的具體架構解析器,它們都受益於一個XML介面。 這個工具包提供了一個全面和透明的XML資料繫結解決方案,A

使用VisualStudio完成自動化C++程式碼生成和編譯工作(GacUI)

    GacUI終於進入製作dll的階段了。昨天上傳了一個新的工程,在Vczh Library++3.0(E:\Codeplex\vlpp\Workspace\Tools\Release\SideProjects\GacUI\GacUI.sln)。這裡面一共有三個工程,有兩個是工具,一個是dll。    為

3d數學基礎-映象矩陣和切變矩陣-C++程式碼實現

#include <iostream.h> #include <math.h> #include <assert.h> const float kPi = 3.1415926f; const float k2Pi = kPi*2.0f;

C程式碼簡要模擬實現一下RPC(遠端過程呼叫)並談談它在程式碼調測中的重要應用

        說明: 本文僅僅是一種模擬的RPC實現, 真正的RPC實現還是稍微有點複雜的。         我們來看看下面這個常見的場景: 在某系統中,我們要對某一函式進行調測, 但是, 很難很難構造出這個函式被呼叫的實際場景, 怎麼辦?         雖然很難構造

c++程式碼實現貪心演算法求解最短路徑問題

貪心演算法求解最短路徑問題: 假設演算法要處理下圖,需要把圖資料組織存放到相應的資料結構中。  這個是標頭檔案stdafx.h中的內容#pragma once #include <stdio.h> #include &

C++程式碼描繪UML中的 關聯 依賴 組合 聚合 泛化

UML的類圖關係分為: 關聯、聚合,組合、依賴、泛化(繼承)。而其中關聯又分為雙向關聯、單向關聯、自身關聯;下面就讓我們一起來看看這些關係究竟是什麼,以及它們的區別在哪裡。1、關聯雙向關聯: C1-C2:指雙方都知道對方的存在,都可以呼叫對方的公共屬性和方法。 使用ROSE

Java程式碼生成0-100隨機數,直到生成88為止,停止迴圈!

實操名稱:生成0-100隨機數,直到生成88為止,停止迴圈! 環境: jdk 1.8 作者:李遠遠 1.詳細程式碼如下: /** * 生成 0-100 隨機數,直到生成 88 為止,停止迴圈! * @author 李遠遠 * */ public clas

C#呼叫c程式碼生成的dll,報PInvoke 簽名與非託管的目標籤名不匹配

C# 在呼叫c程式碼生成的dll時,報錯:對 PInvoke 函式“TestJBIG!TestJBIG.JbigHelper::jbigDecode”的呼叫導致堆疊不對稱。原因可能是託管的 PInvoke 簽名與非託管的目標籤名不匹配。請檢查 PInvoke 簽名的呼叫約定

C程式碼寫貪吃蛇遊戲--按鍵控制蛇移動

通過按鍵控制蛇的移動,首先需要讀取按鍵,通過按鍵來控制。 通過百度後得知用kbhit(); 用一小段程式碼進行測試: 一直輸出Hello World,直到使用者按Esc結束 #include "stdafx.h" #include<st

c語言生成一個猜數遊戲

首先需要生成一個隨機數,c語言中用srand((unsigned int)(time(NULL))產生一個不可預見的隨機數序列,參考程式碼如下: #include <stdio.h> #

Dev c++工具將C程式碼生成dll檔案以及如何呼叫dll檔案

該篇文章是對工作中一個需求的總結,工作需求是要將C語言的函式介面,生成一個DLL檔案,讓labview呼叫。然後我嘗試用dev c++開發工具來實現這個功能,後來因為DLL生成了,但labview呼

C#程式碼執行一個程序

程式碼執行一個程序 使用語言:C# 環境:.net Framework 4.6.1 (當前使用) (貌似支援所有環境,我就不多說了) using System.Diagnostics; na

C# 傳送xml報文到友U8生成憑證系列二(基礎程式碼

上文我們詳細講解了u8voucher.xml、Web.config、U8EAI.asmx、EAIHandler.cs 等程式碼及xml報文格式及相關config配置等,接下來我們將講解Config、Route、Common 目錄下的類怎麼編寫的:config目錄下的檔案:ap

C#——程式碼生成UML圖

前言   由於需要,小編研究了一下如何用程式碼生成UML圖,以下就是小編的過程,非常的簡單。   開啟EA(Enterprise Architect),新建一個包,新建一個圖表,選中圖表,用ctrl

android 調c文件生成so庫並調

dem ges classes lib fault rms img div 節點 公司需要做一個sdk,裏面需要用到別人寫的c文件,第一次做,各種百度,各種學習,現在做一個小總結: 一、新建一個project:例 ExampleDemo, 包名為:com.demo.exam

C#+Selenium+ChromeDriver 生成我的咕咚跑步路線地圖

圖片 num element line text containe 分享 感覺 RR 先上結果:   之前 在公司業務中用過java+Selenium+ChromeDriver ,使用起來非常順手,可以完美模擬真實的用戶瀏覽行為。最近休息的時候想用C#也試一

Wings與parasoft c++ test在單元測試例自動生成能力的比對

RoCE 相同 c++ 比較 關心 分享 多少 自己 ××× 作為一個軟件測試培訓講師,主要側重在白盒測試培訓方面,尤其對C++test比較擅長。最近發現市面上跳出一款Wings工具,據說1分鐘可以自動生成100萬行測試代碼,性能方面大大超越C++ test,就想著抽空來×