Международный конкурс запутанного кода C
Международный конкурс запутанного кода C | |
---|---|
Статус | Активный |
Жанр | Конкурс кодирования |
Частота | Раз в полгода |
Годы активности | 1984–1996, 1998, 2000, 2001, 2004–2006, 2011–2015, 2018-2020 |
Открыт | 1984 |
Основатели | Лэндон Курт Нолл , Ларри Бассель |
Самый последний | 2020 |
Веб-сайт | www.ioccc.org |
International Obfuscated C Code Contest (сокращенно IOCCC ) — компьютерного программирования на наиболее креативно запутанный C. код конкурс Он проводится раз в полгода и описывается как «празднование синтаксической непрозрачности [C]». [1] Победный код 27-го конкурса, проведенного в 2020 году, был опубликован в июле 2020 года. [2] Предыдущие конкурсы проводились в 1984–1996, 1998, 2000, 2001, 2004–2006, 2011–2015 и 2018–2020 годах.
Заявки оцениваются анонимно судейской коллегией. Процесс судейства описан в правилах конкурса. [3] и состоит из отборочных туров. По традиции информация об общем количестве заявок на каждый конкурс не приводится. Заявкам-победителям присваивается категория, например «Наихудшее злоупотребление препроцессором C » или «Наиболее хаотичное поведение», а затем они объявляются на официальном сайте IOCCC. В конкурсе говорится, что объявление на сайте IOCCC является наградой за победу.
История
[ редактировать ]IOCCC была основана Лэндоном Куртом Ноллом и Ларри Басселем в 1984 году, когда они работали в группе портирования Genix компании National Semiconductor. Идея конкурса возникла после того, как они сравнили друг с другом заметки о каком-то плохо написанном коде, который им пришлось исправить, в частности о оболочке Bourne , которая использовала макросы для эмуляции синтаксиса ALGOL 68 , и о глючной версии Finger для BSD. [4] Сам конкурс стал темой вопроса викторины на Computer Bowl 1993 года. [5] После пятилетнего перерыва, начавшегося в 2006 году, конкурс возобновился в 2011 году. [6]
По сравнению с другими соревнованиями по программированию, IOCCC описывается Майклом Суэйном , редактором журнала Dr. Dobb's Journal , как «не столь уж серьезное» . [7]
Правила
[ редактировать ]Ежегодно правила конкурса публикуются на сайте IOCCC. Все материалы публикуются под лицензией Creative Commons BY-SA 3.0 Unported. [8] Правила меняются из года в год и публикуются вместе с набором инструкций, которые пытаются передать дух правил.
Взлом правил конкурса — традиция. - Лэндон Курт Нолл, 2011 г. [6]
Правила часто намеренно содержат лазейки, которые участникам предлагается находить и злоупотреблять. [3] Заявки, в которых используются лазейки, могут привести к изменению правил конкурса следующего года. [3]
Использованы запутывания
[ редактировать ]В записях часто используются странные или необычные приемы, такие как использование препроцессора C для выполнения действий, для которых он не предназначен (в некоторых случаях «эффектно», по словам доктора Доббса , [9] с одной записью, создающей 11-битное ALU в препроцессоре C [10] ), или избегать часто используемых конструкций языка программирования C в пользу гораздо более непонятных способов достижения того же самого.
Вклады включали исходный код, отформатированный так, чтобы он напоминал изображения, текст и т. д. в стиле ASCII , переопределения препроцессора, чтобы сделать код более трудным для чтения, и самомодифицирующийся код . В течение нескольких лет подавалась запись, требующая нового определения некоторых правил на следующий год. Это считается высокой честью. Примером может служить самая короткая в мире самовоспроизводящаяся программа . Запись представляла собой программу, предназначенную для вывода собственного исходного кода и не имевшую 0 байт исходного кода. Когда программа запустилась, она вывела ноль байтов, что соответствует ее исходному коду. [11]
Стремясь довести запутывание до крайности, участники конкурса создали программы, которые обходят стандарты C или приводят к конструкциям, которые запускают редко используемые комбинации путей кода в компиляторах. В результате некоторые из прошлых записей могут не компилироваться напрямую в современном компиляторе, а некоторые могут вызывать сбои.
Примеры
[ редактировать ]В рамках ограничения размера кода всего в несколько килобайт участникам удалось сделать сложные вещи — победителем 2004 года стала операционная система. [12]
Toledo Nanochess
[ редактировать ]Toledo Nanochess — это шахматный движок, созданный мексиканским разработчиком программного обеспечения Оскаром Толедо Гутьерресом, пятикратным победителем IOCCC. В соответствии с правилами IOCCC его длина составляет 1255 символов. Автор утверждает, что это самая маленькая в мире шахматная программа, написанная на языке C.
исходный код Toledo Nanochess и других движков. Доступен [13] Потому что Toledo Nanochess основана на победной игре Толедо на 18-м IOCCC (Лучшая игра). [14] ), оно сильно запутано . [15]
2 февраля 2014 года автор опубликовал книгу Toledo Nanochess: The commented source code , которая содержит полностью прокомментированный исходный код. [16]
По состоянию на 7 февраля 2010 года это, по всей видимости, один из двух шахматных движков, написанных на языке C размером менее 2 килобайт и способных выполнять полноценные шахматные ходы, наряду с Micro-Max голландского физика Герберта Мюллера. преодолела барьер в 1 килобайт. В 2014 году Super Micro Chess [17] – производная от Micro-Max – всего 760 символов (включая пробелы и новые строки). [18] Существует также уменьшенная версия движка Толедо, Toledo Picochess , состоящая из 944 непустых символов.
Отрывок исходного кода
B,i,y,u,b,I[411],*G=I,x=10,z=15,M=1e4;X(w,c,h,e,S,s){int t,o,L,E,d,O=e,N=-M*M,K
=78-h<<x,p,*g,n,*m,A,q,r,C,J,a=y?-x:x;y^=8;G++;d=w||s&&s>=h&&v 0,0)>M;do{_ o=I[
p=O]){q=o&z^y _ q<7){A=q--&2?8:4;C=o-9&z?q["& .$ "]:42;do{r=I[p+=C[l]-64]_!w|p
==w){g=q|p+a-S?0:I+S _!r&(q|A<3||g)||(r+1&z^y)>9&&q|A>2){_ m=!(r-2&7))P G[1]=O,
K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);Z n<=t){L=r?l[r&7]*9-189-h-q:0 _ s)L
+=(1-q?l[p/x+5]-l[O/x+5]+l[p%x+6]*-~!q-l[O%x+6]+o/16*8:!!m*9)+(q?0:!(I[p-1]^n)+
!(I[p+1]^n)+l[n&7]*9-386+!!g*99+(A<2))+!(E^y^9)_ s>h||1<s&s==h&&L>z|d){p[I]=n,O
[I]=m?*g=*m,*m=0:g?*g=0:0;L-=X(s>h|d?0:p,L-N,h+1,G[1],J=q|A>1?0:p,s)_!(h||s-1|B
-O|i-n|p-b|L<-M))P y^=8,u=J;J=q-1|A<7||m||!s|d|r|o<z||v 0,0)>M;O[I]=o;p[I]=r;m?
*m=*g,*g=0:g?*g=9^y:0;}_ L>N){*G=O _ s>1){_ h&&c-L<0)P L _!h)i=n,B=O,b=p;}N=L;}
n+=J||(g=I+p,m=p<O?g-3:g+2,*m<z|m[O-p]||I[p+=p-O]);}}}}Z!r&q>2||(p=O,q|A>2|o>z&
!r&&++C*--A));}}}Z++O>98?O=20:e-O);P N+M*M&&N>-K+1924|d?N:0;}main(){Z++B<121)*G
++=B/x%x<2|B%x<2?7:B/x&4?0:*l++&31;Z B=19){Z B++<99)putchar(B%x?l[B[I]|16]:x)_
x-(B=F)){i=I[B+=(x-F)*x]&z;b=F;b+=(x-F)*x;Z x-(*G=F))i=*G^8^y;}else v u,5);v u,
1);}}
Пи
[ редактировать ]Ниже приведена запись 1988 года, в которой число «пи» вычисляется по площади его тела : [19]
#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_
_-_-_-_
}
(Эта запись была написана на K&R C ; без некоторых изменений она не работает корректно в ANSI C. [20] )
Симулятор полета
[ редактировать ]Другим примером является следующий авиасимулятор, победитель IOCCC 1998 года: [21] как указано и описано в книге «Рассчитываемые ставки: компьютеры, азартные игры и математическое моделирование для победы» (2001). [22] и показано ниже:
#include <math.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
double L ,o ,P
,_=dt,T,Z,D=1,d,
s[999],E,h= 8,I,
J,K,w[999],M,m,O
,n[999],j=33e-3,i=
1E3,r,t, u,v ,W,S=
74.5,l=221,X=7.26,
a,B,A=32.2,c, F,H;
int N,q, C, y,p,U;
Window z; char f[52]
; GC k; main(){ Display*e=
XOpenDisplay( 0); z=RootWindow(e,0); for (XSetForeground(e,k=XCreateGC (e,z,0,0),BlackPixel(e,0))
; scanf("%lf%lf%lf",y +n,w+y, y+s)+1; y ++); XSelectInput(e,z= XCreateSimpleWindow(e,z,0,0,400,400,
0,0,WhitePixel(e,0) ),KeyPressMask); for(XMapWindow(e,z); ; T=sin(O)){ struct timeval G={ 0,dt*1e6}
; K= cos(j); N=1e4; M+= H*_; Z=D*K; F+=_*P; r=E*K; W=cos( O); m=K*W; H=K*T; O+=D*_*F/ K+d/K*E*_; B=
sin(j); a=B*T*D-E*W; XClearWindow(e,z); t=T*E+ D*B*W; j+=d*_*D-_*F*E; P=W*E*B-T*D; for (o+=(I=D*W+E
*T*B,E*d/K *B+v+B/K*F*D)*_; p<y; ){ T=p[s]+i; E=c-p[w]; D=n[p]-L; K=D*m-B*T-H*E; if(p [n]+w[ p]+p[s
]== 0|K <fabs(W=T*r-I*E +D*P) |fabs(D=t *D+Z *T-a *E)> K)N=1e4; else{ q=W/K *4E2+2e2; C= 2E2+4e2/ K
*D; N-1E4&& XDrawLine(e ,z,k,N ,U,q,C); N=q; U=C; } ++p; } L+=_* (X*t +P*M+m*l); T=X*X+ l*l+M *M;
XDrawString(e,z,k ,20,380,f,17); D=v/l*15; i+=(B *l-M*r -X*Z)*_; for(; XPending(e); u *=CS!=N){
XEvent z; XNextEvent(e ,&z);
++*((N=XLookupKeysym
(&z.xkey,0))-IT?
N-LT? UP-N?& E:&
J:& u: &h); --*(
DN -N? N-DT ?N==
RT?&u: & W:&h:&J
); } m=15*F/l;
c+=(I=M/ l,l*H
+I*M+a*X)*_; H
=A*r+v*X-F*l+(
E=.1+X*4.9/l,t
=T*m/32-I*T/24
)/S; K=F*M+(
h* 1e4/l-(T+
E*5*T*E)/3e2
)/S-X*d-B*A;
a=2.63 /l*d;
X+=( d*l-T/S
*(.19*E +a
*.64+J/1e3
)-M* v +A*
Z)*_; l +=
K *_; W=d;
sprintf(f,
"%5d %3d"
"%7d",p =l
/1.7,(C=9E3+
O*57.3)%0550,(int)i); d+=T*(.45-14/l*
X-a*130-J* .14)*_/125e2+F*_*v; P=(T*(47
*I-m* 52+E*94 *D-t*.38+u*.21*E) /1e2+W*
179*v)/2312; select(p=0,0,0,0,&G); v-=(
W*F-T*(.63*m-I*.086+m*E*19-D*25-.11*u
)/107e2)*_; D=cos(o); E=sin(o); } }
Для компиляции этой программы в системе Linux требуется следующая командная строка: [21]
cc banks.c -o banks -DIT=XK_Page_Up -DDT=XK_Page_Down \ -DUP=XK_Up -DDN=XK_Down -DLT=XK_Left -DRT=XK_Right \ -DCS=XK_Return -Ddt=0.02 -lm -lX11 -L/usr/X11R6/lib
Чтобы запустить двоичный файл ( banks
) он должен быть снабжен .sc
файл пейзажа через stdin
вход: [21]
cat pittsburgh.sc | ./banks
Акари
[ редактировать ]Ниже приведена запись 2011 года, в которой уменьшено разрешение ascii-изображения Дона Янга: [23]
/*
+
+
+
+
[ >i>n[t
*/ #include<stdio.h>
/*2w0,1m2,]_<n+a m+o>r>i>=>(['0n1'0)1;
*/int/**/main(int/**/n,char**m){FILE*p,*q;int A,k,a,r,i/*
#uinndcelfu_dset<rsitcdti_oa.nhs>i/_*/;char*d="P%" "d\n%d\40%d"/**/
"\n%d\n\00wb+",b[1024],y[]="yuriyurarararayuruyuri*daijiken**akkari~n**"
"/y*u*k/riin<ty(uyr)g,aur,arr[a1r2a82*y2*/u*r{uyu}riOcyurhiyua**rrar+*arayra*="
"yuruyurwiyuriyurara'rariayuruyuriyuriyu>rarararayuruy9uriyu3riyurar_aBrMaPrOaWy^?"
"*]/f]`;hvroai<dp/f*i*s/<ii(f)a{tpguat<cahfaurh(+uf)a;f}vivn+tf/g*`*w/jmaa+i`ni("/**
*/"i+k[>+b+i>++b++>l[rb";int/**/u;for(i=0;i<101;i++)y[i*2]^="~hktrvg~dmG*eoa+%squ#l2"
":(wn\"1l))v?wM353{/Y;lgcGp`vedllwudvOK`cct~[|ju {stkjalor(stwvne\"gt\"yogYURUYURI"[
i]^y[i*2+1]^4;/*!*/p=(n>1&&(m[1][0]-'-'||m[1][1] !='\0'))?fopen(m[1],y+298):stdin;
/*y/riynrt~(^w^)],]c+h+a+r+*+*[n>)+{>f+o<r<(-m] =<2<5<64;}-]-(m+;yry[rm*])/[*
*/q=(n<3||!(m[2][0]-'-'||m[2][1]))?stdout /*]{ }[*/:fopen(m[2],d+14);if(!p||/*
"]<<*-]>y++>u>>+r >+u+++y>--u---r>++i+++" <)< ;[>-m-.>a-.-i.++n.>[(w)*/!q/**/)
return+printf("Can " "not\x20open\40%s\40" "" "for\40%sing\n",m[!p?1:2],!p?/*
o=82]5<<+(+3+1+&.(+ m +-+1.)<)<|<|.6>4>-+(> m- &-1.9-2-)-|-|.28>-w-?-m.:>([28+
*/"read":"writ");for ( a=k=u= 0;y[u]; u=2 +u){y[k++ ]=y[u];}if((a=fread(b,1,1024/*
,mY/R*Y"R*/,p/*U*/)/* R*/ )>/*U{ */ 2&& b/*Y*/[0]/*U*/=='P' &&4==/*"y*r/y)r\}
*/sscanf(b,d,&k,& A,& i, &r)&& ! (k-6&&k -5)&&r==255){u=A;if(n>3){/*
]&<1<6<?<m.-+1>3> +:+ .1>3+++ . -m-) -;.u+=++.1<0< <; f<o<r<(.;<([m(=)/8*/
u++;i++;}fprintf (q, d,k, u >>1,i>>1,r);u = k-5?8:4;k=3;}else
/*]>*/{(u)=/*{ p> >u >t>-]s >++(.yryr*/+( n+14>17)?8/4:8*5/
4;}for(r=i=0 ; ;){u*=6;u+= (n>3?1:0);if (y[u]&01)fputc(/*
<g-e<t.c>h.a r -(-).)8+<1. >;+i.(<)< <)+{+i.f>([180*/1*
(r),q);if(y[u ]&16)k=A;if (y[u]&2)k--;if(i/*
("^w^NAMORI; { I*/==a/*" )*/){/**/i=a=(u)*11
&255;if(1&&0>= (a= fread(b,1,1024,p))&&
")]i>(w)-;} { /i-f-(-m--M1-0.)<{"
[ 8]==59/* */ )break;i=0;}r=b[i++]
;u+=(/**>> *..</<<<)<[[;]**/+8&*
(y+u))?(10- r?4:2):(y[u] &4)?(k?2:4):2;u=y[u/*
49;7i\(w)/;} y}ru\=*ri[ ,mc]o;n}trientuu ren (
*/]-(int)'`';} fclose( p);k= +fclose( q);
/*] <*.na/m*o{ri{ d;^w^;} }^_^}}
" */ return k- -1+ /*\' '-`*/
( -/*}/ */0x01 ); {;{ }}
; /*^w^*/ ;}
Если программа запускается с использованием собственного исходного кода в качестве входных данных, результат будет следующим:
[root@host ~]# ./akari akari.c
int
*w,m,_namori=('n');
#include<stdio.h>/*;hrd"% dnd4%"*/
/**/int(y),u,r[128*2/*{y}icuhya*rr*rya=
*/];void/**/i(){putchar(u);}int/**/main(/*
"(n"l)?M5{YlcpvdluvKct[j skao(tve"t"oYRYR"
*/int(w),char**n){for(m =256;--m;r[m]/*
"<*]y+u>r>u+y-u-r+i+" ) ;>m.a.i+n>()/q*/
=25<(31&( m -1))||64-( m &192)||2>w?m:(2+
m/*"*,/U// R/)/U * & /Y/0/U/=P &=/"*/)\
&16?m-13 : 13+ m) ;u=+10 ;for(;(m=/*
*>/()/{ p u t-s +(yy*+ n1>7?/:*/
getchar ())+1 ;i() ){if(10/*
"wNMR;{ I/=/" )/{*/==u*1
)i(); if(m-10){
u=/*> *./<)[;*/8*
4;i(); }u=r[ m];}return(
* *n/*{i ;w; }_}
( -*/ *00 ) ; }
[root@host ~]# ./akari akari.c > ./akari.small
[root@host ~]# ./akari ./akari.small
wm_aoi(n)
/*ity,,[2*/{}char*y=
(")M{lpduKtjsa(v""YY"
"*yuruyuri") ;main(/*
/",U/ R)U* Y0U= ="/\
*/){puts (y+ 17/*
"NR{I=" ){/=*
=* */);/*
**/{ ;;}}
[root@host ~]#
[root@host ~]# ./akari ./akari.small > ./akari.smaller
[root@host ~]# ./akari ./akari.smaller
main
(){puts("Y"
"U RU YU "\
"RI" )/*
*/ ;}
[root@host ~]#
См. также
[ редактировать ]Примечания и ссылки
[ редактировать ]- ^ Палмер, Джефф (1 ноября 2004 г.). «За пределами командной строки» . Мир ПК Новая Зеландия . Архивировано из оригинала 10 февраля 2013 года . Проверено 7 апреля 2013 г.
- ^ «Предыдущие победители IOCCC со спойлерами» . МОККЦ . Проверено 1 мая 2023 г.
- ^ Jump up to: а б с «Руководство 2015 года» (обычный текст) . МОККЦ. 2015 . Проверено 1 мая 2023 г.
- ^ «Часто задаваемые вопросы» . МОККЦ . Проверено 1 мая 2023 г.
- ^ «Высшие руководители не могут правильно рассчитывать» . Сан-Хосе Меркьюри Ньюс , Калифорния. 15 мая 1993 г. с. 1А. Через Ньюсбанк . (требуется подписка)
- ^ Jump up to: а б Джексон, Иоав (15 ноября 2011 г.). «Возвращение конкурса запутанного кода» . Мир ПК . Проверено 1 мая 2023 г.
- ^ Суэйн, Майкл (1 мая 2008 г.). «Конкурс должен быть» . Журнал доктора Добба . Проверено 1 мая 2023 г.
- ^ Домашняя страница IOCCC, нижний колонтитул и в каждом файлеhint.txt.
- ^ Спинеллис, Диомидис (5 октября 2006 г.). «Уточнение кода» . Журнал доктора Добба . Проверено 1 мая 2023 г.
- ^ IOCCC 2004 – Лучшее злоупотребление CPP IOCCC. Проверено 1 мая 2023 г.
- ^ «smr.hint» (обычный текст) . МОККЦ. 1994 . Проверено 16 сентября 2006 г.
- ^ «gavin.hint3» (обычный текст) . МОККЦ. 2004 . Проверено 1 мая 2023 г.
- ^ «Толедо Наношесс и Толедо Пикошесс» .
- ^ «Победители: авторы победивших работ IOCCC» .
- ^ «Частично деобфусцированная версия Nanochess» . Гитхаб . Проверено 1 мая 2023 г.
- ^ Толедо Гутьеррес, Оскар (2014). Toledo Nanochess: Прокомментированный исходный код . Лулу . ISBN 978-1-304-86437-6 .
- ^ «Super Micro Chess Engine — Домашняя страница — Чрезвычайно компактный исходный код C и размер исполняемой программы» . smmax.sourceforge.net .
- ^ «Супер Микро ФИДЕ 760» .
- ^ "westley.c" , 5-й Международный конкурс запутанного кода C, 1988 г.
- ^ используя gcc, скомпилируйте с помощью следующей командной строки:
gcc -traditional-cpp -o r r.c
илиgcc -E r.c | sed 's/- -/--/g' > r2.c ; gcc -o r2 r2.c
(Исходный файлr.c
) [ оригинальное исследование? ] - ^ Jump up to: а б с Блог Карла Бэнкса: Симулятор полета IOCCC . blog.aerojockey.com. Проверено 1 мая 2023 г.
- ^ Скиена, Стивен (2001). Расчетные ставки: компьютеры, азартные игры и математическое моделирование для победы . Математическая ассоциация Америки. стр. 152 , 153. ISBN. 978-0521009621 .
- ^ «Победители: авторы победивших работ IOCCC» . www.ioccc.org . Проверено 1 мая 2023 г.