-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsonGcd.lean
More file actions
79 lines (66 loc) · 2.32 KB
/
Copy pathJsonGcd.lean
File metadata and controls
79 lines (66 loc) · 2.32 KB
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
import LeanExe.Ascii.Json
namespace LeanExe
namespace Examples.JsonGcd
def resultFieldName : ByteArray :=
"gcd".toUTF8
structure GcdState where
seen : Bool
failed : Bool
value : UInt64
def gcdFuel : Nat -> UInt64 -> UInt64 -> Option UInt64
| 0, _a, _b => none
| fuel + 1, a, b =>
if b == 0 then
some a
else
gcdFuel fuel b (a % b)
def gcd? (a b : UInt64) : Option UInt64 :=
gcdFuel 128 a b
def addRange (text : AsciiString) (state : GcdState) (range : Ascii.Json.FieldRange) :
GcdState :=
if state.failed then
state
else
match Ascii.Json.parseUInt64Range text range with
| none => { state with failed := true }
| some value =>
if state.seen then
match gcd? state.value value with
| some next => { state with value := next }
| none => { state with failed := true }
else
{ seen := true, failed := false, value := value }
def foldRangesFuel :
Nat -> AsciiString -> Array Ascii.Json.FieldRange -> Nat -> GcdState -> GcdState
| 0, _text, _ranges, _index, state => { state with failed := true }
| fuel + 1, text, ranges, index, state =>
if state.failed || index == ranges.size then
state
else
foldRangesFuel fuel text ranges (index + 1) (addRange text state ranges[index]!)
def foldRanges (text : AsciiString) (ranges : Array Ascii.Json.FieldRange) : GcdState :=
foldRangesFuel (ranges.size + 1) text ranges 0
{ seen := false, failed := false, value := 0 }
def gcdInput? (text : AsciiString) : Option UInt64 :=
match Ascii.Json.parseArrayRanges text with
| none => none
| some ranges =>
let state := foldRanges text ranges
if state.failed || !state.seen then
none
else
some state.value
def requireGcdInput (text : AsciiString) : Except ByteArray UInt64 :=
match gcdInput? text with
| some value => Except.ok value
| none => Except.error Ascii.Json.errorJson
def transformAscii (text : AsciiString) : Except ByteArray ByteArray :=
do
let value <- requireGcdInput text
pure (Ascii.Json.object1UInt64 resultFieldName value)
def transform (input : ByteArray) : Except ByteArray ByteArray :=
match AsciiString.ofByteArray? input with
| some text => transformAscii text
| none => Except.error Ascii.Json.errorJson
end Examples.JsonGcd
end LeanExe