একজন মহামারীবিদ হন!


13

চ্যালেঞ্জ

একদল লোকের চারপাশে কীভাবে রোগ ছড়িয়ে পড়ে তার একটি সাধারণ মডেল আপনাকে অবশ্যই তৈরি করতে হবে।

বিধি এবং প্রয়োজনীয়তা

মডেলটি অবশ্যই 1000 বাই 1000 2 ডি অ্যারে সহ প্রতিটি উপাদান আলাদা আলাদা ব্যক্তি হতে হবে।

আরজিভি ব্যবহার করে ব্যবহারকারীকে তিনটি ভেরিয়েবল ইনপুট করতে হবে: সংক্রমণ হওয়ার সম্ভাবনা (কেউ কীভাবে অন্য কাউকে সংক্রামিত করতে চলেছে), রূপান্তরকরণের সম্ভাবনা এবং সিমুলেশনটি কত সময়ের জন্য চালানো উচিত।

প্রথম পিরিয়ড ( t=0) এ, চার জনকে এলোমেলোভাবে বেছে নেওয়া উচিত এবং এই রোগে আক্রান্ত হতে হবে।

রোগটি যেভাবে আচরণ করে তা নিম্নলিখিত নিয়ম দ্বারা নিয়ন্ত্রিত হয়:

  • এই রোগটি কেবল পাশের ব্যক্তির দিকে চলে, অনুভূমিক এবং অনুভূমিকভাবে চলতে পারে।
  • সংক্রমণ প্রতিটি ব্যক্তির মধ্যে 3 পিরিয়ড অবধি থাকে। আপনি অনাক্রম্যতা ফ্যাক্টর নাও থাকতে পারেন।
  • কোনও ব্যক্তি তিনবার সংক্রামিত হওয়ার পরে, তারা প্রতিরোধক এবং আবার সংক্রামিত হতে পারে না।
  • পূর্ববর্তী রোগ প্রতিরোধী ব্যক্তিদের এই নতুন রূপান্তরিত রোগের জন্য ঝুঁকিপূর্ণ করে তুলতে এই রোগটি পরিবর্তন হতে পারে। রূপান্তরিত রোগের হুবহু একই বৈশিষ্ট্য রয়েছে এবং মূল রোগের মতো একই নিয়ম অনুসরণ করে।
  • যদি কোনও রূপান্তর ঘটে তবে পুরো রোগের পরিবর্তন হয় না, কেবল সেই নির্দিষ্ট 'প্যাকেট' সংক্রমণ করার পরে।
  • একবার কোনও ব্যক্তি একটি ভাইরাস দ্বারা সংক্রামিত হয়ে গেলে, বর্তমান সংক্রমণটি পাস না হওয়া পর্যন্ত তারা আবার সংক্রামিত হতে পারে না।
  • যদি কোনও ব্যক্তি আক্রান্ত হয় তবে তারা সংক্রমণের সময় শুরু থেকে শেষ অবধি সংক্রামক।
  • অনাক্রম্যতার কোনও স্তর নেই - একজন ব্যক্তি হয় অনাক্রম্য হয় বা হয় না।
  • মেমরির ওভারলোড বন্ধ করতে সর্বোচ্চ 800 টি রূপান্তরের সীমা রয়েছে।

নির্দিষ্ট সময়সীমার শেষে, আপনাকে ফলাফলগুলি আউটপুট করা উচিত।

ফলাফলগুলি অবশ্যই 1000 x 1000 গ্রিডের হতে হবে যা দেখায় যে লোকেরা সংক্রামিত এবং কোনটি লোকেরা আক্রান্ত নয়। এটি একটি টেক্সট ফাইল হিসাবে কোনও চিত্র ফাইল বা গ্রাফিক্যাল আউটপুট হিসাবে আউটপুট হতে পারে (যেখানে #FFFFFF স্বাস্থ্যবান ব্যক্তি এবং # 40FF00 একটি সংক্রামিত ব্যক্তি)।

দয়া করে আপনি আপনার উত্তরটিতে ভাষার নাম এবং এটি চালানোর জন্য একটি আদেশ অন্তর্ভুক্ত করতে পারেন।

জয়লাভ

আমার কম্পিউটারে চালানো সবচেয়ে দ্রুত কোড। এর সময়টি পাইথন কোডের নীচের অংশের সাথে পরিমাপ করা হবে:

import time, os
start = time.time()
os.system(command)
end = time.time()
print(end-start)

মনে রাখবেন যে এই স্ক্রিপ্টটি চালানোর সময়, আমি নিম্নলিখিত ডিফল্টগুলি ব্যবহার করব:

Probability of transmission = 1
Chance of mutation = 0.01
Number of periods = 1000

3
আপনি একটি 10- গিগাবিট ফাইল তৈরি করতে চান ?
Ypnypn

1
4 গিগাবাইট সীমাবদ্ধতা রেখে আপনি চিত্র ফাইলে আউটপুট সংরক্ষণের বিকল্পটি পুরোপুরি সরিয়ে
অপ্টিমাইজার

10
1000x1000 : এটি এর মতো আরও!
COTO

1
এও বলুন যে একে অপরের পাশে দু'জন লোক আছেন। প্রথম চুক্তি ভাইরাস V, দ্বিতীয়টি ভাইরাস সংক্রমণ করে V'। সংকোচনের একই সময়ে উভয়ই শেষ হবে। ভাইরাস Vদ্বিতীয় ব্যক্তিকে সংক্রামিত করতে পারে ? (বা আরও কালো-সাদা প্রশ্ন: কোনও ব্যক্তি কি সুস্থ হওয়ার পরে অবিলম্বে সংক্রামিত হতে পারে, তাই তিনি সংক্রমণের
টানা

1
আরেকটি, দুটি স্বাধীন ভাইরাস একই ভাইরাসে রূপান্তর করতে পারে? আমরা আছে বলুন Vব্যক্তি A, এবং Vব্যক্তির মধ্যে আবার B। যখন তারা ভাইরাস সংক্রমণ করে, তখন তারা উভয়ই একই রূপান্তরিত হতে পারে V'? অথবা সম্ভবত তাদের একই ভাইরাস স্ট্রেনে পরিবর্তিত হওয়া উচিত ? যদি তারা নির্বিচারে পরিবর্তন করতে পারে তবে একই ভাইরাসের স্ট্রেনে দুটি ভাইরাস পরিবর্তনের সম্ভাবনা কত?
justhalf

উত্তর:


10

আমি এটি দেখতে দেখতে কৌতূহল ছিলাম তাই আমি জাভাস্ক্রিপ্টে এই দ্রুত এবং নোংরা হ্যাকটি তৈরি করেছি: http://jsfiddle.net/andrewmaxwell/r8m54t9c/

// The probability that a healthy cell will be infected by an adjacent infected cell EACH FRAME.
var infectionProbability = 0.2

// The probability that the infection will mutate on transmission EACH FRAME.
var mutationProbability = 0.00001

// The maximum number of times a cell can be infected by the same infection.
var maxInfections = 3

// The number of frames a cell in infected before it becomes healthy again.
var infectionDuration = 3

// The width and heigh of the board
var size = 400

// The number of cells infected at the beginning.
var startingNum = 4

var imageData, // the visual representation of the board
    cells, // array of cells
    infectionCount // counter that is incremented whenever a mutation occurs

// Just some colors. The colors are re-used as the number of mutations increases.
var colors = [[255,0,0],[255,255,0],[0,255,0],[0,255,255],[0,0,255],[255,0,255],[128,0,0],[128,128,0],[0,128,0],[0,128,128],[0,0,128],[128,0,128],[255,128,128],[255,255,128],[128,255,128],[128,255,255],[128,128,255],[255,128,255]
]

// when a cell is infected, it isn't contagious until the next frame
function infect(person, infection){
    person.infect = true
    person.infectionCounts[infection] = (person.infectionCounts[infection] || 0) + 1
    person.currentInfection = infection
}

// when a mutation occurs, it is given a number and the counter is incremented
function mutation(){
    return infectionCount++
}

function reset(){

    cells = []
    infectionCount = 0
    imageData = T.createImageData(size, size)

    // initialize the cells, store them in a grid temporarily and an array for use in each frame
    var grid = []
    for (var i = 0; i < size; i++){
        grid[i] = []
        for (var j = 0; j < size; j++){
            cells.push(grid[i][j] = {
                infectionTime: 0, // how many frames until they are no longer infected, so 0 is healthy
                infectionCounts: [], // this stores how many times the cell has been infected by each mutation
                neighbors: [] // the neighboring cells
            })
        }
    }

    // store the neighbors of each cell, I just want to minimize the work done each frame
    var neighborCoords = [[0,-1],[1,0],[0,1],[-1,0]]
    for (var i = 0; i < size; i++){
        for (var j = 0; j < size; j++){
            for (var n = 0; n < neighborCoords.length; n++){
                var row = i + neighborCoords[n][0]
                var col = j + neighborCoords[n][1]
                if (grid[row] && grid[row][col]){
                    grid[i][j].neighbors.push(grid[row][col])
                }
            }
        }
    }

    // infect the initial cells
    for (var i = 0; i < startingNum; i++){
        infect(cells[Math.floor(cells.length * Math.random())], 0)
    }
}

function loop(){
    requestAnimationFrame(loop)

    // for each cell marked as infected, set its infectionTime
    for (var i = 0; i < cells.length; i++){
        var p = cells[i]
        if (p.infect){
            p.infect = false
            p.infectionTime = infectionDuration
        }
    }

    for (var i = 0; i < cells.length; i++){
        var p = cells[i]

        // for each infected cell, decrement its timer
        if (p.infectionTime){
            p.infectionTime--

            // for each neighbor that isn't infected, if the probability is right and the neighbor isn't immune to that infection, infect it
            for (var n = 0; n < p.neighbors.length; n++){
                var neighbor = p.neighbors[n]
                if (!neighbor.infectionTime && Math.random() < infectionProbability){
                    var infection = Math.random() < mutationProbability ? mutation() : p.currentInfection
                    if (!neighbor.infectionCounts[infection] || neighbor.infectionCounts[infection] < maxInfections){
                        infect(neighbor, infection)
                    }
                }
            }

            // colors! yay!
            var color = colors[p.currentInfection % colors.length]
            imageData.data[4 * i + 0] = color[0]
            imageData.data[4 * i + 1] = color[1]
            imageData.data[4 * i + 2] = color[2]
        } else {
            imageData.data[4 * i + 0] = imageData.data[4 * i + 1] = imageData.data[4 * i + 2] = 0
        }

        imageData.data[4 * i + 3] = 255
    }

    T.putImageData(imageData, 0, 0)
}

// init canvas and go
C.width = C.height = size
T = C.getContext('2d')
reset()
loop()

1
সংক্রমণ স্থাপন 1-এ প্রোটোবিলিটিটি দেখেছি এমন কিছু মিষ্টি নমুনা তৈরি করেছে!
উইলিয়াম বার্বোসা

আপনার প্রোগ্রামটি আপনার উত্তরে কতক্ষণ সময় নিতে পারে আপনি যুক্ত করতে পারেন?
বিটা ক্ষয়

7

সি ++ 11, 6-8 মিনিট

আমার টেস্ট রানটি আমার ফেডোরা 19, আই 5 মেশিনে প্রায় 6-8 মিনিট সময় নেয়। তবে রূপান্তরটির এলোমেলোতার কারণে এটি দ্রুততর হতে পারে বা তার থেকেও বেশি সময় নিতে পারে। আমি মনে করি স্কোরিংয়ের মানদণ্ডটি পুনরায় সাজানো দরকার।

ফলাফল সমাপ্তির শেষে পাঠ্য হিসাবে ছাপানো হয়, সুস্থ ব্যক্তি বিন্দু ( .) দ্বারা সংজ্ঞায়িত , সংক্ষিপ্ত ব্যক্তি দ্বারা তারকাচিহ্ন দ্বারা ( ) চিহ্নিত করা হয় *, যদি না ANIMATEপতাকাটি সত্য হিসাবে সেট না করা থাকে, তবে এটি ক্ষেত্রে এটি বিভিন্ন ভাইরাস সংক্রমণের জন্য সংক্রামিত লোকদের জন্য বিভিন্ন চরিত্র প্রদর্শন করবে।

এখানে 10x10, 200 পিরিয়ডের জন্য একটি জিআইএফ রয়েছে।

10x10Gif

মিউটেশন আচরণ

প্রতিটি রূপান্তর এর আগে কখনও দেখা যায় না এমন নতুন স্ট্রেন দেবে (সুতরাং এটি সম্ভব যে এক ব্যক্তি চারটি প্রতিবেশী মানুষকে ৪ টি স্বতন্ত্র স্ট্রেন দ্বারা সংক্রামিত করে), যদি না ৮০০ টি স্ট্রেন তৈরি না করা হয়, সেক্ষেত্রে কোনও ভাইরাস আর কোনও রূপান্তর ঘটবে না।

8 মিনিটের ফলাফলটি নিম্নলিখিত সংখ্যক সংক্রামিত লোক থেকে আসে:

সময়কাল 0, সংক্রামিত: 4
সময়কাল 100, সংক্রামিত: 53743
সময়কাল 200, সংক্রামিত: 134451
সময়কাল 300, সংক্রামিত: 173369
পিরিয়ড 400, সংক্রামিত: 228176
পিরিয়ড 500, সংক্রামিত: 261473
পিরিয়ড 600, সংক্রামিত: 276086
সময়কাল 700, সংক্রামিত: 265774 74
সময়কাল 800, সংক্রামিত: 236828
সময়কাল 900, সংক্রামিত: 221275

6 মিনিটের ফলাফল নিম্নলিখিতটি থেকে আসে:

সময়কাল 0, সংক্রামিত: 4
সময়কাল 100, সংক্রামিত: 53627
সময়কাল 200, সংক্রামিত: 129033 33
সময়কাল 300, সংক্রামিত: 186127
পিরিয়ড 400, সংক্রামিত: 213633
পিরিয়ড 500, সংক্রামিত: 193702
পিরিয়ড 600, সংক্রামিত: 173995
সময়কাল 700, সংক্রামিত: 157966
সময়কাল 800, সংক্রামিত: 138281
সময়কাল 900, সংক্রামিত: 129381

ব্যক্তির প্রতিনিধিত্ব

প্রতিটি ব্যক্তি 205 বাইট প্রতিনিধিত্ব করা হয়। ভাইরাস সংরক্ষণের জন্য চারটি বাইট এই ব্যক্তিটি চুক্তি করছেন, এই ব্যক্তি কতদিন আক্রান্ত হয়েছে তা সংরক্ষণের জন্য একটি বাইট এবং 200 বাইট সংরক্ষণের জন্য তিনি কতবার সংক্রমণ করেছেন ভাইরাসের প্রতিটি স্ট্রেনে (2 বিট প্রতিটি)। সম্ভবত সি ++ দ্বারা কিছু অতিরিক্ত বাইট-প্রান্তিককরণ করা হয়েছে তবে মোট আকারটি 200MB এর কাছাকাছি হবে। পরবর্তী পদক্ষেপটি সংরক্ষণ করার জন্য আমার কাছে দুটি গ্রিড রয়েছে, সুতরাং এটি মোট 400 এমবি ব্যবহার করে।

আমি প্রাথমিক পর্যায়ে প্রয়োজনীয় সময় কাটাতে (যা পিরিয়ডস <৪০০ অবধি অবধি কার্যকর)।

প্রোগ্রাম প্রযুক্তিগতকরণ

প্রতি 100 টি পদক্ষেপে এই প্রোগ্রামটি সংক্রামিত ব্যক্তির সংখ্যা মুদ্রণ করবে, যদি না ANIMATEপতাকা সেট না করা হয় , তবে সেক্ষেত্রে trueএটি প্রতি 100 মিমি পুরো গ্রিডটি মুদ্রণ করবে।

এর জন্য সি ++ 11 লাইব্রেরি প্রয়োজন ( -std=c++11পতাকা ব্যবহার করে সংকলন করুন , বা ম্যাক সহ clang++ -std=c++11 -stdlib=libc++ virus_spread.cpp -o virus_spread)।

ডিফল্ট মানগুলির জন্য বা এটির মতো যুক্তি ছাড়াই এটি চালনা করুন:

./virus_spread 1 0.01 1000

#include <cstdio>
#include <cstring>
#include <random>
#include <cstdlib>
#include <utility>
#include <iostream>
#include <deque>
#include <cmath>
#include <functional>
#include <unistd.h>

typedef std::pair<int, int> pair;
typedef std::deque<pair> queue;

const bool ANIMATE = false;
const int MY_RAND_MAX = 999999;

std::default_random_engine generator(time(0));
std::uniform_int_distribution<int> distInt(0, MY_RAND_MAX);
auto randint = std::bind(distInt, generator);
std::uniform_real_distribution<double> distReal(0, 1);
auto randreal = std::bind(distReal, generator);

const int VIRUS_TYPE_COUNT = 800;
const int SIZE = 1000;
const int VIRUS_START_COUNT = 4;

typedef struct Person{
    int virusType;
    char time;
    uint32_t immune[VIRUS_TYPE_COUNT/16];
} Person;

Person people[SIZE][SIZE];
Person tmp[SIZE][SIZE];
queue infecteds;

double transmissionProb = 1.0;
double mutationProb = 0.01;
int periods = 1000;

char inline getTime(Person person){
    return person.time;
}

char inline getTime(int row, int col){
    return getTime(people[row][col]);
}

Person inline setTime(Person person, char time){
    person.time = time;
    return person;
}

Person inline addImmune(Person person, uint32_t type){
    person.immune[type/16] += 1 << (2*(type % 16));
    return person;
}

bool inline infected(Person person){
    return getTime(person) > 0;
}

bool inline infected(int row, int col){
    return infected(tmp[row][col]);
}

bool inline immune(Person person, uint32_t type){
    return (person.immune[type/16] >> (2*(type % 16)) & 3) == 3;
}

bool inline immune(int row, int col, uint32_t type){
    return immune(people[row][col], type);
}

Person inline infect(Person person, uint32_t type){
    person.time = 1;
    person.virusType = type;
    return person;
}

bool inline infect(int row, int col, uint32_t type){
    auto person = people[row][col];
    auto tmpPerson = tmp[row][col];
    if(infected(tmpPerson) || immune(tmpPerson, type) || infected(person) || immune(person, type)) return false;
    person = infect(person, type);
    infecteds.push_back(std::make_pair(row, col));
    tmp[row][col] = person;
    return true;
}

uint32_t inline getType(Person person){
    return person.virusType;
}

uint32_t inline getType(int row, int col){
    return getType(people[row][col]);
}

void print(){
    for(int row=0; row < SIZE; row++){
        for(int col=0; col < SIZE; col++){
            printf("%c", infected(row, col) ? (ANIMATE ? getType(row, col)+48 : '*') : '.');
        }
        printf("\n");
    }
}

void move(){
    for(int row=0; row<SIZE; ++row){
        for(int col=0; col<SIZE; ++col){
            people[row][col] = tmp[row][col];
        }
    }
}

int main(const int argc, const char **argv){
    if(argc > 3){
        transmissionProb = std::stod(argv[1]);
        mutationProb = std::stod(argv[2]);
        periods = atoi(argv[3]);
    }
    int row, col, size;
    uint32_t type, newType=0;
    char time;
    Person person;
    memset(people, 0, sizeof(people));
    for(int row=0; row<SIZE; ++row){
        for(int col=0; col<SIZE; ++col){
            people[row][col] = {};
        }
    }
    for(int i=0; i<VIRUS_START_COUNT; i++){
        row = randint() % SIZE;
        col = randint() % SIZE;
        if(!infected(row, col)){
            infect(row, col, 0);
        } else {
            i--;
        }
    }
    move();
    if(ANIMATE){
        print();
    }
    for(int period=0; period < periods; ++period){
        size = infecteds.size();
        for(int i=0; i<size; ++i){
            pair it = infecteds.front();
            infecteds.pop_front();
            row = it.first;
            col = it.second;
            person = people[row][col];
            time = getTime(person);
            if(time == 0) continue;
            type = getType(person);
            if(row > 0 && randreal() < transmissionProb){
                if(newType < VIRUS_TYPE_COUNT-1 && randreal() < mutationProb){
                    newType++;
                    if(!infect(row-1, col, newType)) newType--;
                } else {
                    infect(row-1, col, type);
                }
            }
            if(row < SIZE-1 && randreal() < transmissionProb){
                if(newType < VIRUS_TYPE_COUNT-1 && randreal() < mutationProb){
                    newType++;
                    if(!infect(row+1, col, newType)) newType--;
                } else {
                    infect(row+1, col, type);
                }
            }
            if(col > 0 && randreal() < transmissionProb){
                if(newType < VIRUS_TYPE_COUNT-1 && randreal() < mutationProb){
                    newType++;
                    if(!infect(row, col-1, newType)) newType--;
                } else {
                    infect(row, col-1, type);
                }
            }
            if(col < SIZE-1 && randreal() < transmissionProb){
                if(newType < VIRUS_TYPE_COUNT-1 && randreal() < mutationProb){
                    newType++;
                    if(!infect(row, col+1, newType)) newType--;
                } else {
                    infect(row, col+1, type);
                }
            }
            time += 1;
            if(time == 4) time = 0;
            person = setTime(person, time);
            if(time == 0){
                person = addImmune(person, type);
            } else {
                infecteds.push_back(std::make_pair(row, col));
            }
            tmp[row][col] = person;
        }
        if(!ANIMATE && period % 100 == 0) printf("Period %d, Size: %d\n", period, size);
        move();
        if(ANIMATE){
            printf("\n");
            print();
            usleep(100000);
        }
    }
    if(!ANIMATE){
        print();
    }
    return 0;
}

আমি সত্যিই এটি পছন্দ করি! আমার একটাই প্রশ্ন আপনি জিআইএফটি কীভাবে তৈরি করেন?
বিটা ক্ষয়

1
আমি এই সরঞ্জামটি ব্যবহার করছি: linux.die.net/man/1/byzanz-record । বর্তমানে এটির জিআইআই নেই, সুতরাং আপনার কমান্ড লাইন = ডি ব্যবহার করতে হবে
জাস্টহেল্ফ

ওহ, দুর্দান্ত, ধন্যবাদ! :)
বিটা ক্ষয়

3

সি # 6-7 মিনিট

সম্পাদনা 2

আমি অবশেষে (5 ঘন্টা) প্রতি 1 পিরিয়ডে 1000x1000 এ প্রায় 1000 পিরিয়ডের (শুধুমাত্র 840 ফ্রেম তখন এটি ক্র্যাশ হয়েছিল) এর জন্য ভার্বোজ আউটপুট তৈরি করেছি, তবে এটি 160MB এর কাছাকাছি এবং আমার সিস্টেমে সমস্ত স্মৃতি প্রদর্শন করার প্রয়োজন (ইরফানভিউ) এমনকি এটি নিশ্চিত নয় যে এটি কোনও ব্রাউজারে কাজ করবে, আমি এটি পরে রেখে দেব।

সম্পাদনা

"বিটা ক্ষয়" এর উত্তর অনুসারে এই আরও দক্ষ করে তুলতে আমি প্রচুর সময় ব্যয় করেছি, "স্ট্র্যান্ডটি এলোমেলোভাবে বেছে নিন" আমি প্রতি পিরিয়ডে কে সংক্রামিত হয় তা বেছে নেওয়ার জন্য কেবল এলোমেলো পদ্ধতি বেছে নিয়েছি, তবে আমি গণনার পদ্ধতিটি পরিবর্তন করেছি এবং প্রতিটি জিনিস থ্রেডেড, আমি আমার পোস্টগুলি নতুন বিবরণ দিয়ে আপডেট করেছি।

আমি এটি করতে পারার নিকটতম অনুমানকে কোড করেছিলাম, আমি আশা করি এটি সমস্ত নিয়ম অনুসরণ করে, এটি আমার সিস্টেমে এক টন মেমরি ব্যবহার করে (প্রায় 1.2 গিগাবাইট)। প্রোগ্রামটি অ্যানিমেটেড জিএফএস আউটপুট করতে পারে (দুর্দান্ত দেখায়, আস্তে আস্তে ধীরে ধীরে) বা "বিটা ক্ষয়" এর চশমার সাথে মেলে একটি চিত্র। এটি হুইলটি পুনর্সংশ্লিষ্ট করার সামান্য কিছু হলেও নিশ্চিতভাবে দুর্দান্ত দেখাচ্ছে:


ফলাফল

(দ্রষ্টব্য: এটি কেবল সংক্রামিত এবং অ সংক্রামিত, অর্থাত্ ভার্জোজ-এর মধ্যে পার্থক্য রাখে)

1000 পিরিয়ডস, 1% রূপান্তর হার, 100% স্প্রেড:

ফলাফল

উদাহরণ (শব্দবহুল)

যাইহোক যাইহোক, নন-ভার্বোস মোডে 100% "সংক্রমণের সম্ভাবনা" ব্যবহার করা এক ধরণের বিরক্তিকর কারণ আপনি সর্বদা একই আকার পান এবং আপনি বিভিন্ন বিবর্তন দেখতে পাচ্ছেন না, যদি আপনি কিছুটা পরামিতিগুলিকে টুইঙ্ক করেন (এবং ভার্বোজ মোড সক্ষম করে) আপনি কিছু দুর্দান্ত দেখায় আউটপুট পাবেন (অ্যানিমেটেড জিআইএফএস প্রতি 10 তম ফ্রেমে প্রদর্শিত হবে):

এলোমেলো - গ্রিডের আকার: 200, প্রোব ট্রান্সমিশন: 100%, প্রোব পরিবর্তন: 1%

100Precent

এলোমেলো - গ্রিডের আকার: 200, প্রোব ট্রান্সমিশন: 20%, প্রবণতা: 1%

20Precent

স্কোরিং

আমি "জাস্টহেলফ" এর সাথে একমত যে স্কোরিং মানদণ্ডটি যথাযথ নাও হতে পারে কারণ মিউটেশনের এলোমেলোতা এবং এলোমেলো শুরুর পয়েন্টগুলির অবস্থানের কারণে প্রতিটি রান আলাদা হয়। হতে পারে আমরা বেশ কয়েকটি রান বা এরকম কিছু গড় করতে পারি ..., যাইহোক যাইহোক এটি সি # তে আমার জন্য অনুগ্রহ করে :( যাইহোক।

কোড

ম্যাগিকআইমেজ লাইব্রেরিটি অন্তর্ভুক্ত করার বিষয়টি নিশ্চিত করুন (x64 বিট সংকলনের জন্য সেট) অন্যথায় এটি তৈরি করবে না ( http://pastebin.com/vEmPF1PM ):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using ImageMagick;
using System.IO;

namespace Infection
{
    class Program
    {
        #region Infection Options
        private const double ProbabilityOfTransmission = .2;
        private const double ChanceOfMutation = 0.01;
        private const Int16 StageSize = 1000;
        private const Int16 MaxNumberOfMutations = 800;
        private const byte MaxInfectionTime = 3;
        private const byte NumberOfPeopleToRandomlyInfect = 4;
        private static int NumberOfPeriods = 1000;
        #endregion Infection Options

        #region Run Options
        private const bool VerbosMode = false;        
        private const int ImageFrequency = 10;
        #endregion Run Options

        #region Stage        
        private static Int16 MutationNumber = 1;

        private class Person
        {
            public Person()
            {
                PreviousInfections = new Dictionary<Int16, byte>();
                InfectionTime = 0;
                CurrentInfection = 0;
                PossibleNewInfections = new List<short>(4);
            }
            public Dictionary<Int16, byte> PreviousInfections { get; set; }
            public byte InfectionTime { get; set; }
            public Int16 CurrentInfection { get; set; }
            public List<Int16> PossibleNewInfections { get; set; }
        }
        private static Person[][] Stage = new Person[StageSize][];
        #endregion Stage

        static void Main(string[] args)
        {
            DateTime start = DateTime.UtcNow;

            //Initialize stage
            for (Int16 i = 0; i < Stage.Length; i++)
            {
                var tmpList = new List<Person>();
                for (Int16 j = 0; j < Stage.Length; j++)
                    tmpList.Add(new Person());
                Stage[i] = tmpList.ToArray();
            }

            //Randomly infect people
            RandomlyInfectPeople(NumberOfPeopleToRandomlyInfect);

            //Run through the periods(NumberOfPeriods times)
            List<MagickImage> output = new List<MagickImage>();
            while (NumberOfPeriods > 0)
            {
                //Print details(verbose)                
                if (VerbosMode && NumberOfPeriods % ImageFrequency == 0)
                {
                    Console.WriteLine("Current Number: " + NumberOfPeriods);
                    Console.WriteLine("Current Mutation: " + MutationNumber);
                    output.Add(BoardToImage());
                }

                Period();
            }

            //Outputs a Animated Gif(verbose)
            if (VerbosMode)
            {
                ImagesToAnimatedGIF(output.ToArray(), Directory.GetCurrentDirectory() + "\\Output.gif");
                System.Diagnostics.Process.Start(Directory.GetCurrentDirectory() + "\\Output.gif");
            }
            //Only outputs the basic result image matching the specs
            SaveBoardToSimpleImage(Directory.GetCurrentDirectory() + "\\FinalState.gif");

            Console.WriteLine("Total run time in seconds: " + (DateTime.UtcNow - start).TotalSeconds);
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }

        #region Image
        private static void SaveBoardToSimpleImage(string filepath)
        {
            using (Bitmap img = new Bitmap(StageSize, StageSize))
            {
                for (int i = 0; i < img.Width; i++)
                    for (int j = 0; j < img.Height; j++)
                        img.SetPixel(i, j, Stage[i][j].CurrentInfection == 0 ? Color.FromArgb(255, 255, 255) :
                            Color.FromArgb(64, 255, 0));
                img.Save(filepath, ImageFormat.Gif);
            }
        }
        private static MagickImage BoardToImage()
        {
            using (Bitmap img = new Bitmap(StageSize, StageSize))
            {
                for (int i = 0; i < img.Width; i++)
                    for (int j = 0; j < img.Height; j++)
                        img.SetPixel(i, j, Stage[i][j].CurrentInfection == 0 ? Color.White :
                            Color.FromArgb(Stage[i][j].CurrentInfection % 255,
                            Math.Abs(Stage[i][j].CurrentInfection - 255) % 255,
                            Math.Abs(Stage[i][j].CurrentInfection - 510) % 255));
                return new MagickImage(img);
            }
        }
        private static void ImagesToAnimatedGIF(MagickImage[] images, string filepath)
        {
            using (MagickImageCollection collection = new MagickImageCollection())
            {
                foreach (var image in images)
                {
                    collection.Add(image);
                    collection.Last().AnimationDelay = 20;
                }
                collection.Write(filepath);
            }
        }
        #endregion Image

        #region Infection
        private static void Period()
        {
            Infect();
            ChooseRandomInfections();
            IncrementDiseaseProgress();
            Cure();

            NumberOfPeriods--;
        }
        private static void Cure()
        {
            Parallel.For(0, Stage.Length, i =>
            {
                for (Int16 j = 0; j < Stage.Length; j++)
                    if (Stage[i][j].CurrentInfection != 0 && Stage[i][j].InfectionTime == MaxInfectionTime + 1)
                    {
                        //Add disease to already infected list
                        if (Stage[i][j].PreviousInfections.ContainsKey(Stage[i][j].CurrentInfection))
                            Stage[i][j].PreviousInfections[Stage[i][j].CurrentInfection]++;
                        else
                            Stage[i][j].PreviousInfections.Add(Stage[i][j].CurrentInfection, 1);

                        //Cure
                        Stage[i][j].InfectionTime = 0;
                        Stage[i][j].CurrentInfection = 0;
                    }
            });
        }
        private static void IncrementDiseaseProgress()
        {
            Parallel.For(0, Stage.Length, i =>
            {
                for (Int16 j = 0; j < Stage.Length; j++)
                    if (Stage[i][j].CurrentInfection != 0)
                        Stage[i][j].InfectionTime++;
            });
        }
        private static void RandomlyInfectPeople(Int16 numberOfPeopleToInfect)
        {
            var randomList = new List<int>();
            while (randomList.Count() < numberOfPeopleToInfect * 2)
            {
                randomList.Add(RandomGen2.Next(StageSize));
                randomList = randomList.Distinct().ToList();
            }
            while (randomList.Count() > 0)
            {
                Stage[randomList.Last()][randomList[randomList.Count() - 2]].CurrentInfection = MutationNumber;
                Stage[randomList.Last()][randomList[randomList.Count() - 2]].InfectionTime = 1;
                randomList.RemoveAt(randomList.Count() - 2);
                randomList.RemoveAt(randomList.Count() - 1);
            }
        }
        private static void Infect()
        {
            Parallel.For(0, Stage.Length, i =>
            {
                for (Int16 j = 0; j < Stage.Length; j++)
                    InfectAllSpacesAround((short)i, j);
            });
        }
        private static void InfectAllSpacesAround(Int16 x, Int16 y)
        {
            //If not infected or just infected this turn return
            if (Stage[x][y].CurrentInfection == 0 || (Stage[x][y].CurrentInfection != 0 && Stage[x][y].InfectionTime == 0)) return;

            //Infect all four directions(if possible)
            if (x > 0)
                InfectOneSpace(Stage[x][y].CurrentInfection, (short)(x - 1), y);

            if (x < Stage.Length - 1)
                InfectOneSpace(Stage[x][y].CurrentInfection, (short)(x + 1), y);

            if (y > 0)
                InfectOneSpace(Stage[x][y].CurrentInfection, x, (short)(y - 1));

            if (y < Stage.Length - 1)
                InfectOneSpace(Stage[x][y].CurrentInfection, x, (short)(y + 1));
        }
        private static void InfectOneSpace(Int16 currentInfection, Int16 x, Int16 y)
        {
            //If the person is infected, or If they've already been infected "MaxInfectionTime" then don't infect
            if (Stage[x][y].CurrentInfection != 0 || (Stage[x][y].PreviousInfections.ContainsKey(currentInfection) &&
                    Stage[x][y].PreviousInfections[currentInfection] >= MaxInfectionTime)) return;

            //If random is larger than change of transmission don't transmite disease
            if (RandomGen2.Next(100) + 1 > ProbabilityOfTransmission * 100) return;

            //Possible mutate
            if (MutationNumber <= MaxNumberOfMutations && RandomGen2.Next(100) + 1 <= ChanceOfMutation * 100)
                lock (Stage[x][y])
                {
                    MutationNumber++;
                    Stage[x][y].PossibleNewInfections.Add(MutationNumber);
                }
            //Regular infection
            else
                lock (Stage[x][y])
                    Stage[x][y].PossibleNewInfections.Add(currentInfection);

        }
        private static void ChooseRandomInfections()
        {
            Parallel.For(0, Stage.Length, i =>
            {
                for (Int16 j = 0; j < Stage.Length; j++)
                {
                    if (Stage[i][j].CurrentInfection != 0 || !Stage[i][j].PossibleNewInfections.Any()) continue;
                    Stage[i][j].CurrentInfection = Stage[i][j].PossibleNewInfections[RandomGen2.Next(Stage[i][j].PossibleNewInfections.Count)];
                    Stage[i][j].PossibleNewInfections.Clear();
                    Stage[i][j].InfectionTime = 0;
                }
            }
            );
        }
        #endregion Infection
    }

    //Fancy Schmancy new random number generator for threaded stuff, fun times
    //http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx
    public static class RandomGen2
    {
        private static Random _global = new Random();
        [ThreadStatic]
        private static Random _local;

        public static int Next()
        {
            Random inst = _local;
            if (inst == null)
            {
                int seed;
                lock (_global) seed = _global.Next();
                _local = inst = new Random(seed);
            }
            return inst.Next();
        }

        public static int Next(int input)
        {
            Random inst = _local;
            if (inst == null)
            {
                int seed;
                lock (_global) seed = _global.Next();
                _local = inst = new Random(seed);
            }
            return inst.Next(input);
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.