Skip to content

Instantly share code, notes, and snippets.

@vietnt
Created March 27, 2016 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vietnt/9ada3dc6c179f51d559f to your computer and use it in GitHub Desktop.
Save vietnt/9ada3dc6c179f51d559f to your computer and use it in GitHub Desktop.
//// See the 'F# Tutorial' project for more help.
//
open System
type Command =
| Block of string * TimeSpan
| Unblock of string
| IsBlocked of string
let maxTimeSpan = TimeSpan.FromDays (365*1000 |> float)
let tryParseCommand (data: string) =
let parts = data.Split ([|' '|], StringSplitOptions.RemoveEmptyEntries)
match parts with
| [| "block"; ip |] -> Some <| Block (ip, maxTimeSpan)
| [| "block"; ip; time |] -> Some <| Block (ip, float time |> TimeSpan.FromSeconds)
| [| "unblock"; ip |] -> Some <| Unblock ip
| [| "is_blocked"; ip |] -> Some <| IsBlocked ip
| _ -> None
let processCommand command reply map =
match command with
| Block (ip, time) -> map |> Map.add ip (DateTime.Now + time)
| Unblock ip -> map |> Map.remove ip
| IsBlocked ip ->
let result =
match map |> Map.tryFind ip with
| None -> false
| Some expired -> expired > DateTime.Now
reply result
map
let loop reply state source =
source |> Seq.fold (fun map command -> map |> processCommand command reply) state
let readLines (path: string) = seq {
use reader = new System.IO.StreamReader (path)
while not reader.EndOfStream do
let line = reader.ReadLine()
yield line}
let load path =
path
|> readLines
|> Seq.choose tryParseCommand
|> loop ignore Map.empty
[<EntryPoint>]
let main argv =
let input = seq { while true do yield Console.ReadLine() }
let state = Map.empty // load "rules.txt"
let display ok =
printfn "%s" (if ok then "yes" else "no")
let _ =
input
|> Seq.choose tryParseCommand
|> loop display state
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment