Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник.docx
Скачиваний:
36
Добавлен:
21.12.2018
Размер:
2.15 Mб
Скачать

Пример, иллюстрирующий использование интервального типа и манипуляции над множествами

Задача:

Компьютер задумывает четырехзначное число, не содержащее двух одинаковых цифр. Вы набираете свое число, и компьютер сообщает количество быков (точно угаданных цифр) и количество коров (цифр, которые есть в задуманном числе, но на другом месте). Например, пусть задуманное число 5734, а вы набрали 0755. Результат будет 1 бык и 2 коровы. Игра продолжается до тех пор, пока вы не получите четыре быка.

Программа на языке Паскаль:

type

playtype = '0'..'9';

seedtype = 0..65535;

scoretype = 0..4;

var

pool, target: set of playtype;

a, b, c, d: playtype;

seed: seedtype;

bulls, cows: scoretype;

function random: real;

begin

random := seed / 65536;

seed := (25173 * seed + 13849) mod 65536;

end;

function unique: playtype;

var ch: char;

begin

repeat

ch := chr(trunc(10 * random) + ord('0'));

until ch in pool;

unique := ch;

pool := pool - [ch];

target := target + [ch];

end;

procedure try(thisone: char);

var ch: char;

begin

read(ch);

if ch in target then

if ch = thisone then

bulls := succ(bulls)

else

cows := succ(cows)

end;

begin

write('Загадайте случайное число, ');

writeln('затем отгадывайте');

readln(seed);

pool := ['0'..'9'];

target := [];

a := unique; b := unique; c := unique; d := unique;

repeat

bulls := 0; cows := 0;

try(a); try(b); try(c); try(d);

writeln('Быков: ', bulls:1, '; коров: ', cows:1);

readln

until bulls = 4;

readln

end.

Примечания:

Пользовательская функция random возвращает случайное число в интервале 0.0 <= random < 1.0.

Функция unique перемещает случайную цифру из pool в target.

Функция try читает следующую цифру и, если необходимо, увеличивает число быков или коров.

Псевдослучайные числа. Функция, возвращающая значение и меняющая параметр

Программа на языке Паскаль:

Рассмотрим такую программу:

var s, i: integer;

function next(var seed: integer): integer;

const

multiplier = 37;

increment = 3;

cycle = 64;

begin

next := seed;

seed := (multiplier * seed + increment) mod cycle

end;

begin

s := 16;

writeln(next(s));

writeln(next(s));

writeln(next(s));

writeln(next(s));

s := 16;

for i := 1 to 64 do

write(next(s):3);

readln

end.

Примечания:

Использование var в заголовке – необычный прием для функции.

Будучи вызвана с параметром s, содержащим число 16, эта функция возвращает число 16. Вместе с тем, возвращая 16, функция изменяет значение, хранящееся в переменной seed (или s), на 19. Если функцию вызвать снова, с полученным значением s, то она возвратит число 19 и изменит значение s на 2. Продолжая вызывать функцию next, получим определенную последовательность целых чисел, начинающуюся с исходного значения s (цикл for).

Замечательным свойством этой последовательности является то, что каждое значение от 0 до 63 встречается в ней один раз. Более того, шестьдесят пятый вызов функции next дает число 16 и начинается новый цикл. Другими словами, начиная с любого желаемого целого, функция генерирует фиксированную перестановку чисел от 0 до 63.

Такой прием используется преимущественно для генерации "случайных" чисел (правильнее их называть псевдослучайными – чтобы подчеркнуть их предсказуемость). Цикл из 64 чисел, конечно, слишком мал; Грогоно предлагает константы для генерации перестановки чисел от 0 до 65 535:

const multiplier = 25173; increment = 13849; cycle = 65536;

Подбор констант с нужными свойствами – нетривиальная задача.

Приведенная выше функция возвращает значение и изменяет значение параметра. Такой способ действий применяется нечасто. В большинстве функций нет необходимости изменять параметры, и, следовательно, нет смысла использовать слово var в заголовке.