Created
February 23, 2021 04:02
-
-
Save rosalogia/fb5060ae9d755d03fe96009e7ed2cfae to your computer and use it in GitHub Desktop.
Short F# script to generate problem sets of a specified size containing problems from multiple sections of a textbook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#r "nuget: FSharp.Json" | |
open FSharp.Json | |
open System.IO | |
type SubSection = | |
{ Name: string | |
; Weight: float | |
; ProblemRange: int * int } | |
type Section = | |
{ Name: string | |
; SubSections: SubSection list } | |
type ProblemSet = | |
{ Section: string | |
; Problems: (string * int list) list } | |
let fromRange (a, b) = [a..b] | |
let totalWeight section = | |
section.SubSections | |
|> List.map (fun it -> it.Weight) | |
|> List.reduce (+) | |
let selectProblems problemCount section (subsection: SubSection) = | |
// Number of questions that should be chosen from this subsection | |
let quantity = int (subsection.Weight / (totalWeight section) * (float problemCount)) | |
let problems = fromRange subsection.ProblemRange | |
let problemsLength = (snd subsection.ProblemRange) - (fst subsection.ProblemRange) | |
if quantity >= problemsLength then | |
(subsection.Name, problems) | |
else | |
// If there are more problems in the subsection than we want to include | |
// in the problemset, determine a number n such that we can choose | |
// every nth problem in the subsection to get as close as possible to | |
// the desired quantity | |
let nth = problemsLength / quantity | |
problems | |
|> List.indexed | |
|> List.filter (fun (i, _) -> i % nth = 0) | |
|> List.map snd | |
|> (fun plist -> (subsection.Name, plist)) | |
let genPSet problemCount section = | |
let problems = | |
section.SubSections | |
|> List.map (selectProblems problemCount section) | |
{Section = section.Name ; Problems = problems} | |
let args = System.Environment.GetCommandLineArgs() | |
let numberOfProblems = int args.[2] | |
let sectionDataPath = args.[3..] |> String.concat " " | |
File.ReadLines(sectionDataPath) | |
|> String.concat "\n" | |
|> Json.deserialize<Section list> | |
|> List.map (genPSet numberOfProblems) | |
|> printfn "%A" |
I'm pretty tempted to do so
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
rewrite it in Ada