Skip to content

Instantly share code, notes, and snippets.

@sgoguen
Created March 6, 2019 21:20
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 sgoguen/d20a727884cc744e3743f4e702ff9960 to your computer and use it in GitHub Desktop.
Save sgoguen/d20a727884cc744e3743f4e702ff9960 to your computer and use it in GitHub Desktop.
let items = [
"1 1/2 cup onions, diced"
"1/4 tsp coriander"
"1 medium carrot"
"1.5 oz olive oil"
"two lemons"
"mint"
]
let tokenize(s) = [ for t in Regex.Split(s, "\\b") do
if String.IsNullOrWhiteSpace(t) = false then
yield t ]
let units = Set.ofList ["cup"; "oz"; "tsp"]
let size = Set.ofList ["small"; "medium"; "large"]
let wordNums = ["zero"; "one"; "two"]
let (|Num|_|) s = if Regex.IsMatch(s, "^[0-9]+$") then Some(int(s)) else None
let (|WordNum|_|) s = wordNums |> List.tryFindIndex(fun w -> s = w)
let (|Unit|_|) s = if units.Contains(s) then Some(s) else None
let (|Size|_|) s = if size.Contains(s) then Some(s) else None
let (|Qty|_|) = function
| Num(w)::Num(n)::"/"::Num(d)::rest -> Some(float(w) + (float(n) / float(d)), rest)
| Num(n)::"/"::Num(d)::rest -> Some((float(n) / float(d)), rest)
| Num(n)::"."::Num(d)::rest -> Some(float(sprintf "%i.%i" n d), rest)
| Num(n)::rest -> Some(float(n), rest)
| WordNum(n)::rest -> Some(float(n), rest)
| list -> None
let oStr x = sprintf "%A" x // Just print in string format
let readIngredient line =
match tokenize line with
| Qty(qty, Unit(unit)::rest) -> oStr(qty, unit, rest)
| Qty(qty, Size(size)::rest) -> oStr(qty, size, rest)
| Qty(qty, rest) -> oStr(qty, rest)
| x -> oStr("Some", x)
items |> List.map readIngredient |> List.map (printfn "%A")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment