Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,5 @@ let sum = {
let predicate = fn(n) => (n % 3 == 0) || (n % 5 == 0)
inspect(sum(filter(predicate, range(1, 1000)))) # 233168
```

More project euler problems can be found in the [examples folder](https://github.com/mkhan45/RustScript2/tree/main/examples).
2 changes: 1 addition & 1 deletion examples/euler1.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let range = {

let filter = {
let helper = fn(f, ls, acc) => match ls
| (hd, ()) -> acc
| (_, ()) -> acc
| (hd, tl) ->
if f(hd)
then helper(f, tl, (hd, acc))
Expand Down
8 changes: 8 additions & 0 deletions examples/euler2.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
let euler2 = {
let aux = fn((a, b), acc) =>
if b < 4000000
then aux((b, a + 4 * b), acc + b)
else acc

aux((0, 2), 0)
}
44 changes: 44 additions & 0 deletions examples/euler3.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
let gcd = fn(a, b) => match (a, b)
| (0, b) -> b
| (a, 0) -> a
| (a, b) -> {
if a > b then {
gcd(b, a)
} else {
let remainder = b % a
if remainder != 0 then (gcd(a, remainder)) else a
}
}

let pollard = fn(n) => match n
| 1 -> ()
| n -> if n % 2 == 0 then {
2
} else {
let g = fn(x, n) => (x * x + 1) % n
let iter = fn(x, y, d) => match (x, y, d)
| (x, y, 1) -> {
let x = g(x, n)
let y = g(g(y, n), n)
let d = gcd(if (x > y) then (x - y) else (y - x), n)
iter(x, y, d)
}
| (_, _, d) -> if d == n then () else d

iter(2, 2, 1)
}

let largest_factor = fn(n) => {
let d = pollard(n)
if d == () then () else n / d
}

let euler3 = {
# repeatedly factors until largest is found
let aux = fn(n) => match largest_factor(n)
| () -> n
| f -> if n == f then f else aux(f)

let n = 600851475143
aux(n)
}
3 changes: 3 additions & 0 deletions lib/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ let rec bind lhs rhs =
(string_of_val (Tuple rhs_ls)) (List.length rhs_ls);
assert false
end
| WildcardPat, _ -> fun state -> state
| _ -> assert false

let rec pattern_matches pat value =
match pat, value with
| WildcardPat, _ -> true
| SinglePat _, _ -> true
| NumberPat lhs, Number rhs ->
Float.equal lhs rhs
Expand Down Expand Up @@ -147,6 +149,7 @@ and eval_expr: expr -> ?tc:bool -> state -> value * state =
| Binary ({op = Mul; _} as e) -> eval_op val_mul e.lhs e.rhs
| Binary ({op = Div; _} as e) -> eval_op val_div e.lhs e.rhs
| Binary ({op = EQ; _} as e) -> eval_op val_eq e.lhs e.rhs
| Binary ({op = NEQ; _} as e) -> eval_op val_neq e.lhs e.rhs
| Binary ({op = LT; _} as e) -> eval_op val_lt e.lhs e.rhs
| Binary ({op = GT; _} as e) -> eval_op val_gt e.lhs e.rhs
| Binary ({op = And; _} as e) -> eval_op val_and e.lhs e.rhs
Expand Down
4 changes: 3 additions & 1 deletion lib/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ let rec val_eq lhs rhs = match lhs, rhs with
in Boolean res
else
Boolean false
| _ -> assert false
| _ -> Boolean false

let val_neq lhs rhs = Boolean (not (val_is_true (val_eq lhs rhs)))

let val_lt lhs rhs = match lhs, rhs with
| Number lhs, Number rhs -> Boolean (Float.compare lhs rhs < 0)
Expand Down
9 changes: 5 additions & 4 deletions lib/parser.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ open Printf
open Base

let op_bp = function
| EQ -> (1, 2)
| And | Or -> (3, 4)
| LT | GT -> (5, 6)
| EQ | NEQ -> (1, 2)
| And | Or -> (3, 4)
| LT | GT -> (5, 6)
| Add | Sub -> (7, 8)
| Mul | Div | Mod -> (9, 10)

Expand Down Expand Up @@ -57,8 +57,9 @@ and parse_pat ls = match ls with
in (TuplePat (List.rev parsed), remaining)
| (Ident s)::xs -> (SinglePat s, xs)
| (Number f)::xs -> (NumberPat f, xs)
| Underscore::xs -> (WildcardPat, xs)
| _ ->
print_toks ls;
printf "Expected pattern, got %s" (string_of_toks ls);
assert false

and parse_let ls =
Expand Down
8 changes: 6 additions & 2 deletions lib/scanner.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type token =
| Hashtag
| Comma
| Pipe
| Underscore

let is_numeric d = Base.Char.is_digit d || phys_equal d '.'
let is_identic c = Base.Char.is_alphanum c || phys_equal c '_'
Expand Down Expand Up @@ -66,19 +67,21 @@ and scan_ls = function
| '&'::'&'::xs -> Operator And :: scan_ls xs
| '|'::'|'::xs -> Operator Or :: scan_ls xs
| '='::'='::xs -> Operator EQ :: scan_ls xs
| '!'::'='::xs -> Operator NEQ :: scan_ls xs
| '%'::xs -> Operator Mod :: scan_ls xs
| '('::xs -> LParen :: scan_ls xs
| ')'::xs -> RParen :: scan_ls xs
| '{'::xs -> LBrace :: scan_ls xs
| '}'::xs -> RBrace :: scan_ls xs
| '='::xs -> Equal :: scan_ls xs
| '_'::xs -> Underscore :: scan_ls xs
| ','::xs -> Comma :: scan_ls xs
| '#'::xs -> Hashtag :: scan_ls xs
| '|'::xs -> Pipe :: scan_ls xs
| 'T'::xs -> True :: scan_ls xs
| 'F'::xs -> False :: scan_ls xs
| d::_ as ls when Base.Char.is_digit d -> scan_digit ls
| i::_ as ls when not (Base.Char.is_digit i) -> scan_ident ls
| d::_ as ls when Char.is_digit d -> scan_digit ls
| i::_ as ls when Char.is_alpha i -> scan_ident ls
| ls ->
printf "Scan Error: %s\n" (String.of_char_list ls);
assert false
Expand Down Expand Up @@ -118,6 +121,7 @@ let string_of_tok = function
| Pipe -> "Pipe"
| Match -> "Match"
| MatchArrow -> "MatchArrow"
| Underscore -> "Underscore"

let string_of_toks ls = String.concat ~sep:" " (List.map ~f:string_of_tok ls)
let print_toks ls = ls |> string_of_toks |> printf "%s\n"
Expand Down
5 changes: 4 additions & 1 deletion lib/types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type operator =
| LT
| GT
| EQ
| NEQ
| And
| Or
| Mod
Expand All @@ -17,6 +18,7 @@ type pattern =
| SinglePat of string
| NumberPat of float
| TuplePat of pattern list
| WildcardPat

and state = (string, value, String.comparator_witness) Map.t

Expand Down Expand Up @@ -67,4 +69,5 @@ let rec string_of_expr = function
and string_of_pat = function
| SinglePat s -> s
| NumberPat f -> Float.to_string f
| TuplePat ls -> "(" ^ (String.concat ~sep:", " (List.map ~f:string_of_pat ls)) ^ ")"
| TuplePat ls -> sprintf "(%s)" (String.concat ~sep:", " (List.map ~f:string_of_pat ls))
| WildcardPat -> "_"
8 changes: 8 additions & 0 deletions test/euler.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ let () =
Map.empty (module String) |> run_file (test_file "euler1.rsc") in
assert_equal_expressions "sum(filter(predicate, range(1, 1000)))" "233168" state;

let state =
Map.empty (module String) |> run_file (test_file "euler2.rsc") in
assert_equal_expressions "euler2" "4613732" state;

let state =
Map.empty (module String) |> run_file (test_file "euler3.rsc") in
assert_equal_expressions "euler3" "6857" state;

printf "Passed\n"