-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sequences.fs
165 lines (137 loc) · 4.36 KB
/
Sequences.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
module Sequences
open System
open System.IO
type TestResult =
| Absent
| Excused
| Score of float
module TestResult =
let fromString s =
if s = "A" then
Absent
else if s = "E" then
Excused
else
let score = s |> float
Score score
let effectiveScore (testResult: TestResult) =
match testResult with
| Absent -> 0.0
| Excused -> 50.0
| Score score -> score
let tryEffectiveScore (testResult: TestResult) =
match testResult with
| Absent -> Some 0.0
| Excused -> None
| Score score -> Some score
type Student = {
Id: string
Surname: string
GivenName: string
MeanScore: float
MinScore: float
MaxScore: float
}
module Student =
let nameParts (s: string) =
let names = s.Split(",")
match names with
| [| surname; givenName |] -> {| Surname = surname.Trim(); GivenName = givenName.Trim() |}
| [| surname |] -> {| Surname = surname.Trim(); GivenName = "(None)" |}
| _ ->
raise <| FormatException $"Invalid name format: \"%s{s}\""
let fromString (s: string) =
let rows = s.Split('\t')
let name = rows[0] |> nameParts
let id = rows[1]
// let scores =
// rows
// |> Array.skip 2
// |> Array.map TestResult.fromString
// |> Array.map TestResult.effectiveScore
let scores =
rows
|> Array.skip 2
|> Array.map TestResult.fromString
|> Array.choose TestResult.tryEffectiveScore
let minScore = scores |> Array.min
let meanScore = scores |> Array.average
let maxScore = scores |> Array.max
{
Surname = name.Surname
GivenName = name.GivenName
Id = id
MeanScore = meanScore
MaxScore = maxScore
MinScore = minScore
}
let printSummary student =
printfn $"%s{student.Surname}\t%s{student.GivenName}\t%s{student.Id}\t%.1f{student.MeanScore}\t%.1f{student.MaxScore}\t%.1f{student.MinScore}"
let printGroupSummary (surname: string, students: Student[]) =
printfn $"%s{surname.ToUpperInvariant()}"
students
|> Array.sortBy _.GivenName
|> Array.iter(fun student ->
printfn $"\t%20s{student.GivenName}\t%s{student.Id}\t%0.1f{student.MeanScore}\t%0.1f{student.MaxScore}\t%0.1f{student.MinScore}\t")
let summarize filePath =
let rows =
filePath
|> File.ReadLines
|> Seq.cache
let count = (rows |> Seq.length) - 1
printfn $"Student count: %i{count}"
rows
|> Seq.skip 1
|> Seq.map Student.fromString
|> Seq.sortBy _.Surname
|> Seq.iter Student.printSummary
module Dates =
let from (startDate: DateTime) =
Seq.initInfinite (fun i -> startDate.AddDays(float i))
Dates.from DateTime.Now
|> Seq.filter (fun i -> i.Month = 1 && i.Day = 1)
|> Seq.truncate 10
|> Seq.iter (fun d -> printfn $"%i{d.Year} %s{d.DayOfWeek.ToString()}" )
module PellSequence =
let pell =
(0, 0, 0)
|>Seq.unfold (fun (n, pn2, pn1) ->
let pn =
match n with
| 0 | 1
-> n
| _
-> 2 * pn2 + pn1
let n' = n + 1
Some (pn, (n', pn1, pn)))
type Pell = { N: int; PN2: int; PN1: int }
let pell2 =
{ N = 0; PN2 = 0; PN1 = 0 }
|>Seq.unfold (fun initPell ->
let pn =
match initPell.N with
| 0 | 1
-> initPell.N
| _
-> 2 * initPell.PN2 + initPell.PN1
let n' = initPell.N + 1
Some (pn, {N = n'; PN2 = initPell.PN1; PN1 = pn}))
PellSequence.pell
|> Seq.truncate 10
|> Seq.iter (fun x -> printf $"%i{x}, ")
printfn "..."
module Drunkard =
let r = Random()
let step () =
r.Next(-1, 2)
type Position = { X: int; Y: int}
let walk =
{ X = 0; Y = 0}
|> Seq.unfold (fun position ->
let x' = position.X + step()
let y' = position.Y + step()
let position' = { X = x'; Y = y' }
Some(position', position'))
Drunkard.walk
|> Seq.take 10
|> Seq.iter (fun p -> printfn $"X: %i{p.X}, Y: %i{p.Y}")