Глава 38. Задание " Г "

Добавлено:
16.11.2016 23:39:29
Герман
Строка:
v:= (v+1+Random(2)) mod 3;
в:
- Код: Выделить всё
function PassWord_3: string;
var S: string; { результат }
v: integer; { вариант очередного символа }
C: char; { очередной символ }
begin
S:='';
v:= Random(3);
while Length(S)<8+Random(5) do begin
case v of
0: C:= Char(Random(10)+Ord('0'));
1: C:= Char(Random(26)+Ord('a'));
2: C:= Char(Random(26)+Ord('A'));
end;
S:= S+C;
v:= (v+1+Random(2)) mod 3;
end;
PassWord_3:=S;
end;
Ну очень интересно, сколько времени ушло на то, чтобы найти эту формулу.
Re: Глава 38. Задание " Г "

Добавлено:
17.11.2016 15:06:53
Oleg_D
Пара минут, наверное. Вы и сами скоро этому научитесь, а логика такова.
Имеем исходное число V, значение которого лежит в диапазоне 0..2 (0, 1, 2). Из него случайным образом надо получить другое число в этом же диапазоне. Это можно сделать прибавлением любого числа, не кратного трём (ноль прибавлять не имеет смысла). Стало быть, имеет смысл прибавить либо 1, либо 2 (либо 4, 5, 7, 8 …). Отсюда выражение 1+Random(2).
Разумеется, после сложения результат может оказаться больше 2, поэтому берём остаток от деления на 3.
Добавлено спустя 19 часов 37 минут 1 секунду:
Вот ещё один вариант решения той же проблемы: сформировать случайное число, отличное от текущего значения V:
var V, N : integer;
. . .
repeat N:= Random(3) until N<>V;
V:= N;
-----
Кстати, в нашей Галактике нередко случаются задачи, в которых надо формировать псевдо-случайные числа или их последовательности в соответствии с некоторыми требованиями. Например, сгенерировать случайное число, принадлежащее некоторому множеству S:
repeat N:= Random(100) until N in S;
Или не принадлежащее ему:
repeat N:= Random(100) until not (N in S);
В этой связи предлагаю всем желающим задачу: написать процедуру, выводящую на экран при каждом своём вызове группу из пяти чисел в диапазоне 0..99 так, чтобы числа следовали по возрастанию (или по убыванию). Например:
1) 18 31 40 90 91
2) 6 7 54 70 81
3) 49 77 89 95 97
и т.д.
Re: Глава 38. Задание " Г "

Добавлено:
18.11.2016 13:27:55
bormant
- Код: Выделить всё
procedure R5;
const u=100; n=5;
var a, i: Integer;
begin
a:=-1;
for i:=n-1 downto 0 do begin
a:=a+1+Random(u-1-a-i); Write(' ',a);
end; WriteLn;
end;
Хоть и просится на первый взгляд:
- Код: Выделить всё
procedure R5;
const u=100; n=5;
var a, p, i: Integer;
begin
i:=n; a:=-1;
repeat
p:=a; repeat a:=p+1+Random(u-p) until a<=u-i;
Write(' ',a); Dec(i);
until i=0; WriteLn;
end;
Re: Глава 38. Задание " Г "

Добавлено:
18.11.2016 20:07:41
Oleg_D
Первый вариант проверил -- работает. Но возникло сильное подозрение, что генерируемые числа чаще будут смещаться в бОльшую сторону. Из любопытства взялся проверить. Заодно проверил и свой вариант генерации такой последовательности. В представленной ниже программе формируется массив с плотностью распределения чисел в интервале 0..99. Для сокращения массива квант по оси X взят равным 5% (можно взять 2% или даже 1%).
Вот код:
- Код: Выделить всё
program Bormant;
const Cu=100; { диапазон генерируемых чисел }
Cn=5; { количество чисел в последовательности }
Cq=5; { квант для массива = 5% }
Cr=1000; { количество испытаний }
type TSet = set of byte;
{ массив для накопления результатов }
TArr = array [0..Cu div Cq -1] of integer;
var Arr : TArr; { массив для накопления результатов }
{ Накопление результатов в массиве }
procedure AddToArray(const aSet: TSet);
var i: integer;
begin
for i:=0 to 255 do begin
if i in aSet then Inc(Arr[i div Cq]);
end;
end;
{ Вывод массива в файл }
procedure ShowArray(var aFile: Text);
var i: integer;
pc : extended;
begin
for i:= 0 to Cu div Cq - 1 do begin
pc:= 100*(Arr[i]/(Cr*Cn));
Writeln(aFile, i*Cq:2,'-',(i+1)*Cq-1:2, pc:5:1,' %');
end;
end;
{ Генерация одной последовательности }
procedure _Bormant(var aSet: TSet);
var a, i: Integer;
begin
aSet:=[]; a:=-1;
for i:=Cn-1 downto 0 do begin
a:=a+1+Random(Cu-1-a-i);
aSet:= aSet + [a];
end;
end;
{ Генерация одной последовательности }
procedure _Oleg(var aSet: TSet);
var i, n: integer;
begin
aSet:=[];
for i:=1 to Cn do begin
repeat n:= Random(Cu) until not (n in aSet);
aSet:= aSet +[n];
end;
end;
var L: string;
S: TSet;
n: integer;
F: Text;
begin
FillChar(Arr, SizeOf(Arr), 0);
for n:= 1 to Cr do begin
_Bormant(S);
AddToArray(S);
end;
ShowArray(Output);
Assign(F,'Bormant.txt'); Rewrite(F);
ShowArray(F);
Close(F);
Writeln('- - - - - - - - - - - - - - -');
FillChar(Arr, SizeOf(Arr), 0);
for n:= 1 to Cr do begin
_Oleg(S);
AddToArray(S);
end;
ShowArray(Output);
Assign(F,'Oleg.txt'); Rewrite(F);
ShowArray(F);
Close(F);
Readln;
end.
Вот результат для _Bormant
- Код: Выделить всё
0- 4 1.0 %
5- 9 1.3 %
10-14 1.4 %
15-19 1.3 %
20-24 1.0 %
25-29 1.3 %
30-34 1.5 %
35-39 1.8 %
40-44 1.7 %
45-49 2.2 %
50-54 2.2 %
55-59 2.2 %
60-64 2.9 %
65-69 3.5 %
70-74 3.8 %
75-79 4.6 %
80-84 5.9 %
85-89 9.1 %
90-94 15.4 %
95-99 35.9 %
А это для _Oleg
- Код: Выделить всё
0- 4 5.6 %
5- 9 5.1 %
10-14 4.5 %
15-19 5.4 %
20-24 5.2 %
25-29 4.7 %
30-34 4.8 %
35-39 4.5 %
40-44 5.1 %
45-49 5.1 %
50-54 4.8 %
55-59 5.3 %
60-64 4.9 %
65-69 4.6 %
70-74 5.0 %
75-79 5.7 %
80-84 4.7 %
85-89 5.0 %
90-94 5.0 %
95-99 5.0 %
Побочный вывод: функция Random весьма неплохо справляется с генерацией равномерного распределения

Re: Глава 38. Задание " Г "

Добавлено:
18.11.2016 23:59:47
bormant
Oleg_D,
в условии не было ничего про распределение полученных 5 чисел

Безусловно, отсортированные 5 чисел (использование множества в этом случае -- вариант сортировки подсчетом) без повторов из диапазона 0..99 распределены более равномерно, чем из сужающегося к концу интервала.
Re: Глава 38. Задание " Г "

Добавлено:
19.11.2016 12:38:59
Oleg_D
bormant писал(а):в условии не было ничего про распределение полученных 5 чисел
Согласен. Это не претензия, а констатация факта, для полноты картины, так сказать.
Добавлено спустя 2 минуты 1 секунду:И, кстати, если бы потребовалась серия более чем из 5 чисел, ваш алгоритм мог бы забуксовать

Re: Глава 38. Задание " Г "

Добавлено:
19.11.2016 13:19:25
bormant
Нет оснований буксовать, обратите внимание на правую границу интервала при генерации ПСЧ, она гарантированно оставляет место для ещё n-1 чисел

Re: Глава 38. Задание " Г "

Добавлено:
19.11.2016 13:30:35
Oleg_D
Согласен, прошу прощения, не внимательно посмотрел.
Добавлено спустя 1 минуту 52 секунды:Кстати, у нас с вами одинаковое количество сообщений на форуме (на данный момент). С чего бы это?
