"Он повернулся, пнул дверь и вышел на крыльцо. Дождь словно только и ждал этого.
Только что он лениво моросил, а тут вдруг хлынул настоящим ливнем."
Аркадий и Борис Стругацкие. Гадкие лебеди.
Здравствуйте, уважаемые читатели!
Вот оно какое- лето! Жарко, зной словно выбелил небо...стоит только выглянуть на
солнце и просто чувствуешь, как на тебя обрушиваются потоки оглушающей и вязкой
теплоты, вот оно всемирное потепление :)
Но "вернёмся к нашим баранам", сегодня рассмотрим одно из применений клеточных
автоматов: модель просачивания жидкости через слой какого-то материала.
Просачивания - ага, сейчас только об этом и разговаривать :)
Сразу оговорюсь: модель эта достаточно грубая. Нус приступим:
модель я построил просто подредактировав исходный код игры Жизнь, который был
приведён в прошлом выпуске. Главная(и единственная) характеристика вещества в данной
задаче - коеффициент просачивания:
const double
p_LeakCoef=0.013;
изменяя это число вы можете посмотреть как будет меняться картина просачивания.
Размер поля я оставил прежний: 20x60 , одна клетка может находиться в
двух состояниях - она либо мокрая(wet), либо сухая(dry), причём если клетка мокрая,
то она в этом состоянии и остаётся, то есть обратных процессов нет. Таким образом
происходит обработка только сухих клеток. Переход ячейки из сухого состояния в
противоположное, происходит так:
подсчитывается число влажных соседей данной клетки в окрестности Мура,
генерируется псевдослучайное число функцией rand() , оно
делится на RAND_MAX для того, чтобы получить число в
пределах от 0 до 1 .
и, наконец, происходит сравнение псевдослучайного числа с произведением коеффициента
просачивания на число мокрых соседних клеток. Если произведение окажется больше
псевдослучайного числа, то мочим клетку :)
Note: Генерация псевдослучайных чисел.
#include<stdlib.h>
int rand(void);
void srand(unsigned seed);
rand() возвращает последовательность псевдослучайных чисел в диапазоне от 0 до RAND_MAX .
srand(seed) позволяет задать посредством аргумента seed новое начало для последовательности
псевдослучайных чисел, которые будут генерироваться последующими вызовами rand() . Если srand потом
будет вызвана с тем же аргументом, последовательнось генерирумых чисел поворится. Отсутствие
вызова srand перед вызовами rand эквивалентна начальному вызову srand с аргументом 1 .
// М.И.Беляков Мобильная операционная система М.:Радио и связь,1991
То есть картинка просачивания при одном и том ж коеффициенте просачивания будет
одинаковой от запуска к запуску. Но надеюсь вы догадались, как этого избежать.
|
А вот и исходник.
//////////////////////////////////////////////////////////////////////
//
// 8.cpp
// for model of leakage
// aka pampers =)
// issue N8
// Started: 16.07.03 9:10:12
//
// XIII
//////////////////////////////////////////////////////////////////////
// * - is wet cell
// a - will wet
#ifndef _8_CPP_
#define _8_CPP_ 1
#include<fstream.h>
#include<stdio.h> // for getchar()
#include<stdlib.h> // for rand()
char *prog_name="pampers v0.02";
// size of massive
#define P_SIZE 20
#define P_SIZEY 60
const double p_LeakCoef=0.013; // coefficient of leakage
// try to change it
typedef unsigned int uint;
// variables
char *file_name="pampers.txt";
fstream fs; // for manipulations with file
char p_mas[P_SIZE+2][P_SIZEY+2]; //massive
int p_i,p_j; // counter's
uint p_time=0; // age of model
uint p_coef=0; // coefficient for check cell
// functions
int in_file(char*); // get data from file and set massive
void calculate(uint,uint); // calculate one cell
int main()
{
// print Hello :)
cout<<"+---------------+\n";
cout<<"| Pampers :) |\n";
cout<<"| |\n";
cout<<"| XIII |\n";
cout<<"+---------------+"<<endl;
cout<<"press Enter for next step; for Exit press q"<<endl;
// set border
for(p_i=0;p_i<P_SIZEY+2;p_i++)
p_mas[0][p_i]=p_mas[P_SIZE+1][p_i]='-';
for(p_j=0;p_j<P_SIZE+2;p_j++)
p_mas[p_j][0]=p_mas[p_j][P_SIZEY+1]='|';
p_mas[P_SIZE+1][0]=p_mas[0][P_SIZEY+1]='+';
p_mas[0][0]=p_mas[P_SIZE+1][P_SIZEY+1]='+';
// set elements of p_mas zero
for(p_i=1;p_i<P_SIZE+1;p_i++)
{
for(p_j=1;p_j<P_SIZEY+1;p_j++)
p_mas[p_i][p_j]='0';
}
// get data
if(in_file(file_name))
return 1; // error open file
while(getchar()!='q')
{
cout<<"Time: "<<p_time++<<endl;
// print massive
for(p_i=0;p_i<P_SIZE+2;p_i++)
{
for(p_j=0;p_j<P_SIZEY+2;p_j++)
{
if(p_mas[p_i][p_j]=='a')
p_mas[p_i][p_j]='*'; // wet
if(p_mas[p_i][p_j]=='0')
cout<<" ";
else
cout<<p_mas[p_i][p_j];
}
cout<<endl;
}
// calculate next step
for(p_i=1;p_i<P_SIZE+1;p_i++)
{
for(p_j=1;p_j<P_SIZEY+1;p_j++)
calculate(p_i,p_j);
}
}
////////////
return 0;
}
int in_file(char*file)
{// get data from file and set life-massive
fs.open(file,ios::in);
if(!fs)
{// can't open file
cout<<"Error open file!\t"<<file_name<<endl;
return 1;
}
// get data
for(p_i=1;p_i<P_SIZE+1;p_i++)
{
for(p_j=1;p_j<P_SIZEY+1;p_j++)
fs>>p_mas[p_i][p_j];
}
fs.close();
return 0;
}
void calculate(uint x,uint y)
{// calculate one cell with x,y
switch(p_mas[x][y])
{
case 'a':
case '+':
case '|':
case '-':
case '*':
break;
case '0':// only for dry cell
//-------------------------------------//
p_coef=0;
if(p_mas[x][y-1]=='*') // west
p_coef++;
if(p_mas[x-1][y-1]=='*')// north-west
p_coef++;
if(p_mas[x-1][y]=='*')// north
p_coef++;
if(p_mas[x-1][y+1]=='*')// north-east
p_coef++;
if(p_mas[x][y+1]=='*')// east
p_coef++;
if(p_mas[x+1][y+1]=='*')// south-east
p_coef++;
if(p_mas[x+1][y]=='*')// south
p_coef++;
if(p_mas[x+1][y-1]=='*')// south-west
p_coef++;
//
// take pseudorandom number in the range 0 to 1.
// yes here very simple case; in reality,
// here must be equation with exp() ; i think so =)
//
if((double)rand()/RAND_MAX<p_LeakCoef*p_coef)
p_mas[x][y]='a';
//-------------------------------------//
break;
default:
break;
}
}
#endif
|
Теперь файл с данными называется pampers.txt .
Вот пример каким он может быть:
000000000000000000**********************00000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
или можете всю первую строчку сделать влажной :) экспериментируйте.
Сразу почему-то вспоминаются эти дурацкие рекламные ролики про памперсы и
прокладки ! :-)
Можно сказать, что модель у нас стохастическая, т.е. в ней присутствует
элемент случайности.
Пока!
|