สร้างโปรแกรม C แบบสั้นที่ใช้เวลานานในการรวบรวม gcc รายการจะถูกทำคะแนนโดยกำหนดเวลาการรวบรวมจากนั้นลบเวลารวบรวมของโปรแกรมอ้างอิง
กฎระเบียบ
- คุณลักษณะภาษา C หรือส่วนขยาย gcc ใด ๆ
- gcc 4.2.1
สร้างโปรแกรม C แบบสั้นที่ใช้เวลานานในการรวบรวม gcc รายการจะถูกทำคะแนนโดยกำหนดเวลาการรวบรวมจากนั้นลบเวลารวบรวมของโปรแกรมอ้างอิง
กฎระเบียบ
คำตอบ:
#define a "xxxxxxxxxxx"
#define b a a a a a a a
#define c b b b b b b b
#define d c c c c c c c
#define e d d d d d d d
#define f e e e e e e e
#define g f f f f f f f
#define h g g g g g g g
#define i h h h h h h h
#define j i i i i i i i
z=j;
main(){char*z=j;}
ทำให้โปรแกรมนี้เป็น c ที่ถูกต้อง
/Zm
จะแก้ไขได้
ทั้งคำตอบของ Charlieและคนก่อนหน้าของฉันทำงานบนหลักการของการให้ pre-processor เขียนโค้ดจำนวนมากแต่พวกเขาส่วนใหญ่ใช้ pre-processor ตัวเอง lexer (ความคิดที่ดีเนื่องจากขั้นตอนนี้ช้าแบบดั้งเดิม) และ parser ฉันก็พยายามที่จะเพิ่มประสิทธิภาพและขั้นตอนการสร้างรหัส แต่ก็เห็นได้ชัดว่าไม่ได้รับมาก
เมื่อคิดถึงว่าคอมไพเลอร์ทั่วไปทำงานอย่างไรฉันก็ตระหนักว่าเราไม่ได้ให้โค้ดเกี่ยวกับตารางสัญลักษณ์ที่เกี่ยวข้องกับสิ่งที่ต้องทำ รายการนี้เป็นความพยายามที่จะแก้ไข มันควรจะเตือนให้รำลึกถึงการวางแนวของวัตถุพื้นฐานในการใช้งาน c แต่ไม่ได้ทำอะไรที่น่าสนใจ: justuses เทคนิคการขยายตัวประมวลผลล่วงหน้าเพื่อประกาศและ trivially (และไม่ถูกต้อง) เริ่มต้นกลุ่มของวัตถุ วัตถุที่ใช้ชนิดที่ซับซ้อนบนขอบเขตหลายระดับทำให้เงาซึ่งกันและกันในการลบที่แตกต่างกัน มันควรจะให้ตารางสัญลักษณ์เป็นผลงานที่แท้จริง
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
// Exercise the symbol table mechanism of the compiler in an effort to
// take a unreasonable about of time compiling
#define PTR(T) T*
#define CONST(T) T const
#define FUNC(NAME,RTYPE,ARG) RTYPE NAME(ARG)
#define FPTR(NAME,RTYPE,ARG) FUNC((*NAME),RTYPE,ARG)
// Forward decalration of repeated OO method pointers
typedef void* (*cctor_ptr)(void*this, void*that, ...);
typedef void* (*dtor_ptr)(void*this);
// Assumes three var-args: sizeof(payload type), cctor, dtor
void* default_ctor(void*this, ...){
// Pull in variadac bits
va_list list;
va_start(list,this);
int size=va_arg(list,int);
cctor_ptr cctor=va_arg(list,cctor_ptr);
dtor_ptr dtor=va_arg(list,dtor_ptr);
va_end(list);
// process
if (!this) this = malloc(size);
if (this) {
memset(this,size,0);
/* various dodges to install the cctor and dtor in the write places */
}
return this;
}
// Copies the payload from that to this;
void* default_cctor(void*restrict this, void* restrict that, ...){
// Pull in variadac bits
va_list list;
va_start(list,that);
int size=va_arg(list,int);
cctor_ptr cctor=va_arg(list,cctor_ptr);
dtor_ptr dtor=va_arg(list,dtor_ptr);
va_end(list);
// process
if (!this) this = malloc(size);
if (this) {
memcpy(this,that,size);
/* various dodges to install the cctor and dtor in the write places */
}
return this;
}
// Assumes that his was allocated with malloc, does not use varargs
void* default_dtor(void*this, ...){
free(this);
return NULL;
};
#define DECLARE_STRUCT(N) struct S##N##_s
#define TYPEDEF_ACCESSOR(N,T) typedef FPTR(f##N##_ptr,CONST(PTR(T)),PTR(CONST(struct S##N##_s)))
#define TYPEDEF_STRUCT(N,T) typedef struct S##N##_s {PTR(T)p; cctor_ptr cctor; dtor_ptr dtor; f##N##_ptr f##N;} S##N
#define OO_STRUCT(N,T) DECLARE_STRUCT(N); TYPEDEF_ACCESSOR(N,T); TYPEDEF_STRUCT(N,T)
OO_STRUCT(1,char);
OO_STRUCT(2,int);
OO_STRUCT(3,double*);
OO_STRUCT(4,S3);
OO_STRUCT(5,S4);
OO_STRUCT(6,S5);
OO_STRUCT(7,S6);
OO_STRUCT(8,S7);
#define SUBSCOPE(A) { \
S1*A##1=default_ctor(NULL,sizeof(char),default_cctor,default_dtor); \
S2 A##2; default_ctor(&A##2,sizeof(int),default_cctor,default_dtor); \
S2*A##3=default_ctor(NULL,sizeof(double*),default_cctor,default_dtor); \
S8 A##5; default_ctor(&A##5,sizeof(S4),default_cctor,default_dtor); \
S6 A##6; default_ctor(&A##6,sizeof(S5),default_cctor,default_dtor); \
S8*A##8=default_ctor(NULL,sizeof(S7),default_cctor,default_dtor); \
}
#define SUBSCOPE2(A,B) { \
S2*B##5=default_ctor(NULL,sizeof(S4),default_cctor,default_dtor); \
S4 A##7; default_ctor(&A##7,sizeof(S6),default_cctor,default_dtor); \
SUBSCOPE(A) SUBSCOPE(B); \
}
#define SUBSCOPE6(A,B,C) { \
S2*A##3=default_ctor(NULL,sizeof(double*),default_cctor,default_dtor); \
S2 B##2; default_ctor(&B##2,sizeof(int),default_cctor,default_dtor); \
S4*C##4=NULL; \
SUBSCOPE2(A,C) SUBSCOPE2(B,C) SUBSCOPE2(A,B); \
}
#define SUBSCOPE24(A,B,C,D) { \
S1*D##1=default_ctor(NULL,sizeof(char),default_cctor,default_dtor); \
S2 C##2; default_ctor(&C##2,sizeof(int),default_cctor,default_dtor); \
S2*B##3=default_ctor(NULL,sizeof(double*),default_cctor,default_dtor); \
S4 A##4; default_ctor(&A##4,sizeof(S3),default_cctor,default_dtor); \
SUBSCOPE6(A,B,C) SUBSCOPE6(A,B,D) SUBSCOPE6(A,C,D) SUBSCOPE6(B,C,D); \
}
#define SUBSCOPE120(A,B,C,D,E) { \
S5*A##5=default_ctor(NULL,sizeof(S4),default_cctor,default_dtor); \
S6*A##6=default_ctor(NULL,sizeof(S5),default_cctor,default_dtor); \
S8 A##8; default_ctor(&A##8,sizeof(S7),default_cctor,default_dtor); \
SUBSCOPE24(A,B,C,D) SUBSCOPE24(A,B,C,E) SUBSCOPE24(A,B,D,E); \
SUBSCOPE24(A,C,D,E) SUBSCOPE24(B,C,D,E); \
}
#define SUBSCOPE720(A,B,C,D,E,F) { \
S5 A##5; default_ctor(&A##5,sizeof(S4),default_cctor,default_dtor); \
S6 A##6; default_ctor(&A##6,sizeof(S5),default_cctor,default_dtor); \
S8*A##8=default_ctor(NULL,sizeof(S7),default_cctor,default_dtor); \
SUBSCOPE120(A,B,C,D,E) SUBSCOPE120(A,B,C,D,F) SUBSCOPE120(A,B,C,E,F); \
SUBSCOPE120(A,B,D,E,F) SUBSCOPE120(A,C,D,E,F) SUBSCOPE120(B,C,D,E,F); \
}
int main(){
S4 s4;
SUBSCOPE720(A,B,C,D,E,F)
}
เวลารวบรวมในเครื่องของฉันเกินกว่า 4 วินาที-O3
และมากกว่า 1 วินาทีโดยไม่มีการปรับให้เหมาะสม
เห็นได้ชัดว่าขั้นตอนต่อไปคือการดำเนินการ OO ให้เสร็จสำหรับคลาส BCD และทำการคำนวณ pi อีกครั้งโดยใช้เพื่อให้ฉันได้รับผลกระทบทั้งสองอย่างเต็มที่
นี่คือ riff ของชุดรูปแบบ exponential-preprocessor-expansion ซึ่งทำสิ่งที่น่าสนใจน้อยที่สุด: คำนวณสองการประมาณเพื่อ pi ตามวิธีอนุกรมและเปรียบเทียบกับทั้งค่าในmath.h
และคาถาปกติ
Ungolfed
#include <math.h>
#include <stdio.h>
// Some random bits we'll need
#define MINUSONODD(n) (n%2?-1:+1)
#define TWON(n) (2*(n))
#define NPLUSONE(n) ((n)+1)
#define TWONPLUSONE(n) NPLUSONE(TWON(n))
#define FACT(n) (tgamma(NPLUSONE(n)))
// The Euler series
// 2^(2n) * (n!)^2 z^(2n+1)
// atan(z) = \sum_n=0^\infty --------------- * ---------------
// (2n+1)! (1 + z^2)^(n+1)
#define TERMEULER(n,z) (pow(2,TWON(n))* \
FACT(n)*FACT(n)* \
pow((z),TWONPLUSONE(n))/ \
FACT(TWONPLUSONE(n)) / \
pow((1+z*z),NPLUSONE(n)) )
// The naive version
// (-1)^n * z^(2n+1)
// atan(z) = \sum_n=0^\infty -----------------
// 2n + 1
#define TERMNAIVE(n,z) (MINUSONODD(n)*pow(z,TWONPLUSONE(n))/TWONPLUSONE(n))
// Define a set of bifruncations of the sum
#define N2TERMS(n,z,ALG) (TERM##ALG(TWON(n),(z)) + TERM##ALG(TWONPLUSONE(n),(z)))
#define N4TERMS(n,z,ALG) (N2TERMS(TWON(n),(z),ALG)+N2TERMS(TWONPLUSONE(n),(z),ALG))
#define N8TERMS(n,z,ALG) (N4TERMS(TWON(n),(z),ALG)+N4TERMS(TWONPLUSONE(n),(z),ALG))
#define N16TERMS(n,z,ALG) (N8TERMS(TWON(n),(z),ALG)+N8TERMS(TWONPLUSONE(n),(z),ALG))
#define N32TERMS(n,z,ALG) (N16TERMS(TWON(n),(z),ALG)+N16TERMS(TWONPLUSONE(n),(z),ALG))
// Sum the fist 32*2+16 = 80 terms of a series...
#define PARTIALSUM(z,ALG) N32TERMS(0,(z),ALG)+N32TERMS(1,(z),ALG)+N16TERMS(4,(z),ALG)
int main(void){
const double PI_TRAD = 4.0L * atan(1.0);
const double PI_NAIVE = 4.0L * PARTIALSUM(0.999999L,NAIVE);
const double PI_EULER = 4.0L * PARTIALSUM(0.999999L,EULER);
printf("pi (math.h) = %10.8f\n",M_PI);
printf("pi (trad.) = %10.8f\n",PI_TRAD);
printf("pi (NAIVE) = %10.8f\n",PI_NAIVE);
printf("pi (EULER) = %10.8f\n",PI_EULER);
}
สมมติว่าคุณกำลังใช้gcc
และglibc
และอาจหรืออาจจะไม่ทำงานกับข้อตกลงอื่น ๆ ใช้เวลาประมวลผลประมาณ 1.0-1.1 วินาที (ประเมินด้วยtime (1)
) เพื่อคอมไพล์ด้วย-03
1ใน MacBook 2.4 GHz Intel Core 2 Duo ของฉัน การคอมไพล์เริ่มต้นใช้เวลาประมวลผลประมาณ 0.4 วินาที
อนิจจาฉันไม่สามารถรับ gcc เพื่อประเมินอย่างใดอย่างหนึ่งpow
หรือtgamma
ตามเวลาคอมไพเลอร์ซึ่งจะช่วยได้จริงๆ
เมื่อคุณเรียกใช้ผลลัพธ์คือ:
pi (math.h) = 3.14159265
pi (trad.) = 3.14159265
pi (NAIVE) = 3.11503599
pi (EULER) = 3.14159065
ซึ่งแสดงให้เห็นว่าซีรีส์ไร้เดียงสาช้าแค่ไหน
1เพื่อให้ได้การพับและการกำจัดนิพจน์ที่คงที่มากที่สุดเท่าที่จะทำได้