Advertisement
Guest User

worm wars 2

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