Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.10.31;
Скачать: CL | DM;

Вниз

Занимательные задачи   Найти похожие ветки 

 
Oleg_Gashev ©   (2002-10-12 18:27) [0]

Здравствуйте!

Тема задач многим нравится на этом форуме. Поэтому вот Вам две:


1) Есть числа от 1 до N. Вывести их случайным образом, без повторений.

2) Вывести все инволюции множества {1,2,3,...,N}.


Успехов.


 
Romkin ©   (2002-10-12 19:01) [1]

2 - Д.Кнут т3 5.1.4 %-)) - считается ли это решением?
Меня больше привлекают немного другие задачи, одна из подобных есть в книге Jon Bentley "Programming Pearls":
3. Имеется файл, содержащий 7-значные телефонные номера (для простоты - текстовый, один номер в строке). Понятно, что номеров не более 10000000, они не повторяются. Нужно выдать файл с теми же номерами, отсортированными по фозрастанию, причем оперативной памяти использовать не более 2 Мб :-)), и как можно быстрее, в идеале за время от 10 сек до пары минут.
Вся изюминка в том, что когда есть решение, понимаешь, насколько оно элементарно.


 
Anatoly Podgoretsky ©   (2002-10-12 19:14) [2]

Тот же Кнут, у него приведены алгоритмы для файлов с очень небольшим использованием памяти, если не ошибаюсь то метод слияния.


 
Romkin ©   (2002-10-12 19:35) [3]

Прошу учесть, что файл с номерами занимает около 85 Мб, и на одно его считывание требуется несколько секунд (в лучшем случае, у меня копирование прошло за 20 сек, а диск довольно быстрый). При сортировке слиянием памяти, конечно, требуется немного, но вот считано/записано будет примерно раз в 20 больше. Я ожидаю, что это займет примерно 10 минут в лучшем случае, а это не слишком приятно. Мне бы хотелось увидеть решение, которое сделает то же самое за время, не намного большее, чем простое копирование файла


 
down   (2002-10-13 11:27) [4]

Как насчет такого алгоритма:
1.Выводим в текстовый файл все возможные номера по порядку,
к каждому номеру справа добавляем пробел
2.Последовательно читаем файл с номерами, каждый прочитанный номер отмечаем в созданном файле (позицию номера в файле знаем, отмечаем, например, заменой пробела на "+")
3.Последовательно читаем созданный файл, если номер отмечен, то
записываем его в другой файл, это и будет результат




 
TTCustomDelphiMaster ©   (2002-10-13 11:52) [5]

Romkin

1. Резервируем память 10000000 бит. (чуть больше 1 Мб)
2. Читаем из файла номера и включаем биты с соответствующим номером.
3. Проверяем в цикле биты. Если включен, записываем его номер в файл.


 
Romkin ©   (2002-10-13 11:53) [6]

2TTCustomDelphiMaster Ты знал, ты знал! %-))


 
TTCustomDelphiMaster ©   (2002-10-13 11:56) [7]

Только что придумал :)


 
Romkin ©   (2002-10-13 12:03) [8]

Просто изюминка этой задачи в том, что все начинают подбирать подходящий метод сортировки...
2down
Насколько понимаю, этот метод тоже подходит, он практически идентичен TTCustomDelphiMaster © (13.10.02 11:52)
Вот только битовый массив в отличие от файла полностью в памяти :-))


 
Forever   (2002-10-13 13:24) [9]

Читаем из файла номера и включаем биты с соответствующим номером.

Можно поподробнее ?


 
TTCustomDelphiMaster ©   (2002-10-13 14:02) [10]

Допустим прочитали из файла номер 1234567.
Включаем бит с номером 6 (1234567 mod 8 = 7) в 154320-м байте (1234567 div 8 = 154320).

На самом деле все немного сложнее. Во первых телефонов с номерами 0 - 999999 не существует (не считая справочных) и памяти можно резервировать на 10 процентов меньше при этом из номера нужно вычитать 1000000. Во вторых вместо операций div и mod применяется смещение битов shl это будет быстрее.


 
down   (2002-10-13 14:58) [11]

2TTCustomDelphiMaster
Идейка-то моя, моя... :)


 
TTCustomDelphiMaster ©   (2002-10-13 15:11) [12]

down

Претендуете на нобелевскую :)


 
down   (2002-10-13 15:21) [13]

Удалено модератором


 
Romkin ©   (2002-10-13 16:03) [14]

Задача № 1.

program GenRec;

{$APPTYPE CONSOLE}

uses
Windows, SysUtils;

const
minPhone = 1000000;
maxPhone = 9999999;

type
TPhoneRec = packed record
Phone: string[7];
Name: string[50];
end;

TPhoneSortRec = record
Rnd: Double;
Phone: integer;
end;

TPhoneSort = array [minPhone .. maxPhone] of TPhoneSortRec;

procedure QuickSort(var A: TPhoneSort; iLo, iHi: Integer);
var
Lo, Hi: Integer;
Mid: Double;
T: TPhoneSortRec;
begin
Lo := iLo;
Hi := iHi;
Mid := A[(Lo + Hi) div 2].Rnd;
repeat
while A[Lo].Rnd < Mid do Inc(Lo);
while A[Hi].Rnd > Mid do Dec(Hi);
if Lo <= Hi then
begin
T := A[Lo];
A[Lo] := A[Hi];
A[Hi] := T;
Inc(Lo);
Dec(Hi);
end;
until Lo > Hi;
if Hi > iLo then QuickSort(A, iLo, Hi);
if Lo < iHi then QuickSort(A, Lo, iHi);
end;

var
PhoneSort: TPhoneSort;
PhoneFile: file of TPhoneRec;
i: integer;
StartTime, EndTime: DWORD;
ANum: double;
Sorted: boolean;
FileName: string;
PhoneRec: TPhoneRec;
begin
// gen phone numbers
writeln("Phone numbers generating...");
StartTime := GetTickCount;
randomize;
for i := minPhone to maxPhone do
with PhoneSort[i] do
begin
Phone := i;
Rnd := random;
end;
EndTime := GetTickCount;
writeln("Generation complete. Time is ",
(EndTime - startTime)/1000, " sec");
writeln("Random sorting...");
StartTime := GetTickCount;
QuickSort(PhoneSort, minPhone, maxPhone);
EndTime := GetTickCount;
writeln("Sort complete. Time is ",
(EndTime - startTime)/1000, " sec");
writeln("Check sorting...");
StartTime := GetTickCount;
ANum := PhoneSort[minPhone].Rnd;
Sorted := true;
for i := minPhone + 1 to maxPhone do
if ANum > PhoneSort[i].Rnd then
Sorted := false;
EndTime := GetTickCount;
write("Check complete. Time is ",
(EndTime - startTime)/1000, " sec Result is ");
if Sorted then
writeln("sorted")
else
writeln("UNsorted!!!");
write("press <Enter> for file generation");
readln;
writeln("Record file...");
StartTime := GetTickCount;
FileName := IncludeTrailingPathDelimiter(ExtractFilePath(paramStr(0))) +
"PhoneRec.dat";
assignFile(PhoneFile, FileName);
rewrite(PhoneFile);
try
for i := minPhone to maxPhone do
begin
with PhoneRec do
begin
Phone := IntToStr(PhoneSort[i].Phone);
Name := IntToStr(i) + " Time is " +
TimeToStr(Now) + " John Dow";
end;
Write(PhoneFile,PhoneRec);
if (i mod 100000) = 0 then
writeln("Writes: ", IntToStr(i - minPhone));
end;
finally
CloseFile(PhoneFile);
end;
EndTime := GetTickCount;
writeln("Recording complete. Time is ",
(EndTime - startTime)/1000, " sec");
write("press <Enter>");
readln;
end.

%-)))))))))))))))
Требует примерно 150 Мб оперативки Ж-)


 
Forever   (2002-10-13 16:09) [15]

TTCustomDelphiMaster, не понял. Ну включил биты.
А где сортировка ? Ведь телефоны то по возрастанию нужно отсортировать...


 
Romkin ©   (2002-10-13 16:19) [16]

А когда массивбитов проходишь последовательно, в выходной файл пишешь номер бита, если он взведен - это и есть номер телефона, они получатся по возрастанию %-)) И только те, которые есть в исходном файле. Задача решена.
А кто говорил, что нужно обязательно сортировать?


 
TTCustomDelphiMaster ©   (2002-10-13 16:19) [17]

...
for i:=0 to 10000000 do // Вот и сортировка :)
if GetBit(i) then
writeln(f, inttostr(i));
...

function GetBit(i: integer): boolean; проверяет i-ый бит.


 
Forever   (2002-10-13 16:28) [18]

А почему они по возрастанию получаются ?


 
Romkin ©   (2002-10-13 16:34) [19]

Потому что в цикле for I по порядку нарастает!!!!


 
Romkin ©   (2002-10-13 17:48) [20]

Классическое решение задачи 1:
вывод в файл, так удобнее

program Rnd1toN;

{$APPTYPE CONSOLE}

uses
SysUtils;

const
N = 2500;

type
TMySort = array [1..N] of integer;

var
MySort: TMySort;
i, k, T: integer;
FileName: string;
MyFile: textFile;

begin
writeLn("Enter the name of result file, please: ");
readln(FileName);
assignFile(MyFile,FileName);
rewrite(MyFile);
try
//initialization
for i := 1 to N do
MySort[i] := i;
randomize;
//main block
for i := 1 to N do
begin
k := random(N - i + 1) + i;
T := MySort[i];
MySort[i] := MySort[k];
MySort[k] := T;
end;
//write result
for i := 1 to N do
writeln(MyFile, IntToStr(MySort[i]));
finally
closeFile(MyFile);
end;
writeln("Done!");
readln;
end.


 
Anatoly Podgoretsky ©   (2002-10-13 18:04) [21]

Давай для интереса приведи решение с TBits простое и экономичное, для отсортированного списак телефонов от "0000000" до "9999999", то о чем в чате говорили.
Интересно многим будет


 
TTCustomDelphiMaster ©   (2002-10-13 18:07) [22]

Первую задачу можно решить по принципу волчка из передачи "что-где-когда". Заполняем массив числами от 1 до N. Выбираем случайно число. На его место записываем пусто, а число выводим. Если в выбраном месте пусто, то двигаемся по стрелке.

Пока писал первый вариант, придумал еше один.
Заполняем массив числами от 1 до N. Выбираем случайно число. На место выбранного перекладывается число из конца массива, и размер массива уменьшается на 1.


 
Malder ©   (2002-10-13 19:41) [23]

Типа:

var M: of integer;
i:integer;
...
setlength(M,N-1);
randomize;
while Length(M)>0 then
begin
i:=int(Random(Length(M)-1));
writeln(F,M[i]);
M[i]:=M[length(M)-1]
setlength(M,length(M)-1);
end;


 
TTCustomDelphiMaster ©   (2002-10-13 20:06) [24]

Типа да, только размер массива не надо уменьшать каждый раз. Достаточно уменьшать значение переменной в которой записана его длина.


 
Oleg_Gashev ©   (2002-10-13 20:25) [25]

У меня было похожее решение первой задачи. Инициализируем масив A[i]:=i и пробегаем все элементы масива подряд, меняя каждый элемент масива с элементом, выбранным случайным образом.


 
TTCustomDelphiMaster ©   (2002-10-13 21:17) [26]

program Rnd1toN;
{$APPTYPE CONSOLE}
uses SysUtils;

const
N = 2500;

type
TMySort = array [1..N] of integer;

var
MySort: TMySort;
i, k: integer;
FileName: string;
MyFile: textFile;

begin
writeLn("Enter the name of result file, please: ");
readln(FileName);
assignFile(MyFile,FileName);
rewrite(MyFile);
try
randomize;
for i := N downto 1 do
MySort[i] := i;
for i := N downto 1 do
begin
k := random(i) + 1;
writeln(MyFile, IntToStr(MySort[k]));
MySort[k] := MySort[i];
end;
finally
closeFile(MyFile);
end;
writeln("Done!");
readln;
end.



Страницы: 1 вся ветка

Текущий архив: 2002.10.31;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.01 c
4-101563
@andrew
2002-09-18 12:53
2002.10.31
Объясните тупому: после CreateProcess(......., si, pi)


14-101440
MVova
2002-10-10 11:36
2002.10.31
Почему ICQ а не MSN


3-101093
Юра
2002-10-09 12:02
2002.10.31
Картинки формата jpg в Paradox


14-101471
Mad_Ghost
2002-10-11 14:02
2002.10.31
Операции сдвига в Delphi


4-101590
PaNiC
2002-09-19 18:40
2002.10.31
Помогите!!! Отдебагить дочерний процесс!!! ;-)