Advertisement
DavidRogers13s

Infection

Oct 16th, 2014
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.97 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Drawing;
  7. using System.Drawing.Imaging;
  8. using ImageMagick;
  9. using System.IO;
  10.  
  11. namespace Infection
  12. {
  13.     class Program
  14.     {
  15.         #region Infection Options
  16.         private const double ProbabilityOfTransmission = .2;
  17.         private const double ChanceOfMutation = 0.01;
  18.         private const Int16 StageSize = 1000;
  19.         private const Int16 MaxNumberOfMutations = 800;
  20.         private const byte MaxInfectionTime = 3;
  21.         private const byte NumberOfPeopleToRandomlyInfect = 4;
  22.         private static int NumberOfPeriods = 1000;
  23.         #endregion Infection Options
  24.  
  25.         #region Run Options
  26.         private const bool VerbosMode = false;        
  27.         private const int ImageFrequency = 10;
  28.         #endregion Run Options
  29.  
  30.         #region Stage        
  31.         private static Int16 MutationNumber = 1;
  32.  
  33.         private class Person
  34.         {
  35.             public Person()
  36.             {
  37.                 PreviousInfections = new Dictionary<Int16, byte>();
  38.                 InfectionTime = 0;
  39.                 CurrentInfection = 0;
  40.                 PossibleNewInfections = new List<short>(4);
  41.             }
  42.             public Dictionary<Int16, byte> PreviousInfections { get; set; }
  43.             public byte InfectionTime { get; set; }
  44.             public Int16 CurrentInfection { get; set; }
  45.             public List<Int16> PossibleNewInfections { get; set; }
  46.         }
  47.         private static Person[][] Stage = new Person[StageSize][];
  48.         #endregion Stage
  49.  
  50.         static void Main(string[] args)
  51.         {
  52.             DateTime start = DateTime.UtcNow;
  53.  
  54.             //Initialize stage
  55.             for (Int16 i = 0; i < Stage.Length; i++)
  56.             {
  57.                 var tmpList = new List<Person>();
  58.                 for (Int16 j = 0; j < Stage.Length; j++)
  59.                     tmpList.Add(new Person());
  60.                 Stage[i] = tmpList.ToArray();
  61.             }
  62.  
  63.             //Randomly infect people
  64.             RandomlyInfectPeople(NumberOfPeopleToRandomlyInfect);
  65.  
  66.             //Run through the periods(NumberOfPeriods times)
  67.             List<MagickImage> output = new List<MagickImage>();
  68.             while (NumberOfPeriods > 0)
  69.             {
  70.                 //Print details(verbose)                
  71.                 if (VerbosMode && NumberOfPeriods % ImageFrequency == 0)
  72.                 {
  73.                     Console.WriteLine("Current Number: " + NumberOfPeriods);
  74.                     Console.WriteLine("Current Mutation: " + MutationNumber);
  75.                     output.Add(BoardToImage());
  76.                 }
  77.  
  78.                 Period();
  79.             }
  80.  
  81.             //Outputs a Animated Gif(verbose)
  82.             if (VerbosMode)
  83.             {
  84.                 ImagesToAnimatedGIF(output.ToArray(), Directory.GetCurrentDirectory() + "\\Output.gif");
  85.                 System.Diagnostics.Process.Start(Directory.GetCurrentDirectory() + "\\Output.gif");
  86.             }
  87.             //Only outputs the basic result image matching the specs
  88.             SaveBoardToSimpleImage(Directory.GetCurrentDirectory() + "\\FinalState.gif");
  89.  
  90.             Console.WriteLine("Total run time in seconds: " + (DateTime.UtcNow - start).TotalSeconds);
  91.             Console.WriteLine("Press enter to exit");
  92.             Console.ReadLine();
  93.         }
  94.  
  95.         #region Image
  96.         private static void SaveBoardToSimpleImage(string filepath)
  97.         {
  98.             using (Bitmap img = new Bitmap(StageSize, StageSize))
  99.             {
  100.                 for (int i = 0; i < img.Width; i++)
  101.                     for (int j = 0; j < img.Height; j++)
  102.                         img.SetPixel(i, j, Stage[i][j].CurrentInfection == 0 ? Color.FromArgb(255, 255, 255) :
  103.                             Color.FromArgb(64, 255, 0));
  104.                 img.Save(filepath, ImageFormat.Gif);
  105.             }
  106.         }
  107.         private static MagickImage BoardToImage()
  108.         {
  109.             using (Bitmap img = new Bitmap(StageSize, StageSize))
  110.             {
  111.                 for (int i = 0; i < img.Width; i++)
  112.                     for (int j = 0; j < img.Height; j++)
  113.                         img.SetPixel(i, j, Stage[i][j].CurrentInfection == 0 ? Color.White :
  114.                             Color.FromArgb(Stage[i][j].CurrentInfection % 255,
  115.                             Math.Abs(Stage[i][j].CurrentInfection - 255) % 255,
  116.                             Math.Abs(Stage[i][j].CurrentInfection - 510) % 255));
  117.                 return new MagickImage(img);
  118.             }
  119.         }
  120.         private static void ImagesToAnimatedGIF(MagickImage[] images, string filepath)
  121.         {
  122.             using (MagickImageCollection collection = new MagickImageCollection())
  123.             {
  124.                 foreach (var image in images)
  125.                 {
  126.                     collection.Add(image);
  127.                     collection.Last().AnimationDelay = 20;
  128.                 }
  129.                 collection.Write(filepath);
  130.             }
  131.         }
  132.         #endregion Image
  133.  
  134.         #region Infection
  135.         private static void Period()
  136.         {
  137.             Infect();
  138.             ChooseRandomInfections();
  139.             IncrementDiseaseProgress();
  140.             Cure();
  141.  
  142.             NumberOfPeriods--;
  143.         }
  144.         private static void Cure()
  145.         {
  146.             Parallel.For(0, Stage.Length, i =>
  147.             {
  148.                 for (Int16 j = 0; j < Stage.Length; j++)
  149.                     if (Stage[i][j].CurrentInfection != 0 && Stage[i][j].InfectionTime == MaxInfectionTime + 1)
  150.                     {
  151.                         //Add disease to already infected list
  152.                         if (Stage[i][j].PreviousInfections.ContainsKey(Stage[i][j].CurrentInfection))
  153.                             Stage[i][j].PreviousInfections[Stage[i][j].CurrentInfection]++;
  154.                         else
  155.                             Stage[i][j].PreviousInfections.Add(Stage[i][j].CurrentInfection, 1);
  156.  
  157.                         //Cure
  158.                         Stage[i][j].InfectionTime = 0;
  159.                         Stage[i][j].CurrentInfection = 0;
  160.                     }
  161.             });
  162.         }
  163.         private static void IncrementDiseaseProgress()
  164.         {
  165.             Parallel.For(0, Stage.Length, i =>
  166.             {
  167.                 for (Int16 j = 0; j < Stage.Length; j++)
  168.                     if (Stage[i][j].CurrentInfection != 0)
  169.                         Stage[i][j].InfectionTime++;
  170.             });
  171.         }
  172.         private static void RandomlyInfectPeople(Int16 numberOfPeopleToInfect)
  173.         {
  174.             var randomList = new List<int>();
  175.             while (randomList.Count() < numberOfPeopleToInfect * 2)
  176.             {
  177.                 randomList.Add(RandomGen2.Next(StageSize));
  178.                 randomList = randomList.Distinct().ToList();
  179.             }
  180.             while (randomList.Count() > 0)
  181.             {
  182.                 Stage[randomList.Last()][randomList[randomList.Count() - 2]].CurrentInfection = MutationNumber;
  183.                 Stage[randomList.Last()][randomList[randomList.Count() - 2]].InfectionTime = 1;
  184.                 randomList.RemoveAt(randomList.Count() - 2);
  185.                 randomList.RemoveAt(randomList.Count() - 1);
  186.             }
  187.         }
  188.         private static void Infect()
  189.         {
  190.             Parallel.For(0, Stage.Length, i =>
  191.             {
  192.                 for (Int16 j = 0; j < Stage.Length; j++)
  193.                     InfectAllSpacesAround((short)i, j);
  194.             });
  195.         }
  196.         private static void InfectAllSpacesAround(Int16 x, Int16 y)
  197.         {
  198.             //If not infected or just infected this turn return
  199.             if (Stage[x][y].CurrentInfection == 0 || (Stage[x][y].CurrentInfection != 0 && Stage[x][y].InfectionTime == 0)) return;
  200.  
  201.             //Infect all four directions(if possible)
  202.             if (x > 0)
  203.                 InfectOneSpace(Stage[x][y].CurrentInfection, (short)(x - 1), y);
  204.  
  205.             if (x < Stage.Length - 1)
  206.                 InfectOneSpace(Stage[x][y].CurrentInfection, (short)(x + 1), y);
  207.  
  208.             if (y > 0)
  209.                 InfectOneSpace(Stage[x][y].CurrentInfection, x, (short)(y - 1));
  210.  
  211.             if (y < Stage.Length - 1)
  212.                 InfectOneSpace(Stage[x][y].CurrentInfection, x, (short)(y + 1));
  213.         }
  214.         private static void InfectOneSpace(Int16 currentInfection, Int16 x, Int16 y)
  215.         {
  216.             //If the person is infected, or If they've already been infected "MaxInfectionTime" then don't infect
  217.             if (Stage[x][y].CurrentInfection != 0 || (Stage[x][y].PreviousInfections.ContainsKey(currentInfection) &&
  218.                     Stage[x][y].PreviousInfections[currentInfection] >= MaxInfectionTime)) return;
  219.  
  220.             //If random is larger than change of transmission don't transmite disease
  221.             if (RandomGen2.Next(100) + 1 > ProbabilityOfTransmission * 100) return;
  222.  
  223.             //Possible mutate
  224.             if (MutationNumber <= MaxNumberOfMutations && RandomGen2.Next(100) + 1 <= ChanceOfMutation * 100)
  225.                 lock (Stage[x][y])
  226.                 {
  227.                     MutationNumber++;
  228.                     Stage[x][y].PossibleNewInfections.Add(MutationNumber);
  229.                 }
  230.             //Regular infection
  231.             else
  232.                 lock (Stage[x][y])
  233.                     Stage[x][y].PossibleNewInfections.Add(currentInfection);
  234.  
  235.         }
  236.         private static void ChooseRandomInfections()
  237.         {
  238.             Parallel.For(0, Stage.Length, i =>
  239.             {
  240.                 for (Int16 j = 0; j < Stage.Length; j++)
  241.                 {
  242.                     if (Stage[i][j].CurrentInfection != 0 || !Stage[i][j].PossibleNewInfections.Any()) continue;
  243.                     Stage[i][j].CurrentInfection = Stage[i][j].PossibleNewInfections[RandomGen2.Next(Stage[i][j].PossibleNewInfections.Count)];
  244.                     Stage[i][j].PossibleNewInfections.Clear();
  245.                     Stage[i][j].InfectionTime = 0;
  246.                 }
  247.             }
  248.             );
  249.         }
  250.         #endregion Infection
  251.     }
  252.  
  253.     //Fancy Schmancy new random number generator for threaded stuff, fun times
  254.     //http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx
  255.     public static class RandomGen2
  256.     {
  257.         private static Random _global = new Random();
  258.         [ThreadStatic]
  259.         private static Random _local;
  260.  
  261.         public static int Next()
  262.         {
  263.             Random inst = _local;
  264.             if (inst == null)
  265.             {
  266.                 int seed;
  267.                 lock (_global) seed = _global.Next();
  268.                 _local = inst = new Random(seed);
  269.             }
  270.             return inst.Next();
  271.         }
  272.  
  273.         public static int Next(int input)
  274.         {
  275.             Random inst = _local;
  276.             if (inst == null)
  277.             {
  278.                 int seed;
  279.                 lock (_global) seed = _global.Next();
  280.                 _local = inst = new Random(seed);
  281.             }
  282.             return inst.Next(input);
  283.         }
  284.     }
  285. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement