_>Да, только для таких случаев труд Кнута "Искусство программирования в сферическом вакууме" и нужен. Я серьезно — кроме как для решения тестовых задач мне ни разу не пришлось его листать.
S>На будущее я посоветовал бы знакомиться в таких случаях с творчеством Д. Кнута. Конкретно для этого случая рулит раздел 5.4 третьего тома — "Внешняя сортировка".
в данном случае нужен Бентли с его "жемчужинами программирования" — у него такой пример был и решение было таким же, как тут предложили (vadimcher). как раз нафиг кнут не нужен тут.
Of course, the code must be complete enough to compile and link.
Господа, задавшие задание, таки вышли на связь — ни вариант с "честной сортировкой", ни предложенный тут вариант с флагами их не устроили. Цитирую дословно(но по памяти): "У вас не было выполнено условие использовать не более 4 кбайт". Мне чисто теоретически стало интересно, но спросить как-то постеснялся — а что они тогда имели в виду? Что общий размер занимаемой приложением памяти не должен быть более 4 кбайт? У меня приложение "return 0" (не путать с "Hello, world!") заняло 4,2 кбайта, а приложение просто пишущее 10 байт во временный файл — так и все 5-6 кбайт. То есть даже с полным использованием внешней сортировки, когда все данные лежат только в файле (не будем уточнять, какие именно данные — "честно" отсортированные числа, или флаги) меньше 5 не получится. Есть конечно разные компиляторы, у них есть разные опции компиляции, есть наконец разные машины... Ну так по этой части в задании ничего сказано не было вообще. Короче то ли это у них дежурная отмазка такая, то ли я чего-то не просек, то ли господа сами не знают чего хотят.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, slava_phirsov, Вы писали:
_>Господа, задавшие задание, таки вышли на связь — ни вариант с "честной сортировкой", ни предложенный тут вариант с флагами их не устроили. Цитирую дословно(но по памяти): "У вас не было выполнено условие использовать не более 4 кбайт". Мне чисто теоретически стало интересно, но спросить как-то постеснялся — а что они тогда имели в виду? Что общий размер занимаемой приложением памяти не должен быть более 4 кбайт? У меня приложение "return 0"
Может они даже разбираться не стали, код читается очень тяжело если честно
А про флаги они видимо не поняли. Там как раз ровно 4кб нужно. (32кб/8)
Обычно по одной задачке не судят. Наверное "не понравилось" или программист не сильно срочно нужен.
Здравствуйте, slava_phirsov, Вы писали:
_>Спасибо, коллеги, за помощь, и все такое
_>Господа, задавшие задание, таки вышли на связь — ни вариант с "честной сортировкой", ни предложенный тут вариант с флагами их не устроили. Цитирую дословно(но по памяти): "У вас не было выполнено условие использовать не более 4 кбайт". Мне чисто теоретически стало интересно, но спросить как-то постеснялся — а что они тогда имели в виду? Что общий размер занимаемой приложением памяти не должен быть более 4 кбайт? У меня приложение "return 0" (не путать с "Hello, world!") заняло 4,2 кбайта, а приложение просто пишущее 10 байт во временный файл — так и все 5-6 кбайт. То есть даже с полным использованием внешней сортировки, когда все данные лежат только в файле (не будем уточнять, какие именно данные — "честно" отсортированные числа, или флаги) меньше 5 не получится. Есть конечно разные компиляторы, у них есть разные опции компиляции, есть наконец разные машины... Ну так по этой части в задании ничего сказано не было вообще. Короче то ли это у них дежурная отмазка такая, то ли я чего-то не просек, то ли господа сами не знают чего хотят.
И еще, пожалуй, на будущее я бы тебе посоветовал писать попроще. Во-первых, как правило, задачки проверяют один-два конкретных вопроса (как здесь, например, знаешь ли ты стандартные методы сортировки и можешь ли ты при этом уложиться в требуемую память). Поэтому решение должно быть по возможности коротким, ясным и решающим конкретную поставленную задачу наиболее простым, но эффективным способом. Из решения должно быть сразу ясно КАК ты решил задачу. Во-вторых, ты у них не один, и у них просто нет возможности, времени и желания "все это читать и разбираться". Никто не будет тратить больше двух минут на твое решение.
Здравствуйте, slava_phirsov, Вы писали:
_>Доброго времени суток всем читающим! Дали мне в одной фирме тестовое задание:
_>
_>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768.
Супер.
Сколько целых:32768
Какой диапазон:1...32768
Повторяются: Нет.
Следовательно, там будут только эти числа из диапазона, 1, 2, 3,..., 32768.
Других чисел не будет вообще.
Сортировать не надо.
Просто надо записать числа от 1 до 32768
Всё.
Примерно так
int main()
{
istream stream("file.txt");
for(int i=1;i<=32768;i++)
{
stream<<i<<" ";
}
//деструктор закроет файл
};
Здравствуйте, slava_phirsov, Вы писали:
_>Доброго времени суток всем читающим! Дали мне в одной фирме тестовое задание:
_>
_>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768.
Супер.
Сколько целых:32768
Какой диапазон:1...32768
Повторяются: Нет.
Следовательно, там будут только эти числа из диапазона, 1, 2, 3,..., 32768.
Других чисел не будет вообще.
Сортировать не надо.
Просто надо записать числа от 1 до 32768
Всё.
Примерно так
int main()
{
ostream stream("file.txt");
for(int i=1;i<=32768;i++)
{
stream<<i<<" ";
}
//деструктор закроет файл
};
Здравствуйте, superdeveloper, Вы писали:
S>Здравствуйте, slava_phirsov, Вы писали:
_>>Доброго времени суток всем читающим! Дали мне в одной фирме тестовое задание:
_>>
_>>Есть файл, который может содержать 32768 целых, неповторяющихся чисел в диапазоне от 1 до 32768.
Здравствуйте, x905, Вы писали:
X>ключевое слово "_может_", ага
Выделяем массив, равный 32768/8=4096 байт
каждому биту ставим в соответствие одно число 1...32768
число — номер бита (число-1)
соответственно биты будут 0...32767
Алгоритм:
1. Обнуляем массив
2. Проходимся по файлу, если это число есть, то включаем бит (число-1)
3. Проходим по всем битам, если бит включен, то заносим в выходной файл число (номер_бита+1)
4.конец агоритма.
Здравствуйте, superdeveloper, Вы писали:
S>Здравствуйте, x905, Вы писали:
X>>ключевое слово "_может_", ага
S>Выделяем массив, равный 32768/8=4096 байт S>каждому биту ставим в соответствие одно число 1...32768 S>число — номер бита (число-1) S>соответственно биты будут 0...32767
S>Алгоритм: S>1. Обнуляем массив S>2. Проходимся по файлу, если это число есть, то включаем бит (число-1) S>3. Проходим по всем битам, если бит включен, то заносим в выходной файл число (номер_бита+1) S>4.конец агоритма.
S>вот.
S>ps. Приём известный.
тред с начала читаем ? уже было, ага )
вопрос есть поинтересней: 4кб — это только на массив, а переменные?, а rintime?
даже helloworld вылезет за 4кб
и как все в 4кб всеже впихнуть?
Здравствуйте, slava_phirsov, Вы писали:
_>Доброго времени суток всем читающим! Дали мне в одной фирме тестовое задание:
_>
_>Есть файл, который может содержать 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;
_>}
_>
Здравствуйте, x905, Вы писали:
X>Здравствуйте, superdeveloper, Вы писали:
S>>Здравствуйте, x905, Вы писали:
X>>>ключевое слово "_может_", ага
S>>Выделяем массив, равный 32768/8=4096 байт S>>каждому биту ставим в соответствие одно число 1...32768 S>>число — номер бита (число-1) S>>соответственно биты будут 0...32767
S>>Алгоритм: S>>1. Обнуляем массив S>>2. Проходимся по файлу, если это число есть, то включаем бит (число-1) S>>3. Проходим по всем битам, если бит включен, то заносим в выходной файл число (номер_бита+1) S>>4.конец агоритма.
S>>вот.
S>>ps. Приём известный.
X>тред с начала читаем ? уже было, ага )
X>вопрос есть поинтересней: 4кб — это только на массив, а переменные?, а rintime? X>даже helloworld вылезет за 4кб X>и как все в 4кб всеже впихнуть?
Была в свое время игрушка, называлась livingstone. Ходилка такая, бродилка. Там бегать, прыгать, стрелять. Графика, насколько я помню, была типа 16-цветная, или даже 4х-цветная, но зато игрушка была достаточно продолжительной и интересной. Так вот, автор поставил себе цель написать ее полностью на ассемблере, и вместить в 64Кб. Вместил. Она даже была .com, а не .exe.
Здравствуйте, x905, Вы писали:
X>вопрос есть поинтересней: 4кб — это только на массив, а переменные?, а rintime? X>даже helloworld вылезет за 4кб X>и как все в 4кб всеже впихнуть?
Что считать памятью?
Регистры тоже память?
Если нет, то всё можно сделать через регистры.
Вообще в Windows есть разные виды ведения памяти, commit/reserve и .т.д.
Можно ли выделять временные файлы, можно ли несколько раз считать исходный файл и т.п.?
Надо поставить более точную задачу.
Здравствуйте, superdeveloper, Вы писали:
S>Что считать памятью? S>Регистры тоже память? S>Если нет, то всё можно сделать через регистры. S>Вообще в Windows есть разные виды ведения памяти, commit/reserve и .т.д.
причем тут венда?
S>Надо поставить более точную задачу.
согласен, сам хотел бы ответ услышать — интересно ведь
но видно не судьба
Вопрос с памятью не понятен, я бы решил, что это о выделяемой памяти через new. хотя может и стековые переменные. код программы в такой обьем не влезет.
от 0 до 32767 чисел. от 1 до 32768 значений.
2Кб на память, 2 кб на массив битов.
Вообще можно не ограничиваться 32К значений. а проходить по 16К (-> 2кб), хоть до 4Гб.
* тогда в первый раз разделить 4Гб на, скажем 512 частей (32 байта по 1 биту на часть. наличие цифр из этого диапазона).
каждую часть разделив еще на 512 получим наши 16кб.
правда файл может быть прочитан(от начала до конца) невероятное число раз.
в случае с 0 до 32767 значений — максимум 4 раза.
в случае с 1 до 32768 значений — максимум 5 раз.
Для 4Гб задачка на мой взгляд интересней, решение универсальней. (хотя да, лишние 2 чтения)
Римское правило. Тот, кто говорит, что Это не может быть сделано, никогда не должен мешать тому, кто Это делает.
Осень, ну вы поняли.
Зачем еще один код? А человек?
M>Может они даже разбираться не стали, код читается очень тяжело если честно
Хм, а это уже, ИМХО, субъективное. Вроде форматирование нормальное (если не считать расстановки фигурных скобок), хотя , со стороны такие вещи всегда виднее.
M>Обычно по одной задачке не судят. Наверное "не понравилось" или программист не сильно срочно нужен.
Задним числом узнал, что их вакансия висит на разных сайтах уже второй год
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, superdeveloper, Вы писали:
S>Что считать памятью? S>Регистры тоже память? S>Если нет, то всё можно сделать через регистры.
S>Вообще в Windows есть разные виды ведения памяти, commit/reserve и .т.д.
Я ж говорил:
и работать под Linux
S>Можно ли выделять временные файлы, можно ли несколько раз считать исходный файл и т.п.?
ИМХО, ты все усложняешь. Тестовое задание по определению представляет собой этюд, а не "взрослый" проект.
S>Надо поставить более точную задачу.
Вспоминается известная история, как Ходжа Насреддин спорил с джинном, кто дальше зашвырнет скалу (вариация на тему Пушкинской сказки о Балде). Джинн кинул огромную скалу на сто шагов. Насреддин же подошел к скале и стал вслух рассуждать: "Если я кину ее на восток — она будет мешать солнцу восходить, и мир погрузится во мрак, если кину на запад — будет мешать солнцу заходить, и весь мир изжарится, кину на север — перестанет дуть ветер, и весь мир протухнет..." ну ит.д. Короче, застращал джинна до того, что тот стал упрашивать Насреддина не трогать скалу.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, x905, Вы писали:
X>в предложенных решениях сразу нарушается условие задачи — 4кб т.к. выделяется место под массив и есть хотябы одна переменная ) X>также не учтено потребление памяти при загрузке программы
Полностью согласен. Если посмотреть top'ом, то программка отжирает мегабайты. Впрочем, и мега-программа "return 0" ведет себя не намного лучше. Предлагай выход? Писать все на ассемблере, вручную распределять память ит.п.?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)