├── .gitattributes
├── .gitignore
├── .merlin
├── 3110 Final Project Writeup.pdf
├── LICENSE.txt
├── Makefile
├── README.md
├── VERSION
├── _tags
├── comparison.ml
├── comparison.mli
├── dictionary.ml
├── dictionary.mli
├── language_files
├── c_info.json
├── cpp_info.json
├── java_info.json
├── ocaml_info.json
├── python_info.json
└── txt_info.json
├── main.ml
├── main.mli
├── preprocessing.ml
├── preprocessing.mli
├── test.ml
├── test_comparison.ml
├── test_dictionary.ml
├── test_preprocessing.ml
├── test_winnow.ml
├── tests
├── MiniFactorialTests
│ ├── Original.java
│ ├── T1-Commented.java
│ ├── T1-Copy.java
│ ├── T1-Whitespaces.java
│ ├── T2-Renamed.java
│ ├── T2-VariableLong.java
│ ├── T3-DummyMethod.java
│ ├── T3-DummyMethodPlus.java
│ ├── T3-EndlessLoop.java
│ ├── T3-ForWhile.java
│ ├── T3-Inlining.java
│ ├── T3-JumpLabel.java
│ ├── T3-LoopEndpoint.java
│ ├── T3-LoopUnrolling.java
│ ├── T3-OutputStream.java
│ ├── T3-VariableBigInt.java
│ ├── T4-AlgorithmChange.java
│ ├── T4-Approximation.java
│ ├── T4-ProGuardObfuscation.java
│ └── T4-Recursive.java
├── SSID_demo
│ ├── 01.java
│ ├── 02.java
│ ├── 03.java
│ ├── 04.java
│ ├── 05.java
│ ├── 06.java
│ ├── 07.java
│ ├── 08.java
│ ├── 09.java
│ └── 10.java
├── test1
│ ├── intset.ml
│ └── intset1.ml
├── test10
│ ├── add.ml
│ ├── add_test.ml
│ ├── btrees.ml
│ ├── discussiongame.ml
│ ├── hello.ml
│ └── lab03_test.ml
├── test11
│ ├── Camel.txt
│ ├── CamelMaybeCopy.txt
│ ├── Camelcopy.txt
│ ├── Camelcopy2.txt
│ ├── Camelcopy3.txt
│ └── Camels.txt
├── test12
│ ├── DumbAI.java
│ └── DumbAI2.java
├── test13
│ ├── heaplib.c
│ └── heaplib2.c
├── test14
│ ├── P2.py
│ └── P2_2.py
├── test15
│ ├── all_subarray.cpp
│ └── all_subarray_2.cpp
├── test2
│ ├── main.ml
│ └── main1.ml
├── test3
│ ├── labsoln.ml
│ └── labsoln1.ml
├── test4
│ ├── functions.ml
│ └── functions1.ml
├── test5
│ ├── queens_lazy.ml
│ └── queens_tail.ml
├── test6
│ ├── kmp.ml
│ └── strpos.ml
├── test7
│ ├── strpos.ml
│ └── strpos2.ml
├── test8
│ ├── lab03.ml
│ ├── lab031.ml
│ ├── lab032.ml
│ ├── lab033.ml
│ └── lab034.ml
└── test9
│ ├── prelimpract.ml
│ ├── prelimpract1.ml
│ └── prelimpract2.ml
├── winnowing.ml
└── winnowing.mli
/.gitattributes:
--------------------------------------------------------------------------------
1 | tests/* linguist-generated
2 | language_files/* linguist-generated
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | tests/.DS_Store
3 | _build/
4 | ocamoss
--------------------------------------------------------------------------------
/.merlin:
--------------------------------------------------------------------------------
1 | PKG oUnit
2 | PKG yojson
3 | PKG ANSITerminal
4 | B _build
--------------------------------------------------------------------------------
/3110 Final Project Writeup.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobYang1024/OCaMOSS/5a78137bf717d2bb8248489f0619a01ebea9d1df/3110 Final Project Writeup.pdf
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Aniroodh Ravikumar, Danny Yang, Robert Yang, Gauri Jain
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | build:
2 | ocamlbuild -use-ocamlfind main.native && mv main.native ocamoss
3 |
4 | test:
5 | ocamlbuild -use-ocamlfind test.native && ./test.native
6 |
7 | clean:
8 | ocamlbuild -clean
9 |
10 | run:
11 | ocamlbuild -use-ocamlfind main.native && mv main.native ocamoss && ./ocamoss
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## OCaMoss User's Guide
2 |
3 | Plagiarism detection software, inspired by MOSS and implemented in OCaml.
4 | Runs using a command-line interface.
5 |
6 | This is NOT an OCaml client for MOSS, this is a completely separate program. For more details about the system or how MOSS works in general, read the PDF report in this repository or [this blog post](https://yangdanny97.github.io/blog/2019/05/03/MOSS) I wrote.
7 |
8 | Note: this was originally written as the final project for a course - it has since been updated by me, so some aspects of the PDF report may not be accurate. In particular, the latest version of OCaMOSS no longer uses a 2-3 tree.
9 |
10 |
11 |
12 | - To build - `make`
13 | - To build & run the REPL - `make run`
14 | - To build & run unit tests -`make test`
15 |
16 | Required Dependencies:
17 | - Yojson
18 | - ANSITerminal
19 | - OUnit (for unit tests)
20 |
21 |
22 |
23 | ### Commands:
24 | (note - commands are case-sensitive)
25 |
26 | - `run [threshold]` - runs OCaMoss on the working directory.
27 | The threshold argument gives the program the percentage of the file to match with
28 | another for it to be flagged as plagiarised, and must be at least 0.4 and at most 1
29 | - `dir` - lists the working directory and the files that it contains
30 | - `setdir [dir]` - sets the relative directory to look for files and resets any
31 | results
32 | - `results` - lists the file names for which there are results
33 | - `results [filename]` - lists the detailed results of overlap for that file
34 | (Make sure to include the extension of the file)
35 | - `resultpairs` -- lists all the pairs of files for which there are positive results
36 | - `compare [fileA] [fileB]` - prints out specific overlaps of fileA and fileB
37 | (Make sure to include the extension of the files)
38 | - `quit` - exits the REPL
39 | - `help` - display the available commands
40 |
41 |
42 |
43 | ### Usage instructions/tutorial:
44 |
45 | 1. `setdir` to folder you want to test. requirements: file names have no spaces
46 | and all files have the same extension
47 | (example: `setdir tests/test1`)
48 | 2. `run` with desired params (example: `run 0.5` is the same as `run`)
49 | 3. `results` to view list of results, [results filename] to view list of
50 | results for specific file, and [`compare A B` to compare matching patterns for
51 | two files (example: `results Camel.txt`)
52 |
53 | Example for runnning test case 1 and inspecting results:
54 | 1. `setdir tests/test1`
55 | 2. `run`
56 | 3. `results/results intset.ml/compare intset1.ml intset.ml/resultpairs`
57 |
58 |
59 |
60 | ### Other information:
61 |
62 | #### Similarity score:
63 | - used as a measure of how likely file A plagiarized from file B
64 | - ratio of # matching hashes between A and B : # hashes in fingerprint for A
65 | - overall similarity score for A is the average of all similarity scores
66 | for file A that are > 0.5
67 | - threshold score for detecting possible plagiarism varies with the file type, but experimentally we determined it to be around 0.5
68 |
69 | #### Supported languages/file formats:
70 | - OCaml - .ml
71 | - Java - .java
72 | - C - .c
73 | - Python - .py
74 | - English - .txt (note: english comparison does NOT account for semantics)
75 |
76 |
77 |
78 | Self-generated test case descriptions (test case N is in directory tests/testN):
79 |
80 | NOTE: to replicate results, run using threshold = 0.4
81 |
82 | 1) exact duplicates - should return positive result
83 | 2) variable names changed - should return positive result
84 | 3) functions/comments reordered - should return positive result
85 | 4) functions1.ml is a copy of functions.ml but with large sections deleted - should return positive result for functions1 but not functions
86 | 5) different implementations of the same algorithm - should NOT return positive
87 | result
88 | 6) completely different files - should NOT return positive result
89 | 7) functions/comments reordered - should return positive result
90 | 8) more than 2 files - files changed respectively as follows: function/variable names changed; random spaces/new lines added; rec declarations/ match statement lines changed - should return positive result for all files except for lab034.ml which is a dummy.
91 | 9) more than 2 files - files changed respectively as follows: same comments but different code; comments deleted and same code with variable/function names changed - should NOT return positive result for first and should return positive result for second
92 | 10) large group of all different files - should NOT return positive result
93 | 11) txt files check - files are changed respectively as follows: exact wikipedia article; edited but very similar wikipedia article; sentences shifted around of original; exact same; a file that says “camel” five times; a more hazy edit of the original - should return positive result for all except last two: “Camels.txt” and “CamelMaybeCopy.txt”
94 | 12) Java check - test for a Java file, where one file has all comments removed
95 | 13) C check - test for a C file where one file has all comments removed
96 | 14) Python check - test for a Python file, where one files has comments removed and variable names changed.
97 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | This is version 1, released 02/09/18.
--------------------------------------------------------------------------------
/_tags:
--------------------------------------------------------------------------------
1 | true: package(unix), package(oUnit), package(yojson), package(ANSITerminal)
2 |
--------------------------------------------------------------------------------
/comparison.ml:
--------------------------------------------------------------------------------
1 | open Dictionary
2 |
3 | module StringKey = struct
4 | type t = string
5 | let compare k1 k2 = Stdlib.compare k1 k2
6 | end
7 |
8 | module HashValue = struct
9 | type t = (int*int) list
10 | let format d = ()
11 | end
12 |
13 | module FileDict = HashtblDict (StringKey)(HashValue)
14 |
15 | module DictValue = struct
16 | type t = FileDict.t
17 | let format d = ()
18 | end
19 |
20 | module CompDict = HashtblDict (StringKey)(DictValue)
21 |
22 | let intersection v1 v2 =
23 | let rec intersection_helper lst1 lst2 common =
24 | match lst1 with
25 | | [] -> common
26 | | (h,p)::t ->
27 | let acc = if List.mem_assoc h lst2 then (h,p)::common
28 | else common in
29 | intersection_helper t lst2 acc
30 |
31 | in
32 | List.rev(intersection_helper v1 v2 [])
33 |
34 | let make_pair_comp k0 file_list =
35 | List.fold_left (fun x (k,v) ->
36 | FileDict.insert k (intersection (List.assoc k0 file_list) v) x)
37 | FileDict.empty file_list
38 |
39 | let compare d =
40 | let file_list = FileDict.to_list d in
41 | List.fold_left (fun x (k,v) ->
42 | CompDict.insert k (make_pair_comp k file_list) x)
43 | CompDict.empty file_list
44 |
45 | let cmp_tuple (k1,s1) (k2,s2) =
46 | if Stdlib.compare s1 s2 = 0 then Stdlib.compare k1 k2
47 | else -(Stdlib.compare s1 s2)
48 |
49 | let create_sim_list comp_dict t =
50 | let create_sim_list_helper comp_dict =
51 | List.fold_left (fun x (k,d) -> match FileDict.find k d with
52 | | None -> failwith "Unimplemented"
53 | | Some v -> let file_length = float_of_int (List.length v) in
54 | let file_ss =
55 | List.fold_left (fun (score,n) (k1,v1) ->
56 | if StringKey.compare k k1 = 0 then (score,n)
57 | else begin
58 | if file_length = 0.0 then (score,n)
59 | else
60 | let s = ((float_of_int (List.length v1))/.file_length) in
61 | if s >= t then (score+.s,n+.1.0) else (score,n)
62 | end) (0.0,0.0) (FileDict.to_list d)
63 | in
64 | let sim_score = if (snd file_ss) = 0.0 then 0.0
65 | else (fst file_ss)/.(snd file_ss) in
66 | if sim_score >= t then (k,sim_score)::x else x)
67 | [] (CompDict.to_list comp_dict)
68 | in
69 | List.sort (cmp_tuple) (create_sim_list_helper comp_dict)
70 |
71 | let create_pair_sim_list f_name f_dict_list =
72 | try
73 | if f_dict_list = [] then [] else
74 | let f_length = float_of_int (List.length (List.assoc f_name f_dict_list)) in
75 | List.fold_left (fun lst (k,v) ->
76 | if k = f_name then lst
77 | else if f_length = 0.0 then (k,0.0)::lst
78 | else begin
79 | (k,(float_of_int(List.length v))/.f_length)::lst
80 | end) [] f_dict_list
81 | with
82 | | Division_by_zero -> failwith "Invalid file dictionary"
83 |
--------------------------------------------------------------------------------
/comparison.mli:
--------------------------------------------------------------------------------
1 | open Dictionary
2 |
3 | (* [StringKey] is a module that represents a key of a dictionary of type
4 | * string. *)
5 | module StringKey : Comparable with type t = string
6 |
7 | (* [HashValue] is a module that represents a value of a dictionary of type
8 | * int list.
9 | *)
10 | module HashValue : Formattable with type t = (int*int) list
11 |
12 | (* [FileDict] is a module that represents a dictionary with keys of type string
13 | * and values of type int list.
14 | *)
15 | module FileDict : Dictionary with type Key.t = string
16 | and type Value.t = (int*int) list
17 |
18 | (* [DictValue] is a module that represents a value of a dictionary of type
19 | * FileDict.t
20 | *)
21 | module DictValue : Formattable with type t = FileDict.t
22 |
23 | (* [CompDict] is a module that represents a dictionary with keys of type string
24 | * and values of type FileDict.t
25 | *)
26 | module CompDict: Dictionary with type Key.t = string
27 | and type Value.t = FileDict.t
28 |
29 | (* [intersection v1 v2] returns a list of elements present in both v1 and
30 | * v2. The elements are in the order that they appear in v1, and the positions
31 | * are as they are in the corresponding values in v1.
32 | *)
33 | val intersection : HashValue.t -> HashValue.t -> HashValue.t
34 |
35 | (* [make_pair_comp k0 file_list comp_dict] returns a file dictionary where the
36 | * keys are the keys from file_list, and each value is the intersection of
37 | * the values in file_list of the key mapped to that value, and the key k0.
38 | *)
39 | val make_pair_comp : string -> (StringKey.t * HashValue.t) list -> FileDict.t
40 |
41 | (* [compare d] returns a comparison dictionary whose keys are the keys
42 | * from d, and whose values are dictionaries representing pairwise comparisons
43 | * of that key with every other key in d.
44 | *)
45 | val compare : FileDict.t -> CompDict.t
46 |
47 | (* [create_sim_list threshold comp_dict] assigns a similarity score to each of
48 | * the keys in comp_dict, and returns a list of files whose similarity scores
49 | * are above threshold, and their overall similarity score. The similarity of
50 | * one file with another is calculated as the number of matching hashes between
51 | * the files divided by the number of hashes of the file itself, and hence the
52 | * similarity score of a file is the average of the similarities of that
53 | * file with every other file. The files are ordered in decreasing order of
54 | * similarity, and files that have the same similarity score are ordered by
55 | * increasing order of filename.
56 | *)
57 | val create_sim_list : CompDict.t -> float -> (StringKey.t * float) list
58 |
59 | (* [create_pair_sim_list f_name f_dict_list] returns a list of files and
60 | * their corresponding pair similarity scores when compared with f_name.
61 | * requires: The value in f_dict_list corresponding to f_name cannot be
62 | * an empty list, unless f_dict_list itself is an empty list. *)
63 | val create_pair_sim_list : StringKey.t -> (StringKey.t * HashValue.t) list ->
64 | (StringKey.t * float) list
65 |
--------------------------------------------------------------------------------
/dictionary.ml:
--------------------------------------------------------------------------------
1 | open Hashtbl
2 | open Seq
3 |
4 | module type Comparable = sig
5 | type t
6 | val compare: t -> t -> int
7 | end
8 |
9 | module type Formattable = sig
10 | type t
11 | val format: t -> unit
12 | end
13 |
14 | module type Dictionary = sig
15 | module Key : Comparable
16 | module Value : Formattable
17 | type key = Key.t
18 | type value = Value.t
19 | type t
20 | val empty : t
21 | val size : t -> int
22 | val member : key -> t -> bool
23 | val find : key -> t -> value option
24 | val insert : key -> value -> t -> t
25 | val to_list : t -> (key * value) list
26 | end
27 |
28 | module type DictionaryMaker =
29 | functor (K : Comparable) (V : Formattable)
30 | -> Dictionary with module Key = K and module Value = V
31 |
32 | module HashtblDict (K : Comparable) (V : Formattable) = struct
33 |
34 | module Key = K
35 |
36 | module Value = V
37 |
38 | type key = Key.t
39 |
40 | type value = Value.t
41 |
42 | type t = Tbl of (key, value) Hashtbl.t
43 |
44 | let empty = Tbl(Hashtbl.create 10000)
45 |
46 | let size (Tbl d) = Hashtbl.length d
47 |
48 | let member k (Tbl d) =
49 | match Hashtbl.find_opt d k with
50 | |Some _ -> true
51 | |None -> false
52 |
53 | let find k (Tbl d) = Hashtbl.find_opt d k
54 |
55 | let insert k v (Tbl d) =
56 | let cpy = (Hashtbl.copy d) in
57 | Hashtbl.add cpy k v ; Tbl(cpy)
58 |
59 | let to_list (Tbl d) =
60 | Hashtbl.fold (fun k v acc -> (k, v) :: acc) d []
61 | end
62 |
--------------------------------------------------------------------------------
/dictionary.mli:
--------------------------------------------------------------------------------
1 |
2 | (* A [Comparable] is a value that can be compared. *)
3 | module type Comparable = sig
4 |
5 | (* Type t gives the type of the value that is stored in the comparable. *)
6 | type t
7 |
8 | (* [compare t1 t2] returns a positive number if t1 is greater than t2,
9 | * a negative number if it is less than t2 and 0 if they are equal.
10 | *)
11 | val compare: t -> t -> int
12 |
13 | end
14 |
15 |
16 | module type Formattable = sig
17 |
18 | type t
19 |
20 | val format: t -> unit
21 |
22 | end
23 |
24 | (* A [Dictionary] maps keys to values. The keys
25 | * must be comparable, but there are no restrictions
26 | * on the values.
27 | *)
28 |
29 | module type Dictionary = sig
30 |
31 | module Key : Comparable
32 |
33 | module Value : Formattable
34 |
35 | type key = Key.t
36 |
37 | type value = Value.t
38 |
39 | (* Type t represents how the dictionary itself is implemented and stored as.
40 | *)
41 | type t
42 |
43 | (* [empty] represents an empty dictionary. *)
44 | val empty : t
45 |
46 | (* [size d] represents the size of the dictionary d. *)
47 | val size : t -> int
48 |
49 | (* [member k dict] returns true if k is a binding in the dictionary d
50 | * and false if not.
51 | *)
52 | val member : key -> t -> bool
53 |
54 | (* [find k dict] returns None if k is not a binding in dict, and Some v
55 | * if v is the value bound to k in dict.
56 | *)
57 | val find : key -> t -> value option
58 |
59 | (* [insert k v dict] adds a new binding of k with value v to dict if k is not
60 | * in dict already, and binds k to a new value v if it is already
61 | * present in the dictionary, and returns the new dictionary.
62 | *)
63 | val insert : key -> value -> t -> t
64 |
65 | (* [to_list dict] returns an association list where each element of the list
66 | * is a tuple of a key and it's corresponding value in dict. *)
67 | val to_list : t -> (key * value) list
68 |
69 | end
70 |
71 | module type DictionaryMaker =
72 | functor (K : Comparable)
73 | -> functor (V : Formattable)
74 | -> Dictionary with module Key = K and module Value = V
75 |
76 | module HashtblDict : DictionaryMaker
77 |
--------------------------------------------------------------------------------
/language_files/c_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keywords": ["auto", "double", "int", "struct", "break", "else", "long", "switch",
3 | "case", "enum", "register", "typedef", "char", "extern", "return", "union",
4 | "const","float", "short", "unsigned", "continue", "for", "signed", "void",
5 | "default", "goto", "sizeof", "volatile", "do", "if", "static", "while","ctype",
6 | "errno","h","limits","locale","math","setjmp","stdarg","stddef","stdio","stdlib","size_t", "wchar_t",
7 | "div_t", "ldiv_t", "assert", "isalnum","isalpha","iscntrl","isdigit", "toupper",
8 | "isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit", "tolower",
9 | "CHAR_BIT","SCHAR_MIN","SCHAR_MAX","UCHAR_MAX","CHAR_MIN","CHAR_MAX","MB_LEN_MAX",
10 | "SHRT_MIN","SHRT_MAX","USHRT_MAX","INT_MIN","INT_MAX","UINT_MAX","LONG_MIN","LONG_MAX","ULONG_MAX",
11 | "acos","asin","atan","atan2","ceil","cos","cosh","exp","fabs","floor","fmod","frexp",
12 | "ldexp","log","log10","modf","pow","sin","sinh","sqrt","tanh","raise","signal","sig_atomic_t",
13 | "SIG_DFL","SIG_ERR","SIG_IGN","va_list","va_start","va_arg","va_end","NULL","offsetof",
14 | "ptrdiff_t","_IOLBF","_IOFBF","BUFSIZ","EOF","FILE","FILENAME_MAX","FOPEN_MAX","fpos_t",
15 | "L_tmpnam","TMP_MAX","_IONBF","SEEK_CUR","stderr","stdin","stdout","SEEK_END",
16 | "SEEK_SET","fgets","gets","fopen","freopen","tmpfile","fclose","feof",
17 | "ferror","fflush","fgetc","fgetpos","fprintf","fputc","fputs","fscanf","fseek",
18 | "fsetpos","getc","getchar","printf","putc","putchar","puts","remove","rename","scanf",
19 | "setvbuf","sprintf","sscanf","ungetc","vfprintf","vprintf","vsprintf","int","fread",
20 | "fwrite","clearerr","perror","rewind","setbuf","memchr","strcat","strchr","strcpy","strerror",
21 | "strncat","strncpy","strpbrk","strrchr","strstr","strtok","memcmp","strcmp","strcoll",
22 | "strncmp","strcspn","strlen","strspn","strxfrm","memcpy","memmove","memset","clock_t","time_t",
23 | "asctime","ctime","clock","difftime","strftime","tm","mktime","time", "EXIT_FAILURE",
24 | "EXIT_SUCCESS", "RAND_MAX","MB_CUR_MAX","atof","getenv","div","strtod","abs","atexit","atoi",
25 | "mblen","mbtowc","rand","wctomb","ldiv","mbstowcs","wcstombs","system",
26 | "bsearch","calloc","malloc","realloc","abort","exit","free","qsort","srand","include"],
27 | "special characters": ["(", ")", "[", "]", "{", "}", "*", ",", ":", "=", ";",
28 | ".", "#", "-", "~", "!", "&", "+", "-", "/", "&", "<", ">", "|" , "%" , "^"],
29 | "comment-start" : "/*",
30 | "comment-end" : "*/",
31 | "comment" : "//",
32 | "comments-nest": false,
33 | "strings":true
34 | }
--------------------------------------------------------------------------------
/language_files/cpp_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keywords": ["BUFSIZ", "CHAR_BIT", "CHAR_MAX", "CHAR_MIN", "EOF", "EXIT_FAILURE", "EXIT_SUCCESS",
3 | "FALSE", "FILE", "FILENAME_MAX", "FOPEN_MAX", "INT_MAX", "INT_MIN", "LONG_MAX", "LONG_MIN",
4 | "L_tmpnam", "MB_CUR_MAX", "MB_LEN_MAX", "NULL", "RAND_MAX", "SCHAR_MAX", "SCHAR_MIN", "SEEK_CUR",
5 | "SEEK_END", "SEEK_SET", "SHRT_MAX", "SHRT_MIN", "SIG_DFL", "SIG_ERR", "SIG_IGN", "TMP_MAX",
6 | "TRUE", "UCHAR_MAX", "UINT_MAX", "ULONG_MAX", "USHRT_MAX", "_IOFBF", "_IOLBF", "_IONBF",
7 | "abort", "abs", "acos", "alignas", "alignof", "and", "and_eq", "asctime", "asin", "asm",
8 | "assert", "atan", "atan2", "atexit", "atof", "atoi", "atomic_cancel", "atomic_commit",
9 | "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "bsearch", "calloc", "case",
10 | "catch", "ceil", "char", "char16_t", "char32_t", "class", "clearerr", "clock", "clock_t",
11 | "co_await", "co_return", "co_yield", "compl", "concept", "const", "const_cast", "constexpr",
12 | "continue", "cos", "cosh", "ctime", "ctype", "decltype", "default", "delete", "difftime", "div",
13 | "div_t", "do", "double", "dynamic_cast", "else", "enum", "errno", "exit", "exp", "explicit",
14 | "export", "extern", "fabs", "fclose", "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets",
15 | "float", "floor", "fmod", "fopen", "for", "fpos_t", "fprintf", "fputc", "fputs", "fread",
16 | "free", "freopen", "frexp", "friend", "fscanf", "fseek", "fsetpos", "fwrite", "getc", "getchar",
17 | "getenv", "gets", "goto", "h", "if", "import", "include", "inline", "int", "isalnum", "isalpha",
18 | "iscntrl", "isdigit", "isgraph", "islower", "isprint", "ispunct", "isspace", "isupper", "isxdigit",
19 | "ldexp", "ldiv", "ldiv_t", "limits", "locale", "log", "log10", "long", "malloc", "math", "mblen",
20 | "mbstowcs", "mbtowc", "memchr", "memcmp", "memcpy", "memmove", "memset", "mktime", "modf", "module",
21 | "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "offsetof", "operator",
22 | "or", "or_eq", "perror", "pow", "printf", "private", "protected", "ptrdiff_t", "public", "putc",
23 | "putchar", "puts", "qsort", "raise", "rand", "realloc", "register", "reinterpret_cast", "remove",
24 | "rename", "requires", "return", "rewind", "scanf", "setbuf", "setjmp", "setvbuf", "short",
25 | "sig_atomic_t", "signal", "signed", "sin", "sinh", "size_t", "sizeof", "sprintf", "sqrt",
26 | "srand", "sscanf", "static", "static_assert", "static_cast", "stdarg", "stddef", "stderr",
27 | "stdin", "stdio", "stdlib", "stdout", "strcat", "strchr", "strcmp", "strcoll", "strcpy",
28 | "strcspn", "strerror", "strftime", "strlen", "strncat", "strncmp", "strncpy", "strpbrk",
29 | "strrchr", "strspn", "strstr", "strtod", "strtok", "struct", "strxfrm", "switch", "synchronized",
30 | "system", "tanh", "template", "this", "thread_local", "throw", "time", "time_t", "tm", "tmpfile",
31 | "tolower", "toupper", "try", "typedef", "typeid", "typename", "ungetc", "union", "unsigned",
32 | "using", "va_arg", "va_end", "va_list", "va_start", "vfprintf", "virtual", "void", "volatile",
33 | "vprintf", "vsprintf", "wchar_t", "wcstombs", "wctomb", "while", "xor", "xor_eq"],
34 | "special characters": ["(", ")", "[", "]", "{", "}", "*", ",", ":", "=", ";",
35 | ".", "#", "-", "~", "!", "&", "+", "-", "/", "&", "<", ">", "|" , "%" , "^"],
36 | "comment-start" : "/*",
37 | "comment-end" : "*/",
38 | "comment" : "//",
39 | "comments-nest": false,
40 | "strings":true
41 | }
--------------------------------------------------------------------------------
/language_files/java_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keywords": ["abstract", "continue", "for", "new", "switch", "assert", "default", "package",
3 | "synchronized", "boolean", "do", "if", "private", "this", "break", "double", "implements",
4 | "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum",
5 | "instanceof", "return", "transient", "catch", "extends", "int", "short", "try", "char", "final",
6 | "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile",
7 | "float", "native", "super", "while", "Boolean", "Byte", "Character", "Class", "ClassLoader",
8 | "ClassValue", "Compiler", "Double", "Enum", "Float", "InheritableThreadLocal", "Integer ",
9 | "Long", "Math", "Number", "Object", "Package", "Process", "ProcessBuilder", "Runtime",
10 | "RuntimePermission", "SecurityManager", "Short", "StackTraceElement", "StrictMath", "String",
11 | "StringBuffer", "StringBuilder", "System", "Thread", "ThreadGroup", "ThreadLocal",
12 | "Throwable", "Void", "AbstractCollection", "AbstractList", "AbstractMap", "AbstractQueue",
13 | "AbstractSequentialList", "AbstractSet", "ArrayDeque", "ArrayList", "Arrays", "BitSet",
14 | "Calendar", "Collections", "Currency", "Date", "Dictionary", "EnumMap", "EnumSet",
15 | "EventListenerProxy", "EventObject", "FormattableFlags", "Formatter", "GregorianCalendar",
16 | "HashMap","HashSet", "Hashtable", "IdentityHashMap", "LinkedHashMap", "LinkedHashSet", "LinkedList",
17 | "ListResourceBundle", "Locale", "Objects", "Observable", "PriorityQueue", "Properties",
18 | "PropertyPermission", "PropertyResourceBundle", "Random", "ResourceBundle",
19 | "ResourceBundle.Control", "Scanner", "ServiceLoader", "SimpleTimeZone", "Stack",
20 | "StringTokenizer", "Timer", "TimerTask", "TimeZone", "TreeMap", "TreeSet", "UUID",
21 | "Vector", "WeakHashMap"],
22 | "special characters": ["!", "$", "%", "&", "*", "+", "-", ".", "/", ":", ";",
23 | "<", "=", ">", "?", "^", "|", "\"", "'", "(", ")", ",", "[", "]",
24 | "{", "}", "~", "@"],
25 | "comment-start" : "/*",
26 | "comment-end" : "*/",
27 | "comment": "//",
28 | "comments-nest": false,
29 | "strings":true
30 | }
31 |
--------------------------------------------------------------------------------
/language_files/ocaml_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keywords": ["and", "as", "assert", "asr", "begin", "class", "constraint",
3 | "do", "done", "downto", "else", "end", "exception", "external",
4 | "false", "for", "fun", "function", "functor", "if", "in", "include",
5 | "inherit", "initializer", "land", "lazy", "let", "lor", "lsl", "lsr",
6 | "lxor", "match", "method", "mod", "module", "mutable", "new", "nonrec",
7 | "object", "of", "open", "or", "private", "rec", "sig", "struct", "then",
8 | "to", "true", "try", "type", "val", "virtual", "when", "while", "with",
9 | "Arg", "Array", "ArrayLabels", "Buffer", "Bytes", "BytesLabels", "Callback",
10 | "Char", "Complex", "Digest", "Ephemeron", "Filename", "Format", "Gc",
11 | "Genlex", "Hashtbl", "Int32", "Int64", "Lazy", "Lexing", "List",
12 | "ListLabels", "Map", "Marshal", "MoreLabels", "Nativeint", "Oo", "Parsing",
13 | "Printexc", "Printf", "Queue", "Random", "Scanf", "Set", "Sort",
14 | "Spacetime", "Stack", "StdLabels", "Stream", "String", "StringLabels",
15 | "Sys", "Uchar", "Weak", "failwith"],
16 | "special characters": ["!", "$", "%", "&", "*", "+", "-", ".", "/", ":", ";",
17 | "<", "=", ">", "?", "@", "^", "|", "~", "#", "\"", "(", ")", ",", "[", "]",
18 | "{", "}"],
19 | "comment-start": "(*",
20 | "comment-end": "*)",
21 | "comment": "",
22 | "comments-nest": true,
23 | "strings":true
24 | }
25 |
--------------------------------------------------------------------------------
/language_files/python_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keywords": ["False", "None", "True", "and", "as", "assert", "break", "class", "continue",
3 | "def", "del", "elif", "else", "except", "finally", "for", "from", "global", "if", "import",
4 | "in", "is", "lambda", "nonlocal", "not", "or", "pass", "raise", "return", "try",
5 | "while", "with", "yield","__future__","__main__","abc","aifc","argparse","array","ast",
6 | "asynchat","asyncore","atexit","audioop","base64","bdb","binascii","binhex","bisect",
7 | "builtins","bz2","calendar","cgi","cgitb","chunk","cmath","cmd","code","codecs","codeop",
8 | "collections","colorsys","compileall","configparser","contextlib","copy","copyreg","crypt",
9 | "csv","ctypes","curses","datetime","dbm","decimal","difflib","dis","distutils","doctest",
10 | "email","errno","faulthandler","fcntl","filecmp","fileinput","fnmatch","formatter","fpectl",
11 | "fractions","ftplib","functools","gc","getopt","getpass","gettext","glob","grp","gzip",
12 | "hashlib","heapq","hmac","html","http","imaplib","imghdr","imp","importlib","inspect","io",
13 | "ipaddress","itertools","json","keyword","linecache","locale","logging","lzma","macpath",
14 | "mailbox","mailcap","marshal","math","mimetypes","mmap","modulefinder","msilib","msvcrt",
15 | "multiprocessing","netrc","nis","nntplib","numbers","operator","optparse","os","os.path",
16 | "ossaudiodev","parser","pdb","pickle","pickletools","pipes","pkgutil","platform","plistlib",
17 | "poplib","posix","pprint","pty","pwd","py_compile","pyclbr","pydoc","queue","quopri",
18 | "random","re","readline","reprlib","resource","rlcompleter","runpy","sched","select","shelve","shlex",
19 | "shutil","signal","site","smtpd","smtplib","sndhdr","socket","socketserver","spwd","sqlite3","ssl",
20 | "stat","string","stringprep","struct","subprocess","sunau","symbol","symtable","sys","sysconfig","syslog",
21 | "tabnanny","tarfile","telnetlib","tempfile","termios","test","test","textwrap","threading","time",
22 | "timeit","tkinter","token","tokenize","trace","traceback","tty","turtle","types","unicodedata",
23 | "unittest","urllib","uu","uuid","venv","warnings","wave","weakref","webbrowser","winreg",
24 | "winsound","wsgiref","xdrlib","xml","xmlrpc","zipfile","zipimport","zlib"],
25 | "special characters": ["!", "%", "&", "*", "+", "-", ".", "/", ":", ";",
26 | "<", "=", ">", "?", "^", "|", "~", "\"", "(", ")", ",", "[", "]", "{", "}", "'"],
27 | "comment-start": "'''",
28 | "comment-end": "'''",
29 | "comment": "#",
30 | "comments-nest": false,
31 | "strings":false
32 | }
33 |
--------------------------------------------------------------------------------
/language_files/txt_info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keywords": [],
3 | "special characters": [],
4 | "comment-start":"",
5 | "comment-end":"",
6 | "comment":"",
7 | "comments-nest": false,
8 | "strings":false
9 | }
10 |
--------------------------------------------------------------------------------
/main.mli:
--------------------------------------------------------------------------------
1 | open Preprocessing
2 | open Comparison
3 |
4 | type color = RED | GREEN | CYAN | TEXT
5 |
6 | (* type representing the state of the interface *)
7 | type state = {display: (color * string) list; directory: string; results:
8 | CompDict.t option; result_files: (color * string) list;
9 | threshold: float}
10 |
11 | (* type for commands recognised by MOSS
12 | * RUN - runs MOSS on the current directory of the state, no arguments
13 | * HELP - lists the available commands, no arguments
14 | * SETDIR - sets the working directory where MOSS looks for files, takes
15 | * 1 argument, displays the working directory
16 | * DIR - displays the working directory and all the files it contains
17 | * RESULTS - displays results, takes 0 arguments
18 | * (lists files that are contained in results, and their similarity scores)
19 | * or 1 argument (lists similarity scores for that file vs other files)
20 | * COMPARE - compares two files, printing out the similar sections, takes 2
21 | * arguments
22 | *)
23 | type cmd = RUN of string | DIR | HELP | SETDIR of string
24 | | RESULTS of string | PAIR | COMPARE of (string*string)| ERROR
25 |
26 | (* this is printed every time the user enters the help command *)
27 | val help: string
28 |
29 | (* represents the initial state of OCaMoss when it starts:
30 | * displays a welcome message and a list of commands
31 | * default params of k=35 w=40
32 | * no results loaded and no working directory preset *)
33 | val newstate: state
34 |
35 | (* parses the string of a user into specific commands for MOSS *)
36 | val parse: string -> cmd
37 |
38 | (* [repl st] the REPL for entering commands to MOSS,
39 | * side effects: prints the string in the display field in [st] and
40 | * some progress indicators when running and displaying results
41 | * expected behavior for commands:
42 | *
43 | * [run]
44 | * - runs MOSS on the current directory of the state
45 | * - displays an error message if current directory is not set,
46 | * if files are invalid file type, or if not all files have same extn
47 | * - displays list of files that are likely to be plagiarized
48 | * - two optional params for w and k, with the following conditions:
49 | * w is in range [20,100], k is in range [15,40], k < w
50 | * - if only one param is provided, if params are invalid an error
51 | * message will be displayed
52 | *
53 | * [help]
54 | * - lists the available commands, takes no arguments
55 | *
56 | * [setdir]
57 | * - sets the working directory where MOSS looks for files, takes
58 | * 1 argument, the directory path relative to the folder main.ml is in
59 | * - displays the files in the new directory
60 | * - displays error message if directory is incorrect
61 | *
62 | * [dir]
63 | * - displays the working directory and all the files it contains
64 | *
65 | * [results]
66 | * if 0 arguments:
67 | * - displays all files that have results, and their overall similarity scores
68 | * if 1 argument (name of a file:
69 | * - if valid file name of a file with results, displays the similarity score
70 | * of that file compared to all other files in results
71 | * - if there are no results to display, an error message will be shown
72 | *
73 | * [compare]
74 | * - if results exist, and both arguments are valid file names with results,
75 | * a side by side printout of the matching patterns in the fingerprints of
76 | * files will be displayed
77 | * - otherwise, an error message will be displayed
78 | *
79 | * [quit]
80 | * - exits the repl
81 | *
82 | * invalid commands will display an error message
83 | *)
84 | val repl : state -> unit
85 |
--------------------------------------------------------------------------------
/preprocessing.ml:
--------------------------------------------------------------------------------
1 | open Winnowing
2 | open Unix
3 | open Filename
4 | open Yojson.Basic.Util
5 |
6 | type comment_info = {
7 | single_comment: string;
8 | multi_comment_start: string;
9 | multi_comment_end: string;
10 | nest: bool;
11 | strings: bool;
12 | }
13 |
14 | type language_info = {
15 | keywords: string list;
16 | special_chars: char list;
17 | comment_info: comment_info;
18 | }
19 |
20 | let get_language_info language_file =
21 | let path_to_language_file =
22 | String.concat "/" ["language_files"; language_file] in
23 | let json = Yojson.Basic.from_file path_to_language_file in
24 | let keywords_list = json |> member "keywords"
25 | |> to_list |> List.map to_string in
26 | let special_chars = json |> member "special characters"
27 | |> to_list |> List.map to_string
28 | |> List.map (fun str -> String.get str 0) in
29 | let one_line_comm_st = json |> member "comment" |> to_string in
30 | let mult_line_comm_st = json |> member "comment-start" |> to_string in
31 | let mult_line_comm_end = json |> member "comment-end" |> to_string in
32 | let comments_nest = json |> member "comments-nest" |> to_bool in
33 | let rm_string = json |> member "strings" |> to_bool in
34 | let comment_info = {
35 | single_comment = one_line_comm_st;
36 | multi_comment_start = mult_line_comm_st;
37 | multi_comment_end = mult_line_comm_end;
38 | nest = comments_nest;
39 | strings = rm_string
40 | } in
41 | {
42 | keywords = keywords_list;
43 | special_chars = special_chars;
44 | comment_info = comment_info;
45 | }
46 |
47 | let keywords l = l.keywords
48 | let special_chars l = l.special_chars
49 | let comment_info l = l.comment_info
50 |
51 | (* [rem_white_space code_string] returns a string list representing the strings
52 | * in [code_string] separated by tabs, newlines, carriage returns, and spaces,
53 | * with empty strings filtered out of said list.
54 | *
55 | * example: [rem_white_space " Hello World " = ["Hello"; "World"]]
56 | *)
57 | let rem_white_space code_string =
58 | code_string |>
59 | String.split_on_char '\t' |> String.concat " " |>
60 | String.split_on_char '\n' |> String.concat " " |>
61 | String.split_on_char '\r' |> String.concat " " |>
62 | String.split_on_char ' ' |>
63 | List.filter (fun str -> str <> "")
64 |
65 | (* [split_and_keep_on_spec_chars spec_chars str] essentially does the same
66 | * thing as [String.split_on_char] for each character in [spec_char], except
67 | * each of the characters in [spec_char] are themselves an element in the
68 | * resulting list.
69 | *
70 | * example:
71 | * [split_and_keep_on_spec_chars [!;?] "Hello!World?" =
72 | * ["Hello"; "!"; "World"; "?"]]
73 | *)
74 | let split_and_keep_on_spec_chars spec_chars str =
75 | let rec str_to_chr_arr str =
76 | let tail_len = String.length str - 1 in
77 | match str with
78 | | "" -> []
79 | | str -> (String.get str 0)::(str_to_chr_arr (String.sub str 1 tail_len))
80 | in
81 | let char_array = str_to_chr_arr str in
82 | (List.fold_left
83 | (fun acc_arr chr ->
84 | let str_of_chr = String.make 1 chr in
85 | if List.mem chr spec_chars then
86 | List.cons "" (List.cons str_of_chr acc_arr)
87 | else
88 | match acc_arr with
89 | | h::t -> (String.concat "" [h;str_of_chr])::t
90 | | [] -> failwith "Array should never be empty")
91 | [""]
92 | char_array) |> List.filter (fun str -> str <> "") |> List.rev
93 |
94 | (* [split_on_str str_to_split_on acc_str_arr str_to_split] splits up
95 | * [str_to_split] on every instance of [str_to_split_on] when
96 | * [acc_str_arr] = []. [acc_str_arr] acts as an accumulator array that stores
97 | * the accumulating string array as splitting is being done.
98 | *
99 | * example:
100 | * [split_on_str "Hello" [] "HelloWorldHelloWorldHello" =
101 | * ["Hello"; "World"; "Hello"; "World"; "Hello"]
102 | *)
103 | let rec split_on_str str_to_split_on acc_str_arr str_to_split =
104 | let str_to_split_on_len = String.length str_to_split_on in
105 | let str_to_split_len = String.length str_to_split in
106 | let new_acc_arr_else_case acc_str_arr str_to_split_on str_to_add =
107 | match acc_str_arr with
108 | | [] -> [str_to_add]
109 | | h::t ->
110 | if h = str_to_split_on then str_to_add::acc_str_arr
111 | else
112 | let new_acc_arr_hd = String.concat "" [h; str_to_add] in
113 | new_acc_arr_hd::t
114 | in
115 | if String.length str_to_split = 0 then List.rev acc_str_arr
116 | else
117 | try
118 | if str_to_split_on = (String.sub str_to_split 0 str_to_split_on_len) then
119 | let head_str = str_to_split_on in
120 | let tail_len = str_to_split_len - str_to_split_on_len in
121 | let tail_str = String.sub str_to_split str_to_split_on_len tail_len in
122 | split_on_str str_to_split_on (head_str::acc_str_arr)tail_str
123 | else
124 | let head_str = String.sub str_to_split 0 1 in
125 | let tail_len = str_to_split_len - 1 in
126 | let tail_str = String.sub str_to_split 1 tail_len in
127 | let new_acc_arr =
128 | new_acc_arr_else_case acc_str_arr str_to_split_on head_str in
129 | split_on_str str_to_split_on new_acc_arr tail_str
130 | with Invalid_argument _ ->
131 | let new_acc_arr =
132 | new_acc_arr_else_case acc_str_arr str_to_split_on str_to_split in
133 | List.rev new_acc_arr
134 |
135 | (* [remove_strings code_str], when treating [code_str] as a block of code,
136 | * removes all instances of strings in code_str.
137 | *
138 | * example: [remove_strings "let str = \"Hello\"" = "let str = "]
139 | *)
140 | let remove_strings code_str =
141 | let code_str = String.split_on_char '\'' code_str |> String.concat "\"" in
142 | let filter_from_arr (acc_arr, start) str =
143 | if str = "\"" && start = false then
144 | (" "::acc_arr, true)
145 | else if str = "\"" then
146 | (" "::acc_arr, false)
147 | else
148 | if start then (" s "::acc_arr, start)
149 | else (" "::str::acc_arr, false)
150 | in
151 | let split_on_strings_arr = split_on_str "\"" [] code_str in
152 | let acc_tup =
153 | List.fold_left filter_from_arr ([], false) split_on_strings_arr in
154 | match acc_tup with
155 | | (acc_arr, _) -> List.rev acc_arr
156 |
157 | (* [remove_comments comment_start comment_end comments_nest code_str], where
158 | * - [comment_start] is a string that indicates the start of a comment.
159 | * - [comment_end] is a string that indicates the end of a comment.
160 | * - [comments_nest] is a bool that indicates whether or not comments nest in
161 | * the language that [code_str] is written in.
162 | * - and [code_str] is the string representation of code whose comments are to
163 | * be removed.
164 | * returns [code_str] but with all of its comments removed.
165 | *)
166 | let remove_comments
167 | comment_start comment_end comments_nest code_str =
168 | let do_filter_from_arr (acc_arr, nesting) str =
169 | if str = comment_start then
170 | if comments_nest then (" "::acc_arr, nesting + 1)
171 | else (" "::acc_arr, 1)
172 | else if str = comment_end then
173 | if comments_nest then (" "::acc_arr, nesting - 1)
174 | else (" "::acc_arr, 0)
175 | else
176 | if nesting > 0 then (acc_arr, nesting)
177 | else (" "::str::acc_arr, 0)
178 | in
179 | let split_on_comments_arr =
180 | split_on_str comment_start [] code_str |>
181 | List.map (split_on_str comment_end []) |> List.flatten
182 | in
183 | let acc_tup =
184 | List.fold_left do_filter_from_arr ([], 0) split_on_comments_arr in
185 | match acc_tup with
186 | | (acc_arr, _) -> List.rev acc_arr
187 |
188 | (* [replace_generics keywords spec_chars str_arr] goes through the list, and
189 | * replaces any string that
190 | * - isn't a keyword
191 | * - isn't the string representation of a special character
192 | * - isn't the string representation of an int
193 | * with the letter "v". All relevant keywords and special characters are found
194 | * in [keywords] and [spec_chars], respectively.
195 | *
196 | * example: [
197 | * replace_generics
198 | * ["if"; "then"; "else"]
199 | * ['['; ']']
200 | * ["if"; "some_bool"; "then"; "["; "]"; "else"; "["; "one_element"; "]"] =
201 | * ["if"; "v"; "then"; "["; "]"; "else"; "["; "v"; "]"]
202 | * ]
203 | *)
204 | let replace_generics keywords spec_chars str_arr =
205 | List.map
206 | (fun str ->
207 | if List.mem str keywords ||
208 | ((String.length str = 1) && (List.mem (String.get str 0) spec_chars))
209 | then str
210 | else
211 | try
212 | int_of_string str |> string_of_int
213 | with Failure _ -> "v" )
214 | str_arr
215 |
216 | (* Refer to preprocessing.mli for this function's specifications *)
217 | let remove_noise comment_info code_string keywords spec_chars is_txt =
218 | if is_txt then code_string
219 | else
220 | let rm_one_line_comment s =
221 | if comment_info.single_comment = "" then s
222 | else
223 | remove_comments comment_info.single_comment "\n" false s
224 | |> String.concat ""
225 | in
226 | let rm_mult_line_comment s =
227 | if comment_info.multi_comment_start = "" then s
228 | else
229 | remove_comments comment_info.multi_comment_start comment_info.multi_comment_end comment_info.nest s
230 | |> String.concat ""
231 | in
232 | let rm_strings s =
233 | if comment_info.strings then remove_strings s |> String.concat ""
234 | else s
235 | in
236 | rm_strings code_string |> rm_mult_line_comment |> rm_one_line_comment |>
237 | split_and_keep_on_spec_chars spec_chars |>
238 | List.map rem_white_space |> List.flatten |>
239 | replace_generics keywords spec_chars |>
240 | String.concat ""
241 |
242 | (* Refer to preprocessing.mli for this function's specifications *)
243 | let k_grams s k =
244 | let rec k_grams_helper acc s n =
245 | try
246 | let n_sub_str = String.sub s 0 n in
247 | let tail_str = String.sub s 1 ((String.length s)-1) in
248 | k_grams_helper (n_sub_str::acc) tail_str n
249 | with Invalid_argument _ -> List.rev acc
250 | in
251 | k_grams_helper [] s k
252 |
253 | (* [determine_language_file f] returns the string that represents the name of
254 | * of the json file that contains all relevant information about the language
255 | * that the code in the file named [f] is written in.
256 | *)
257 | let determine_language_file f =
258 | if check_suffix f "txt" then "txt_info.json"
259 | else if check_suffix f "ml" then "ocaml_info.json"
260 | else if check_suffix f "mli" then "ocaml_info.json"
261 | else if check_suffix f "c" then "c_info.json"
262 | else if check_suffix f "cpp" then "cpp_info.json"
263 | else if check_suffix f "java" then "java_info.json"
264 | else if check_suffix f "py" then "python_info.json"
265 | else failwith "This file format is not supported"
266 |
267 | let get_ngrams f n =
268 | let rec hash_helper f_channel s =
269 | try
270 | let line = input_line f_channel in
271 | hash_helper f_channel (s^line^"\n")
272 | with
273 | | End_of_file -> s in
274 | let language_file = determine_language_file f in
275 | let language_info = get_language_info language_file in
276 | let keywords = language_info.keywords in
277 | let spec_chars = language_info.special_chars in
278 | let f_string = hash_helper (open_in f) language_file in
279 | let is_txt = check_suffix f "txt" in
280 | let com_info = language_info.comment_info in
281 | let noise_removed_str =
282 | remove_noise com_info f_string keywords spec_chars is_txt in
283 | k_grams noise_removed_str n
284 |
285 | (* Refer to preprocessing.mli for this function's specifications *)
286 | let hash_file f =
287 | let n_grams = get_ngrams f 35 in
288 | List.map (Hashtbl.hash) n_grams
289 |
290 | (* Refer to preprocessing.mli for this function's specifications *)
291 | let rec get_file_positions dir dir_name filename positions =
292 | try
293 | let f_name = Unix.readdir dir in
294 | if f_name <> filename then get_file_positions dir dir_name filename
295 | positions
296 | else begin
297 | let f = dir_name ^ Filename.dir_sep ^ f_name in
298 | let n_grams = get_ngrams f 35 in
299 | let results = List.map (fun x ->
300 | (string_of_int x, List.nth n_grams (x - 1))
301 | ) positions in
302 | List.sort (fun a b ->
303 | Stdlib.compare (snd a |> Hashtbl.hash) (snd b |> Hashtbl.hash)
304 | ) results
305 | end
306 | with
307 | | _ -> []
308 |
--------------------------------------------------------------------------------
/preprocessing.mli:
--------------------------------------------------------------------------------
1 | open Winnowing
2 | open Unix
3 |
4 | type comment_info = {
5 | single_comment: string;
6 | multi_comment_start: string;
7 | multi_comment_end: string;
8 | nest: bool;
9 | strings: bool;
10 | }
11 |
12 | type language_info = {
13 | keywords: string list;
14 | special_chars: char list;
15 | comment_info: comment_info;
16 | }
17 |
18 | (* [get_language_info language_file] gets the language info from a particular language JSON file and returns it as a record
19 | * requires: language_file is well-formatted JSON with the necessary fields
20 | *)
21 | val get_language_info : string -> language_info
22 |
23 | (* [remove_noise c_i_q code_str keywords spec_chars comments_nest remove_strings],
24 | * where
25 | * - [c_i_q] represents a comment_info record
26 | * - [code_str] is the string representation of the code whose noise is to be
27 | * removed.
28 | * - [keywords] represents a list of keywords in the language that [code_str] is
29 | * written in that are to be kept upon noise removal, and not replaced by a
30 | * generic character.
31 | * - [spec_chars] represents a list of special characters in the language that
32 | * [code_str] is written in that are to be kept upon noise removal, and not
33 | * replaced by a generic character.
34 | * - [comments_nest] is a bool that indicates whether or not multi-line
35 | * comments nest in the language.
36 | * - and [remove_strings] is a bool that indicates whether or not strings are to
37 | * be removed from files of this language
38 | * is a function that takes outputs a "noise removed" version of [code_str],
39 | * where noise removal in this case indicates removing all instances of white
40 | * space, strings (if set to be removed), and comments, and replacing all
41 | * programmer defined variable/class/interface/module/type/function/method etc.,
42 | * names with a generic character 'v'.
43 | *)
44 | val remove_noise : comment_info -> string -> string list -> char list -> bool -> string
45 |
46 | (* [k_grams str n] creates a list of strings of length n, starting at each
47 | * character in [str] up to and including ([str] length - [n])th character.
48 | *
49 | * example:
50 | * [k_grams "Hello World" 3 =
51 | * ["Hel"; "ell"; "llo"; "lo "; "o W"; " Wo"; "Wor"; "orl"; "rld"]]
52 | *)
53 | val k_grams : string -> int -> string list
54 |
55 | (* [hash_file f] returns a list of hashes for n-grams of a file f with default
56 | * n = 35, where the file has been preprocessed by removing whitespace,
57 | * removing comments, replacing all variable names and strings with a generic
58 | * tag, while making sure that keywords and module names remain intact.
59 | *)
60 | val hash_file : string -> int list
61 |
62 | (* [get_file_positions dir dir_name filename positions] rehashes file filename
63 | * from directory dir, preprocessing it similar to how it would be in hash_file,
64 | * and returns a list of parts of the files that start at the values in
65 | * positions once the files have been preprocessed.
66 | *)
67 | val get_file_positions : Unix.dir_handle ->
68 | string -> string -> int list -> (string * string) list
69 |
--------------------------------------------------------------------------------
/test.ml:
--------------------------------------------------------------------------------
1 | open OUnit2
2 |
3 | let suite = "Final Project Test Suite" >:::
4 | Test_winnow.tests
5 | @
6 | Test_comparison.tests
7 | @
8 | Test_dictionary.tests
9 | @
10 | Test_preprocessing.tests
11 |
12 | (* The following line must be the one and only place
13 | * in your entire source code that calls [OUnit2.run_test_tt_main]. *)
14 | let _ = run_test_tt_main suite
15 |
--------------------------------------------------------------------------------
/test_comparison.ml:
--------------------------------------------------------------------------------
1 | open OUnit2
2 | open Dictionary
3 | open Comparison
4 |
5 | let assoc_compare l1 l2 =
6 | if List.length l1 <> List.length l2 then false
7 | else
8 | List.fold_left (fun acc (k,v) -> acc && List.assoc k l2 = v) true l1
9 |
10 | let unordered_list_compare l1 l2 =
11 | if List.length l1 <> List.length l2 then false
12 | else
13 | List.fold_left (fun acc x -> acc && List.mem x l2) true l1
14 |
15 | let filedict_equal d1 d2 =
16 | assert_equal ~cmp:assoc_compare (FileDict.to_list d1) (FileDict.to_list d2)
17 |
18 | let compdict_equal d1 d2 =
19 | assert_equal ~cmp:assoc_compare (CompDict.to_list d1) (CompDict.to_list d2)
20 |
21 | let emp_file = FileDict.empty
22 |
23 | let se_dict = FileDict.insert "a" [(1,0)] emp_file
24 | let de_dict = FileDict.(empty |> insert "a" [(1,0);(2,0)]
25 | |> insert "b" [(1,0);(3,0)])
26 | let emp_e_dict = FileDict.(empty |> insert "a" [] |> insert "b" [(7,0);(4,0)]
27 | |> insert "c" [(4,0);(8,0);(13,0)])
28 |
29 | let def_p_comp = FileDict.(empty |> insert "a" [(1,0);(2,0)]
30 | |> insert "b" [(1,0)])
31 | let des_p_comp = FileDict.(empty |> insert "a" [(1,0)]
32 | |> insert "b" [(1,0);(3,0)])
33 | let emp_e_f_p_comp = FileDict.(empty |> insert "a" [] |> insert "b" []
34 | |> insert "c" [])
35 | let emp_e_s_p_comp = FileDict.(empty |> insert "a" []
36 | |> insert "b" [(7,0);(4,0)]
37 | |> insert "c" [(4,0)])
38 | let emp_e_t_p_comp = FileDict.(empty |> insert "a" [] |> insert "b" [(4,0)]
39 | |> insert "c" [(4,0);(8,0);(13,0)])
40 |
41 |
42 | let emp_comp = CompDict.empty
43 | let se_comp = CompDict.(insert "a" se_dict empty)
44 | let def_comp = CompDict.(insert "a" def_p_comp empty)
45 | let de_comp = CompDict.insert "b" des_p_comp def_comp
46 | let emp_e_comp = CompDict.(empty |> insert "a" emp_e_f_p_comp
47 | |> insert "b" emp_e_s_p_comp
48 | |> insert "c" emp_e_t_p_comp)
49 |
50 | let get_files = List.map (fun (k,s) -> k)
51 |
52 | let tests = [
53 |
54 | (* The test cases for intersection has cases that test what happens with
55 | * one or more empty lists, single element lists, 2 lists with the order
56 | * reversed, lists with elements of same hash but different position,
57 | * and lists with different number of elements, which are all the edge
58 | * cases, and then a couple of general cases. *)
59 | "empty lists" >:: (fun _ -> assert_equal ~cmp:assoc_compare [] (intersection [] []));
60 | "one list empty" >:: (fun _ -> assert_equal ~cmp:assoc_compare []
61 | ((intersection [(12,7);(9,13)] [])));
62 | "single lists uneq" >::
63 | (fun _ -> assert_equal ~cmp:assoc_compare [] (intersection [(1,0)] [(2,0)]));
64 | "single lists eq" >::
65 | (fun _ -> assert_equal ~cmp:assoc_compare [(1,0)] (intersection [(1,0)] [(1,0)]));
66 | "diff order" >:: (fun _ -> assert_equal ~cmp:assoc_compare [(1,0);(2,0)]
67 | ((intersection [(1,0);(2,0)] [(2,0);(1,0)])));
68 | "second order" >:: (fun _ -> assert_equal ~cmp:assoc_compare [(2,0);(1,0)]
69 | ((intersection [(2,0);(1,0)] [(1,0);(2,0)] )));
70 | "diff pos" >:: (fun _ -> assert_equal ~cmp:assoc_compare [(1,3);(2,1)]
71 | ((intersection [(1,3);(2,1)] [(2,2);(1,5)])));
72 | "diff number of elems" >:: (fun _ -> assert_equal ~cmp:assoc_compare [(1,0);(2,1)]
73 | ((intersection [(1,0);(7,3);(2,1);(4,3)]
74 | [(2,2);(1,5)])));
75 | "simp case" >::
76 | (fun _ -> assert_equal ~cmp:assoc_compare [(1,0);(2,0)]
77 | ((intersection [(3,0);(1,0);(2,0)] [(2,0);(1,0)])));
78 | "long case" >:: (fun _ -> assert_equal ~cmp:assoc_compare [(41,0);(20,0);(7,0);(53,0)]
79 | (intersection [(82,0);(23,0);(46,0);(93,0);(41,0);(20,0);
80 | (47,0);(7,0);(84,0);(53,0)]
81 | [(80,0);(42,0);(41,0);(53,0);(72,0);(7,0);(20,0);(100,0)]));
82 |
83 |
84 | (* The test cases for make_pair_comp test if the function works on an
85 | * empty file, on a single entry file dictionary, if it works correctly for
86 | * either part of a double entry file dictionary with the corresponding
87 | * changes, and if it works if one of the entries in a file dictionary
88 | * is empty, which are all the edge cases. *)
89 | "empty file" >:: (fun _ -> filedict_equal emp_file
90 | (make_pair_comp "" []));
91 | "single entry" >:: (fun _ -> filedict_equal se_dict
92 | (make_pair_comp "a" [("a",[(1,0)])]));
93 | "double entry first" >:: (fun _ -> filedict_equal def_p_comp
94 | (make_pair_comp "a" (FileDict.to_list de_dict)));
95 | "double entry second" >:: (fun _ -> filedict_equal des_p_comp
96 | (make_pair_comp "b" (FileDict.to_list de_dict)));
97 | "empty entry in file" >:: (fun _ -> filedict_equal emp_e_f_p_comp
98 | (make_pair_comp "a" (FileDict.to_list emp_e_dict)));
99 | "empty entry second" >:: (fun _ -> filedict_equal emp_e_s_p_comp
100 | (make_pair_comp "b" (FileDict.to_list emp_e_dict)));
101 | "empty entry third" >:: (fun _ -> filedict_equal emp_e_t_p_comp
102 | (make_pair_comp "c" (FileDict.to_list emp_e_dict)));
103 |
104 |
105 | (* The test for compare test if it works on an empty file dictionary,
106 | * a single entry file dictionary, a double entry file dictionary,
107 | * and a file dictionary with an empty entry, which are all the edge
108 | * cases. *)
109 | "empty comp" >:: (fun _ -> compdict_equal emp_comp
110 | (compare emp_file));
111 | "single entry comp" >:: (fun _ -> compdict_equal se_comp
112 | (compare se_dict));
113 | "double entry comp" >:: (fun _ -> compdict_equal de_comp
114 | (compare de_dict));
115 | "empty entry comp" >:: (fun _ -> compdict_equal emp_e_comp
116 | (compare emp_e_dict));
117 |
118 |
119 | (* The test cases for create_sim_list test if the function works for
120 | * an empty comparison dictionary, one with a single entry, one with two
121 | * entries, and only with an empty entry, which are all the edge cases. *)
122 | "empty sim" >:: (fun _ -> assert_equal ~cmp:assoc_compare []
123 | (create_sim_list emp_comp 0.5));
124 | "single entry sim" >:: (fun _ -> assert_equal ~cmp:assoc_compare []
125 | (create_sim_list se_comp 0.5));
126 | "double entry sim" >:: (fun _ -> assert_equal ~cmp:unordered_list_compare ["a";"b"]
127 | (create_sim_list de_comp 0.5 |> get_files));
128 | "empty entry sim" >:: (fun _ -> assert_equal ~cmp:unordered_list_compare ["b"]
129 | (create_sim_list emp_e_comp 0.5 |> get_files));
130 |
131 |
132 | (* The tests for create_pair_sim_list test if it works on an empty file
133 | * dictionary list, a single entry list, a double entry list for both entries
134 | * and for a list with an empty entry with every other filename than that of
135 | * of the one with the empty entry, since a precondition is that that case
136 | * will not work, which are all of the edge cases. *)
137 | "empty pair" >:: (fun _ -> assert_equal ~cmp:assoc_compare []
138 | (create_pair_sim_list "" []));
139 | "single entry" >:: (fun _ -> assert_equal ~cmp:assoc_compare []
140 | (create_pair_sim_list "a" (FileDict.to_list se_dict)));
141 | "double entry first" >:: (fun _ -> assert_equal ~cmp:assoc_compare [("b",0.5)]
142 | (create_pair_sim_list "a" (FileDict.to_list def_p_comp)));
143 | "double entry second" >:: (fun _ -> assert_equal ~cmp:assoc_compare [("a",0.5)]
144 | (create_pair_sim_list "b" (FileDict.to_list des_p_comp)));
145 | "empty entry second" >:: (fun _ -> assert_equal ~cmp:assoc_compare [("c",0.5);("a",0.0)]
146 | (create_pair_sim_list "b" (FileDict.to_list emp_e_s_p_comp)));
147 | "empty entry third" >:: (fun _ -> assert_equal ~cmp:unordered_list_compare ["b";"a"]
148 | ((create_pair_sim_list "c" (FileDict.to_list emp_e_t_p_comp)) |> get_files));
149 |
150 | ]
--------------------------------------------------------------------------------
/test_dictionary.ml:
--------------------------------------------------------------------------------
1 | open Dictionary
2 | open OUnit2
3 |
4 | let assoc_compare l1 l2 =
5 | if List.length l1 <> List.length l2 then false
6 | else
7 | List.fold_left (fun acc (k,v) -> acc && List.assoc k l2 = v) true l1
8 |
9 | module ValString = struct
10 | type t = string
11 | let format s =
12 | print_string s;
13 | end
14 |
15 | module KeyString = struct
16 | type t = string
17 | let compare x y = Stdlib.compare x y
18 | end
19 |
20 | module DictString = HashtblDict (KeyString) (ValString)
21 |
22 | let t1 = DictString.(insert "A" "a" empty)
23 | let t2 = DictString.(insert "L" "l" t1)
24 | let t3 = DictString.(insert "G" "g" t2)
25 | let t4 = DictString.(insert "O" "o" t3)
26 | let t5 = DictString.(insert "R" "r" t4)
27 | let t6 = DictString.(insert "I" "i" t5)
28 | let t7 = DictString.(insert "T" "t" t6)
29 | let t8 = DictString.(insert "H" "h" t7)
30 | let t9 = DictString.(insert "M" "m" t8)
31 | let t = DictString.(insert "S" "s" t9)
32 |
33 | let tests = [
34 | "insert first" >::(fun _ -> assert_equal ~cmp:assoc_compare [("A","a")] (DictString.to_list t1));
35 | "insert 2" >:: (fun _ -> assert_equal ~cmp:assoc_compare [("A","a");("L","l")]
36 | (DictString.to_list t2));
37 | "insert 2" >:: (fun _ -> assert_equal ~cmp:assoc_compare [("A","a"); ("G", "g");("L","l")]
38 | (DictString.to_list t3));
39 | "insert 3" >:: (fun _ -> assert_equal ~cmp:assoc_compare [("A","a"); ("G", "g");("L","l");
40 | ("O","o")] (DictString.to_list t4));
41 | "insert 4" >:: (fun _ -> assert_equal ~cmp:assoc_compare
42 | [("A","a"); ("G","g");("L","l"); ("O","o");("R","r")]
43 | (DictString.to_list t5));
44 | "insert 5" >:: (fun _ -> assert_equal ~cmp:assoc_compare
45 | [("A","a"); ("G","g"); ("I", "i");("L","l"); ("O","o");("R","r")]
46 | (DictString.to_list t6));
47 | "insert 6" >:: (fun _ -> assert_equal ~cmp:assoc_compare
48 | [("A","a"); ("G","g");("I","i");("L","l"); ("O","o");("R","r"); ("T","t")]
49 | (DictString.to_list t7));
50 | "insert 7" >:: (fun _ -> assert_equal ~cmp:assoc_compare
51 | [("A","a"); ("G","g");("H","h");("I","i");("L","l"); ("O","o");("R","r");
52 | ("T","t")] (DictString.to_list t8));
53 | "insert 8" >:: (fun _ -> assert_equal ~cmp:assoc_compare
54 | [("A","a"); ("G","g");("H","h");("I","i");("L","l");
55 | ("M","m");("O","o");("R","r"); ("T","t")]
56 | (DictString.to_list t9));
57 | "Inserted Correct" >:: (fun _ ->
58 | assert_equal ~cmp:assoc_compare [("A", "a"); ("G", "g"); ("H", "h"); ("I", "i"); ("L", "l");
59 | ("M", "m"); ("O", "o"); ("R", "r"); ("S", "s"); ("T", "t")]
60 | (DictString.to_list t));
61 |
62 |
63 | "size_empty" >:: (fun _ -> assert_equal 0 DictString.(size empty));
64 | "size_1" >:: (fun _ -> assert_equal 1 DictString.(size t1));
65 | "size_mid" >:: (fun _ -> assert_equal 5 DictString.(size t5));
66 | "size_full" >:: (fun _ -> assert_equal 10 DictString.(size t));
67 |
68 | "string_member" >:: (fun _ -> assert_equal true
69 | (DictString.member "A" t1));
70 | "member_empty" >:: (fun _ -> assert_equal false
71 | (DictString.(member "empty" empty)));
72 | "member_fake" >:: (fun _ -> assert_equal false (DictString.member "B" t1));
73 | "member_two" >:: (fun _ -> assert_equal true (DictString.member "R" t));
74 | "member_three" >:: (fun _ -> assert_equal true (DictString.member "S" t));
75 |
76 | "find_fake" >:: (fun _ -> assert_equal (None) (DictString.find "fake" t));
77 | "find_none" >:: (fun _ -> assert_equal (None) DictString.(find "K" empty));
78 | "find_first" >:: (fun _ -> assert_equal (Some("a"))
79 | (DictString.find "A" t1));
80 |
81 | "find_two" >:: (fun _ -> assert_equal (Some "g") DictString.(find "G" t));
82 | "find_three" >:: (fun _ -> assert_equal (Some "m") DictString.(find "M" t));
83 | ]
84 |
--------------------------------------------------------------------------------
/test_preprocessing.ml:
--------------------------------------------------------------------------------
1 | open OUnit2
2 | open Preprocessing
3 |
4 | let ocaml_keywords =
5 | ["and"; "as"; "assert"; "asr"; "begin"; "class"; "constraint";
6 | "do"; "done"; "downto"; "else"; "end"; "exception"; "external";
7 | "false"; "for"; "fun"; "function"; "functor"; "if"; "in"; "include";
8 | "inherit"; "initializer"; "land"; "lazy"; "let"; "lor"; "lsl"; "lsr";
9 | "lxor"; "match"; "method"; "mod"; "module"; "mutable"; "new"; "nonrec";
10 | "object"; "of"; "open"; "or"; "private"; "rec"; "sig"; "struct"; "then";
11 | "to"; "true"; "try"; "type"; "val"; "virtual"; "when"; "while"; "with";
12 | "Arg"; "Array"; "ArrayLabels"; "Buffer"; "Bytes"; "BytesLabels"; "Callback";
13 | "Char"; "Complex"; "Digest"; "Ephemeron"; "Filename"; "Format"; "Gc";
14 | "Genlex"; "Hashtbl"; "Int32"; "Int64"; "Lazy"; "Lexing"; "List";
15 | "ListLabels"; "Map"; "Marshal"; "MoreLabels"; "Nativeint"; "Oo"; "Parsing";
16 | "Printexc"; "Printf"; "Queue"; "Random"; "Scanf"; "Set"; "Sort";
17 | "Spacetime"; "Stack"; "StdLabels"; "Stream"; "String"; "StringLabels";
18 | "Sys"; "Uchar"; "Weak"; "failwith"]
19 |
20 | let ocaml_spec_chars =
21 | ['!'; '$'; '%'; '&'; '*'; '+'; '-'; '.'; '/'; ':'; ';'; '<';
22 | '='; '>'; '?'; '@'; '^'; '|'; '~'; '#'; '\"'; '('; ')'; ',';
23 | '['; ']'; '{'; '}']
24 |
25 | let ocaml_comments_info =
26 | {
27 | single_comment = "";
28 | multi_comment_start = "(*";
29 | multi_comment_end = "*)";
30 | nest= true;
31 | strings= true;
32 | }
33 |
34 | let java_keywords =
35 | ["abstract"; "continue"; "for"; "new"; "switch"; "assert"; "default";
36 | "package"; "synchronized"; "boolean"; "do"; "if"; "private"; "this"; "break";
37 | "double"; "implements"; "protected"; "throw"; "byte"; "else"; "import";
38 | "public"; "throws"; "case"; "enum"; "instanceof"; "return"; "transient";
39 | "catch"; "extends"; "int"; "short"; "try"; "char"; "final"; "interface";
40 | "static"; "void"; "class"; "finally"; "long"; "strictfp"; "volatile";
41 | "float"; "native"; "super"; "while"; "Boolean"; "Byte"; "Character"; "Class";
42 | "ClassLoader"; "ClassValue"; "Compiler"; "Double"; "Enum"; "Float";
43 | "InheritableThreadLocal"; "Integer "; "Long"; "Math"; "Number"; "Object";
44 | "Package"; "Process"; "ProcessBuilder"; "Runtime"; "RuntimePermission";
45 | "SecurityManager"; "Short"; "StackTraceElement"; "StrictMath"; "String";
46 | "StringBuffer"; "StringBuilder"; "System"; "Thread"; "ThreadGroup";
47 | "ThreadLocal"; "Throwable"; "Void"; "AbstractCollection"; "AbstractList";
48 | "AbstractMap"; "AbstractQueue"; "AbstractSequentialList"; "AbstractSet";
49 | "ArrayDeque"; "ArrayList"; "Arrays"; "BitSet"; "Calendar"; "Collections";
50 | "Currency"; "Date"; "Dictionary"; "EnumMap"; "EnumSet"; "EventListenerProxy";
51 | "EventObject"; "FormattableFlags"; "Formatter"; "GregorianCalendar";
52 | "HashMap";"HashSet"; "Hashtable"; "IdentityHashMap"; "LinkedHashMap";
53 | "LinkedHashSet"; "LinkedList"; "ListResourceBundle"; "Locale"; "Objects";
54 | "Observable"; "PriorityQueue"; "Properties"; "PropertyPermission";
55 | "PropertyResourceBundle"; "Random"; "ResourceBundle";
56 | "ResourceBundle.Control"; "Scanner"; "ServiceLoader"; "SimpleTimeZone";
57 | "Stack"; "StringTokenizer"; "Timer"; "TimerTask"; "TimeZone"; "TreeMap";
58 | "TreeSet"; "UUID"; "Vector"; "WeakHashMap"]
59 |
60 | let java_spec_chars =
61 | ['!'; '$'; '%'; '&'; '*'; '+'; '-'; '.'; '/'; ':'; ';';
62 | '<'; '='; '>'; '?'; '^'; '|'; '\"'; '\''; '('; ')'; ','; '['; ']';
63 | '{'; '}'; '~'; '@']
64 |
65 | let java_comments_info =
66 | {
67 | single_comment = "//";
68 | multi_comment_start = "/*";
69 | multi_comment_end = "*/";
70 | nest= false;
71 | strings= true;
72 | }
73 |
74 | let test_fun_str =
75 | "(* Hello World this is a comment *)
76 | (* (* This is a nested comment *) *)
77 | (* This is a multi line comment
78 | This is a multi line comment *)
79 | (* This is a multi line (* nested comment
80 | Wowie this is *) quite the comment *)
81 | let split_and_keep_on_spec_chars spec_chars str =
82 | let char_array = str_to_chr_arr str in
83 | (List.fold_left
84 | (fun acc_arr chr ->
85 | let str_of_chr = String.make 1 chr in
86 | if List.mem chr spec_chars then
87 | List.cons \"\" (List.cons str_of_chr acc_arr)
88 | else
89 | (* Hello I am yet another comment *)
90 | match acc_arr with
91 | | h::t -> (String.concat \"\" [h;str_of_chr])::t
92 | | [] -> failwith \"Array should never be empty\"
93 | )
94 | [\"\"]
95 | char_array) |> List.filter (fun str -> str <> \"\") |> List.rev"
96 |
97 | let expected_res_str = String.concat ""
98 | ["letvvv=letv=vvin(List.v(funvv->letv=String.v1vinifList.vvvthenList.v";
99 | "(List.vvv)elsematchvwith|v::v->(String.v[v;v])::v|[]->failwithv";
100 | ")[]v)|>List.v(funv->v<>)|>List.v"]
101 |
102 | let test_fun_str3 = "wow(*wow wow wow*)wow"
103 |
104 | let expected_res_str3 = "vv"
105 |
106 | let test_fun_str4 = "wow (* wow wow wow"
107 |
108 | let expected_res_str4 = "v"
109 |
110 | let test_fun_str5 =
111 | "/**
112 | * A DumbAI is a Controller that always chooses the blank space with the
113 | * smallest column number from the row with the smallest row number.
114 | */
115 | public class DumbAI extends Controller"
116 |
117 | let expected_res_str5 = "publicclassvextendsv"
118 |
119 | let test_fun_str6 =
120 | "// Note: Calling delay here will make the CLUI work a little more
121 | Hello World
122 | I am the World
123 | hahaha"
124 |
125 | let expected_res_str6 = "vvvvvvv"
126 |
127 | let test_fun_str7 =
128 | "package controller;
129 |
130 | import java.util.ArrayList;
131 | import java.util.List;
132 |
133 | import model.Board;
134 | import model.Game;
135 | import model.Location;
136 | import model.NotImplementedException;
137 | import model.Player;
138 |
139 | /**
140 | * A DumbAI is a Controller that always chooses the blank space with the
141 | * smallest column number from the row with the smallest row number.
142 | */
143 | public class DumbAI extends Controller {
144 |
145 | public DumbAI(Player me) {
146 | super(me);
147 | // TODO Auto-generated constructor stub
148 | //throw new NotImplementedException();
149 | }
150 |
151 | protected @Override Location nextMove(Game g) {
152 | // Note: Calling delay here will make the CLUI work a little more
153 | // nicely when competing different AIs against each other.
154 |
155 | // TODO Auto-generated method stub
156 | //throw new NotImplementedException();
157 |
158 | Board b = g.getBoard();
159 | // find available moves
160 | for (int row = 0;row:: (fun _ -> assert_equal (k_grams "test" 3) ["tes"; "est"]);
182 | "k_grams_1" >:: (fun _ -> assert_equal (k_grams "Hello World" 5)
183 | ["Hello"; "ello "; "llo W"; "lo Wo"; "o Wor"; " Worl"; "World"]);
184 | "ocaml_keywords" >:: (fun _ -> assert_equal
185 | ocaml_info.keywords
186 | ocaml_keywords);
187 | "ocaml_spec_chars" >:: (fun _ -> assert_equal
188 | ocaml_info.special_chars ocaml_spec_chars);
189 | "ocaml_comments_info" >:: (fun _ -> assert_equal
190 | ocaml_info.comment_info
191 | ocaml_comments_info);
192 |
193 | "java_keywords" >:: (fun _ -> assert_equal java_info.keywords java_keywords);
194 | "java_spec_chars" >:: (fun _ -> assert_equal java_info.special_chars java_spec_chars);
195 | "java_comments_info" >:: (fun _ -> assert_equal
196 | java_info.comment_info
197 | java_comments_info);
198 |
199 |
200 | "remove_noise" >::
201 | (fun _ -> assert_equal
202 | (remove_noise
203 | ocaml_comments_info
204 | test_fun_str
205 | ocaml_keywords ocaml_spec_chars
206 | false)
207 | expected_res_str);
208 |
209 | "remove_noise_3" >::
210 | (fun _ -> assert_equal
211 | (remove_noise
212 | ocaml_comments_info
213 | test_fun_str3
214 | ocaml_keywords ocaml_spec_chars
215 | false)
216 | expected_res_str3);
217 |
218 | "remove_noise_4" >::
219 | (fun _ -> assert_equal
220 | (remove_noise
221 | ocaml_comments_info
222 | test_fun_str4
223 | ocaml_keywords ocaml_spec_chars
224 | false)
225 | expected_res_str4);
226 |
227 | "remove_noise_5" >::
228 | (fun _ -> assert_equal
229 | (remove_noise
230 | java_comments_info
231 | test_fun_str5
232 | java_keywords java_spec_chars
233 | false)
234 | expected_res_str5);
235 |
236 | "remove_noise_6" >::
237 | (fun _ -> assert_equal
238 | (remove_noise
239 | java_comments_info
240 | test_fun_str6
241 | java_keywords java_spec_chars
242 | false)
243 | expected_res_str6);
244 |
245 | "remove_noise_7" >::
246 | (fun _ -> assert_equal
247 | (remove_noise
248 | java_comments_info
249 | "abc<=def"
250 | java_keywords java_spec_chars
251 | false)
252 | "v<=v");
253 |
254 | "remove_noise_8" >::
255 | (fun _ -> assert_equal
256 | (remove_noise
257 | ocaml_comments_info
258 | "let x = \"(*\" in let y = 5 in \"*)\""
259 | ocaml_keywords ocaml_spec_chars
260 | false)
261 | "letv=vinletv=5inv");
262 |
263 | "remove_noise_9" >::
264 | (fun _ -> assert_equal
265 | (remove_noise
266 | ocaml_comments_info
267 | "let x = 'y'"
268 | ocaml_keywords ocaml_spec_chars
269 | false)
270 | "letv=v");
271 | ]
272 |
--------------------------------------------------------------------------------
/test_winnow.ml:
--------------------------------------------------------------------------------
1 | open OUnit2
2 | open Winnowing
3 |
4 | (* helper function for sorting winnowing results (int*int) list representing
5 | * hash * position tuples sorts from least to greatest, by hash value first,
6 | * then by position if hashes are equal
7 | *)
8 | let sort_results r =
9 | let cmp x y =
10 | let res = Stdlib.compare (fst x) (fst y) in
11 | if res = 0 then Stdlib.compare (snd x) (snd y) else res
12 | in
13 | List.sort (cmp) r
14 |
15 | (* helper function for converting results to strings
16 | * inputs: (int * int) list representing winnowing results
17 | * returns: a string representation of the hashes contained in the input
18 | * side effects: prints the string that is created *)
19 | let res_to_string r =
20 | List.rev r |> List.map (fun x -> fst x) |> List.map (string_of_int) |>
21 | List.fold_left (fun a x -> a ^ x ^ ",") ""
22 |
23 | (* Non-trivial test cases generated with a Python implementation of the same
24 | * algorithm *)
25 | (* 10 hashes, w = 5 *)
26 | let t1 = [407;345;-163;-695;54;898;-182;759;172;-345]
27 | let r1 = "407,345,-163,-695,-182,-345,"
28 |
29 | (* 100 hashes, w = 10 *)
30 | let t2 = [-525;-765;990;457;-841;-446;-407;386;-433;-145;370;-133;-170;348;-532;
31 | 328;306;-325;-856;-131;971;266;-88;-608;-274;539;10;-367;389;68;147;
32 | 81;-745;51;750;640;148;416;-983;645;-692;-169;-162;-76;562;894;881;
33 | -883;244;121;-501;-281;311;-903;20;-285;-533;-818;-273;241;103;318;
34 | 161;763;-790;-348;961;655;431;301;217;-680;834;385;-92;76;-354;-683;
35 | 23;-898;-16;734;-806;-474;-728;-349;-900;107;-118;-160;808;273;351;
36 | 117;53;695;261;-803;-571;-564]
37 | let r2 = "-525,-765,-841,-532,-856,-608,-745,-983,-883,-903,-818,-790,-680,"^
38 | "-683,-898,-900,-160,-803,"
39 |
40 | (* 100 hashes, w = 5 *)
41 | let t3 = [-688;288;-953;-376;-521;480;-314;723;428;260;-804;-915;471;990;-243;
42 | -230;-684;-694;682;948;404;-474;-704;746;886;634;92;-87;778;-424;120;
43 | -883;-293;-463;594;-408;58;518;-300;-938;-641;413;873;102;-35;-978;
44 | -921;-909;-745;-693;-318;-612;-475;366;-173;749;181;215;-487;-264;
45 | -33;730;613;-43;-464;-779;435;123;-313;-252;116;-175;-291;21;-932;
46 | -105;-816;-697;312;-332;-140;702;949;864;-134;217;-579;-601;-616;59;
47 | -478;-381;107;-88;-696;872;-431;533;-397;-918]
48 | let r3 = "-688,-953,-521,-314,-804,-915,-684,-694,-704,-87,-424,-883,-463,"^
49 | "-408,-938,-641,-978,-921,-909,-745,-693,-612,-475,-173,-487,-264,"^
50 | "-464,-779,-313,-291,-932,-816,-697,-332,-140,-134,-579,-601,-616,"^
51 | "-478,-696,-918,"
52 |
53 | (* 100 hashes, w = 20 *)
54 | let t4 = [-776;271;540;-580;-710;803;690;980;611;-305;252;-404;-377;544;-982;
55 | -577;-792;139;574;-107;752;-108;-326;354;-339;-323;-317;-571;-995;
56 | 797;-517;-594;-130;-95;-343;-989;-979;-623;299;-941;534;-542;-328;
57 | -23;632;280;640;-74;-3;471;-770;356;-204;-354;-273;124;743;143;575;
58 | -75;-391;329;724;-253;680;-63;-891;-564;92;-100;-892;263;-671;100;
59 | 496;205;468;-936;408;-195;422;600;382;726;991;-397;172;164;373;559;
60 | 185;495;584;-311;-257;-869;-136;968;-12;932]
61 | let r4 = "-776,-982,-995,-989,-979,-941,-770,-891,-892,-936,-869,"
62 |
63 | (* tests to check Winnowing functionality *)
64 | let tests = [
65 | "winnow0" >:: (fun _ -> assert_equal "" (winnow 1 [] |> res_to_string));
66 | "winnow1" >:: (fun _ -> assert_equal "1," (winnow 1 [1] |> res_to_string));
67 | "winnow2" >:: (fun _ -> assert_equal "1,2,3,4,5," (winnow 1 [1;2;3;4;5]
68 | |> res_to_string));
69 | "winnow3" >:: (fun _ -> assert_equal "5,4,3,2,1," (winnow 1 [5;4;3;2;1]
70 | |> res_to_string));
71 | "winnow4" >:: (fun _ -> assert_equal "5,4,3,2,1," (winnow 1 [5;4;3;2;1]
72 | |> res_to_string));
73 | "winnow5" >:: (fun _ -> assert_equal "1,2,3,4," (winnow 2 [1;2;3;4;5]
74 | |> res_to_string));
75 | "winnow6" >:: (fun _ -> assert_equal r1 (winnow 5 t1 |> res_to_string));
76 | "winnow7" >:: (fun _ -> assert_equal r2 (winnow 10 t2 |> res_to_string));
77 | "winnow8" >:: (fun _ -> assert_equal r3 (winnow 5 t3 |> res_to_string));
78 | "winnow9" >:: (fun _ -> assert_equal r4 (winnow 20 t4 |> res_to_string));
79 | ]
80 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/Original.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static int factorial(int n)
7 | {
8 | int ret = 1;
9 | for (int i = 1; i <= n; ++i) ret *= i;
10 | return ret;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T1-Commented.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Class with comments.
3 | * More comments.
4 | *
5 | * @author Author
6 | * @see #factorial(int)
7 | *
8 | */
9 | public class main {
10 | /**
11 | * Function with comments.
12 | * More comments.
13 | * @param args
14 | */
15 | public static void main(String[] args)
16 | { //prints factorial of ten
17 | System.out.println(factorial(10)); }
18 | /**
19 | * Function with comments.
20 | * More comments.
21 | * Factorial of n.
22 | * @param n
23 | * @return factorial
24 | */
25 | public static int factorial(int n) {
26 | //lots of comments
27 | int ret = 1;
28 | //lots of comments
29 | for (int i = 1;i <= n;++i)
30 | //lots of comments
31 | ret *= i;
32 | //lots of comments
33 | return ret;
34 | }
35 | }
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T1-Copy.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static int factorial(int n)
7 | {
8 | int ret = 1;
9 | for (int i = 1; i <= n; ++i) ret *= i;
10 | return ret;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T1-Whitespaces.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args)
4 | { System.out.println(factorial(10)); }
5 | public static int factorial(int n) {
6 | int ret = 1;
7 | for (
8 | int i = 1;
9 | i <= n;
10 | ++i
11 | )
12 | ret *= i; return ret;
13 | } }
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T2-Renamed.java:
--------------------------------------------------------------------------------
1 |
2 | public class renamed {
3 | public static void renamed(String[] commandline_parameters) {
4 | System.out.println(fakultaet(10));
5 | }
6 | public static int fakultaet(int parameter)
7 | {
8 | int result = 1;
9 | for (int current = 1; current <= parameter; ++current) result *= current;
10 | return result;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T2-VariableLong.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static long factorial(long n)
7 | {
8 | long ret = 1;
9 | for (long i = 1; i <= n; ++i) ret *= i;
10 | return ret;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-DummyMethod.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static int factorial(int n)
7 | {
8 | int ret = 1;
9 | for (int i = 1; i <= n; ++i) {
10 | dummy();
11 | ret *= i;
12 | }
13 | return ret;
14 | }
15 | public static void dummy() {
16 | Thread.yield();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-DummyMethodPlus.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | dummy();
5 | System.out.println(factorial(10));
6 | dummy();
7 | }
8 | public static int factorial(int n)
9 | {
10 | dummy();
11 | int ret = 1;
12 | dummy();
13 | for (int i = 1; i <= n; ++i) {
14 | dummy();
15 | ret *= i;
16 | dummy();
17 | }
18 | dummy();
19 | return ret;
20 | }
21 | public static boolean dummy() {
22 | assert true;
23 | Thread.yield();
24 | assert true;
25 |
26 | Thread.yield();
27 | assert true;
28 | return true;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-EndlessLoop.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static int factorial(int n)
7 | {
8 | int ret = 1;
9 | int i = 0;
10 | while (true) {
11 | i++;
12 | ret *= i;
13 | if (i >=n ) break;
14 | }
15 |
16 | return ret;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-ForWhile.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static int factorial(int n)
7 | {
8 | int ret = 1;
9 | int i = 1;
10 | while (i <= n) {
11 | ret *= i;
12 | i++;
13 | }
14 | return ret;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-Inlining.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | int ret = 1;
5 | for (int i = 1; i <= 10; ++i) ret *= i;
6 | System.out.println(ret);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-JumpLabel.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 |
4 | static int currentFactor = 1;
5 | static int currentResult = 1;
6 |
7 | public static void main(String[] args) {
8 |
9 | System.out.println(factorial(10));
10 |
11 |
12 | }
13 |
14 | public static int factorial(int n)
15 | {
16 | fac:
17 | while(currentFactor!=n) {
18 | currentResult *= currentFactor;
19 | continue fac;
20 | }
21 | return currentResult;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-LoopEndpoint.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 | public static void main(String[] args) {
4 | System.out.println(factorial(10));
5 | }
6 | public static int factorial(int n)
7 | {
8 | int ret = 1;
9 | for (int i = 1; i < n+1; ++i) ret *= i;
10 | return ret;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-LoopUnrolling.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 |
4 | public static void main(String[] args) {
5 | System.out.println(factorial10());
6 | }
7 |
8 | public static int factorial10()
9 | {
10 | int ret = 1;
11 | ret *= 2;
12 | ret *= 3;
13 | ret *= 4;
14 | ret *= 5;
15 | ret *= 6;
16 | ret *= 7;
17 | ret *= 8;
18 | ret *= 9;
19 | ret *= 10;
20 | return ret;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-OutputStream.java:
--------------------------------------------------------------------------------
1 | import java.io.PrintWriter;
2 |
3 |
4 | public class main {
5 | public static void main(String[] args) {
6 | PrintWriter outStream;
7 | outStream = new PrintWriter(System.out);
8 | outStream.println(factorial(10));
9 | }
10 | public static int factorial(int n)
11 | {
12 | int ret = 1;
13 | for (int i = 1; i <= n; ++i) ret *= i;
14 | return ret;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T3-VariableBigInt.java:
--------------------------------------------------------------------------------
1 | import java.math.BigInteger;
2 |
3 |
4 | public class main {
5 |
6 | public static void main(String[] args) {
7 | System.out.println(factorial(10));
8 | }
9 |
10 | public static BigInteger factorial(int n)
11 | {
12 | BigInteger newNameForBigI = BigInteger.ONE;
13 | for (int j = 1; j <= n; ++j) {
14 | newNameForBigI = newNameForBigI.multiply(BigInteger.valueOf(j));
15 | }
16 | return newNameForBigI;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T4-AlgorithmChange.java:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2004-2009 Peter Luschny, MIT License applies.
2 | // See http://en.wikipedia.org/wiki/MIT_License
3 | // Visit http://www.luschny.de/math/factorial/FastFactorialFunctions.htm
4 | // Comments mail to: peter(at)luschny.de
5 |
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.concurrent.Callable;
10 | import java.util.concurrent.ExecutorService;
11 | import java.util.concurrent.Executors;
12 | import java.util.concurrent.Future;
13 |
14 |
15 | public class main {
16 | // Same algorithm as Split
17 | // but computing products concurrently.
18 |
19 | public static void main(String[] args) {
20 | main x = new main();
21 | System.out.println(x.factorial(10));
22 | }
23 |
24 |
25 | public Xint factorial(int n) {
26 | if (n < 0) {
27 | throw new ArithmeticException("Factorial: n has to be >= 0, but was " + n);
28 | }
29 |
30 | if (n < 2) {
31 | return Xint.ONE;
32 | }
33 |
34 | // -- log2n = floor(log2(n));
35 | int log2n = 31 - Integer.numberOfLeadingZeros(n);
36 | int proc = Runtime.getRuntime().availableProcessors();
37 |
38 | ExecutorService exe = Executors.newFixedThreadPool(proc);
39 | ArrayList> tasks = new ArrayList>(log2n);
40 |
41 | int high = n, low = n >>> 1, shift = low, taskCounter = 0;
42 |
43 | // -- It is more efficient to add the big intervals
44 | // -- first and the small ones later!
45 | while ((low + 1) < high) {
46 | tasks.add(new Product(low + 1, high));
47 | high = low;
48 | low >>= 1;
49 | shift += low;
50 | taskCounter++;
51 | }
52 |
53 | Xint p = Xint.ONE, r = Xint.ZERO;
54 |
55 | try {
56 | List> products = exe.invokeAll(tasks);
57 |
58 | Future R = exe.submit(new Callable() {
59 |
60 | @Override
61 | public Xint call() {
62 | return Xint.ONE;
63 | }
64 | });
65 |
66 | while (--taskCounter >= 0) {
67 | p = p.multiply(products.get(taskCounter).get());
68 | R = exe.submit(new Multiply(R.get(), p));
69 | }
70 |
71 | r = R.get();
72 | } catch (Throwable e) {
73 | }
74 |
75 | exe.shutdownNow();
76 | return r.shiftLeft(shift);
77 | }
78 |
79 | final static class Multiply implements Callable {
80 |
81 | private final Xint a, b;
82 |
83 | public Multiply(Xint a, Xint b) {
84 | this.a = a;
85 | this.b = b;
86 | }
87 |
88 | @Override
89 | public Xint call() {
90 | return a.multiply(b);
91 | }
92 | }
93 | } // endOfFactorialSplitRecursive
94 |
95 | final class Product implements Callable {
96 |
97 | private final int n, m;
98 |
99 | public Product(int n, int m) {
100 | this.n = n;
101 | this.m = m;
102 | }
103 |
104 | @Override
105 | public Xint call() {
106 | return product(n, m);
107 | }
108 |
109 | public static Xint product(int n, int m) {
110 | n = n | 1; // Round n up to the next odd number
111 | m = (m - 1) | 1; // Round m down to the next odd number
112 |
113 | if (m == n) {
114 | return Xint.valueOf(m);
115 | }
116 | if (m == (n + 2)) {
117 | return Xint.valueOf((long) n * m);
118 | }
119 |
120 | int k = (n + m) >>> 1;
121 | return product(n, k).multiply(product(k + 1, m));
122 | }
123 | }
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T4-Approximation.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobYang1024/OCaMOSS/5a78137bf717d2bb8248489f0619a01ebea9d1df/tests/MiniFactorialTests/T4-Approximation.java
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T4-ProGuardObfuscation.java:
--------------------------------------------------------------------------------
1 | import java.io.PrintStream;
2 |
3 | public class main
4 | {
5 | public static void main(String[] paramArrayOfString)
6 | {
7 | paramArrayOfString = 1;
8 | for (String[] arrayOfString = 1; arrayOfString <= 10; arrayOfString++)
9 | paramArrayOfString *= arrayOfString;
10 | System.out.println(paramArrayOfString);
11 | }
12 | }
13 |
14 | /* Location: C:\Users\Admin\Desktop\totest\Main-JARExport\main-jar.jar
15 | * Qualified Name: main
16 | * JD-Core Version: 0.6.0
17 | */
--------------------------------------------------------------------------------
/tests/MiniFactorialTests/T4-Recursive.java:
--------------------------------------------------------------------------------
1 |
2 | public class main {
3 |
4 | public static void main(String[] args) {
5 | System.out.println(factorial(10));
6 | }
7 |
8 | public static int factorial(int n)
9 | {
10 | if (n == 0) return 1;
11 | return n * factorial(n-1);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tests/SSID_demo/01.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | /**
4 | * Driver class, you may have to change it to fit your implementation
5 | * Make sure you compile and run this class
6 | */
7 | public class CitiesDriver {
8 | static Scanner sc;
9 |
10 | /** Read in the tree
11 | */
12 | public static void readTree () {
13 | /// Read in the tree
14 | // read in one integer
15 | int n = sc.nextInt();
16 | // read in tree, safety line
17 | for (int i=0;i= 0) {
145 | if (!myTree[index].isSafe()) return false;
146 | else {
147 | if (index == target) return true;
148 |
149 | if (directPath(myTree[index].left(),target)) return true;
150 | else return directPath(myTree[index].right(),target);
151 | }
152 | }
153 |
154 | return false;
155 | }
156 |
157 | public boolean search (int index, int target) {
158 |
159 | if (index >= 0) {
160 | if (index == target) return true;
161 |
162 | if (search(myTree[index].left(),target)) return false;
163 | else return search(myTree[index].right(),target);
164 | }
165 |
166 | return false;
167 | }
168 |
169 | public void print (MyNode[] tree, int index) {
170 |
171 | if (index >= 0) {
172 | print(tree,tree[index].left());
173 |
174 | System.out.print(index);
175 | if (!tree[index].isSafe()) System.out.print("*");
176 | System.out.print(" ");
177 |
178 | print(tree,tree[index].right());
179 | }
180 |
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/tests/SSID_demo/03.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | /**
4 | * Driver class
5 | */
6 |
7 | public class CitiesDriver {
8 |
9 | public static Scanner sc;
10 | public static MyTree tree;
11 |
12 | // Read in the tree
13 | public static void readTree () {
14 |
15 | // Read in the tree
16 | // read in one integer
17 | int read1Integer = sc.nextInt();
18 |
19 | tree = new MyTree (read1Integer );
20 |
21 | // read in tree, safety line
22 | for (int i = 0; i < read1Integer ; i++) {
23 | tree.setSafe(i,sc.nextInt());
24 | }
25 |
26 | // loop to read pairs of children
27 | for (int i = 0; i < read1Integer ; i++) {
28 | tree.setNode(i,sc.nextInt(),sc.nextInt());
29 | }
30 |
31 |
32 |
33 | }
34 |
35 | // Read in query statements
36 | public static void readQueries () {
37 |
38 | // read in one integer
39 | int read1Integer = sc.nextInt();
40 |
41 | // loop to read pairs of children for query
42 | for (int i=0;i= 0) {
148 | if (!myTree[index].isSafe()) return false;
149 | else {
150 | if (index == target) return true;
151 |
152 | if (directPath(myTree[index].left(),target)) return true;
153 | else return directPath(myTree[index].right(),target);
154 | }
155 | }
156 |
157 | return false;
158 | }
159 |
160 | public boolean searchTree (int index, int target) {
161 |
162 | if (index >= 0) {
163 | if (index == target) return true;
164 |
165 | if (searchTree(myTree[index].left(),target)){
166 | return false;
167 | }
168 | else{
169 | return searchTree(myTree[index].right(),target);
170 | }
171 | }
172 |
173 | return false;
174 | }
175 |
176 | public void print (MyNode[] tree, int index) {
177 |
178 | if (index >= 0) {
179 | print(tree,tree[index].left());
180 |
181 | System.out.print(index);
182 | if (!tree[index].isSafe()) System.out.print("*");
183 | System.out.print(" ");
184 |
185 | print(tree,tree[index].right());
186 | }
187 |
188 | }
189 |
190 | }
191 |
--------------------------------------------------------------------------------
/tests/SSID_demo/04.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | /**
4 | * Driver class, you may have to change it to fit your implementation
5 | * Make sure you compile and run this class
6 | */
7 | public class CitiesDriver {
8 | static Scanner sc;
9 | static MyTree tree;
10 |
11 | /** Read in the tree
12 | */
13 | public static void readTree () {
14 | // Read in the tree
15 | // Read in size of the tree
16 | int n = sc.nextInt();
17 | tree = new MyTree(n); //Create MyTree with n nodes
18 | // read in tree, safety line
19 | for (int i=0;i q; //Queue for BFS
108 |
109 | /*
110 | Fill up the tree with the nodes and set the size of the tree
111 | Even more boring stuff
112 | */
113 | public MyTree(int n){
114 | for (int i = 0; i < n; i++)
115 | myTree[i] = new MyNode();
116 | size = n;
117 | }
118 | public void updateSafety(int node, int safe){
119 | myTree[node].setIsSafe(safe == 1);
120 | }
121 | public void updateNode(int node, int left, int right){
122 | myTree[node].setLeft(left);
123 | myTree[node].setRight(right);
124 | if (left != -1)
125 | myTree[left].setParent(node);
126 | if (right != -1)
127 | myTree[right].setParent(node);
128 | }
129 | /*
130 | In this problem, we are given a tree. Therefore, given any nodes u and v, there is only one unique path from u to v.
131 | This is because a tree is acyclic and all the nodes are connected. The question asks whether it is possible to find a
132 | "safe" path from nodes u to v.
133 |
134 | The easiest way to solve this problem would be to view the binary tree as a graph instead of a binary tree and run BFS/DFS
135 | on the tree. Personally I prefer coding BFS, hence I coded BFS. I used the binary tree structure as an adjacency list, where
136 | there is an edge from the current node to its left child, an edge from the current node to its right child and an edge from the
137 | current node to its parent.
138 |
139 | After running BFS, I recreate the path using the array pre[] (which stores the predecessor of the node) and check whether the
140 | path is safe. The runtime for BFS is O(N) for every query (where N is the size of binary tree). Suppose there are M queries, then
141 | it will take O(MN) to run all M queries.
142 | */
143 | public boolean isPathSafe(int start, int end){
144 | int[] pre = new int[size]; //Stores who is the pre of the current node in the path
145 | boolean[] visited = new boolean[size]; //To store whether the particular node is visited
146 | q = new LinkedList ();
147 | //Start of BFS
148 | q.offer(new Integer(start));
149 | visited[start] = true;
150 | while (q.size()!=0){
151 | int u = q.poll();
152 | if (u == end)
153 | break;
154 | int left = myTree[u].getLeft();
155 | int right = myTree[u].getRight();
156 | int parent = myTree[u].getParent();
157 | if (left != -1 && visited[left] == false){
158 | visited[left] = true;
159 | q.offer(new Integer(left));
160 | pre[left] = u;
161 | }
162 | if (right != -1 && visited[right] == false){
163 | visited[right] = true;
164 | q.offer(new Integer(right));
165 | pre[right] = u;
166 | }
167 | if (parent != -1 && visited[parent] == false){
168 | visited[parent] = true;
169 | q.offer(new Integer(parent));
170 | pre[parent] = u;
171 | }
172 | }
173 | int curnode = end;
174 | //If the path is safe, then logical and of all the nodes in the path will yield whether the path is safe
175 | boolean isSafe = myTree[start].getIsSafe();
176 | while (curnode != start){
177 | isSafe = myTree[curnode].getIsSafe() && isSafe;
178 | curnode = pre[curnode];
179 | }
180 | return isSafe;
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/tests/SSID_demo/05.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | /**
4 | * Driver class, you may have to change it to fit your implementation
5 | * Make sure you compile and run this class
6 | */
7 | public class CitiesDriver {
8 | static Scanner sc;
9 | static MyTree tree;
10 |
11 |
12 | public static void main(String[] args) {
13 | sc = new Scanner(System.in);
14 |
15 | readTree(); // read in the tree
16 | readQ(); // read in the queries
17 | }
18 |
19 |
20 |
21 | /** Read in query statements
22 | */
23 | public static void readQ () {
24 | // read in one integer
25 | int j = sc.nextInt();
26 | // loop to read pairs of children for query
27 | for (int i=0;i q; //Queue for BFS
115 |
116 | /*
117 | Fill up the tree with the nodes and set the size of the tree
118 | Even more boring stuff
119 | */
120 |
121 | public void updateNode(int node, int left, int right){
122 | myTree[node].setLeft(left);
123 | myTree[node].setRight(right);
124 | if (left != -1)
125 | myTree[left].setParent(node);
126 | if (right != -1)
127 | myTree[right].setParent(node);
128 | }
129 | public MyTree(int n){
130 | for (int i = 0; i < n; i++)
131 | myTree[i] = new MyNode();
132 | size = n;
133 | }
134 | public void updateSafety(int node, int safe){
135 | myTree[node].setIsSafe(safe == 1);
136 | }
137 |
138 | /*
139 | In this problem, we are given a tree. Therefore, given any nodes u and v, there is only one unique path from u to v.
140 | This is because a tree is acyclic and all the nodes are connected. The question asks whether it is possible to find a
141 | "safe" path from nodes u to v.
142 |
143 | The easiest way to solve this problem would be to view the binary tree as a graph instead of a binary tree and run BFS/DFS
144 | on the tree. Personally I prefer coding BFS, hence I coded BFS. I used the binary tree structure as an adjacency list, where
145 | there is an edge from the current node to its left child, an edge from the current node to its right child and an edge from the
146 | current node to its parent.
147 |
148 | After running BFS, I recreate the path using the array pre[] (which stores the predecessor of the node) and check whether the
149 | path is safe. The runtime for BFS is O(N) for every query (where N is the size of binary tree). Suppose there are M queries, then
150 | it will take O(MN) to run all M queries.
151 | */
152 | public boolean isPathOk(int start, int end){
153 | int[] pre = new int[size]; //Stores who is the pre of the current node in the path
154 | boolean[] visited = new boolean[size]; //To store whether the particular node is visited
155 | q = new LinkedList ();
156 | //Start of BFS
157 | q.offer(new Integer(start));
158 | visited[start] = true;
159 | while (q.size()!=0){
160 | int u = q.poll();
161 | if (u == end)
162 | break;
163 |
164 | int right = myTree[u].getRight();
165 | int left = myTree[u].getLeft();
166 | int parent = myTree[u].getParent();
167 |
168 | if (right != -1 && visited[right] == false){
169 | visited[right] = true;
170 | q.offer(new Integer(right));
171 | pre[right] = u;
172 | }
173 | if (left != -1 && visited[left] == false){
174 | visited[left] = true;
175 | q.offer(new Integer(left));
176 | pre[left] = u;
177 | }
178 | if (parent != -1 && visited[parent] == false){
179 | visited[parent] = true;
180 | q.offer(new Integer(parent));
181 | pre[parent] = u;
182 | }
183 | }
184 | int curnode = end;
185 | //If the path is safe, then logical and of all the nodes in the path will yield whether the path is safe
186 | boolean isSafe = myTree[start].getIsSafe();
187 | while (curnode != start){
188 | isSafe = myTree[curnode].getIsSafe() && isSafe;
189 | curnode = pre[curnode];
190 | }
191 | return isSafe;
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/tests/SSID_demo/06.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 |
4 | public class CitiesDriver {
5 | static Scanner scanner;
6 | static MyTree tree;
7 |
8 |
9 |
10 | public static void readTree () {
11 |
12 | int n = scanner.nextInt();
13 | tree = new MyTree(n);
14 |
15 |
16 | int i = 0;
17 | while(i q;
101 |
102 |
103 | public MyTree(int n){
104 | for (int i = 0; i < n; i++)
105 | myTree[i] = new MyNode();
106 | size = n;
107 | }
108 | public void updateSafety(int node, int safe){
109 | myTree[node].setIsCitySafe(safe == 1);
110 | }
111 | public void updateNode(int node, int left, int right){
112 | myTree[node].setLeft(left);
113 | myTree[node].setRight(right);
114 | if (left != -1)
115 | myTree[left].setParent(node);
116 | if (right != -1)
117 | myTree[right].setParent(node);
118 | }
119 |
120 | public boolean isPathSafe(int start, int end){
121 | int[] pre = new int[size];
122 | boolean[] visited = new boolean[size];
123 | q = new LinkedList ();
124 |
125 | q.offer(new Integer(start));
126 | visited[start] = true;
127 | while (q.size()!=0){
128 | int u = q.poll();
129 | if (u == end)
130 | break;
131 | int left = myTree[u].getLeft();
132 | int right = myTree[u].getRight();
133 | int parent = myTree[u].getParent();
134 | if (left != -1 && visited[left] == false){
135 | visited[left] = true;
136 | q.offer(new Integer(left));
137 | pre[left] = u;
138 | }
139 | if (right != -1 && visited[right] == false){
140 | visited[right] = true;
141 | q.offer(new Integer(right));
142 | pre[right] = u;
143 | }
144 | if (parent != -1 && visited[parent] == false){
145 | visited[parent] = true;
146 | q.offer(new Integer(parent));
147 | pre[parent] = u;
148 | }
149 | }
150 | int curnode = end;
151 |
152 | boolean isCitySafe = myTree[start].isIsCitySafe();
153 | while (curnode != start){
154 | isCitySafe = myTree[curnode].isIsCitySafe() && isCitySafe;
155 | curnode = pre[curnode];
156 | }
157 | return isCitySafe;
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/tests/SSID_demo/07.java:
--------------------------------------------------------------------------------
1 | /** Class for a tree node
2 | */
3 | class MyNode {
4 | // You may use this class if you'd like. It may help you if you use
5 | // an array based implementation of a binary tree
6 |
7 | // you can add other variables if you'd like
8 | boolean isSafe; // is the city safe?
9 | int leftChildIndex; // left child index in array
10 | int rightChildIndex; // right child index in array
11 |
12 | // fill in your accessor and mutator methods here
13 | // ...
14 |
15 | public MyNode( int i ) {
16 | if( i == 0 ) {
17 | isSafe = false;
18 | } else
19 | isSafe = true;
20 | }
21 |
22 | //accessors
23 | public int getLeft(){
24 | return leftChildIndex;
25 | }
26 |
27 | public int getRight(){
28 | return rightChildIndex;
29 | }
30 |
31 | //mutators
32 | public void setLeft(int left){
33 | this.leftChildIndex = left;
34 | }
35 |
36 | public void setRight (int right){
37 | this.rightChildIndex = right;
38 | }
39 |
40 | public boolean isSafe(){
41 | return isSafe;
42 | }
43 | }
44 |
45 | /** Class for a binary tree ADT
46 | */
47 | public class MyTree {
48 | // You may want to use an array based implementation for
49 | // your tree, or change this to another implementation
50 |
51 | // Note that this code and the driver code do not necessarily
52 | // match well -- you decide how you want these two parts to work
53 | // together.
54 |
55 | private final int MAX_NODES = 1000;
56 | MyNode[] myTree = new MyNode[MAX_NODES];
57 | int size = 0; // make sure to update this variable as needed
58 |
59 | // fill in your ADT methods here
60 | // ...
61 |
62 | //insert the cities
63 | public void insert (int n, int leftIndex, int rightIndex){
64 | myTree[size] = new MyNode(n);
65 | myTree[size].setLeft(leftIndex);
66 | myTree[size].setRight(rightIndex);
67 | size++;
68 | }
69 |
70 | //use recursive methods to find result
71 | public boolean queries(int depature, int arrive){
72 | if (depature != arrive){
73 | return queries(getParent(depature), 0)&& queries(getParent(arrive), 0)&& myTree[depature].isSafe && myTree[arrive].isSafe;
74 | } else return myTree[depature].isSafe;
75 | }
76 |
77 | /*public boolean allSafe(int depature, int root){
78 | if (departure == root){
79 | return myTree[0].isSafe;
80 | } else
81 | return myTree[departure].isSafe && allSafe(getParent(depature), myTree[0]);
82 | }*/
83 |
84 | //method to find the parents of the city
85 | public int getParent(int city){
86 | for (int i = city; i >=0; i --){
87 | if(myTree[i].getRight() == city || myTree[i].getLeft() == city){
88 | return i;
89 | }
90 | }
91 | //return 0 if no parent, meaning this city is the root
92 | return 0;
93 | }
94 | }
95 |
96 | import java.util.*;
97 |
98 | /**
99 | * Driver class, you may have to change it to fit your implementation
100 | * Make sure you compile and run this class
101 | */
102 | public class CitiesDriver {
103 | static Scanner sc;
104 | //create all the array lists for storing all the input read
105 | static int [] cities;
106 | static int [] leftChild;
107 | static int [] rightChild;
108 | static int [] departCities;
109 | static int [] arriveCities;
110 | //initialize a Mytree instance
111 | static MyTree tree = new MyTree();
112 |
113 | /** Read in the tree
114 | */
115 | public static void readTree () {
116 | /// Read in the tree
117 | // read in one integer
118 | int n = sc.nextInt();
119 | // read in tree, safety line
120 |
121 | cities = new int [n];
122 | //read in the cities
123 | for (int i=0;i rep_ok
18 |
19 | let size s =
20 | List.length (rep_ok s)
21 |
22 | let insert x s =
23 | List.sort_uniq compare (x :: rep_ok s) |> rep_ok
24 |
25 | let member x s =
26 | List.mem x (rep_ok s)
27 |
28 | let remove x s =
29 | List.filter (fun y -> x <> y) (rep_ok s) |> rep_ok
30 |
31 | let choose s =
32 | match (rep_ok s) with
33 | | [] -> None
34 | | x :: xs -> Some x
35 |
36 |
37 | let to_list s =
38 | rep_ok s
39 |
--------------------------------------------------------------------------------
/tests/test1/intset1.ml:
--------------------------------------------------------------------------------
1 | (* Abstraction Function: [[x_1, ..., x_n]] represents the set
2 | * ${x_1, ..., x_n}$.
3 | * Representation Invariant: [[x_1, ..., x_n]] must form a strictly increasing
4 | * sequence. That is, the list should be sorted with no duplicates.
5 | *)
6 | type t =
7 | int list
8 |
9 | let rep_ok s =
10 | if s = List.sort_uniq compare s then
11 | s
12 | else
13 | failwith "RI"
14 |
15 |
16 | let empty =
17 | [] |> rep_ok
18 |
19 | let size s =
20 | List.length (rep_ok s)
21 |
22 | let insert x s =
23 | List.sort_uniq compare (x :: rep_ok s) |> rep_ok
24 |
25 | let member x s =
26 | List.mem x (rep_ok s)
27 |
28 | let remove x s =
29 | List.filter (fun y -> x <> y) (rep_ok s) |> rep_ok
30 |
31 | let choose s =
32 | match (rep_ok s) with
33 | | [] -> None
34 | | x :: xs -> Some x
35 |
36 |
37 | let to_list s =
38 | rep_ok s
39 |
--------------------------------------------------------------------------------
/tests/test10/add.ml:
--------------------------------------------------------------------------------
1 | let add x y =
2 | x+y
3 |
--------------------------------------------------------------------------------
/tests/test10/add_test.ml:
--------------------------------------------------------------------------------
1 | open OUnit
2 | open Add
3 |
4 | let tests = "test suite for add" >::: [
5 | "onetwo" >:: (fun _ -> assert_equal 3 (add 1 2));
6 | "sevone" >:: (fun _ -> assert_equal 8 (add 7 1));
7 | ]
8 |
9 | let _ = run_test_tt_main tests
10 |
--------------------------------------------------------------------------------
/tests/test10/btrees.ml:
--------------------------------------------------------------------------------
1 | type 'a tree = Leaf | Node of 'a tree * 'a * 'a tree
2 |
3 | let rec preorder a = function
4 | | Leaf -> (match a with
5 | | [] -> []
6 | | h::t -> preorder t h)
7 | | Node (l, v, r) -> v:: preorder (r::a) l
8 |
9 | let rec inorder a = function
10 | | Leaf -> []
11 | | Node (Leaf, v, _) -> (match a with
12 | | [] -> []
13 | | h::t -> v::inorder t h)
14 | | Node (l,v,r) -> inorder
15 |
--------------------------------------------------------------------------------
/tests/test10/discussiongame.ml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobYang1024/OCaMOSS/5a78137bf717d2bb8248489f0619a01ebea9d1df/tests/test10/discussiongame.ml
--------------------------------------------------------------------------------
/tests/test10/hello.ml:
--------------------------------------------------------------------------------
1 | print_endline "Does this change something"
2 |
--------------------------------------------------------------------------------
/tests/test10/lab03_test.ml:
--------------------------------------------------------------------------------
1 | open OUnit
2 | open Lab03
3 |
4 | let tests = "testing lab03" >::: [
5 | "prod1" >:: (fun _ -> assert_equal 1 (mult []));
6 | "prod2" >:: (fun _ -> assert_equal 24 (mult [1;2;3;4]));
7 | "prod3" >:: (fun _ -> assert_equal 60 (mult [3;4;5]));
8 |
9 | "bigred" >:: (fun _ -> assert_equal true (bigred ["bigred"; "i"]));
10 | "bigred1" >:: (fun _ -> assert_equal false (bigred []));
11 | "bigred2" >:: (fun _ -> assert_equal false (bigred ["hello"]));
12 |
13 | "twoorfour3" >:: (fun _ -> assert_equal true (twoOrFour [1;2;3;4]));
14 | "twoorfour" >:: (fun _ -> assert_equal true (twoOrFour ["bigred"; "i"]));
15 | "twoorfour1" >:: (fun _ -> assert_equal false (twoOrFour []));
16 | "twoorfour2" >:: (fun _ -> assert_equal false (twoOrFour ["hello"]));
17 | "twoorfour4" >:: (fun _ -> assert_equal false (twoOrFour [1;2;3;4;5;5]));
18 |
19 | "1" >:: (fun _ -> assert_equal true (twoEl [1;1;3]));
20 | "2" >:: (fun _ -> assert_equal false (twoEl [1;2;3]));
21 | "3" >:: (fun _ -> assert_equal false (twoEl [1;3]));
22 | "4" >:: (fun _ -> assert_equal false (twoEl [1]));
23 | "5" >:: (fun _ -> assert_equal true (twoEl [1;1]));
24 |
25 |
26 |
27 |
28 |
29 |
30 | ]
31 |
32 | let _ = run_test_tt_main tests
33 |
--------------------------------------------------------------------------------
/tests/test11/Camel.txt:
--------------------------------------------------------------------------------
1 | A camel is an even-toed ungulate in the genus Camelus that bears distinctive fatty deposits known as "humps" on its back. Camels have long been domesticated and, as livestock, they provide food (milk and meat) and textiles (fiber and felt from hair). As working animals, camels—who are uniquely suited to their desert habitats—are a vital means of transport for passengers and cargo. There are three surviving species of camel. The one-humped dromedary makes up 94% of the world's camel population, and the two-humped Bactrian camel makes up the remainder. The Wild Bactrian camel is a separate species and is now critically endangered.
2 | The word camel is derived via Latin: camelus and Greek: κάμηλος (kamēlos) from Hebrew or Phoenician: gāmāl.[4][5] Used informally, "camel" (or, more correctly, "camelid") refers to any of the seven members of the family Camelidae: the dromedary, the Bactrian, and the wild Bactrian (the true camels) plus the llama, the alpaca, the guanaco, and the vicuña[6] (the "New World" camelids).
3 |
--------------------------------------------------------------------------------
/tests/test11/CamelMaybeCopy.txt:
--------------------------------------------------------------------------------
1 | A camel is an even-toed ungulate in the genus Camelus that walks in deserts. Camels are domesticated and provide food and textiles from their hair. Camels are important forms of transportation through deserts. There are three species of camel. The one-humped dromedary, two-humped Bactrian camel, and the Wild Bactrian camel which is critically endangered.
2 | Camel comes from the Latin word: camelus and Greek: κάμηλος (kamēlos) from Hebrew or Phoenician: gāmāl. “Camelid” informally refers to any of the seven members of the family Camelidae: the dromedary, the Bactrian, the wild Bactrian, the llama, the alpaca, the guanaco, and the vicuña[6] (the "New World" camelids)
3 | Camels are pretty cool. They can do it all and are awesome. They also love functional programming. A lot! Their next mission is to take over the world using the enigma machine.
4 |
--------------------------------------------------------------------------------
/tests/test11/Camelcopy.txt:
--------------------------------------------------------------------------------
1 | Camels are even-toed ungulate in the genus Camelus that bear distinctive fatty deposits known as "humps" on their backs. Camels provide food (milk and meat) and textiles. Camels are super awesome!!!!! Woohooo!.
2 |
3 |
4 | The word camel is derived via Latin: camelus and Greek: κάμηλος (kamēlos) from Hebrew or Phoenician: gāmāl. Camels are LITERALLY SO COOL!!!! Used informally, "camel" (or, more correctly, "camelid") refers to any of the seven members of the family Camelidae: the dromedary, the Bactrian, and the wild Bactrian plus the llama, the alpaca, the guanaco, and the vicuña[6] (the "New World" camelids).
5 |
6 |
7 |
8 |
9 |
10 | As working animals, camels—who are uniquely suited to their desert habitats—are a vital means of transport for passengers and cargo. CAMELS ARE AMAAAAAAAAAAAAAAAAAAAAAAAAAAZINGGGGGGGGGGGGGGG!!!!!!!!!!!!!!!!!! There are three surviving species of camel. The one-humped dromedary makes up 94% of the world's camel population, and the two-humped Bactrian camel makes up the remainder. The Wild Bactrian camel is a separate species and is now critically endangered.
--------------------------------------------------------------------------------
/tests/test11/Camelcopy2.txt:
--------------------------------------------------------------------------------
1 | The word camel is derived via Latin: camelus and Greek: κάμηλος (kamēlos) from Hebrew or Phoenician: gāmāl.[4][5] A camel is an even-toed ungulate in the genus Camelus that bears distinctive fatty deposits known as "humps" on its back. Used informally, "camel" (or, more correctly, "camelid") refers to any of the seven members of the family Camelidae: the dromedary, the Bactrian, and the wild Bactrian (the true camels) plus the llama, the alpaca, the guanaco, and the vicuña[6] (the "New World" camelids).
2 | Camels have long been domesticated and, as livestock, they provide food (milk and meat) and textiles (fiber and felt from hair). As working animals, camels—who are uniquely suited to their desert habitats—are a vital means of transport for passengers and cargo. There are three surviving species of camel. The one-humped dromedary makes up 94% of the world's camel population, and the two-humped Bactrian camel makes up the remainder. The Wild Bactrian camel is a separate species and is now critically endangered.
3 |
--------------------------------------------------------------------------------
/tests/test11/Camelcopy3.txt:
--------------------------------------------------------------------------------
1 | A camel is an even-toed ungulate in the genus Camelus that bears distinctive fatty deposits known as "humps" on its back. Camels have long been domesticated and, as livestock, they provide food (milk and meat) and textiles (fiber and felt from hair). As working animals, camels—who are uniquely suited to their desert habitats—are a vital means of transport for passengers and cargo. There are three surviving species of camel. The one-humped dromedary makes up 94% of the world's camel population, and the two-humped Bactrian camel makes up the remainder. The Wild Bactrian camel is a separate species and is now critically endangered.
2 | The word camel is derived via Latin: camelus and Greek: κάμηλος (kamēlos) from Hebrew or Phoenician: gāmāl.[4][5] Used informally, "camel" (or, more correctly, "camelid") refers to any of the seven members of the family Camelidae: the dromedary, the Bactrian, and the wild Bactrian (the true camels) plus the llama, the alpaca, the guanaco, and the vicuña[6] (the "New World" camelids).
3 |
--------------------------------------------------------------------------------
/tests/test11/Camels.txt:
--------------------------------------------------------------------------------
1 | Camel camel camel camel camel.
--------------------------------------------------------------------------------
/tests/test12/DumbAI.java:
--------------------------------------------------------------------------------
1 | package controller;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import model.Board;
7 | import model.Game;
8 | import model.Location;
9 | import model.NotImplementedException;
10 | import model.Player;
11 |
12 | /**
13 | * A DumbAI is a Controller that always chooses the blank space with the
14 | * smallest column number from the row with the smallest row number.
15 | */
16 | public class DumbAI extends Controller {
17 |
18 | public DumbAI(Player me) {
19 | super(me);
20 | // TODO Auto-generated constructor stub
21 | //throw new NotImplementedException();
22 | }
23 |
24 | protected @Override Location nextMove(Game g) {
25 | // Note: Calling delay here will make the CLUI work a little more
26 | // nicely when competing different AIs against each other.
27 |
28 | // TODO Auto-generated method stub
29 | //throw new NotImplementedException();
30 |
31 | Board b = g.getBoard();
32 | // find available moves
33 | for (int row = 0;row
2 | #include
3 | #include "heaplib.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | /* Useful shorthand: casts a pointer to a (char *) before adding */
11 | #define ADD_BYTES(base_addr, num_bytes) (((char *)(base_addr)) + (num_bytes))
12 |
13 | typedef struct _block_info_t {
14 | unsigned int block_size;
15 | //unsigned int alloc_status;
16 | }block_info_t;
17 |
18 | void coalesceNext(block_info_t* block) {
19 | block_info_t * next_ptr = ((block_info_t *)ADD_BYTES(block, block->block_size));
20 | if((next_ptr->block_size%2)==0) {
21 | block->block_size += next_ptr->block_size;
22 | }
23 | }
24 |
25 | /* See the .h for the advertised behavior of this library function.
26 | * These comments describe the implementation, not the interface.
27 | *
28 | * YOUR COMMENTS GO HERE.
29 | */
30 | void hl_init(void *heap, unsigned int heap_size) {
31 |
32 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
33 |
34 | int * heap_size_val = (int *)(ADD_BYTES(heap, start_offset));
35 | *heap_size_val = (heap_size - start_offset - 8);
36 |
37 | block_info_t * start_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
38 | start_ptr->block_size = heap_size - start_offset - 8;
39 | return;
40 | }
41 |
42 | /* See the .h for the advertised behavior of this library function.
43 | * These comments describe the implementation, not the interface.
44 | *
45 | * YOUR COMMENTS GO HERE.
46 | */
47 | void *hl_alloc(void *heap, unsigned int block_size) {
48 |
49 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
50 | int heap_size = *((int *)(ADD_BYTES(heap, start_offset)));
51 |
52 | int bestSize = INT_MAX;
53 | block_info_t * bestBlock = NULL;
54 |
55 | block_info_t * current_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
56 |
57 | if(block_size==0){
58 | return (void *)(current_ptr);
59 | }
60 |
61 | int totalSize = 0;
62 |
63 | while(totalSize<(heap_size)) {
64 | totalSize+=((current_ptr->block_size/2)*2);
65 |
66 |
67 | if((current_ptr->block_size >= (block_size + (8 - ((4+block_size)%8)) + 4))&&((current_ptr->block_size % 2) == 0)) {
68 | if(current_ptr->block_size < bestSize) {
69 | bestBlock = current_ptr;
70 | bestSize = current_ptr->block_size;
71 | }
72 | }
73 | if(totalSizeblock_size/2)*2)));
75 | }
76 | }
77 |
78 | if(!bestBlock) {
79 | return 0;
80 | }
81 |
82 | bestBlock->block_size+=1;
83 |
84 | if(bestBlock->block_size >= (4 + block_size + (8 - ((4 + block_size)%8)) + 8)) {
85 |
86 | block_info_t * splitBlock = (block_info_t *)(ADD_BYTES(bestBlock, 4 + block_size + (8 - (((4 +block_size)%8)))));
87 | splitBlock->block_size = ((bestSize/2)*2) - (block_size + (8 - (4+block_size)%8) + 4);
88 |
89 | bestBlock->block_size = block_size + (8 - (4+block_size)%8) + 5;
90 |
91 | if(current_ptr!=bestBlock) {
92 | coalesceNext(splitBlock);
93 | }
94 |
95 | }
96 |
97 | return ((void *)ADD_BYTES(bestBlock, 4));
98 | }
99 |
100 | /* See the .h for the advertised behavior of this library function.
101 | * These comments describe the implementation, not the interface.
102 | *
103 | * YOUR COMMENTS GO HERE.
104 | */
105 | void hl_release(void *heap, void *block) {
106 |
107 | if(block){
108 | block_info_t * block_ptr = (block_info_t *)(ADD_BYTES(block, -4));
109 | block_ptr->block_size = ((block_ptr->block_size/2)*2);
110 |
111 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
112 | int heap_size = *((int *)(ADD_BYTES(heap, start_offset)));
113 |
114 | int totalSize = 0;
115 | block_info_t * prev_ptr = NULL;
116 | block_info_t * current_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
117 | block_info_t * next_ptr = NULL;
118 |
119 | while(totalSize<(heap_size)) {
120 | totalSize+=((current_ptr->block_size/2)*2);
121 | if(((block_info_t *)(ADD_BYTES(current_ptr, 4)))==block) {
122 | break;
123 | }
124 | if (totalSize<(heap_size)) {
125 | prev_ptr = current_ptr;
126 | current_ptr = ((block_info_t *)(ADD_BYTES(current_ptr, ((current_ptr->block_size/2)*2))));
127 | }
128 | }
129 |
130 | if(totalSizeblock_size/2)*2))));
132 | }
133 |
134 | if(next_ptr) {
135 | coalesceNext(current_ptr);
136 | }
137 |
138 | if(prev_ptr) {
139 |
140 | if((prev_ptr->block_size%2) == 0) {
141 | coalesceNext(prev_ptr);
142 | }
143 |
144 | }
145 |
146 | }
147 |
148 | return;
149 |
150 | }
151 |
152 | /* See the .h for the advertised behavior of this library function.
153 | * These comments describe the implementation, not the interface.
154 | *
155 | * YOUR COMMENTS GO HERE.
156 | */
157 | void *hl_resize(void *heap, void *block, unsigned int new_size) {
158 |
159 | if(!block) {
160 | return hl_alloc(heap, new_size);
161 | }
162 | block_info_t * block_ptr = (block_info_t *)(ADD_BYTES(block, -4));
163 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
164 | int heap_size = *((int *)(ADD_BYTES(heap, start_offset)));
165 |
166 | int bestSize = INT_MAX;
167 | block_info_t * bestBlock = NULL;
168 |
169 | block_info_t * current_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
170 | //block_info_t * prev_ptr = NULL;
171 |
172 | //block_info_t * prev_block_ptr = NULL;
173 |
174 | int totalSize = 0;
175 |
176 | while(totalSize<(heap_size)) {
177 | totalSize+=((current_ptr->block_size/2)*2);
178 |
179 | if((current_ptr->block_size >= (new_size + (8 - ((4+new_size)%8)) + 4))&&(((current_ptr->block_size%2) == 0)
180 | ||(current_ptr == block_ptr))) {
181 | if(current_ptr->block_size < bestSize) {
182 | bestBlock = current_ptr;
183 | bestSize = current_ptr->block_size;
184 | }
185 | }
186 |
187 | if(current_ptr == block_ptr) {
188 | //prev_block_ptr = prev_ptr;
189 | }
190 |
191 | if(totalSizeblock_size/2)*2)));
194 | }
195 | }
196 | //printf("After the while loop\n");
197 | if(!bestBlock) {
198 | return 0;
199 | }
200 |
201 |
202 | block_ptr->block_size = (block_ptr->block_size/2)*2;
203 |
204 | int content_copy_size = (((block_ptr->block_size-4) > new_size)?new_size:(block_ptr->block_size-4));
205 | memmove(((void *)(ADD_BYTES(bestBlock, 4))), block, content_copy_size);
206 |
207 | //printf("After memmove\n");
208 |
209 | bestBlock->block_size = ((bestBlock->block_size/2)*2)+1;
210 |
211 | if(bestBlock->block_size >= (4 + new_size + (8 - ((4+new_size)%8)) + 8)) {
212 |
213 | block_info_t * splitBlock = (block_info_t *)(ADD_BYTES(bestBlock, 4 + new_size + (8 - (((4 +new_size)%8)))));
214 | splitBlock->block_size = ((bestSize/2)*2) - (new_size + (8 - (4+new_size)%8) + 4);
215 | //printf("%d\n", bestSize);
216 | //printf("%d\n", splitBlock->block_size);
217 |
218 | bestBlock->block_size = new_size + (8 - (4+new_size)%8) + 5;
219 | //printf("%d\n", bestBlock->block_size);
220 |
221 | if(current_ptr!=bestBlock) {
222 | coalesceNext(splitBlock);
223 | }
224 | }
225 | /*
226 | if(bestBlock!= block_ptr) {
227 | if(block_ptr!=current_ptr) {
228 | coalesceNext(block_ptr);
229 | }
230 |
231 | if(prev_block_ptr) {
232 | if(prev_block_ptr->block_size%2==0) {
233 | coalesceNext(prev_block_ptr);
234 | }
235 | }
236 | }
237 | */
238 |
239 | return ((void *)ADD_BYTES(bestBlock, 4));
240 | }
241 |
--------------------------------------------------------------------------------
/tests/test13/heaplib2.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "heaplib.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #define ADD_BYTES(base_addr, num_bytes) (((char *)(base_addr)) + (num_bytes))
11 |
12 | typedef struct _block_info_t {
13 | unsigned int block_size;
14 | }block_info_t;
15 |
16 | void coalesceNext(block_info_t* block) {
17 | block_info_t * next_ptr = ((block_info_t *)ADD_BYTES(block, block->block_size));
18 | if((next_ptr->block_size%2)==0) {
19 | block->block_size += next_ptr->block_size;
20 | }
21 | }
22 |
23 | void hl_init(void *heap, unsigned int heap_size) {
24 |
25 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
26 |
27 | int * heap_size_val = (int *)(ADD_BYTES(heap, start_offset));
28 | *heap_size_val = (heap_size - start_offset - 8);
29 |
30 | block_info_t * start_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
31 | start_ptr->block_size = heap_size - start_offset - 8;
32 | return;
33 | }
34 |
35 | void *hl_alloc(void *heap, unsigned int block_size) {
36 |
37 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
38 | int heap_size = *((int *)(ADD_BYTES(heap, start_offset)));
39 |
40 | int bestSize = INT_MAX;
41 | block_info_t * bestBlock = NULL;
42 |
43 | block_info_t * current_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
44 |
45 | if(block_size==0){
46 | return (void *)(current_ptr);
47 | }
48 |
49 | int totalSize = 0;
50 |
51 | while(totalSize<(heap_size)) {
52 | totalSize+=((current_ptr->block_size/2)*2);
53 |
54 |
55 | if((current_ptr->block_size >= (block_size + (8 - ((4+block_size)%8)) + 4))&&((current_ptr->block_size % 2) == 0)) {
56 | if(current_ptr->block_size < bestSize) {
57 | bestBlock = current_ptr;
58 | bestSize = current_ptr->block_size;
59 | }
60 | }
61 | if(totalSizeblock_size/2)*2)));
63 | }
64 | }
65 |
66 | if(!bestBlock) {
67 | return 0;
68 | }
69 |
70 | bestBlock->block_size+=1;
71 |
72 | if(bestBlock->block_size >= (4 + block_size + (8 - ((4 + block_size)%8)) + 8)) {
73 |
74 | block_info_t * splitBlock = (block_info_t *)(ADD_BYTES(bestBlock, 4 + block_size + (8 - (((4 +block_size)%8)))));
75 | splitBlock->block_size = ((bestSize/2)*2) - (block_size + (8 - (4+block_size)%8) + 4);
76 |
77 | bestBlock->block_size = block_size + (8 - (4+block_size)%8) + 5;
78 |
79 | if(current_ptr!=bestBlock) {
80 | coalesceNext(splitBlock);
81 | }
82 |
83 | }
84 |
85 | return ((void *)ADD_BYTES(bestBlock, 4));
86 | }
87 |
88 | void hl_release(void *heap, void *block) {
89 |
90 | if(block){
91 | block_info_t * block_ptr = (block_info_t *)(ADD_BYTES(block, -4));
92 | block_ptr->block_size = ((block_ptr->block_size/2)*2);
93 |
94 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
95 | int heap_size = *((int *)(ADD_BYTES(heap, start_offset)));
96 |
97 | int totalSize = 0;
98 | block_info_t * prev_ptr = NULL;
99 | block_info_t * current_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
100 | block_info_t * next_ptr = NULL;
101 |
102 | while(totalSize<(heap_size)) {
103 | totalSize+=((current_ptr->block_size/2)*2);
104 | if(((block_info_t *)(ADD_BYTES(current_ptr, 4)))==block) {
105 | break;
106 | }
107 | if (totalSize<(heap_size)) {
108 | prev_ptr = current_ptr;
109 | current_ptr = ((block_info_t *)(ADD_BYTES(current_ptr, ((current_ptr->block_size/2)*2))));
110 | }
111 | }
112 |
113 | if(totalSizeblock_size/2)*2))));
115 | }
116 |
117 | if(next_ptr) {
118 | coalesceNext(current_ptr);
119 | }
120 |
121 | if(prev_ptr) {
122 |
123 | if((prev_ptr->block_size%2) == 0) {
124 | coalesceNext(prev_ptr);
125 | }
126 | }
127 | }
128 | return;
129 |
130 | }
131 |
132 | void *hl_resize(void *heap, void *block, unsigned int new_size) {
133 |
134 | if(!block) {
135 | return hl_alloc(heap, new_size);
136 | }
137 | block_info_t * block_ptr = (block_info_t *)(ADD_BYTES(block, -4));
138 | int start_offset = ((uintptr_t)(heap) % 8==0)?0:(8 - ((uintptr_t)(heap) % 8));
139 | int heap_size = *((int *)(ADD_BYTES(heap, start_offset)));
140 |
141 | int bestSize = INT_MAX;
142 | block_info_t * bestBlock = NULL;
143 |
144 | block_info_t * current_ptr = (block_info_t *)(ADD_BYTES(heap, start_offset+4));
145 |
146 | int totalSize = 0;
147 |
148 | while(totalSize<(heap_size)) {
149 | totalSize+=((current_ptr->block_size/2)*2);
150 |
151 | if((current_ptr->block_size >= (new_size + (8 - ((4+new_size)%8)) + 4))&&(((current_ptr->block_size%2) == 0)
152 | ||(current_ptr == block_ptr))) {
153 | if(current_ptr->block_size < bestSize) {
154 | bestBlock = current_ptr;
155 | bestSize = current_ptr->block_size;
156 | }
157 | }
158 |
159 | if(current_ptr == block_ptr) {
160 | }
161 |
162 | if(totalSizeblock_size/2)*2)));
164 | }
165 | }
166 | if(!bestBlock) {
167 | return 0;
168 | }
169 |
170 |
171 | block_ptr->block_size = (block_ptr->block_size/2)*2;
172 |
173 | int content_copy_size = (((block_ptr->block_size-4) > new_size)?new_size:(block_ptr->block_size-4));
174 | memmove(((void *)(ADD_BYTES(bestBlock, 4))), block, content_copy_size);
175 |
176 | bestBlock->block_size = ((bestBlock->block_size/2)*2)+1;
177 |
178 | if(bestBlock->block_size >= (4 + new_size + (8 - ((4+new_size)%8)) + 8)) {
179 |
180 | block_info_t * splitBlock = (block_info_t *)(ADD_BYTES(bestBlock, 4 + new_size + (8 - (((4 +new_size)%8)))));
181 | splitBlock->block_size = ((bestSize/2)*2) - (new_size + (8 - (4+new_size)%8) + 4);
182 |
183 | bestBlock->block_size = new_size + (8 - (4+new_size)%8) + 5;
184 |
185 | if(current_ptr!=bestBlock) {
186 | coalesceNext(splitBlock);
187 | }
188 | }
189 |
190 | return ((void *)ADD_BYTES(bestBlock, 4));
191 | }
192 |
--------------------------------------------------------------------------------
/tests/test15/all_subarray.cpp:
--------------------------------------------------------------------------------
1 | // https://www.geeksforgeeks.org/print-all-subarrays-with-sum-in-a-given-range/
2 | #include
3 | using namespace std;
4 |
5 | // Function to find subarrrays in given range
6 | void subArraySum(int arr[], int n,
7 | int leftsum, int rightsum)
8 | {
9 | int curr_sum, i, j, res = 0;
10 |
11 | // Pick a starting point
12 | for (i = 0; i < n; i++) {
13 | curr_sum = arr[i];
14 |
15 | // Try all subarrays starting with 'i'
16 | for (j = i + 1; j <= n; j++) {
17 | if (curr_sum > leftsum
18 | && curr_sum < rightsum) {
19 | cout << "{ ";
20 |
21 | for (int k = i; k < j; k++)
22 | cout << arr[k] << " ";
23 |
24 | cout << "}\n";
25 | }
26 | if (curr_sum > rightsum || j == n)
27 | break;
28 | curr_sum = curr_sum + arr[j];
29 | }
30 | }
31 | }
32 |
33 | // Driver Code
34 | int main()
35 | {
36 | int arr[] = { 15, 2, 4, 8, 9, 5, 10, 23 };
37 | int N = sizeof(arr) / sizeof(arr[0]);
38 |
39 | int L = 10, R = 23;
40 |
41 | subArraySum(arr, N, L, R);
42 |
43 | return 0;
44 | }
--------------------------------------------------------------------------------
/tests/test15/all_subarray_2.cpp:
--------------------------------------------------------------------------------
1 | // https://www.geeksforgeeks.org/print-all-subarrays-with-sum-in-a-given-range/
2 | #include
3 | using namespace std;
4 |
5 | // Function to find subarrrays in given range
6 | void subArraySum(int arr[], int n,
7 | int left_sum, int right_sum)
8 | {
9 | int current_sum, i, j, res = 0;
10 |
11 | // Pick a starting point
12 | for (i = 0; i < n; i++) {
13 | current_sum = arr[i];
14 |
15 | // Try all subarrays starting with 'i'
16 | for (j = i + 1; j <= n; j++) {
17 | if (current_sum > left_sum
18 | && current_sum < right_sum) {
19 | cout << "{ ";
20 |
21 | for (int k = i; k < j; k++)
22 | cout << arr[k] << " ";
23 |
24 | cout << "}\n";
25 | }
26 | if (current_sum > right_sum || j == n)
27 | break;
28 | current_sum = current_sum + arr[j];
29 | }
30 | }
31 | }
32 |
33 | // Driver Code
34 | int main()
35 | {
36 | int arr[] = { 15, 2, 4, 8, 9, 5, 10, 23 };
37 | int N = sizeof(arr) / sizeof(arr[0]);
38 |
39 | int L = 10, R = 23;
40 |
41 | subArraySum(arr, N, L, R);
42 |
43 | return 0;
44 | }
--------------------------------------------------------------------------------
/tests/test2/main.ml:
--------------------------------------------------------------------------------
1 | open Ast
2 |
3 | (* [is_value e] is whether [e] is a syntactic value *)
4 | let is_value : expr -> bool = function
5 | | Int _ | Bool _ -> true
6 | | Binop _ | Var _ | Let _ | If _ -> false
7 |
8 | (* [subst e v x] is e{v/x}, that is, [e] with [v]
9 | * substituted for [x]. *)
10 | let rec subst e v x = match e with
11 | | Var y -> if x=y then v else e
12 | | Bool b -> Bool b (* NEW *)
13 | | Int n -> Int n
14 | | Binop(op,el,er) -> Binop(op, subst el v x, subst er v x) (* NEW *)
15 | | Let(y,ebind,ebody) ->
16 | let ebind' = subst ebind v x in
17 | if x=y
18 | then Let(y, ebind', ebody)
19 | else Let(y, ebind', subst ebody v x)
20 | | If(eguard,ethen,eelse) -> (* NEW *)
21 | If(subst eguard v x, subst ethen v x, subst eelse v x)
22 |
23 | (* A single step of evaluation. *)
24 | let rec step = function
25 | | Int _ | Bool _ -> failwith "Does not step"
26 | | Var _ -> failwith "Unbound variable"
27 | | Binop(Plus, Int n1, Int n2) -> Int (n1+n2) (* NEW *)
28 | | Binop(Mult, Int n1, Int n2) -> Int (n1*n2) (* NEW *)
29 | | Binop(Leq, Int n1, Int n2) -> Bool (n1<=n2) (* NEW *)
30 | | Binop(op, Int n1, e2) -> Binop(op, Int n1, step e2) (* NEW *)
31 | | Binop(op, e1, e2) -> Binop(op, step e1, e2)
32 | | Let(x,Int n,e2) -> subst e2 (Int n) x
33 | | Let(x,Bool b,e2) -> subst e2 (Bool b) x
34 | | Let(x,e1,e2) -> Let(x,step e1, e2)
35 | | If(Bool true, e2, _) -> e2
36 | | If(Bool false, _, e3) -> e3
37 | | If(e1,e2,e3) -> If(step e1, e2, e3)
38 |
39 | (* [eval e] is the [e -->* v] judgement. That is,
40 | * keep applying [step] until a value is produced. *)
41 | let rec eval : expr -> expr = fun e ->
42 | if is_value e then e
43 | else eval (step e)
44 |
45 | (* Parse a string into an ast *)
46 | let parse s =
47 | let lexbuf = Lexing.from_string s in
48 | let ast = Parser.prog Lexer.read lexbuf in
49 | ast
50 |
51 | (* Extract a value from an ast node.
52 | Raises Failure if the argument is a node containing a value. *)
53 | let extract_value = function
54 | | Int i -> VInt i
55 | | Bool b -> VBool b (* NEW *)
56 | | _ -> failwith "Not a value"
57 |
58 | (* Interpret an expression *)
59 | let interp e =
60 | e |> parse |> eval |> extract_value
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/tests/test2/main1.ml:
--------------------------------------------------------------------------------
1 | open Ast
2 |
3 | (* [is_value e] is whether [e] is a syntactic value *)
4 | let is_value : expr -> bool = function
5 | | I _ | B _ -> true
6 | | Bop _ | Var _ | Let _ | If _ -> false
7 |
8 | (* [subst e v x] is e{v/x}, that is, [e] with [v]
9 | * substituted for [x]. *)
10 | let rec subst e v x = match e with
11 | | Var y -> if x=y then v else e
12 | | B b -> B b (* NEW *)
13 | | I n -> I n
14 | | Bop(op,el,er) -> Bop(op, subst el v x, subst er v x) (* NEW *)
15 | | Let(y,ebind,ebody) ->
16 | let ebind' = subst ebind v x in
17 | if x=y
18 | then Let(y, ebind', ebody)
19 | else Let(y, ebind', subst ebody v x)
20 | | If(eguard,ethen,eelse) -> (* NEW *)
21 | If(subst eguard v x, subst ethen v x, subst eelse v x)
22 |
23 | (* A single step of evaluation. *)
24 | let rec step = function
25 | | I _ | B _ -> failwith "Does not step"
26 | | Var _ -> failwith "Unbound variable"
27 | | Bop(Plus, I n1, I n2) -> I (n1+n2) (* NEW *)
28 | | Bop(Mult, I n1, I n2) -> I (n1*n2) (* NEW *)
29 | | Bop(Leq, I n1, I n2) -> B (n1<=n2) (* NEW *)
30 | | Bop(op, I n1, e2) -> Bop(op, I n1, step e2) (* NEW *)
31 | | Bop(op, e1, e2) -> Bop(op, step e1, e2)
32 | | Let(x,I n,e2) -> subst e2 (I n) x
33 | | Let(x,B b,e2) -> subst e2 (B b) x
34 | | Let(x,e1,e2) -> Let(x,step e1, e2)
35 | | If(B true, e2, _) -> e2
36 | | If(B false, _, e3) -> e3
37 | | If(e1,e2,e3) -> If(step e1, e2, e3)
38 |
39 | (* [eval e] is the [e -->* v] judgement. That is,
40 | * keep applying [step] until a value is produced. *)
41 | let rec eval : expr -> expr = fun e ->
42 | if is_value e then e
43 | else eval (step e)
44 |
45 | (* Parse a string Io an ast *)
46 | let parse s =
47 | let lexbuf = Lexing.from_string s in
48 | let ast = Parser.prog Lexer.read lexbuf in
49 | ast
50 |
51 | (* Extract a value from an ast node.
52 | Raises Failure if the argument is a node containing a value. *)
53 | let extract_value = function
54 | | I i -> VI i
55 | | B b -> VB b (* NEW *)
56 | | _ -> failwith "Not a value"
57 |
58 | (* Interpret an expression *)
59 | let interp e =
60 | e |> parse |> eval |> extract_value
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/tests/test3/labsoln.ml:
--------------------------------------------------------------------------------
1 | (********************************************************************
2 | * exercise: list expressions
3 | ********************************************************************)
4 |
5 | let lst1 = [1;2;3;4;5]
6 | let lst2 = 1::2::3::4::5::[]
7 | let lst3 = [1]@[2;3;4]@[5]
8 |
9 | (********************************************************************
10 | * exercise: product
11 | ********************************************************************)
12 |
13 | (* returns: the product of all the elements of [lst], or [1] if [lst]
14 | * is empty.
15 | *)
16 | let rec product lst =
17 | match lst with
18 | | [] -> 1
19 | | h::t -> h * product t
20 |
21 | (* Here's a simpler way to write that using the [function] syntactic sugar
22 | * discussed in the notes...
23 | *)
24 | let rec product' = function
25 | | [] -> 1
26 | | h::t -> h * product' t
27 |
28 | (********************************************************************
29 | * exercise: bad add
30 | ********************************************************************)
31 |
32 | (* see the files add.ml and add_test.ml *)
33 |
34 | (********************************************************************
35 | * exercise: patterns
36 | ********************************************************************)
37 |
38 | (* returns: whether the first element of the input is ["bigred"]
39 | *)
40 | let first_is_bigred = function
41 | | [] -> false
42 | | h::_ -> h = "bigred"
43 |
44 | (* returns: whether the input has exactly two or four elements
45 | *)
46 | let two_or_four_elements = function
47 | | _::_::[] -> true
48 | | _::_::_::_::[] -> true
49 | | _ -> false
50 |
51 | (* returns: whether the first two elements of the input are equal
52 | *)
53 | let eq_first_two = function
54 | | a::b::_ -> a = b
55 | | _ -> false
56 |
57 | (********************************************************************
58 | * exercise: library
59 | ********************************************************************)
60 |
61 | (* returns: the fifth element of the input list, or zero if the
62 | * list is empty
63 | *)
64 | let fifth_element lst =
65 | if (List.length lst) >= 5 then List.nth lst 4 else 0
66 |
67 | (* returns: the input list, sorted in descending order
68 | *)
69 | let sort_list_descending lst =
70 | List.rev (List.sort Pervasives.compare lst)
71 |
72 | (* A more idiomatic way to write the above function is
73 | * with the pipeline operator. This makes use of
74 | * partial application with List.sort.
75 | *)
76 | let sort_list_descending' lst =
77 | lst |> List.sort Pervasives.compare |> List.rev
78 |
79 | (********************************************************************
80 | * exercise: library puzzle
81 | ********************************************************************)
82 |
83 | (* returns: the last element of [lst]
84 | * requires: [lst] is nonempty
85 | *)
86 | let last_element lst =
87 | List.nth lst (List.length lst - 1)
88 |
89 | (* another solution...
90 | *)
91 | let last_element' lst =
92 | lst |> List.rev |> List.hd
93 |
94 | (* returns: whether [lst] contains any zeros
95 | *)
96 | let any_zeros lst =
97 | List.exists (fun x -> x = 0) lst
98 |
99 | (********************************************************************
100 | * exercise: take drop
101 | ********************************************************************)
102 |
103 | (* returns: [take n lst] is the first [n] elements of [lst], or
104 | * just [lst] if [lst] has fewer than [n] elements.
105 | * requires: [n >= 0]
106 | *)
107 | let rec take n lst =
108 | if n = 0 then [] else match lst with
109 | | [] -> []
110 | | x::xs -> x :: take (n-1) xs
111 |
112 | (* returns: [drop n lst] is all but the first [n] elements of [lst],
113 | * or just [[]] if [lst] has fewer than [n] elements.
114 | * requires: [n >= 0]
115 | *)
116 | let rec drop n lst =
117 | if n = 0 then lst else match lst with
118 | | [] -> []
119 | | x::xs -> drop (n-1) xs
120 |
121 | (********************************************************************
122 | * exercise: take drop tail
123 | ********************************************************************)
124 |
125 | (* returns: [take_rev n xs acc] is [lst1 @ acc], where [lst] is
126 | * the first [n] elements of [xs] (or just [xs] if [xs] has
127 | * fewer than [n] elements) in reverse order.
128 | * requires: [n >= 0] *)
129 | let rec take_rev n xs acc =
130 | if n = 0 then acc else match xs with
131 | | [] -> acc
132 | | x::xs' -> take_rev (n-1) xs' (x::acc)
133 |
134 | (* returns: [take n lst] is the first [n] elements of [lst], or
135 | * just [lst] if [lst] has fewer than [n] elements.
136 | * requires: [n >= 0]
137 | *)
138 | let take_tr n lst =
139 | take_rev n lst [] |> List.rev
140 |
141 | (* In the solution above, we factored out a helper function called
142 | * [take_rev]. It is tail recursive. The helper function takes
143 | * the same arguments as the original function, and one additional
144 | * argument [acc] called an *accumulator*. We accumulate the answer
145 | * in it, eventually returning it when either [xs] is empty
146 | * or [n] is 0. This is a general recipe one can follow in making
147 | * any recursive function be tail recursive. That same recipe was
148 | * followed in creating the definition of [(--)] below. *)
149 |
150 | (* the "natural" solution to [drop] above is already tail recursive *)
151 | let drop_tr = drop
152 |
153 | (* returns: [from i j l] is the list containing the integers from
154 | * [i] to [j], inclusive, followed by the list [l].
155 | * example: [from 1 3 [0] = [1;2;3;0]] *)
156 | let rec from i j l =
157 | if i>j then l
158 | else from i (j-1) (j::l)
159 |
160 | (* returns: [i -- j] is the list containing the integers from
161 | * [i] to [j], inclusive.
162 | *)
163 | let (--) i j =
164 | from i j []
165 |
166 | let longlist = 0 -- 1_000_000
167 |
168 | (* [take 1_000_000 longlist] should produce a stack overflow,
169 | * but [take_tr 1_000_000 longlist] should not. *)
170 |
--------------------------------------------------------------------------------
/tests/test3/labsoln1.ml:
--------------------------------------------------------------------------------
1 | (********************************************************************
2 | * exercise: list expressions
3 | ********************************************************************)
4 |
5 | let lst1 = [1;2;3;4;5]
6 | let lst2 = 1::2::3::4::5::[]
7 | let lst3 = [1]@[2;3;4]@[5]
8 |
9 | (********************************************************************
10 | * exercise: bad add
11 | ********************************************************************)
12 |
13 | (* see the files add.ml and add_test.ml *)
14 |
15 | (********************************************************************
16 | * exercise: patterns
17 | ********************************************************************)
18 |
19 | (* returns: whether the first element of the input is ["bigred"]
20 | *)
21 | let first_is_bigred = function
22 | | [] -> false
23 | | h::_ -> h = "bigred"
24 |
25 | (* returns: whether the input has exactly two or four elements
26 | *)
27 | let two_or_four_elements = function
28 | | _::_::[] -> true
29 | | _::_::_::_::[] -> true
30 | | _ -> false
31 |
32 | (* returns: whether the first two elements of the input are equal
33 | *)
34 | let eq_first_two = function
35 | | a::b::_ -> a = b
36 | | _ -> false
37 |
38 | (********************************************************************
39 | * exercise: library
40 | ********************************************************************)
41 |
42 | (* returns: the fifth element of the input list, or zero if the
43 | * list is empty
44 | *)
45 | let fifth_element lst =
46 | if (List.length lst) >= 5 then List.nth lst 4 else 0
47 |
48 | (* returns: the input list, sorted in descending order
49 | *)
50 | let sort_list_descending lst =
51 | List.rev (List.sort Pervasives.compare lst)
52 |
53 | (* A more idiomatic way to write the above function is
54 | * with the pipeline operator. This makes use of
55 | * partial application with List.sort.
56 | *)
57 | let sort_list_descending' lst =
58 | lst |> List.sort Pervasives.compare |> List.rev
59 |
60 | (********************************************************************
61 | * exercise: library puzzle
62 | ********************************************************************)
63 |
64 | (* returns: the last element of [lst]
65 | * requires: [lst] is nonempty
66 | *)
67 | let last_element lst =
68 | List.nth lst (List.length lst - 1)
69 |
70 | (* another solution...
71 | *)
72 | let last_element' lst =
73 | lst |> List.rev |> List.hd
74 |
75 | (* returns: whether [lst] contains any zeros
76 | *)
77 | let any_zeros lst =
78 | List.exists (fun x -> x = 0) lst
79 |
80 | (* returns: [take_rev n xs acc] is [lst1 @ acc], where [lst] is
81 | * the first [n] elements of [xs] (or just [xs] if [xs] has
82 | * fewer than [n] elements) in reverse order.
83 | * requires: [n >= 0] *)
84 | let rec take_rev n xs acc =
85 | if n = 0 then acc else match xs with
86 | | [] -> acc
87 | | x::xs' -> take_rev (n-1) xs' (x::acc)
88 |
89 | (********************************************************************
90 | * exercise: take drop
91 | ********************************************************************)
92 |
93 | (* returns: [take n lst] is the first [n] elements of [lst], or
94 | * just [lst] if [lst] has fewer than [n] elements.
95 | * requires: [n >= 0]
96 | *)
97 | let rec take n lst =
98 | if n = 0 then [] else match lst with
99 | | [] -> []
100 | | x::xs -> x :: take (n-1) xs
101 |
102 | (* returns: [drop n lst] is all but the first [n] elements of [lst],
103 | * or just [[]] if [lst] has fewer than [n] elements.
104 | * requires: [n >= 0]
105 | *)
106 | let rec drop n lst =
107 | if n = 0 then lst else match lst with
108 | | [] -> []
109 | | x::xs -> drop (n-1) xs
110 |
111 | (********************************************************************
112 | * exercise: take drop tail
113 | ********************************************************************)
114 |
115 | (* returns: [take n lst] is the first [n] elements of [lst], or
116 | * just [lst] if [lst] has fewer than [n] elements.
117 | * requires: [n >= 0]
118 | *)
119 | let take_tr n lst =
120 | take_rev n lst [] |> List.rev
121 |
122 | (* In the solution above, we factored out a helper function called
123 | * [take_rev]. It is tail recursive. The helper function takes
124 | * the same arguments as the original function, and one additional
125 | * argument [acc] called an *accumulator*. We accumulate the answer
126 | * in it, eventually returning it when either [xs] is empty
127 | * or [n] is 0. This is a general recipe one can follow in making
128 | * any recursive function be tail recursive. That same recipe was
129 | * followed in creating the definition of [(--)] below. *)
130 |
131 | (* the "natural" solution to [drop] above is already tail recursive *)
132 | let drop_tr = drop
133 |
134 | (* returns: [from i j l] is the list containing the integers from
135 | * [i] to [j], inclusive, followed by the list [l].
136 | * example: [from 1 3 [0] = [1;2;3;0]] *)
137 | let rec from i j l =
138 | if i>j then l
139 | else from i (j-1) (j::l)
140 |
141 | (* returns: [i -- j] is the list containing the integers from
142 | * [i] to [j], inclusive.
143 | *)
144 | let (--) i j =
145 | from i j []
146 |
147 | let longlist = 0 -- 1_000_000
148 |
149 | (* [take 1_000_000 longlist] should produce a stack overflow,
150 | * but [take_tr 1_000_000 longlist] should not. *)
151 |
152 | (********************************************************************
153 | * exercise: product
154 | ********************************************************************)
155 |
156 | (* returns: the product of all the elements of [lst], or [1] if [lst]
157 | * is empty.
158 | *)
159 | let rec product lst =
160 | match lst with
161 | | [] -> 1
162 | | h::t -> h * product t
163 |
164 | (* Here's a simpler way to write that using the [function] syntactic sugar
165 | * discussed in the notes...
166 | *)
167 | let rec product' = function
168 | | [] -> 1
169 | | h::t -> h * product' t
170 |
--------------------------------------------------------------------------------
/tests/test4/functions.ml:
--------------------------------------------------------------------------------
1 | (********************************************************************
2 | * exercise: fib
3 | ********************************************************************)
4 |
5 | (* returns: element [n] of the Fibonacci sequence *)
6 | (* requires: [n >= 0] *)
7 | let rec fib n =
8 | if n = 0 then 0
9 | else if n = 1 then 1
10 | else fib (n-1) + fib (n-2)
11 |
12 | (********************************************************************
13 | * exercise: fib fast
14 | ********************************************************************)
15 |
16 | (* requires: n > 0 *)
17 | (* returns: element [n] of the Fibonacci-like sequence, assuming
18 | * the first two elements are [pp] and [p]. *)
19 | let rec h n pp p =
20 | if n = 1 then p
21 | else h (n-1) p (pp+p)
22 |
23 | (* returns: element [n] of the Fibonacci sequence
24 | * requires: [n >= 0] *)
25 | let fib_fast n =
26 | if n=0 then 0
27 | else h n 0 1
28 |
29 | (* on a 64-bit OCaml implementation, fib_fast 91 overflows. *)
30 |
31 | (********************************************************************
32 | * exercise: poly types
33 | ********************************************************************)
34 |
35 | let f x = if x then x else x
36 | (* bool -> bool *)
37 | (* x must be a bool to to be used as the conditional in the if expression *)
38 |
39 | let g x y = if y then x else x
40 | (* 'a -> bool -> 'a *)
41 | (* x could have any type *)
42 |
43 | let h x y z = if x then y else z
44 | (* bool -> 'a -> 'a -> 'a *)
45 | (* both branches of the if expression must have the same type,
46 | * so y and z must have the same type (which could be anything) *)
47 |
48 | let i x y z = if x then y else y
49 | (* bool -> 'a -> 'b -> 'a *)
50 | (* z could have any type, and moreover, that type could be different
51 | * than the type of y *)
52 |
53 | (********************************************************************
54 | * exercise: divide
55 | ********************************************************************)
56 |
57 | let divide ~numerator:x ~denominator:y = x /. y
58 |
59 | (********************************************************************
60 | * exercise: addx
61 | ********************************************************************)
62 |
63 | let addx x = fun y -> x + y
64 | (* int -> int -> int*)
65 |
66 | let add5 = addx 5
67 | (* int -> int *)
68 | (* [add 5 2] is equivalent to [fun y -> 5 y]
69 | so [add5 2] evaluates to 7 *)
70 |
71 | let add3 = addx 3
72 | (* int -> int *)
73 | (* add3 8 = 11 *)
74 |
75 | (********************************************************************
76 | * exercise: associativity
77 | ********************************************************************)
78 |
79 | let add x y = x+y
80 |
81 | (* Only add (5 1) produces an error, because it tries to apply
82 | * the value 5 to the argument 1, but 5 is not a function, so it
83 | * cannot be applied. *)
84 |
85 | (********************************************************************
86 | * exercise: average
87 | ********************************************************************)
88 |
89 | let ($$) a b =
90 | (a +. b) /. 2.
91 |
--------------------------------------------------------------------------------
/tests/test4/functions1.ml:
--------------------------------------------------------------------------------
1 | (********************************************************************
2 | * exercise: fib
3 | ********************************************************************)
4 |
5 | (* returns: element [n] of the Fibonacci sequence *)
6 | (* requires: [n >= 0] *)
7 | let rec fib n =
8 | if n = 0 then 0
9 | else if n = 1 then 1
10 | else fib (n-1) + fib (n-2)
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | (********************************************************************
22 | * exercise: associativity
23 | ********************************************************************)
24 |
25 | let add x y = x+y
26 |
27 | (* Only add (5 1) produces an error, because it tries to apply
28 | * the value 5 to the argument 1, but 5 is not a function, so it
29 | * cannot be applied. *)
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | (********************************************************************
50 | * exercise: poly types
51 | ********************************************************************)
52 |
53 | let f x = if x then x else x
54 | (* bool -> bool *)
55 | (* x must be a bool to to be used as the conditional in the if expression *)
56 |
57 | let g x y = if y then x else x
58 | (* 'a -> bool -> 'a *)
59 | (* x could have any type *)
60 |
61 | let h x y z = if x then y else z
62 | (* bool -> 'a -> 'a -> 'a *)
63 | (* both branches of the if expression must have the same type,
64 | * so y and z must have the same type (which could be anything) *)
65 |
66 | let i x y z = if x then y else y
67 | (* bool -> 'a -> 'b -> 'a *)
68 | (* z could have any type, and moreover, that type could be different
69 | * than the type of y *)
70 |
71 | (********************************************************************
72 | * exercise: fib fast
73 | ********************************************************************)
74 |
75 |
76 |
77 |
78 |
79 |
80 | (* requires: n > 0 *)
81 | (* returns: element [n] of the Fibonacci-like sequence, assuming
82 | * the first two elements are [pp] and [p]. *)
83 | let rec h n pp p =
84 | if n = 1 then p
85 | else h (n-1) p (pp+p)
86 |
87 | (* returns: element [n] of the Fibonacci sequence
88 | * requires: [n >= 0] *)
89 | let fib_fast n =
90 | if n=0 then 0
91 | else h n 0 1
92 |
93 | (* on a 64-bit OCaml implementation, fib_fast 91 overflows. *)
94 |
95 |
96 | (********************************************************************
97 | * exercise: divide
98 | ********************************************************************)
99 |
100 | let divide ~numerator:x ~denominator:y = x /. y
101 |
102 | (********************************************************************
103 | * exercise: addx
104 | ********************************************************************)
105 |
106 | let addx x = fun y -> x + y
107 | (* int -> int -> int*)
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | let add5 = addx 5
116 | (* int -> int *)
117 | (* [add 5 2] is equivalent to [fun y -> 5 y]
118 | so [add5 2] evaluates to 7 *)
119 |
120 | let add3 = addx 3
121 | (* int -> int *)
122 | (* add3 8 = 11 *)
123 |
124 | (********************************************************************
125 | * exercise: average
126 | ********************************************************************)
127 |
128 | let ($$) a b =
129 | (a +. b) /. 2.
130 |
--------------------------------------------------------------------------------
/tests/test5/queens_lazy.ml:
--------------------------------------------------------------------------------
1 | type 'a lval =
2 | | Val of 'a
3 | | Delayed of (unit -> 'a);;
4 |
5 | (* The forcing function. *)
6 | let force = function
7 | | Val v -> v
8 | | Delayed f -> f ();;
9 |
10 | (* The type of lazy lists. *)
11 | type 'a llist =
12 | | Nil
13 | | Cons of 'a lcell
14 |
15 | and 'a lcell = { mutable hd : 'a lval; mutable tl : 'a llist lval};;
16 |
17 | let ( *::* ) x y = Cons { hd = Delayed x; tl = Delayed y };;
18 | let ( -::* ) x y = Cons { hd = Val x; tl = Delayed y };;
19 | let ( -::- ) x y = Cons { hd = Val x; tl = Val y };;
20 | let ( --::* ) x y = Cons { hd = x; tl = Delayed y };;
21 | let ( --::-- ) x y = Cons { hd = x; tl = y };;
22 |
23 | let force_hd = function
24 | | Cons {hd = Val v} -> v
25 | | Cons ({hd = lv} as c) ->
26 | let v = force lv in
27 | c.hd <- Val v;
28 | v
29 | | Nil ->
30 | failwith "force_hd";;
31 |
32 | let force_tl = function
33 | | Cons {tl = Val v} -> v
34 | | Cons ({tl = lv} as c) ->
35 | let v = force lv in
36 | c.tl <- Val v;
37 | v;
38 | | Nil ->
39 | failwith "force_tl";;
40 |
41 | let force_hd = function
42 | | {hd = Val v} -> v
43 | | {hd = lv} as c ->
44 | let v = force lv in
45 | c.hd <- Val v;
46 | v;;
47 |
48 | let force_tl = function
49 | | {tl = Val v} -> v
50 | | {tl = lv} as c ->
51 | let v = force lv in
52 | c.tl <- Val v;
53 | v;;
54 |
55 | (* The corresponding functions and functionals:
56 | interval, map, filter_append, concmap. *)
57 | let rec map f = function
58 | | Nil -> Nil
59 | | Cons c ->
60 | f (force_hd c) -::* (fun () -> map f (force_tl c));;
61 |
62 | let rec iter f = function
63 | | Nil -> ()
64 | | Cons c ->
65 | f (force_hd c); iter f (force_tl c);;
66 |
67 | let rec length = function
68 | | Nil -> 0
69 | | Cons c ->
70 | 1 + length (force_tl c);;
71 |
72 | let rec interval n m =
73 | if n > m then Nil else n -::* (fun () -> interval (n + 1) m);;
74 |
75 | let rec rev_append l1 l2 =
76 | match l1 with
77 | | Nil -> l2
78 | | Cons { hd = x; tl = l} ->
79 | x --::* (fun () -> rev_append (force l) l2);;
80 |
81 | let rec filter_append p l l0 =
82 | match (l : 'a llist) with
83 | | Nil -> l0
84 | | Cons c ->
85 | let x = force_hd c in
86 | if p x then x -::* (fun () -> filter_append p (force_tl c) l0)
87 | else filter_append p (force_tl c) l0;;
88 |
89 | let rec concmap f = function
90 | | Nil -> Nil
91 | | Cons c ->
92 | f (force_hd c)
93 | (concmap f (force_tl c));;
94 |
95 | let rec safe x d = function
96 | | Nil -> true
97 | | Cons { hd = h; tl = t} ->
98 | let h = force h in
99 | x <> h && x <> h + d && x <> h - d && safe x (d + 1) (force t);;
100 |
101 | let rec ok = function
102 | | Nil -> true
103 | | Cons { hd = h; tl = t} ->
104 | safe (force h) 1 (force t);;
105 |
106 | let find_solutions size =
107 | let line = interval 1 size in
108 | let rec gen n size =
109 | if n = 0 then Nil -::- Nil else
110 | concmap
111 | (fun b -> filter_append ok (map (fun q -> q -::- b) line))
112 | (gen (n - 1) size) in
113 | gen size size;;
114 |
115 | (* 2. Printing results. *)
116 |
117 | let print_solutions size solutions =
118 | let sol_num = ref 1 in
119 | iter
120 | (fun chess ->
121 | Printf.printf "\nSolution number %i\n" !sol_num;
122 | sol_num := !sol_num + 1;
123 | iter
124 | (fun line ->
125 | let count = ref 1 in
126 | while !count <= size do
127 | if !count = line then print_string "Q " else print_string "- ";
128 | count := !count + 1
129 | done;
130 | print_newline ())
131 | chess)
132 | solutions;;
133 |
134 | let print_number_of_solutions size sols =
135 | let sol_num = length sols in
136 | Printf.printf "The %i queens problem has %i solutions.\n" size sol_num;;
137 |
138 | let print_result size =
139 | let sols = find_solutions size in
140 | print_number_of_solutions size sols;
141 | print_newline ();
142 | let pr =
143 | print_string "Do you want to see the solutions ? "; read_line () in
144 | if pr = "y" then print_solutions size sols;;
145 |
146 | (* 3. Main program. *)
147 |
148 | let queens () =
149 | let size =
150 | print_string "Chess boards's size ? "; read_int () in
151 | print_result size;;
152 |
153 | if !Sys.interactive then queens () else
154 | let size =
155 | if Array.length Sys.argv <> 2 then 8 else (int_of_string Sys.argv.(1)) in
156 | let sols = find_solutions size in
157 | print_number_of_solutions size sols;;
158 |
--------------------------------------------------------------------------------
/tests/test5/queens_tail.ml:
--------------------------------------------------------------------------------
1 | open List;;
2 |
3 | let map f l =
4 | let rec loop accu = function
5 | | [] -> accu
6 | | x :: l -> loop (f x :: accu) l in
7 | loop [] l;;
8 |
9 | let rec interval n m =
10 | if n > m then [] else n :: interval (n + 1) m;;
11 |
12 | let rev_append l1 l2 =
13 | let rec loop accu = function
14 | | [] -> accu
15 | | h :: t -> loop (h :: accu) t in
16 | loop l2 l1;;
17 |
18 | let filter_append p l l0 =
19 | let rec loop accu = function
20 | | [] -> accu
21 | | h :: t -> if p h then loop (h :: accu) t else loop accu t in
22 | let rev_res = loop [] l in
23 | rev_append rev_res l0;;
24 |
25 | let concmap f l =
26 | let rec loop accu = function
27 | | [] -> accu
28 | | h :: t -> loop (f h accu) t in
29 | loop [] l;;
30 |
31 | let rec safe x d = function
32 | | [] -> true
33 | | h :: t ->
34 | x <> h && x <> h + d && x <> h - d && safe x (d + 1) t;;
35 |
36 | let rec ok = function
37 | | [] -> true
38 | | h :: t -> safe h 1 t;;
39 |
40 | let find_solutions size =
41 | let line = interval 1 size in
42 | let rec gen n size =
43 | if n = 0 then [[]] else
44 | concmap
45 | (fun b -> filter_append ok (map (fun q -> q :: b) line))
46 | (gen (n - 1) size) in
47 | gen size size;;
48 |
49 | (* 2. Printing results. *)
50 |
51 | let print_solutions size solutions =
52 | let sol_num = ref 1 in
53 | iter
54 | (fun chess ->
55 | Printf.printf "\nSolution number %i\n" !sol_num;
56 | sol_num := !sol_num + 1;
57 | iter
58 | (fun line ->
59 | let count = ref 1 in
60 | while !count <= size do
61 | if !count = line then print_string "Q " else print_string "- ";
62 | count := !count + 1
63 | done;
64 | print_newline ())
65 | chess)
66 | solutions;;
67 |
68 | let print_result size =
69 | let solutions = find_solutions size in
70 | let sol_num = List.length solutions in
71 | Printf.printf "The %i queens problem has %i solutions.\n" size sol_num;
72 | print_newline ();
73 | let pr =
74 | print_string "Do you want to see the solutions ? "; read_line () in
75 | if pr = "y" then print_solutions size solutions;;
76 |
77 | (* 3. Main program. *)
78 |
79 | let queens () =
80 | let size =
81 | print_string "Chess boards's size ? "; read_int () in
82 | print_result size;;
83 |
84 | if !Sys.interactive then () else queens ();;
--------------------------------------------------------------------------------
/tests/test6/kmp.ml:
--------------------------------------------------------------------------------
1 | let init_next p =
2 | let m = String.length p in
3 | let next = Array.create m 0 in
4 | let i = ref 1 and j = ref 0 in
5 | while !i < m - 1 do
6 | if p.[!i] = p.[!j] then begin incr i; incr j; next.(!i) <- !j end else
7 | if !j = 0 then begin incr i; next.(!i) <- 0 end else j := next.(!j)
8 | done;
9 | next;;
10 |
11 | let kmp p =
12 | let next = init_next p
13 | and m = String.length p in
14 | function s ->
15 | let n = String.length s
16 | and i = ref 0
17 | and j = ref 0 in
18 | while !j < m && !i < n do
19 | if s.[!i] = p.[!j] then begin incr i; incr j end else
20 | if !j = 0 then incr i else j := next.(!j)
21 | done;
22 | if !j >= m then !i - m else raise Not_found;;
23 |
24 | let find_pat p s =
25 | try
26 | let i = kmp p s in
27 | print_string "Match found at character ";
28 | print_int i;
29 | print_newline ();
30 | exit 0
31 | with Not_found ->
32 | print_string "Pattern ";
33 | print_string p;
34 | print_string " does not match string ";
35 | print_string s;
36 | print_newline ();
37 | exit 2;;
38 |
39 | let usage () =
40 | print_string
41 | "Usage: kmp \n\
42 | returns the index of the first occurrence of in string \n";
43 | exit 2;;
44 |
45 | let main () =
46 | let args = Sys.argv in
47 | if Array.length args < 2 then usage () else
48 | let p = Sys.argv.(1)
49 | and s = Sys.argv.(2) in
50 | find_pat p s;;
51 |
52 | if !Sys.interactive then () else main ();;
--------------------------------------------------------------------------------
/tests/test6/strpos.ml:
--------------------------------------------------------------------------------
1 | let find_sub_string p s =
2 | let plen = String.length p in
3 | if plen = 0 then 0 else
4 | let slen = String.length s in
5 | if slen = 0 then raise Not_found else
6 | let rec find c i =
7 | if i >= slen then raise Not_found else
8 | if s.[i] = c then find_rest c 1 (i + 1) else find c (i + 1)
9 | and find_rest c j i =
10 | if j >= plen then (i - plen) else
11 | if i >= slen then raise Not_found else
12 | if p.[j] = s.[i] then find_rest c (j + 1) (i + 1) else
13 | find c (i + 1 - j) in
14 | find p.[0] 0;;
15 |
16 | let find_pat p s =
17 | try
18 | let i = find_sub_string p s in
19 | print_string "Match found at character ";
20 | print_int i;
21 | print_newline ();
22 | exit 0
23 | with Not_found ->
24 | print_string "Pattern ";
25 | print_string p;
26 | print_string " does not match string ";
27 | print_string s;
28 | print_newline ();
29 | exit 2;;
30 |
31 | let usage () =
32 | print_string
33 | "Usage: strstr2 \n\
34 | returns the index of the first occurrence of in string \n";
35 | exit 2;;
36 |
37 | let main () =
38 | let args = Sys.argv in
39 | if Array.length args < 2 then usage () else
40 | let p = Sys.argv.(1)
41 | and s = Sys.argv.(2) in
42 | find_pat p s;;
43 |
44 | if !Sys.interactive then () else main ();;
--------------------------------------------------------------------------------
/tests/test7/strpos.ml:
--------------------------------------------------------------------------------
1 | let find_sub_string p s =
2 | let plen = String.length p in
3 | if plen = 0 then 0 else
4 | let slen = String.length s in
5 | if slen = 0 then raise Not_found else
6 | let rec find c i =
7 | if i >= slen then raise Not_found else
8 | if s.[i] = c then find_rest c 1 (i + 1) else find c (i + 1)
9 | and find_rest c j i =
10 | if j >= plen then (i - plen) else
11 | if i >= slen then raise Not_found else
12 | if p.[j] = s.[i] then find_rest c (j + 1) (i + 1) else
13 | find c (i + 1 - j) in
14 | find p.[0] 0;;
15 |
16 | let find_pat p s =
17 | try
18 | let i = find_sub_string p s in
19 | print_string "Match found at character ";
20 | print_int i;
21 | print_newline ();
22 | exit 0
23 | with Not_found ->
24 | print_string "Pattern ";
25 | print_string p;
26 | print_string " does not match string ";
27 | print_string s;
28 | print_newline ();
29 | exit 2;;
30 |
31 | let usage () =
32 | print_string
33 | "Usage: strstr2 \n\
34 | returns the index of the first occurrence of in string \n";
35 | exit 2;;
36 |
37 | let main () =
38 | let args = Sys.argv in
39 | if Array.length args < 2 then usage () else
40 | let p = Sys.argv.(1)
41 | and s = Sys.argv.(2) in
42 | find_pat p s;;
43 |
44 | if !Sys.interactive then () else main ();;
--------------------------------------------------------------------------------
/tests/test7/strpos2.ml:
--------------------------------------------------------------------------------
1 |
2 |
3 | let usage () =
4 | print_string
5 | "Usage: strstr2 \n\
6 | returns the index of the first occurrence of in string \n";
7 | exit 2;;
8 |
9 | let main () =
10 | let args = Sys.argv in
11 | if Array.length args < 2 then usage () else
12 | let p = Sys.argv.(1)
13 | and s = Sys.argv.(2) in
14 | find_pat p s;;
15 |
16 | if !Sys.interactive then () else main ();;
17 |
18 | let find_pat p s =
19 | try
20 | let i = find_sub_string p s in
21 | print_string "Match found at character ";
22 | print_int i;
23 | print_newline ();
24 | exit 0
25 | with Not_found ->
26 | print_string "Pattern ";
27 | print_string p;
28 | print_string " does not match string ";
29 | print_string s;
30 | print_newline ();
31 | exit 2;;
32 |
33 |
34 |
35 |
36 |
37 | let find_sub_string p s =
38 | let plen = String.length p in
39 | if plen = 0 then 0 else
40 | let slen = String.length s in
41 | if slen = 0 then raise Not_found else
42 | let rec find c i =
43 | if i >= slen then raise Not_found else
44 | if s.[i] = c then find_rest c 1 (i + 1) else find c (i + 1)
45 | and find_rest c j i =
46 | if j >= plen then (i - plen) else
47 | if i >= slen then raise Not_found else
48 | if p.[j] = s.[i] then find_rest c (j + 1) (i + 1) else
49 | find c (i + 1 - j) in
50 | find p.[0] 0;;
--------------------------------------------------------------------------------
/tests/test8/lab03.ml:
--------------------------------------------------------------------------------
1 | let rec mult x =
2 | match x with
3 | | [] -> 1
4 | | h::t -> h * mult t
5 |
6 | let rec stringadd x =
7 | match x with
8 | | [] -> ""
9 | | h::t -> h ^ stringadd t
10 |
11 | let bigred x =
12 | match x with
13 | | [] -> false
14 | | h::t -> if h = "bigred" then true else false
15 |
16 | let rec twoOrFour_helper x acc =
17 | match x with
18 | | [] -> if acc = 2 || acc = 4 then true else false
19 | | h::t -> twoOrFour_helper t (acc+1)
20 |
21 | let twoOrFour x = twoOrFour_helper x 0
22 |
23 | let twoEl x =
24 | match x with
25 | | [] -> false
26 | | h::[] -> false
27 | | h::h1::t -> if h=h1 then true else false
28 |
29 | let fifth x =
30 | match x with
31 | | [] -> 0
32 | | h::t -> if List.length x <5 then 0 else List.nth x 5
33 |
34 | let backsort x = List.rev (List.sort Pervasives.compare x)
35 |
36 | let last x = List.nth x (List.length x - 1)
37 |
38 | let has0 x = List.exists (fun x -> x=0) x
39 |
40 | let rec take n x y size =
41 | match x with
42 | | [] -> y
43 | | h::t -> if n = size then y else take n t (List.append y [h]) (size + 1)
44 |
45 | let rec drop n x size =
46 | match x with
47 | | [] -> x
48 | | h::t -> if n = size then x else drop n t (size + 1)
49 |
50 | (* returns: [from i j l] is the list containing the integers from
51 | * [i] to [j], inclusive, followed by the list [l].
52 | * example: [from 1 3 [0] = [1;2;3;0]] *)
53 | let rec from i j l =
54 | if i>j then l
55 | else from i (j-1) (j::l)
56 |
57 | (* returns: [i -- j] is the list containing the integers from
58 | * [i] to [j], inclusive.
59 | *)
60 | let (--) i j =
61 | from i j []
62 |
--------------------------------------------------------------------------------
/tests/test8/lab031.ml:
--------------------------------------------------------------------------------
1 | (*function/variable names changed from lab03 and order of functions changed*)
2 |
3 | let bagreed i =
4 | match i with
5 | | [] -> false
6 | | h::t -> if h = "bigred" then true else false
7 |
8 | (* returns: [from i j l] is the list containing the integers from
9 | * [i] to [j], inclusive, followed by the list [l].
10 | * example: [from 1 3 [0] = [1;2;3;0]] *)
11 | let rec froooom i j l =
12 | if i>j then l
13 | else froooom i (j-1) (j::l)
14 |
15 | (* returns: [i -- j] is the list containing the integers from
16 | * [i] to [j], inclusive.
17 | *)
18 | let (--) i j =
19 | froooom i j []
20 |
21 | let rec twoOr4_hulper x acc =
22 | match x with
23 | | [] -> if acc = 2 || acc = 4 then true else false
24 | | h::t -> twoOr4_hulper t (acc+1)
25 |
26 | let rec drap n x size =
27 | match x with
28 | | [] -> x
29 | | h::t -> if n = size then x else drap n t (size + 1)
30 |
31 | let twoOrFour x = twoOr4_hulper x 0
32 |
33 | let twoEl x =
34 | match x with
35 | | [] -> false
36 | | h::[] -> false
37 | | h::h1::t -> if h=h1 then true else false
38 |
39 | let fifth x =
40 | match x with
41 | | [] -> 0
42 | | h::t -> if List.length x <5 then 0 else List.nth x 5
43 |
44 | let rec malt z =
45 | match z with
46 | | [] -> 1
47 | | h::t -> h * malt t
48 |
49 | let rec strongidd wow =
50 | match wow with
51 | | [] -> ""
52 | | h::t -> h ^ strongidd t
53 |
54 | let backsort x = List.rev (List.sort Pervasives.compare x)
55 |
56 | let last x = List.nth x (List.length x - 1)
57 |
58 | let has0 x = List.exists (fun x -> x=0) x
59 |
60 | let rec take n x y size =
61 | match x with
62 | | [] -> y
63 | | h::t -> if n = size then y else take n t (List.append y [h]) (size + 1)
64 |
--------------------------------------------------------------------------------
/tests/test8/lab032.ml:
--------------------------------------------------------------------------------
1 | (*exact replica of lab031 with extra spaces and indents*)
2 |
3 | let bagreed i =
4 | match i with
5 |
6 | | [] -> false
7 | | h:: t -> if h = "bigred" then true else false
8 |
9 | (* returns: [from i j l] is the list containing the integers from
10 | * [i] to [j], inclusive, followed by the list [l].
11 | * example: [from 1 3 [0] = [1;2;3;0]] *)
12 | let rec froooom i j l =
13 | if i>j then l
14 |
15 |
16 |
17 |
18 | else froooom i (j-1) (j::l)
19 |
20 | (* returns: [i -- j] is the list containing the integers from
21 | * [i] to [j], inclusive.
22 | *)
23 | let (--) i j =
24 | froooom i j []
25 |
26 | let rec twoOr4_hulper x acc =
27 | match x with
28 | | [] -> if acc = 2 || acc = 4 then true else false
29 | | h::t -> twoOr4_hulper t (acc+1
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | )
47 |
48 | let rec drap n x size =
49 | match x with
50 | | [ ] ->
51 |
52 |
53 |
54 |
55 |
56 |
57 | x
58 | | h::t -> if n = size then x else drap n t (size + 1)
59 |
60 | let twoOrFour x = twoOr4_hulper x 0
61 |
62 | let twoEl x =
63 | match x with
64 | | [] -> false
65 | | h::[] -> false
66 | | h::h1::t -> if h=h1 then true else false
67 |
68 | let fifth x =
69 | match x with
70 | | [] -> 0
71 | | h::t
72 |
73 |
74 |
75 | -> if List.length x <5 then 0 else List.nth x 5
76 |
77 | let rec malt z =
78 | match z with
79 | | [] -> 1
80 | | h::t -> h * malt t
81 |
82 | let rec strongidd wow =
83 | match wow with
84 | | [] -> ""
85 | | h::t -> h ^ strongidd t
86 |
87 | let backsort x = List.rev (List.sort Pervasives.compare x)
88 |
89 | let last x = List.nth x (List.length x - 1)
90 |
91 | let has0 x = List.exists (fun x -> x=0) x
92 |
93 | let rec take n x y size =
94 | match x with
95 | | [] -> y
96 |
97 | | h::t -> if n = size then y
98 |
99 |
100 | else take n t (List.append y [h]) (size + 1)
101 |
--------------------------------------------------------------------------------
/tests/test8/lab033.ml:
--------------------------------------------------------------------------------
1 | (* More function/varuable names and orders changed. Add random rec declarations
2 | and get rid of lines for matching*)
3 | let bagreed i =
4 | match i with
5 | [] -> false
6 | | h::t -> if h = "bigred" then true else false
7 |
8 | (* returns: [from i j l] is the list containing the integers from
9 | * [i] to [j], inclusive, followed by the list [l].
10 | * example: [from 1 3 [0] = [1;2;3;0]] *)
11 | let rec froooom i j l =
12 | if i>j then l
13 | else froooom i (j-1) (j::l)
14 |
15 | (* returns: [i -- j] is the list containing the integers from
16 | * [i] to [j], inclusive.
17 | *)
18 | let (--) i j =
19 | froooom i j []
20 |
21 | let rec twoOr4_hulper x acc =
22 | match x with
23 | [] -> if acc = 2 || acc = 4 then true else false
24 | | h::t -> twoOr4_hulper t (acc+1)
25 |
26 | let rec drap n x size =
27 | match x with
28 | | [] -> x
29 | | h::t -> if n = size then x else drap n t (size + 1)
30 |
31 | let twoOrFour x = twoOr4_hulper x 0
32 |
33 | let twoEl x =
34 | match x with
35 | | [] -> false
36 | | h::[] -> false
37 | | h::h1::t -> if h=h1 then true else false
38 |
39 | let fifth x5x5x =
40 | match x5x5x with
41 | | [] -> 0
42 | | h::t -> if List.length x5x5x <5 then 0 else List.nth x5x5x 5
43 |
44 | let rec malt z =
45 | match z with
46 | | [] -> 1
47 | | h::t -> h * malt t
48 |
49 | let rec strongidd wow =
50 | match wow with
51 | | [] -> ""
52 | | r::m -> r ^ strongidd m
53 |
54 | let backsort x = List.rev (List.sort Pervasives.compare x)
55 |
56 | let last x = List.nth x (List.length x - 1)
57 |
58 | let hasssss0 x = List.exists (fun x -> x=0) x
59 |
60 | let rec take n x y size =
61 | match x with
62 | | [] -> y
63 | | s::l -> if n = size then y else take n l (List.append y [s]) (size + 1)
64 |
--------------------------------------------------------------------------------
/tests/test8/lab034.ml:
--------------------------------------------------------------------------------
1 | let rec mult x =
2 | x*x
3 |
4 | let rec stringadd x =
5 | x^x
6 |
7 | let bigred x =
8 | x ^ "red" ^ x
9 |
10 | let rec twoOrFour_helper x acc =
11 | x + acc
12 |
13 | let twoOrFour x = twoOrFour_helper x 0
14 |
15 | let twoEl x =
16 | 908
17 |
18 | let fifth x =
19 | x + 5
20 |
21 | let backsort x = x * -1
22 |
23 | let last x = x - x
24 |
25 | let has0 x = 0
26 |
27 | let rec take n x y size =
28 | match x with
29 | | [] -> x
30 | | h::t -> t
31 |
32 | let rec drop n x size =
33 | match x with
34 | | [] -> 45
35 | | h::t -> size
36 |
37 | (* returns: [from i j l] is the list containing the integers from
38 | * [i] to [j], inclusive, followed by the list [l].
39 | * example: [from 1 3 [0] = [1;2;3;0]] *)
40 | let rec from i j l =
41 | if i>j then l
42 | else j
43 |
44 | (* returns: [i -- j] is the list containing the integers from
45 | * [i] to [j], inclusive.
46 | *)
47 | let (--) i j =
48 | i - j
49 |
--------------------------------------------------------------------------------
/tests/test9/prelimpract.ml:
--------------------------------------------------------------------------------
1 | (*unit -> 'a
2 | True -> P
3 |
4 | ('a, ('b,'c))
5 | P and (Q and R)
6 |
7 | (('a*'b)or'*'c) or'
8 | (P or Q) or R
9 |
10 | void -> 'a
11 | False -> P
12 |
13 | ('a*'a neg) or'
14 | P \/ ~P
15 |
16 | 'a*'b or' -> 'b*'a or'
17 |
18 | ('a*'b neg) or' -> ('b->'a)
19 |
20 | ('a*'b)-> 'a
21 | (P/\Q) -> P
22 | f(1,2) -> substitution {(1,2)/x} snd ((fun x -> x,x) (fst x)) -> snd ((fun x -> x,x) (fst (1,2)))
23 | function application-> snd ((fun x -> x,x) (1))
24 | substituion -> snd ({1/x} x,x) -> snd (1,1)
25 | function app -> 1
26 |
27 | desugar
28 | let fact = rec fact -> fun x ->
29 | if x <= 1 then 1 else x * (fact (x - 1)) in
30 | fact 3
31 |
32 | step rec
33 | let fact =
34 | fun x ->
35 | if x <= 1 then 1 else x * (fact (x - 1)) {F/fact} in fact 3
36 |
37 | substitute
38 | let fact = fun x ->
39 | if x <= 1 then 1 else x * (F (x - 1)) in
40 | (fact) 3
41 |
42 | application
43 | if x <= 1 then 1 else x * (F (x - 1)) {3/x}
44 | -> if 3 <= 1 then 1 else 3 * (F (3 - 1))
45 |
46 | step bool
47 | if false then 1 else 3 * (F (3 - 1))
48 |
49 | 3 * (rec fact -> fun x -> if x <= 1 then 1 else x * (fact (x-1))) 2
50 |
51 | 3 * fun x -> if x <= 1 then 1 else x * (fact (x-1))) 2 {F/fact}
52 |
53 | 3 * fun x -> if x <= 1 then 1 else x * (F (x-1))) 2
54 |
55 | 3 * (if x <= 1 then 1 else x * (F (x-1))) {2/x})
56 |
57 | 3 * (if 2 <= 1 then 1 else 2 * (F (2-1))))
58 | 3 * (if false then 1 else 2 * (F (2-1))))
59 |
60 | 3 * 2 * F (2-1)
61 |
62 | 3 * 2 * rec fact -> fun x -> if x <= 1 then 1 else x * (fact (x-1)) (1)
63 |
64 | 3 * 2 * (fun x -> if x <= 1 then 1 else x * (fact (x-1)) (1) {F/fact})
65 |
66 | 3 * 2 * (fun x -> if x <= 1 then 1 else x * (F (x-1)) (1))
67 |
68 | 3 * 2 * (if 1 <= 1 then 1 else 1 * (fact (1-1))
69 |
70 | 3 * 2 * (if true then 1 else 1 * (fact (1-1))
71 |
72 | 3 * 2 * 1
73 |
74 | 6
75 |
76 | ('a*'b neg) or' -> ('b->'a)
77 |
78 |
79 | {} 110 + 3*1000 => 3110 op rule
80 | because {} 110 => 110 const rule
81 | and {} 3*1000 => 3000 op rule
82 | because {}3=> 3 const rule
83 | and {}1000=>1000 const rule
84 | and 3*1000 = 3000
85 | and 110 + 3000 = 3110
86 |
87 | {} if 2+3<4 then 1+1 else 2+2 => 4 if rule
88 | because {}2+3<4 => false op rule
89 | because {} 2+3 => 5 op rule
90 | because {} 2 => 2 const
91 | and {} 3 => 3 const
92 | and 2+3=5
93 | and {}4=> 4 const
94 | and 5<4 => false
95 | and {}2+2 => 4 op
96 | because {}2 => 2 const
97 | and {}2 => 2 const
98 | and 2++2 = 4
99 |
100 | {} let x=0 in x + (let x=1 in x) => 1 let rule
101 | because {}0=> 0 const rule
102 | and {(x,0)} (x + (let x=1 in x))=> 1 op +
103 | because {(x,0)} x => 0 var rule
104 | and {(x,0)} (let x = 1 in x) => 1 let rule
105 | because {x,0} 1=>1 const
106 | and {(x,1)} x => 1 var rule
107 | and 0 + 1 = 1
108 |
109 | {} match Left 2 with Left x-> x+1| Right x -> x-1 =>3 match rule
110 | because {}Left 2 => Left 2 left rule
111 | because 2=>2 const rule
112 | and {(x,2)} x+1 => 3 op +
113 | because x=>2 var rule
114 | and 1=>1 const rule
115 | and 2+1 = 3
116 |
117 | {} (fun x -> x+1) 2 => 3 application
118 | because {},fun x->x+1=> (|fun x -> x+1,{}|) closure
119 | and {}2 => 2 const
120 | and {(x,2)} x + 1 => 3 op +
121 | because x=>2 var
122 | and 1=>1 const
123 | and 1+2 = 3
124 |
125 | {} let f = fun x -> x+1 in f 2 => 3 let rule
126 | because {} fun x -> x+1 => (|fun x -> x+1|,{}) closure
127 | and {(f, fun x -> x+1)} f 2 => 3 application
128 | because {(f, fun x -> x+1)} f=> fun x -> x+1 var rule
129 | and {(f, fun x -> x+1)} 2=>2 const
130 | and {(x,2)} x + 1 => 3 op +
131 | because {(x,2)} x => 2 var
132 | and {(x,2)}1=>1 const
133 | and 2+1 = 3
134 |
135 | {} let x = 1 in let f = fun y -> x in let x = 2 in f 0 => 1 let rule
136 | because {}1=> 1 const
137 | and {(x,1)} let f = fun y -> x in let x = 2 in f 0 => 1 let rule
138 | because {(x,1)} fun y -> x => {fun y -> x, (x,1)} closure
139 | and {(x,1); (f, fun y -> x)} let x = 2 in f 0 => 1 let rule
140 | because {(x,1); (f, fun y -> x)} 2=>2 const
141 | and {(x,2); (f, closure)} f 0 => 1 application
142 | because f => {fun y -> x, (x,1)} var
143 | and {(x,2); (f, closure)} 0 =>0 const
144 | and {(x,1);(y,0)} x => 1 var rule
145 |
146 |
147 |
148 | *)
149 |
150 | type ('a,'b) or' = Left of 'a | Right of 'b
151 |
152 | let p_and_q_comm (p,q) = (q,p)
153 |
154 | let p_or_q_comm p_or_q = match p_or_q with
155 | | Left a -> Right a
156 | | Right b -> Left b
157 |
158 | type void = {nope : 'a .'a}
159 | type 'a neg = 'a -> void
160 | let explode (f:void) : 'b = f.nope
161 |
162 | let ex (p, (q:'a neg)) = explode (q p)
163 | let f x = fst x
164 |
--------------------------------------------------------------------------------
/tests/test9/prelimpract1.ml:
--------------------------------------------------------------------------------
1 | (* comments are exactly same as prelimpract. functions are completely different
2 |
3 | unit -> 'a
4 | True -> P
5 |
6 | ('a, ('b,'c))
7 | P and (Q and R)
8 |
9 | (('a*'b)or'*'c) or'
10 | (P or Q) or R
11 |
12 | void -> 'a
13 | False -> P
14 |
15 | ('a*'a neg) or'
16 | P \/ ~P
17 |
18 | 'a*'b or' -> 'b*'a or'
19 |
20 | ('a*'b neg) or' -> ('b->'a)
21 |
22 | ('a*'b)-> 'a
23 | (P/\Q) -> P
24 | f(1,2) -> substitution {(1,2)/x} snd ((fun x -> x,x) (fst x)) -> snd ((fun x -> x,x) (fst (1,2)))
25 | function application-> snd ((fun x -> x,x) (1))
26 | substituion -> snd ({1/x} x,x) -> snd (1,1)
27 | function app -> 1
28 |
29 | desugar
30 | let fact = rec fact -> fun x ->
31 | if x <= 1 then 1 else x * (fact (x - 1)) in
32 | fact 3
33 |
34 | step rec
35 | let fact =
36 | fun x ->
37 | if x <= 1 then 1 else x * (fact (x - 1)) {F/fact} in fact 3
38 |
39 | substitute
40 | let fact = fun x ->
41 | if x <= 1 then 1 else x * (F (x - 1)) in
42 | (fact) 3
43 |
44 | application
45 | if x <= 1 then 1 else x * (F (x - 1)) {3/x}
46 | -> if 3 <= 1 then 1 else 3 * (F (3 - 1))
47 |
48 | step bool
49 | if false then 1 else 3 * (F (3 - 1))
50 |
51 | 3 * (rec fact -> fun x -> if x <= 1 then 1 else x * (fact (x-1))) 2
52 |
53 | 3 * fun x -> if x <= 1 then 1 else x * (fact (x-1))) 2 {F/fact}
54 |
55 | 3 * fun x -> if x <= 1 then 1 else x * (F (x-1))) 2
56 |
57 | 3 * (if x <= 1 then 1 else x * (F (x-1))) {2/x})
58 |
59 | 3 * (if 2 <= 1 then 1 else 2 * (F (2-1))))
60 | 3 * (if false then 1 else 2 * (F (2-1))))
61 |
62 | 3 * 2 * F (2-1)
63 |
64 | 3 * 2 * rec fact -> fun x -> if x <= 1 then 1 else x * (fact (x-1)) (1)
65 |
66 | 3 * 2 * (fun x -> if x <= 1 then 1 else x * (fact (x-1)) (1) {F/fact})
67 |
68 | 3 * 2 * (fun x -> if x <= 1 then 1 else x * (F (x-1)) (1))
69 |
70 | 3 * 2 * (if 1 <= 1 then 1 else 1 * (fact (1-1))
71 |
72 | 3 * 2 * (if true then 1 else 1 * (fact (1-1))
73 |
74 | 3 * 2 * 1
75 |
76 | 6
77 |
78 | ('a*'b neg) or' -> ('b->'a)
79 |
80 |
81 | {} 110 + 3*1000 => 3110 op rule
82 | because {} 110 => 110 const rule
83 | and {} 3*1000 => 3000 op rule
84 | because {}3=> 3 const rule
85 | and {}1000=>1000 const rule
86 | and 3*1000 = 3000
87 | and 110 + 3000 = 3110
88 |
89 | {} if 2+3<4 then 1+1 else 2+2 => 4 if rule
90 | because {}2+3<4 => false op rule
91 | because {} 2+3 => 5 op rule
92 | because {} 2 => 2 const
93 | and {} 3 => 3 const
94 | and 2+3=5
95 | and {}4=> 4 const
96 | and 5<4 => false
97 | and {}2+2 => 4 op
98 | because {}2 => 2 const
99 | and {}2 => 2 const
100 | and 2++2 = 4
101 |
102 | {} let x=0 in x + (let x=1 in x) => 1 let rule
103 | because {}0=> 0 const rule
104 | and {(x,0)} (x + (let x=1 in x))=> 1 op +
105 | because {(x,0)} x => 0 var rule
106 | and {(x,0)} (let x = 1 in x) => 1 let rule
107 | because {x,0} 1=>1 const
108 | and {(x,1)} x => 1 var rule
109 | and 0 + 1 = 1
110 |
111 | {} match Left 2 with Left x-> x+1| Right x -> x-1 =>3 match rule
112 | because {}Left 2 => Left 2 left rule
113 | because 2=>2 const rule
114 | and {(x,2)} x+1 => 3 op +
115 | because x=>2 var rule
116 | and 1=>1 const rule
117 | and 2+1 = 3
118 |
119 | {} (fun x -> x+1) 2 => 3 application
120 | because {},fun x->x+1=> (|fun x -> x+1,{}|) closure
121 | and {}2 => 2 const
122 | and {(x,2)} x + 1 => 3 op +
123 | because x=>2 var
124 | and 1=>1 const
125 | and 1+2 = 3
126 |
127 | {} let f = fun x -> x+1 in f 2 => 3 let rule
128 | because {} fun x -> x+1 => (|fun x -> x+1|,{}) closure
129 | and {(f, fun x -> x+1)} f 2 => 3 application
130 | because {(f, fun x -> x+1)} f=> fun x -> x+1 var rule
131 | and {(f, fun x -> x+1)} 2=>2 const
132 | and {(x,2)} x + 1 => 3 op +
133 | because {(x,2)} x => 2 var
134 | and {(x,2)}1=>1 const
135 | and 2+1 = 3
136 |
137 | {} let x = 1 in let f = fun y -> x in let x = 2 in f 0 => 1 let rule
138 | because {}1=> 1 const
139 | and {(x,1)} let f = fun y -> x in let x = 2 in f 0 => 1 let rule
140 | because {(x,1)} fun y -> x => {fun y -> x, (x,1)} closure
141 | and {(x,1); (f, fun y -> x)} let x = 2 in f 0 => 1 let rule
142 | because {(x,1); (f, fun y -> x)} 2=>2 const
143 | and {(x,2); (f, closure)} f 0 => 1 application
144 | because f => {fun y -> x, (x,1)} var
145 | and {(x,2); (f, closure)} 0 =>0 const
146 | and {(x,1);(y,0)} x => 1 var rule
147 |
148 |
149 |
150 | *)
151 |
152 | type student = {
153 | name: string;
154 | mutable gpa: float;
155 | }
156 |
157 | let student1 = {
158 | name = "Alice";
159 | gpa = 3.7;
160 | }
161 |
162 | type vector = float array
163 |
164 | let norm vec= sqrt (Array.fold_left (+.) 0. (Array.map (fun x -> x *. x) vec))
165 |
166 | let normalize vec =
167 | for x = 0 to Array.length vec -1
168 | do vec.(x) <- vec.(x) * 2 done
169 |
--------------------------------------------------------------------------------
/tests/test9/prelimpract2.ml:
--------------------------------------------------------------------------------
1 | (* all comments gone. Constructor names/ type variables changed.
2 | *)
3 |
4 | type ('z,'f) or' = Blah of 'z | Bloo of 'f
5 |
6 | let p_and_q_comm (p,q) = (q,p)
7 |
8 | let p_or_q_comm p_or_q = match p_or_q with
9 | | Blah a -> Bloo a
10 | | Bloo b -> Blah b
11 |
12 | type hi = {hehe : 'm .'m}
13 | type 'va neg = 'va -> hi
14 | let explode (f:hi) : 'b = f.hehe
15 |
16 | let ex (p, (q:'a neg)) = explode (q p)
17 | let f x = fst x
18 |
--------------------------------------------------------------------------------
/winnowing.ml:
--------------------------------------------------------------------------------
1 | module type BoundedQueueWithCounter = sig
2 | type 'a t
3 | val empty : int -> 'a t
4 | val create : int -> 'a -> 'a t
5 | val is_empty : 'a t -> bool
6 | val is_full : 'a t -> bool
7 | val size : 'a t -> int
8 | val enqueue : 'a -> 'a t -> 'a t
9 | val dequeue : 'a t -> 'a option * 'a t
10 | val count : 'a t -> int
11 | val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
12 | val to_list: 'a t -> 'a list
13 | end
14 |
15 | module Window : BoundedQueueWithCounter = struct
16 |
17 | type 'a t = { data: ('a list) * ('a list) ; maxsize: int ; size: int ; count: int}
18 |
19 | let empty n =
20 | if n = 0 then failwith "Cannot create queue of size 0!"
21 | else
22 | { data = ([],[]); maxsize = n; size = n; count = 0}
23 |
24 | let create n i =
25 | let rec gen l acc i =
26 | if l = 0 then acc else gen (l - 1) (i::acc) i
27 | in
28 | if n = 0 then failwith "Cannot create queue of size 0!"
29 | else
30 | let initdata = gen n [] i in
31 | { data = (initdata,[]); maxsize = n; size = n; count = 0}
32 |
33 | let is_empty q = (q.size = 0)
34 |
35 | let is_full q = (q.size = q.maxsize)
36 |
37 | let size q = q.size
38 |
39 | let rec dequeue q =
40 | match q.data with
41 | |h::t, b -> (Some h, {q with data = (t,b) ; size = q.size - 1})
42 | |[],[] -> (None, q)
43 | |[], h::t -> dequeue {q with data = (List.rev (h::t),[])}
44 |
45 | let rec enqueue item q =
46 | if is_full q then dequeue q |> snd |> enqueue item
47 | else
48 | match q.data with
49 | |f,b -> {q with data = (f,item::b); size = q.size + 1 ;count = q.count + 1}
50 |
51 | let count q = q.count
52 |
53 | let to_list q = (fst q.data)@(snd q.data |> List.rev)
54 |
55 | let fold f init q =
56 | List.fold_left f init (to_list q)
57 |
58 |
59 | end
60 |
61 | (* h = hashes list, w = window size *)
62 | let winnow w h =
63 | (* calculates the global position of the i-th hash in the window
64 | example: if [global_pos 5 W] = 100, then the 5th hash in W is the 100th
65 | hash that was processed by the winnowing algorithm. *)
66 | let global_pos i w =
67 | let c = Window.count w in
68 | let s = Window.size w in
69 | c - (s - 1 - i)
70 | in
71 | (* helper function *)
72 | let mincheck ((minval,minpos),count) x =
73 | if x <= minval then ((x, count), count + 1)
74 | else ((minval, minpos), count + 1)
75 | in
76 |
77 | (* At the end of each iteration, min is a tuple of the (value,position)
78 | of the rightmost minimal hash in the
79 | current window. hash x is only added to the fingerprint [res] the
80 | first time an instance of x is selected as the
81 | rightmost minimal hash of a window.
82 |
83 | hashes - the complete list of hashes
84 | window - window object
85 | acc - list of selected hash x position pairs
86 | n - counter for position of hashes
87 | (v,p) - value and position of minimum hash
88 | *)
89 | let rec winnowhelper hashes window acc n (v,p) =
90 | if n = List.length hashes then acc
91 | else begin
92 | let nexthash = List.nth hashes n in
93 | let new_window = Window.enqueue nexthash window in
94 | if nexthash <= v then
95 | let new_acc = (nexthash, global_pos (Window.size new_window - 1)
96 | new_window)::acc in
97 | winnowhelper hashes new_window new_acc (n+1) (nexthash,
98 | Window.size new_window - 1)
99 | else begin
100 | let p = p - 1 in
101 | if p < 0 then
102 | let new_min = fst (Window.fold mincheck ((max_int,0),0) new_window) in
103 | let new_acc = (fst new_min, global_pos (snd new_min) new_window)::acc in
104 | winnowhelper hashes new_window new_acc (n+1) new_min
105 | else
106 | winnowhelper hashes new_window acc (n+1) (v,p)
107 | end
108 | end
109 | in
110 | let window = Window.create w max_int in
111 | let res = winnowhelper h window [] 0 (max_int, 0) in res
112 |
--------------------------------------------------------------------------------
/winnowing.mli:
--------------------------------------------------------------------------------
1 | (* custom data structure representing a bounded queue which also keeps track
2 | * of its current size
3 | * and the total number of times enqueue has been called *)
4 | module type BoundedQueueWithCounter = sig
5 | type 'a t
6 |
7 | (* [empty n] returns an empty queue with capacity n *)
8 | val empty : int -> 'a t
9 |
10 | (* [create n i] returns a full queue with capacity n,
11 | * with every element initialized to i *)
12 | val create : int -> 'a -> 'a t
13 |
14 | (* [is_empty q] checks if q is empty and returns a boolean *)
15 | val is_empty : 'a t -> bool
16 |
17 | (* [is_full q] checks if q is full and returns a boolean *)
18 | val is_full : 'a t -> bool
19 |
20 | (* [size q] returns the number of elements currently in q *)
21 | val size : 'a t -> int
22 |
23 | (* [enqueue v q] returns a queue that has the contents of q with the
24 | * value v enqueued at the tail
25 | * if q is full, then the first element will be dequeued before v is
26 | * enqueued *)
27 | val enqueue : 'a -> 'a t -> 'a t
28 |
29 | (* [dequeue q] dequeues the first element (head) of q and returns a tuple
30 | * of the element and the updated queue the dequeued element is stored as
31 | * an option
32 | * if q is empty then the first value of the tuple will be None*)
33 | val dequeue : 'a t -> 'a option * 'a t
34 |
35 | (* [count q] returns the number of elements that have been enqueued
36 | * (including ones that are no longer in the queue) *)
37 | val count : 'a t -> int
38 |
39 | (* [fold f init q] folds [f] over a list of the elements in [q] from
40 | * the head to the tail with initial value [init] *)
41 | val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
42 |
43 | (* [to_list q] returns a list representation of the elements of q in order,
44 | * with the first element being the head and the last element being the tail
45 | *)
46 | val to_list: 'a t -> 'a list
47 | end
48 |
49 | (* an implementation of BoundedQueueWithCounter using a record type and using
50 | * two lists to store data. The first list stores the front of the queue,
51 | * the second list stores the back of the queue in reverse order.
52 | *
53 | * AF: the elements of the queue is stored in the [data] field, the current
54 | * size stored in [size], the maximum size stored in [maxsize], and number of
55 | * times an element has been enqueued stored in [count]
56 | *
57 | * RI: [size] <= [maxsize], [size],[maxsize],[count] cannot be negative, [size]
58 | * is sum of the lengths of both lists in [data], the head of the first list
59 | * in data is the head of the queue, the head of the second list is the tail
60 | * of the queue
61 | *)
62 | module Window : BoundedQueueWithCounter
63 |
64 | (* [winnow w h] applies the winnowing algorithm for a list of hashes [h] with
65 | * window size [w] returns: a list of (v,p) tuples where v is a hash value and
66 | * p is the position in the original input the (v,p) list is not guaranteed to
67 | * be in any particular order requires: [w] is a positive integer
68 | *)
69 | val winnow: int -> int list -> (int * int) list
70 |
--------------------------------------------------------------------------------