Advertisement
Guest User

worm wars 2

a guest
Aug 28th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 10.34 KB | None | 0 0
  1.  
  2. open System
  3.  
  4.  
  5. type Hosts = {suspectable:int; infected:int; immune:int}
  6.  
  7. type Network = {id:char; hosts:Hosts;}
  8.  
  9. type Link = { network1:char; network2:char; capacity:int }
  10.  
  11. type Rate = {S:float ; I:float; R:float}
  12.  
  13. type payload =
  14. |Destination of Char*Char*Char
  15. |Internal of Char
  16.  
  17. type deliverable = { parcel:payload; quantity:int }
  18.  
  19. //handles IO as results
  20. type IOWorkFlow() =
  21.  
  22.     member this.Bind(x, f) = Result.bind f x
  23.  
  24.     member this.Return(x) =  Ok x
  25.  
  26. let inputStreamWorkFlow = new IOWorkFlow()
  27.  
  28. //Natural number
  29. let (|Nat|_|) str =
  30.    match System.Int32.TryParse(str) with
  31.    | (true,int) when int > 0 -> Some(int)
  32.    | _ -> None
  33. //Integer greater then 0
  34. let (|ZeroNAT|_|) str =
  35.    match System.Int32.TryParse(str) with
  36.    | (true,int) when int >= 0 -> Some(int)
  37.    | _ -> None
  38.  
  39. let (|Float|_|) str =
  40.     match Double.TryParse(str) with
  41.     | (true,v)  when v > 0.0 ->  Some(v)
  42.     | _ -> None
  43. //checks string for a single character
  44. let (|Char|_|) (str:string) =
  45.     match str |> String.length with
  46.     | 1 -> Some (str |> Seq.head)
  47.     | _ -> None
  48.  
  49. let getNaturalNumber () =
  50.     match Console.ReadLine() with
  51.     | Nat v -> Ok v
  52.     | _ -> Error "invalid number, must be greater then 0"
  53.  
  54. let tryRead() =
  55.     match Console.ReadLine() with
  56.     | null -> Error "not Expecting empty input"
  57.     | v -> Ok v
  58.  
  59. let maybeNetwork (str:string) =
  60.     match str.Split(' ', StringSplitOptions.RemoveEmptyEntries) with
  61.     | [|Char c; Nat h; ZeroNAT i |] -> Ok {id = c; hosts = {suspectable = h-i ; infected = i; immune = 0} }
  62.     | _ -> Error "Invalid network"
  63.  
  64. let maybeLink (str:string) =
  65.    match str.Split(' ', StringSplitOptions.RemoveEmptyEntries) with
  66.    | [|Char c1; Char c2; Nat cap  |] -> Ok { network1=c1; network2=c2; capacity= cap}
  67.    | _ -> Error "Invalid Link networkID1(char) networkID2(char) capacity(int greater then 0)"
  68.  
  69. let maybeRate (str:string) =
  70.     match str.Split(' ', StringSplitOptions.RemoveEmptyEntries) with
  71.     | [|Float spread; Float infected; Float rate |] -> Ok {S = spread; I = infected; R = rate;}
  72.     | _ -> Error "Invalid Rate spread(float) infected(float) rate(float)"
  73.  
  74. let getNetworks n =
  75.     //Some kind of sequence or list to replace this?
  76.    let rec tryNewnetwork lis =
  77.  
  78.        printfn "enter network ID(char) hosts(integer greater then 0 ) infected(integer greater or equal to 0)"
  79.  
  80.        tryRead()
  81.        |> Result.bind(maybeNetwork)
  82.        |> Result.bind(fun x -> if not ( lis |> List.exists(fun y -> x.id = y.id)) then Ok x else Error "A network with that ID already exists")
  83.        |>function
  84.        | Ok  newNet -> match (newNet::lis)  with
  85.                         | v when List.length v  = n -> v
  86.                         | v -> tryNewnetwork v
  87.        | Error e ->  printfn "%s" e
  88.                      tryNewnetwork lis
  89.    tryNewnetwork []
  90.  
  91. let identicalLink link1 link2 =
  92.     ((link1.network1 = link2.network1 && link1.network2 = link2.network2 )||(link1.network1 = link2.network2 && link1.network2 = link2.network1))
  93.  
  94. let linkHasNetworks networkLis link1  =
  95.     List.exists(fun y -> link1.network1 = y.id) networkLis && List.exists(fun y -> link1.network2 = y.id) networkLis
  96.  
  97. let getLinks n networkLis =
  98.      //Some kind of sequence or list to replace this?
  99.    let rec trylistofLinks lis =
  100.  
  101.        printfn "enter Link networkID1(char) networkID2(char) capacity(int greater then 0)"
  102.  
  103.        tryRead()
  104.        |> Result.bind(maybeLink)
  105.        |> Result.bind(fun x -> match x.network1 = x.network2 with
  106.                                | false -> Ok x
  107.                                | true -> Error "can't connect to the same network")
  108.        |> Result.bind(fun x -> if not ( lis |> List.exists(fun y -> identicalLink x y ))
  109.                                 then Ok x
  110.                                 else Error "A Link connecting these two networks already exists")
  111.        |> Result.bind(fun x ->  match linkHasNetworks networkLis x with
  112.                                 | true -> Ok x
  113.                                 | false -> Error "Both networks need to exist")
  114.        |>function
  115.        | Ok  newLink-> match (newLink::lis)  with
  116.                         | v when List.length v = n -> v
  117.                         | v-> trylistofLinks v
  118.        | Error e ->  printfn "%s" e
  119.                      trylistofLinks lis
  120.    trylistofLinks []
  121.  
  122. let getRate () =
  123.     printfn "Enter rate spread(float) infected(float) rate(float)"
  124.     tryRead()
  125.     |> Result.bind maybeRate
  126.  
  127. let countLinkedSuspectHosts links  network =
  128.     links
  129.     |> List.filter(fun x -> x.network1 = network.id || x.network2 = network.id)
  130.  
  131. let generatePacketsonLink  connectedLis network  =
  132.     let rnd = System.Random()
  133.  
  134.     [0 .. network.hosts.infected ]
  135.     |> List.map( fun _ ->
  136.    
  137.             let indexToSend = rnd.Next( List.length connectedLis )
  138.             match indexToSend  with
  139.             | 0 -> Internal network.id
  140.             | _ -> let newdestination = (List.item indexToSend connectedLis  )
  141.                    Destination (newdestination.network1,newdestination.network2,network.id)
  142.     )      
  143.  
  144. let spreadInternally rate network internalSpread =
  145.     let rnd = System.Random()
  146.     let newlyInfected =  (float) network.hosts.suspectable * rate.I * rnd.NextDouble() + List.fold(fun accu x -> match x  with
  147.                                                                                                                  | Internal v -> accu+1.0
  148.                                                                                                                  | _ -> accu) 0.0 internalSpread
  149.                                                                                                                  |> int
  150.     {network with hosts ={network.hosts with suspectable = network.hosts.suspectable - newlyInfected ; infected = network.hosts.infected + newlyInfected; } } //Spreading the virus within the hosts
  151.  
  152. let fillLinks packetSize linkLis spreadPath = //sending data over the link this handles the dropping part due to high traffic
  153.         linkLis
  154.         |> List.map(fun x -> (x,x.capacity/packetSize)) //get the capcity
  155.         |> List.map(fun x -> List.filter(fun y -> match y with
  156.                                                   | Destination (v1,v2,_) when (fst x).network1 = v1 && (fst x).network2 = v2 -> true
  157.                                                   | _ -> false
  158.                                                   ) spreadPath
  159.  
  160.                              |> List.truncate (snd x) ) //take the capcity
  161.         |> List.concat
  162. let calculateExternallyInfectedHosts rate network newNum =
  163.     let rnd = System.Random()
  164.     let newlyInfected = (float)newNum * rate.I * rnd.NextDouble() |> int
  165.     let cappedInfected = if newlyInfected < network.hosts.suspectable then newlyInfected else network.hosts.suspectable
  166.     {network with hosts = {suspectable = network.hosts.suspectable - cappedInfected; infected = network.hosts.infected + cappedInfected; immune = network.hosts.immune}}
  167. //receiving virus from external packets                                                
  168. let spreadExternally rate networks packets =
  169.     networks
  170.     |> List.map(fun x -> calculateExternallyInfectedHosts rate x (List.length (List.filter (fun z -> match z with
  171.                                                                                                      | Destination (_,_,v3) when v3 = x.id-> true
  172.                                                                                                      | _ -> false
  173.                                                                                                      ) packets )))
  174. let immuniseAndRecover networks rate =
  175.     let rnd = System.Random()
  176.     networks
  177.     |> List.map(fun x ->
  178.        let newlyRecovered =   (float) x.hosts.infected * rnd.NextDouble() * rate.R |> int  
  179.        let newlyImmunised =   (float) x.hosts.suspectable * rnd.NextDouble() * rate.I |> int
  180.  
  181.        let cappedRecovered = if newlyRecovered < x.hosts.infected then newlyRecovered else x.hosts.infected
  182.        let cappedImmunised = if newlyImmunised < x.hosts.suspectable then newlyImmunised else x.hosts.suspectable
  183.  
  184.        {x with hosts = {suspectable = (x.hosts.suspectable - newlyImmunised); infected = x.hosts.infected - newlyRecovered ;immune = x.hosts.immune + newlyRecovered + newlyImmunised}}
  185.     )
  186. let simulate packetSize (networks:Network list) (links:Link List) rate  =
  187.     Seq.unfold(fun state ->
  188.         let pcktsize,rte,networkLis,linksLis = state
  189.        
  190.         let spreadPath =
  191.              networkLis
  192.              |> List.map(fun x -> let connectedInfo = countLinkedSuspectHosts linksLis  x
  193.                                   generatePacketsonLink  connectedInfo x
  194.                                   )
  195.              |> List.concat
  196.  
  197.  
  198.         let networksPostInternalSpread =
  199.              networkLis
  200.              |> List.map(fun x -> spreadInternally rte x (List.filter( fun y -> match y with
  201.                                                                                 |Internal v when v = x.id -> true
  202.                                                                                 | _ -> false) spreadPath))
  203.        
  204.         let culledLinks =  fillLinks pcktsize linksLis spreadPath    
  205.        
  206.         let exeternalSpreadNetwork = spreadExternally rte networksPostInternalSpread culledLinks
  207.        
  208.         //Todo immunisation
  209.         let finalNetwork = immuniseAndRecover exeternalSpreadNetwork rate
  210.  
  211.         Some (networkLis,(pcktsize,rte,finalNetwork,linksLis))
  212.     ) (packetSize, rate, networks, links )
  213.  
  214. let inputAll() =
  215.  
  216.     inputStreamWorkFlow
  217.         {
  218.            printfn "Enter Number of networks"
  219.            let! networks = getNaturalNumber()
  220.                            |> Result.map getNetworks
  221.            printfn "Enter Number of Links"
  222.            let! links = getNaturalNumber()
  223.                         |> Result.map (fun n -> getLinks n networks)
  224.                        
  225.            let! rate = getRate()
  226.  
  227.            printfn "Enter packet size"
  228.            let! packetSize = getNaturalNumber()
  229.            
  230.            return simulate packetSize networks links rate
  231.         }
  232.  
  233.  
  234. [<EntryPoint>]
  235. let main argv =
  236.     inputAll()
  237.     |>function
  238.     | Ok result -> result
  239.                    |> Seq.take 40
  240.                    |> Seq.iter( List.iter(  printfn "%A" ) )
  241.     | Error e -> printfn "%s" e
  242.     0 // return an integer exit code
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement