IOCCC

Из Википедије, слободне енциклопедије

IOCCC (енгл. International Obfuscated C Code Contest) је такмичење на пољу програмирања, на коме је циљ написати што креативнији нејасан C код. Суштина је у писању неразумног и несхватљивог изворног кода са свим могућим злоупотребама правила писања у намери да се у што мање кода смести што комплекснији програм. Оснивачи такмичења су Landon Curt Noll и Larry Bassel, а такмичење се од године 1984. одржава редовно, са изузетком година 1997., 1999., 2002., 2003. Идеја потиче од веома нејасног кода који су ова два програмера у то време одржавали. Одлучили су да направе такмичење за најгори могући C код, и заиста: у оквиру ограничења од неколико килобајта, такмичари остварују разне ствари - победнички код на такмичењу 2004. године је постао оперативни систем.

Бројни примери се могу видети на IOCCC сајту.


Правила 2004 године[уреди]

Да би нам помогли око ширине посла, молимо вас да пратите следећа правила:

  1. Ваш код мора бити комплетан програм.
  2. Величина вашег програма мора бити <= 4096 килобајта. Број симбола, искључујући празнине (табулатор, размак, нову линију, formfeed, return (carriage return)), сваки ; { или } праћен са празнином или крајем фајла мора бити <= 2048 килобајта.
  3. Пријаве требају да буду извршене према упутствима на: http://www.ioccc.org/2004/submit. Напомена: Механизам за пријављивање ће бити доступан након 26. Јануара 2004, 00:00 UTC. Погледајте линк изнад за више информација.
  4. Ако је ваша пријава селектована као победничка, биће модификована према следећем:
    1. Ваше инструкције за компајлирање фајла ће бити смештене у makefile. Ако су ваше инструкције један makefile требало би да он буде портабилан и употребљив унутар једног главног makefile.
    2. Вашем коду ће бити промењено име према нашем избору (обично ваше презиме или anonymus) евентуално праћено са неким бројем и ".c".
    3. Ваша пријава ће бити компајлирана у фајл са горе наведеним именом без ".c". Ако ваша пријава захтева да build file постоји, наведите то у напоменама. Ваш makefile ће бити тако направљен да садржи потребне информације о овоме. Име овог фајла ће бити име вашег програма, евентуално праћено са неколико цифара и завршно са ".sh".
      У случају потребе достављене напомене уз вашу пријаву требају да садрже објашњење о токе како ваш код треба да буде измењен да би радио са новим именима фајлова.
  5. Сва три фајла: build file, ваш код и извршна верзија ће бити третирани као фајлови који се могу само читати (read only). Ако вашој пријави треба да мења ове фајлове, то треба да буде урађено прављењем копије фајлова и њиховим мењањем. Ако је ово случај, наведите то у вашим напоменама.
  6. Ваш код би требао без проблема да се компајлира са једним ANSI C компајлером, а ако су очекиване икакве грешке приликом компајлирања, оне морају бити документоване међу вањим напоменама.
  7. Програм мора бити оригиналан рад. Сви програми ће бити постављени у јавни домен. Сви програми који су експлицитно заштићени ауторским правима ће бити одбијени.
  8. Пријаве морају бити достављене до 29. фебруара 2004. 23:59:59 UTC. (UTC је еквивалент Greenwich Mean Time). Путем е-поњте ће вам бити послата једна потврда пре затварања такмичења.
  9. Сваки учесник може да пошаље до 8 пријава по такмичарској години. Свака пријава мора бити засебно послата.
  10. Пријаве које захтевају човечију помоћ да би биле компајлиране нису дозвољене.
  11. Програми који захтевају специјалне привилегије (setuid, setgid, super-user,special owner or group) нису дозвољене.
  12. Донекле вас охраврујемо залЛегалну злоупотребу правила. Пријава која, по мишљењу судија, крши правила ће бити дисквалификована. Пријаве које покушавају да злоупотребе правила морају у напоменама садржати покушај објашњења зашто су њихове злоупотребе правила легалне.
  13. Ваш код не сме да садржи окталне вредности високог бит-сета без escape-симбола. На пример, ваш код не сме да садржи окталне вредности имеђу 128 и 255.
  14. Сваки програм који не може да буде компајлиран због линија са завршном контролом M (\r \015) ће бити одбијен.
  15. Када шаљете пријаву, морате навести исправу адресу е-поште која је у стању да шаље и прима пошту. Слање пријава путем е-поште има две фазе које укључују потребу коришћена кода за потврду. Овај код ће вам бити послат на е-пошту у току прве фазе. Пријаве послате без активне и валидне адресе е-поште ће бити дисквалификоване. Судије нису одговорне за кашњење е-поште. Молимо вас планирајте довољно врмена за аутоматизовану размену е-поште као дела ваше пријаве.
  16. Веома вас охрабеујемо да пошаљете оригиналне пријаве. Више сличних пријава није препоручљиво.

Пример и анализа[уреди]

Сваки OCC програм може бити објашњен његовом формалном анализом. Најчешће је потребно изразити га замењивањем нејасних делова кода еквивалентним али јаснијим.

Овде ће бити објашњен један програм који штампа карту Индије.

#include<stdio.h>
main()
{
int a,b,c;
for (b=c=10;a=
"- LLLLLL?, LMKC,XYZHELLO FOLKS,\
TFy!QJu ROo TNn(ROo)SLq SLq ULo+\
UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^\
NBELPeHBFHT}TnALVlBLOFAkHFOuFETp\
HCStHAUFAgcEAelclcn^r^r\\tZvYxXy\
T|S~Pn SPm SOn TNn ULo0ULo#ULo-W\
Hq!WFs XDt!" [b+++21];)

for(; a-- > 64 ; )
putchar ( ++c=='Z' ? c = c/ 9:33^b&1);
}

Овај програм се да написати и овако. Понашање је еквивалентно.

#include <stdio.h>

const char *p = "                               TFy!QJu ROo TNn(\
ROo)SLq SLq ULo+UHs UJq TNn*RPn/QPbEWS_JSWQAIJO^NBELPeHBFHT}TnAL\
VlBLOFAkHFOuFETpHCStHAUFAgcEAelclcn^r^r\\tZvYxXyT|S~Pn SPm SOn T\
Nn ULo0ULo#ULo-WHq!WFs XDt!";

main()
{
   int   a, // одређује када се итерације прекидају
         b, // одређује да ли ће бити штампани узвичници или размаци
         c; // одређује када се прелази у следећу линију

   for(b=c=10;a=p[b+21];) // пролази са офсетом кроз стринг
   {
      b++;
      while( a > 64 ) // штампање низа узвичника или размака
      {
         a--;
         c++;

         if(c==90) // замена за c=='Z', време је за нови ред
         {
            c = 10;
            putchar('\n');
         }
         else
         {
            if(b%2) putchar(' '); // (не)парност b одлучује шта ће бити штампано
            else putchar('!');
         }
      }
   }

   return 0;
}

Коментари у коду већ говоре понешто. Прва ствар која се да приметити јесте да првих 31 симбола стринга неће бити употребљени у програму, те се на њиховом месту сме оставити било шта. Конкретно овде су стављени знаци размака. Од 32. симбола па надаље почиње се са читањем симбола редом помоћу вредности b+21. Тај део стринга је у ствари компримована карта која одређује колико и када ће којих симбола бити исписано, у секвенци. На пример када се променљивој a додели прво слово коришћеног дела низа, T, иста ће бити декрементирана до вредности 64 (или ће се прећи на следећу, уколико је у старту мања од 65) и за то време ће бити штампано 'T'-64 = 84 - 64 = 20 симбола. Зависно од парности b ови симболи могу бити узвичници (непарно) или размаци (парно). Значи на почетку излаза би се требало наћи 20 размака као што и јесте случај. Следи 'F' 'F'-64 = 70-64 = 6, што уз инкрементирање b значи да следи шест узвичника итд.

Променљива c одређује када ће бити штампан знак за нову линију. У почетку је она 10, а увећава се за један приликом штампања сваког знака узвика или размака, док се нова линија штампа сваки пут када иста достигне вредност 90 (ASCII код за 'Z'). Након штампања знака за нову линију вредност c бива враћена на 10 и тако даље.

Када се дође до краја стринга, променљива a ће у услову for петље добити вредност нула што значи завршавање ове петље, а са њом и програма.

Спољашње везе[уреди]