- 23, Oct 2024
- #1
После реализации Быстрая сортировка в BrainF***Я понял, что, вероятно, это было не так быстро. Операции, которые в обычных языках имеют размер O(1) (например, индексация массива), в BF значительно длиннее. Большинство правил эффективной сортировки могут быть выброшены за рамки при написании кода. Тьюринговская тряпка.
Итак, вот задача: реализовать «самую быструю процедуру сортировки BrainF***». Я буду измерять время всех записей, используя переводчик ниже. Интерпретатор использует ленту беззнаковых символов размером 16 КБ. И лента, и ячейки переносятся при продвижении/приращении за пределы. Чтение EOF помещает 0 в текущую ячейку. Измеренное время включает в себя как время анализа исходного файла, так и время обработки всех входных файлов. Самый быстрый код побеждает.
Тестовый вектор будет представлять собой набор файлов Ascii, предназначенных для проверки крайних случаев сортировки, включая
Уже отсортированный список: «заказано»
Author Program Average Time Best Set Worst Set AShelly Quicksort 3224.4 ms reverse (158.6) onlynine (1622.4) K.Randall Counting 3162.9 ms reverse (320.6) onlynine (920.1) AShelly Coinsort 517.6 ms reverse (54.0) onlynine (178.5) K.Randall CountingV2 267.8 ms reverse (41.6) random (70.5) AShelly Strandsort 242.3 ms reverse (35.2) random (81.0)
Список с обратной сортировкой: «обратный»
#include <windows.h> #include <stdio.h> #define MS_PER_SEC 1000.0f #define MAXSIZE (0x4000) #define MAXMASK (MAXSIZE-1) typedef __int64 sysTime_t; typedef unsigned char Uint8; typedef unsigned short Uint16; typedef struct instruction_t { Uint8 inst; Uint16 pair; } Instruction; Instruction prog[MAXSIZE] = {0}; Uint8 data[MAXSIZE] = {0}; const Uint8 FEND = EOF; sysTime_t read_time() { __int64 counts; QueryPerformanceCounter((LARGE_INTEGER*)&counts); return counts; } float sysTime_to_ms(sysTime_t timeIn) { __int64 countsPerSec; QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec); return (float)timeIn * MS_PER_SEC / (float)countsPerSec; } int main(int argc, char* argv[]) { FILE* fp; Uint8 c; Uint16 i = 0; Uint16 stack = 0; sysTime_t start_time; sysTime_t elapsed=0,delta; if (argc<3) exit(printf("Error: Not Enough Arguments\n")); fp = fopen(argv[1],"r"); if (!fp) exit(printf("Error: Can't Open program File %s\n",argv[1])); start_time=read_time(); while (FEND != (c = fgetc(fp)) && i <MAXSIZE) { switch (c) { case '+': case '-': case ',': case '.': case '>': case '<': prog[++i].inst = c; break; case '[': prog[++i].inst = c; prog[i].pair=stack; stack = i; break; case ']': if (!stack) exit(printf("Unbalanced ']' at %d\n",i)); prog[++i].inst = c; prog[i].pair=stack; stack = prog[stack].pair; prog[prog[i].pair].pair=i; break; } } if (stack) exit(printf("Unbalanced '[' at %d\n",stack)); elapsed = delta = read_time()-start_time; printf("Parse Time: %f ms\n", sysTime_to_ms(delta)); for (stack=2;stack<argc;stack++) { Instruction *ip = prog; fp = fopen(argv[stack],"r"); if (!fp) exit(printf("Can't Open input File %s\n",argv[stack])); printf("Processing %s:\n", argv[stack]); memset(data,i=0,sizeof(data)); start_time=read_time(); //Run the program while (delta) { switch ((++ip)->inst) { case '+': data[i]++; break; case '-': data[i]--; break; case ',': c=getc(fp);data[i]=(FEND==c)?0:c; break; case '.': putchar(data[i]); break; case '>': i=(i+1)&MAXMASK; break; case '<': i=(i-1)&MAXMASK; break; case '[': if (!data[i]) ip = prog+ip->pair; break; case ']': if (data[i]) ip = prog+ip->pair; break; case 0: delta=0; break; } } delta = read_time()-start_time; elapsed+=delta; printf("\nProcessing Time: %f ms\n", sysTime_to_ms(delta)); } printf("\nTotal Time for %d files: %f ms\n", argc-2, sysTime_to_ms(elapsed)); }
Файл, состоящий из множества копий нескольких уникальных значений: «onlynine».
bftime program.bf infile1 [infile2 ...]
Совершенно случайный файл ascii: «случайный»
sysTime_to_ms()
Случайный файл в диапазоне 1..255: «весь диапазон».
read_time()
Каждый входной файл имеет не более 255 байт.
Вот переводчик. Он написан для консольного режима Windows, но его легко портировать: просто замените öè—@œ™S±ü¼ÓuǯŠf΀n‚ZÊ,ˆÖÄC?tÚDý^öhfF†¬I÷xxÖ÷GààuÈ©ÈÑdàu.y×€ôã…ìcÑ–:*‰˜IP¥©9Ä¢¬]Š\3*\®ªZP!YFõ®ÊÖžáîÓ¹PŸ—wNì/S=Ìœ'g°Ì²¬½ÕQ¹ÀpbWÓ³
»y »ïløó„9k–ƒ~ÕfnšÂt|Srvì^%ÛÀâû¯WWDs‰sç2e£+PÆ@½ã”^$f˜¦K?•òâ¨÷ žøÇÖ¼$NƒRMÉE‹G´QO¨©l¬k¦Ó
and 'fQ`0R0gssT)70O>tP[2{9' 0.HMyTjW7-!SyJQ3]gsccR'UDrnOEK~ca 'KnqrgA3i4dRR8g.'JbjR;D67sVOPllHe,&VG"HDY_'Wi"ra?n.5nWrQ6Mac;&}~T_AepeUk{:Fwl%0`FI8#h]J/Cty-;qluRwk|S U$^|mI|D0\^- csLp~`VM;cPgIT\m\(jOdRQu#a,aGI?TeyY^*"][E-/S"KdWEQ,P<)$:e[_.`V0:fpI zL"GMhao$C4?*x
с эквивалентами для конкретной платформы.
Использование: ibbkninbkrauickabcufrfckbfikfbbakninfaafafbikuccbariauaibiraacbfkfnbbibknkbfankbbunfruarrnrrrbrniaanfbruiicbuiniakuuiubbknanncbuanbcbcfifuiffbcbckikkfcufkkbbakankffikkkbnfnbncbacbfnaauurfrncuckkrfnufkribnfbcfbkbcrkriukncfrcnuirccbbcuaaifiannarcrnfrbarbiuk
~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!
Результаты на данный момент
Вот среднее время 5 запусков полного набора векторов:
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
#самый быстрый код #brainfuck