Покритикуйте лисапед
От: slava_phirsov Россия  
Дата: 01.10.09 17:11
Оценка: :))) :))) :))
Доброго времени суток всем читающим! Дали мне в одной фирме тестовое задание:


Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768. Числа в файле расположены случайным образом. Написать программу, осуществляющую сортировку данного файла, результатом которой будет файл с отсортированными по возрастанию числами. Для осуществления сортировки разрешено использовать максимально 4Кб оперативной памяти.


...и все это должно быть написано на С (не путать с C++) и работать под Linux. В общем, переизобрести GNU "sort -n". Ладно, я, покурив, сочинил овнокод, отослал, никакого ответа, ессно — как модно нынче стало выражаться, "слив засчитан". Но все равно интересно, чтобы коллеги посмотрели со стороны и высказали замечания — на будущее.

Собственно, вот оно:

#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <assert.h>

/*
    Merge-sort algorithm implementation.
    Application read data from stdin, sort it using merge-sort
    with RAM usage limitation and write data to stdout.
    Data  values are integers in range 1..32768
    (NB! Zero value is excluded).
*/

/* RAM buffer size (in bytes)*/
#define BUF_RAW_SIZE 4096
/* Input values total number limit */
#define NUM_VALUES_MAX 32768
/* Value type */
typedef unsigned VAL_T;
/* Iterator type */
typedef unsigned ITER_T;
/* Size of one input value (in bytes) */
#define VAL_SIZE sizeof(VAL_T)
/* RAM buffer size (in input values) */
#define BUF_SIZE (BUF_RAW_SIZE / VAL_SIZE)
/* Temporary files quantity limit */
#define NUM_TMP_FILES_MAX (NUM_VALUES_MAX / BUF_SIZE + 1)
/* Single data value format string, is used by printf/scanf */
#define VAL_FMT "%u\n"
/* Cast some arbitrary pointer to (VAL_T*) and dereference it */
#define VAL_DEREF(Z) (*((const VAL_T*)Z))

/* Struct represents data stored in the temporary file */
typedef struct {
    /*
        Temporary file associated with data,
        NULL if file is not created or was exhausted
    */
    FILE* pfile;
    /*
        Stack top value, is 0 if no data is present;
        NB! We rely, that each data value is >= 1
    */
    VAL_T top;
} OnDiskStack;

/* Size of one OnDiskStack instance */
#define ODS_SIZE (sizeof(OnDiskStack))
/* Get the top value of OnDiskStack instance given by pointer to. */
#define ODSREF_TOP(Z) (((const OnDiskStack*)Z)->top)

/*
    Predicate, compares two VAL_T values,
    is needed by std library qsort algorithm.
    See qsort info for detailes.
*/
int compare(const void* a, const void* b) {
    return (VAL_DEREF(a) > VAL_DEREF(b)) - (VAL_DEREF(a) < VAL_DEREF(b));
}

/*
    Predicate, compares two OnDiskStack instances by
    top values. Is used by std library qsort algorithm
    and also at stacks resorting (see main(), resort() functions).
    Truth table:
        a->top  |   b->top  | compare_s(a, b)
    ------------+-----------+-----------------
         0      |     0     |       0
    ------------+-----------+-----------------
       S!=0     |     0     |      -1
    ------------+-----------+-----------------
         0      |   S!=0    |       1
    ------------+-----------+-----------------
        S1      |    S2     | compare(S1, S2)
*/
int compare_s(const void* a, const void* b) {
    return
        compare(&ODSREF_TOP(a), &ODSREF_TOP(b)) *
        ((ODSREF_TOP(a) && ODSREF_TOP(b)) ? 1: -1);
}

/*
    Sort data in ascending order by std library qsort
    and place to OnDiskStack (i.e. to temporary file);
    Arguments:
        buf - pointer to data buffer;
        size - buffer size;
        stack - pointer to destination stack (
            stack s.b. empty, with no temporary file associated,
            stack data would be lost otherwise
        ).
*/
void sortnflush (
    VAL_T* buf, ITER_T size,
    OnDiskStack* stack
) {
    stack->pfile = NULL;
    stack->top = 0;
    switch (size) {
        case 1:
            stack->top = buf[0];
        case 0:
            break;
        default:
            if (!(stack->pfile = tmpfile())) {
                fprintf(stderr, "Temporary file creation failed\n");
                exit(EXIT_FAILURE);
            };
            qsort(buf, size, VAL_SIZE, compare);
            stack->top = buf[0];
            /*
                HACK! Write operation may be interrupted
                in some cicrcuimstances, but we treat
                such situation as an error
            */
            if (fwrite(&buf[1], VAL_SIZE, size - 1, stack->pfile) != (size - 1)) {
                fprintf(stderr, "Temporary file write failed\n");
                exit(EXIT_FAILURE);
            };
            rewind(stack->pfile);
            break;
    };
}

/*
    Stacks resorting.
    Stacks [1..(num_stacks - 1)] are assumed to be sorted.
    Find the place to insert the first stack, and do insert.
*/
void resort(OnDiskStack* stacks, ITER_T num_stacks) {
    OnDiskStack buf_stack;
    switch (num_stacks) {
        case 2:
            if (compare_s(&stacks[0], &stacks[1]) == 1) {
                buf_stack = stacks[0];
                stacks[0] = stacks[1];
                stacks[1] = buf_stack;
            };
        case 0:
            ;
        case 1:
            break;
        default:
            if (compare_s(&stacks[0], &stacks[1]) == 1) {
                ITER_T beg = 1;
                ITER_T end = num_stacks;
                ITER_T mid;
                buf_stack = stacks[0];
                /*
                    Search the place to insert stacks[0] in
                    range [beg, end)
                */
                do {
                    mid = (end + beg) / 2;
                    switch (compare_s(&buf_stack, &stacks[mid])) {
                        case 0:
                            beg = end = mid;
                            break;
                        case 1:
                            beg = mid;
                            break;
                        case -1:
                            end = mid;
                            break;
                        default:
                            /* We should never go here */
                            assert(0);
                            break;
                    };
                } while ((end - beg) > 1);
                memmove(stacks, &stacks[1], beg * ODS_SIZE);
                stacks[beg] = buf_stack;
            };
            break;
    };
}

/* Application entry point */
int main(int argc, char* argv[]) {

    /* On-disk stacks to store sorted portions of input data */
    static OnDiskStack stacks[NUM_TMP_FILES_MAX];
    /* Actual number of temporary storages used */
    ITER_T num_stacks;
    
    /*
        Read input data to buffer, sort buffer
        and put to on-disk stack when buffer is full or
        when stdin is terminated
    */
    {
        /* Input data buffer */
        static VAL_T buf[BUF_SIZE];
        /* Actual number of items stored in buffer*/
        ITER_T num_bufd = num_stacks = 0;
        
        int scan_ok;
        do {
            scan_ok = (scanf(VAL_FMT, &buf[num_bufd]) == 1);
            if (scan_ok) {
                if (!buf[num_bufd]) {
                    fprintf(stderr, "Input data s.b. > 0\n");
                    exit(EXIT_FAILURE);
                };
                ++num_bufd;
            };
            if ((BUF_SIZE == num_bufd) || (!scan_ok)) {
                if (NUM_TMP_FILES_MAX == num_stacks) {
                    fprintf(stderr, "Input data limit exceeded\n");
                    exit(EXIT_FAILURE);
                };
                sortnflush(buf, num_bufd, &stacks[num_stacks]);
                num_stacks++;
                num_bufd = 0;
            };
        } while (scan_ok);
    };
    
    /*
        Merge all data in stacks, write data to stdout
    */
    if (!num_stacks)
        return EXIT_SUCCESS;
    {
        qsort(stacks, num_stacks, ODS_SIZE, compare_s);
        while (stacks[0].top) {
            printf(VAL_FMT, stacks[0].top);
            if (!stacks[0].pfile) {
                stacks[0].top = 0;
            } else if (fread(&stacks[0].top, VAL_SIZE, 1, stacks[0].pfile) != 1) {
                if (feof(stacks[0].pfile)) {
                    stacks[0].pfile = NULL;
                    stacks[0].top = 0;
                } else {
                    fprintf(stderr, "Temporary file read failed\n");
                    exit(EXIT_FAILURE);
                };
            };
            resort(stacks, num_stacks);
        };
    };
    return EXIT_SUCCESS;
}


Заранее спасибо
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re: Покритикуйте лисапед
От: vadimcher  
Дата: 01.10.09 17:34
Оценка: 1 (1) +5
Здравствуйте, slava_phirsov, Вы писали:

_>Доброго времени суток всем читающим! Дали мне в одной фирме тестовое задание:



_>

_>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768. Числа в файле расположены случайным образом. Написать программу, осуществляющую сортировку данного файла, результатом которой будет файл с отсортированными по возрастанию числами. Для осуществления сортировки разрешено использовать максимально 4Кб оперативной памяти.


_>...и все это должно быть написано на С (не путать с C++) и работать под Linux. В общем, переизобрести GNU "sort -n". Ладно, я, покурив, сочинил овнокод, отослал, никакого ответа, ессно — как модно нынче стало выражаться, "слив засчитан". Но все равно интересно, чтобы коллеги посмотрели со стороны и высказали замечания — на будущее.


_>Собственно, вот оно:

_>
_>...
_>


Я так думаю, что они все еще изучают твой очень длинный-длинный код...
А нельзя было сделать так: выделить 4Кб памяти, по биту на каждое возможное значение, далее пробежать по файлу и отметить те значения, которые там встретились, а дальше просто пробежать по 4Кб памяти и вывести те числа, которые в файле были:
char iwasthere[32768 / 8] = {}; // 4Кб
while (ifil >> num)
    iwasthere[num / 8] |= (1 << (num % 8));
for (int i = 0; i < 32768; ++i)
    if (iwasthere[i / 8] & (1 << (i % 8)))
        ofil << i << endl;

Как-то так...

А вот зайца кому, зайца-выбегайца?!
Re[2]: Покритикуйте лисапед
От: slava_phirsov Россия  
Дата: 01.10.09 17:40
Оценка: :)
Здравствуйте, vadimcher, Вы писали:

V>А нельзя было сделать так: выделить 4Кб памяти, по биту на каждое возможное значение, далее пробежать по файлу и отметить те значения, которые там встретились, а дальше просто пробежать по 4Кб памяти и вывести те числа, которые в файле были


Кстати, да. Осталась одна надежда — гордо заявить, что мой код лучше, потому что будет быстрее работать (ну мало ли, бывают же чудеса, хе-хе). Надо попробовать написать твой вариант и прогнать под gprof-ом.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[2]: Покритикуйте лисапед
От: Mephisto666 Великобритания  
Дата: 01.10.09 17:40
Оценка:
Здравствуйте, vadimcher, Вы писали:


V>Я так думаю, что они все еще изучают твой очень длинный-длинный код...

V>А нельзя было сделать так: выделить 4Кб памяти, по биту на каждое возможное значение, далее пробежать по файлу и отметить те значения, которые там встретились, а дальше просто пробежать по 4Кб памяти и вывести те числа, которые в файле были:

+1
пришла абсолютно та же идея в голову.
Re[3]: Покритикуйте лисапед
От: vadimcher  
Дата: 01.10.09 17:48
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, vadimcher, Вы писали:


V>>А нельзя было сделать так: выделить 4Кб памяти, по биту на каждое возможное значение, далее пробежать по файлу и отметить те значения, которые там встретились, а дальше просто пробежать по 4Кб памяти и вывести те числа, которые в файле были


_>Кстати, да. Осталась одна надежда — гордо заявить, что мой код лучше, потому что будет быстрее работать (ну мало ли, бывают же чудеса, хе-хе). Надо попробовать написать твой вариант и прогнать под gprof-ом.


Здесь только два нюанса. Чтобы побыстрее работало массив лучше делать интами типа int[32768 / 8 / sizeof(int)], и, кроме того, у тебя входящие числа не от 0 до 32767, а от 1 до 32768, будь осторожен!

А вот зайца кому, зайца-выбегайца?!
Re: Покритикуйте лисапед
От: Sergey Россия  
Дата: 01.10.09 18:43
Оценка: 30 (1)
Здравствуйте, slava_phirsov, Вы писали:

_>

_>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768. Числа в файле расположены случайным образом. Написать программу, осуществляющую сортировку данного файла, результатом которой будет файл с отсортированными по возрастанию числами. Для осуществления сортировки разрешено использовать максимально 4Кб оперативной памяти.


_>...и все это должно быть написано на С (не путать с C++) и работать под Linux. В общем, переизобрести GNU "sort -n". Ладно, я, покурив, сочинил овнокод, отослал, никакого ответа, ессно — как модно нынче стало выражаться, "слив засчитан". Но все равно интересно, чтобы коллеги посмотрели со стороны и высказали замечания — на будущее.


На будущее я посоветовал бы знакомиться в таких случаях с творчеством Д. Кнута. Конкретно для этого случая рулит раздел 5.4 третьего тома — "Внешняя сортировка".
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Покритикуйте лисапед
От: Сергей Мухин Россия  
Дата: 01.10.09 19:00
Оценка: +1
Здравствуйте, slava_phirsov, Вы писали:


_>

_>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768. Числа в файле расположены случайным образом. Написать программу, осуществляющую сортировку данного файла, результатом которой будет файл с отсортированными по возрастанию числами. Для осуществления сортировки разрешено использовать максимально 4Кб оперативной памяти.


А условие точно такое? Если заменить в первой фразе написать "Есть файл, который содержит 32768 целых" задача как раз для собеседования
---
С уважением,
Сергей Мухин
Re: Покритикуйте лисапед
От: Тролль-323  
Дата: 01.10.09 19:32
Оценка:
_>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768.

Так… Что-то я туплю на ночь глядя…

Это как бы шутка такая? На внимательность?

Тогда ведь получается, что он содержит каждое число от 1 до 32768 по одному разу.

Сортированный файл просто будет содержать тупо числа от 1 до 32768?
Re[2]: Покритикуйте лисапед
От: Sashaka Россия  
Дата: 01.10.09 19:38
Оценка:
Здравствуйте, Тролль-323, Вы писали:

_>>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768.


Т3>Так… Что-то я туплю на ночь глядя…


Т3>Это как бы шутка такая? На внимательность?


Т3>Тогда ведь получается, что он содержит каждое число от 1 до 32768 по одному разу.


Т3>Сортированный файл просто будет содержать тупо числа от 1 до 32768?


может содержать 32768, а может и меньше ? =)
Re[3]: Покритикуйте лисапед
От: RomikT Германия  
Дата: 01.10.09 19:55
Оценка:
Здравствуйте, Sashaka, Вы писали:

S>Здравствуйте, Тролль-323, Вы писали:


_>>>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768.


Т3>>Так… Что-то я туплю на ночь глядя…

Т3>>Это как бы шутка такая? На внимательность?
Т3>>Тогда ведь получается, что он содержит каждое число от 1 до 32768 по одному разу.
Т3>>Сортированный файл просто будет содержать тупо числа от 1 до 32768?

S>может содержать 32768, а может и меньше ? =)


А может и больше. А может вообще содержать не числа, а строки
В общем, аккуратнее надо с формулировками...
Re[2]: Покритикуйте лисапед
От: slava_phirsov Россия  
Дата: 01.10.09 19:56
Оценка:
Здравствуйте, vadimcher, Вы писали:

...

Вот лисапед 2.0


#include <stdio.h>
#include <stdlib.h>

#include <string.h>

/*
    Read data from stdin, sort it
    (RAM usage is strongly limited)
    and write data to stdout.
    Data  values are integers in range 1..32768
    (NB! Zero value is excluded, each input value
    in sequence is unique, non-repetitive).
    Algorithm doesn't store input data in buffer,
    it stores one bit for each possible value, indicating
    whether this particular value was encountered or not.
*/

/* RAM buffer size (in bytes)*/
#define BUF_SIZE 4096
/* Value type */
typedef unsigned VAL_T;
/* Iterator type */
typedef unsigned ITER_T;
/* Single data value format string, is used by printf/scanf */
#define VAL_FMT "%u\n"
/* Get particular bit in particular byte value*/
#define GET_BIT (buf[byte_pos] & (MASKS[bit_pos]))

/* Application entry point */
int main(int argc, char* argv[]) {
    
    /* Masks used to select single bit from the byte */
    static unsigned char MASKS[8] = {1, 2, 4, 8, 16, 32, 64, 128};

    /* Input data buffer */
    static unsigned char buf[BUF_SIZE];
    memset(buf, 0, BUF_SIZE);
    /*
        Read input data from stdin and accumulate it into buffer
        in compressed form
    */
    {
        VAL_T value;
        while (scanf(VAL_FMT, &value) == 1) {
            ITER_T byte_pos, bit_pos;
            if (!value) {
                fprintf(stderr, "Input data s.b. > 0\n");
                exit(EXIT_FAILURE);
            };
            --value;
            byte_pos = value / 8;
            bit_pos = (value % 8);
            if (GET_BIT) {
                fprintf(stderr, "Input data is duplicated\n");
                exit(EXIT_FAILURE);
            };
            buf[byte_pos] |= MASKS[bit_pos];
        };
    };
    
    /*
        Write accumulated data to stdout
    */
    {
        ITER_T byte_pos, bit_pos;
        for (byte_pos = 0; byte_pos < BUF_SIZE; ++byte_pos)
            for (bit_pos = 0; bit_pos < 8; ++bit_pos)
                if (GET_BIT)
                    printf(VAL_FMT, byte_pos * 8 + bit_pos + 1);
    };
    
    return EXIT_SUCCESS;
}


Как и следовало ожидать, gprof не сумел замерить скорость выполнения — выдал 0.0
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[2]: Покритикуйте лисапед
От: Sergey Россия  
Дата: 01.10.09 19:59
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

_>>

_>>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768. Числа в файле расположены случайным образом. Написать программу, осуществляющую сортировку данного файла, результатом которой будет файл с отсортированными по возрастанию числами. Для осуществления сортировки разрешено использовать максимально 4Кб оперативной памяти.


СМ>А условие точно такое? Если заменить в первой фразе написать "Есть файл, который содержит 32768 целых" задача как раз для собеседования


А блин реально задача на внимательность
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[2]: Покритикуйте лисапед
От: slava_phirsov Россия  
Дата: 01.10.09 20:41
Оценка: +1
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, slava_phirsov, Вы писали:


СМ>А условие точно такое? Если заменить в первой фразе написать "Есть файл, который содержит 32768 целых" задача как раз для собеседования


Как ни странно, мне эта мысль тоже приходила в голову. И насчет неопределенности формата данных в файле тоже мелькало, но я забил. А условие и в самом деле точно такое. А вот до решения с хранением флагов я как-то не допер... Тут надо или действительно быстро соображать, или просто знать готовое решение — задача из серии "Постройте 4 треугольника из 6-ти спичек", "Сколько раз надо спуститься в подвал, чтобы проверить какой выключатель какую лампочку контролирует", "Как измерить высоту дома при помощи барометра" ит.д. (список можно продолжать). Буду знать...
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[2]: Покритикуйте лисапед
От: slava_phirsov Россия  
Дата: 01.10.09 20:56
Оценка: -1 :))
Здравствуйте, Sergey, Вы писали:

S>На будущее я посоветовал бы знакомиться в таких случаях с творчеством Д. Кнута. Конкретно для этого случая рулит раздел 5.4 третьего тома — "Внешняя сортировка".


Achtung, ОФФТОП:

Да, только для таких случаев труд Кнута "Искусство программирования в сферическом вакууме" и нужен. Я серьезно — кроме как для решения тестовых задач мне ни разу не пришлось его листать. Увы, но то, что пишет дедушка Кнут, на практике мало востребованно (во всяком случае в моей практике) — гораздо чаще приходилось листать Майерса, книгу "Банды Четырех", Гласса, Бека. Ах да, раз мне потребовалось при решении задачи допускового анализа почитать то, что пишет Кнут про обход кортежей. Все здорово, но его супероптимизированный алгоритм считал минут двадцать, а мой некошерный управился за несколько секунд. И это не в упрек Кнуту будь сказано, просто его алгоритм обхода был рассчитан на некий абстрактный процедурно-ориентированный язык программирования, и все было организовано при помощи циклов, а я писал под Octave, и реализовал алгоритм в терминах операций с матрицами — дальнейшие пояснения, думаю, излишни. В конкретных условиях работы "неправильный" алгоритм оказался лучше "правильного". Поэтому я и хулигански приписал про "сферический вакуум"
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[3]: Покритикуйте лисапед
От: vadimcher  
Дата: 01.10.09 20:59
Оценка: +2
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, Sergey, Вы писали:


S>>На будущее я посоветовал бы знакомиться в таких случаях с творчеством Д. Кнута. Конкретно для этого случая рулит раздел 5.4 третьего тома — "Внешняя сортировка".


_>Achtung, ОФФТОП:


_>Да, только для таких случаев труд Кнута "Искусство программирования в сферическом вакууме" и нужен. Я серьезно — кроме как для решения тестовых задач мне ни разу не пришлось его листать. Увы, но то, что пишет дедушка Кнут, на практике мало востребованно (во всяком случае в моей практике) — гораздо чаще приходилось листать Майерса, книгу "Банды Четырех", Гласса, Бека. Ах да, раз мне потребовалось при решении задачи допускового анализа почитать то, что пишет Кнут про обход кортежей. Все здорово, но его супероптимизированный алгоритм считал минут двадцать, а мой некошерный управился за несколько секунд. И это не в упрек Кнуту будь сказано, просто его алгоритм обхода был рассчитан на некий абстрактный процедурно-ориентированный язык программирования, и все было организовано при помощи циклов, а я писал под Octave, и реализовал алгоритм в терминах операций с матрицами — дальнейшие пояснения, думаю, излишни. В конкретных условиях работы "неправильный" алгоритм оказался лучше "правильного". Поэтому я и хулигански приписал про "сферический вакуум"


Зря ты так. Я думаю ты очень часто пользуешься трудами дедушки Кнута, даже не подозревая об этом...

А вот зайца кому, зайца-выбегайца?!
Re[3]: Покритикуйте лисапед
От: Yuki-no Tenshi Украина  
Дата: 02.10.09 07:31
Оценка: 1 (1)
_>Как ни странно, мне эта мысль тоже приходила в голову. И насчет неопределенности формата данных в файле тоже мелькало, но я забил. А условие и в самом деле точно такое. А вот до решения с хранением флагов я как-то не допер... Тут надо или действительно быстро соображать, или просто знать готовое решение — задача из серии "Постройте 4 треугольника из 6-ти спичек", "Сколько раз надо спуститься в подвал, чтобы проверить какой выключатель какую лампочку контролирует", "Как измерить высоту дома при помощи барометра" ит.д. (список можно продолжать). Буду знать...

Вот в этой книжке "Жемчужины программирования" описана твоя задача. Книга эта не так объёмна, как тот же Кнут, но там рассматриваются всякие интересные задачи на пределах возможности машины. А вообще, согласен, что это тестовое задание на знание алгоритмов. Сходу, не прочитав определённую литературу, правильное решение не получится.
雪の天使
Re: о лисапеде
От: Pavel Dvorkin Россия  
Дата: 02.10.09 07:51
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

В свое время в одном сборнике задач для школьных олимпиад была предолжена следующая задача

Дан массив из целых чисел, содержащий только нули и единицы. Отсортировать массив.



Ну, правда, баллов за нее давали немного.
With best regards
Pavel Dvorkin
Re[4]: Покритикуйте лисапед
От: slava_phirsov Россия  
Дата: 02.10.09 09:01
Оценка:
Здравствуйте, vadimcher, Вы писали:

V>Зря ты так. Я думаю ты очень часто пользуешься трудами дедушки Кнута, даже не подозревая об этом...


И даже подозревая — когда работаю в Texmaker'е А когда я втыкаю комп в розетку, я получаю электроэнергию от ЛАЭС, т.е., сам того не подозревая, пользуюсь трудами Курчатова, вернее, Бора, вернее Эйнштейна — ну, короче, идея ясна. Пафос был не в том, что Кнут — не крут, а в том, что в повседневности его книга, вот лично мне, как среднему (во всех смыслах) кодеру не очень-то и нужна... Ты (и другие знатоки трудов Кнута) можешь меня поправить, но вот темы, которые реально мне нужны каждый (или почти каждый) день, и о которых Кнут не пишет:

  1. Разработка архитектуры на макро или на микро-уровне (можно тут еще вспомнить недавние споры в этой же ветке форума на предмет — когда надо кидать исключение, когда возвращать код ошибки, а когда использовать assert)
  2. Объектно-ориентированное программирование (паттерны)
  3. Функциональное программирование
  4. Организация работы программиста
  5. Тестирование

Вот эту повседневность я у Кнута не нашел (может быть, плохо искал? ОК, ткните носом, плиз). Пример с Октавой я привел выше — Кнут ведь писал "вообще", а в каждом конкретном случае общее решение как правило проигрывает (хороший философский принцип, примером его могут служить и две реализации лисапеда, породившего данный топик — "общая", которая "по-честному" собирает данные во временные файлы и "чисто конкретная", которая хранит только флаги).
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[5]: Покритикуйте лисапед
От: x905  
Дата: 02.10.09 09:22
Оценка:
в предложенных решениях сразу нарушается условие задачи — 4кб т.к. выделяется место под массив и есть хотябы одна переменная )
также не учтено потребление памяти при загрузке программы
Re[3]: Покритикуйте лисапед
От: alzt  
Дата: 02.10.09 09:49
Оценка:
Здравствуйте, Sashaka, Вы писали:

Т3>>Тогда ведь получается, что он содержит каждое число от 1 до 32768 по одному разу.


Т3>>Сортированный файл просто будет содержать тупо числа от 1 до 32768?


S>может содержать 32768, а может и меньше ? =)


Вначале выделить массив целых из 32768. Затем обнулить его.
Затем заполнять.
При выводе игнорировать нули.

Минусы: неэффективно при маленьком размере файла.

Если немного подумать, то оказывается, что значение массива будет зависеть от индекса.
Поэтому массив целых можно заменить на массив булевых констант.

Если надо оптимизировать по памяти, то можно сжать булевы константы до битовых флагов, как писал vadimcher.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.