mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
Merge branch 'woojin' into 'main'
Add assignment 8, 11, 12 See merge request kaist-cp-class/cs220-private!12
This commit is contained in:
611
Cargo.lock
generated
611
Cargo.lock
generated
@@ -3,10 +3,68 @@
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.66"
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
@@ -16,24 +74,27 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.3"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.77"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -43,55 +104,65 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.29"
|
||||
version = "4.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
|
||||
checksum = "b417ae4361bca3f5de378294fc7472d3c4ed86a5ef9f49e93ae722f432aae8d2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"is-terminal",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c90dc0f0e42c64bff177ca9d7be6fcc9ddb0f26a6e062174a61c84dd6c644d4"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.0.21"
|
||||
version = "4.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
|
||||
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.5"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
|
||||
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.6"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
@@ -99,9 +170,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
@@ -110,9 +181,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.13"
|
||||
version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
@@ -123,9 +194,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.14"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@@ -145,21 +216,26 @@ name = "cs220"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx",
|
||||
"clap",
|
||||
"etrace",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"ndarray",
|
||||
"ndarray-rand",
|
||||
"ntest",
|
||||
"num-traits",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"rayon",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.6"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
@@ -167,19 +243,25 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -200,56 +282,60 @@ checksum = "f17311e68ea07046ee809b8513f6c259518bc10173681d98c21f8c3926f56f40"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.1"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"io-lifetimes",
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
@@ -271,25 +357,71 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.138"
|
||||
version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.3"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.7.1"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray-rand"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65608f937acc725f5b164dcf40f4f0bc5d67dc268ab8a649d3002606718c4588"
|
||||
dependencies = [
|
||||
"ndarray",
|
||||
"rand",
|
||||
"rand_distr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntest"
|
||||
version = "0.9.0"
|
||||
@@ -308,7 +440,7 @@ checksum = "be7d33be719c6f4d09e64e27c1ef4e73485dc4cc1f4d22201f89860a7fe22e22"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -320,36 +452,59 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.14.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.19",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.5.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0"
|
||||
checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
@@ -357,9 +512,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.5.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344"
|
||||
checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@@ -367,97 +522,123 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.5.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c"
|
||||
checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.5.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20"
|
||||
checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha1",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.2.1"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
|
||||
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
version = "1.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.0"
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_distr"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
@@ -467,13 +648,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.4"
|
||||
version = "0.38.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
|
||||
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
@@ -481,21 +661,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.149"
|
||||
name = "sha2"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
|
||||
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
@@ -510,9 +684,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.105"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -520,60 +694,76 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
name = "syn"
|
||||
version = "2.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
name = "toml_datetime"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.19.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
|
||||
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
@@ -582,41 +772,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27f51fb4c64f8b770a823c043c7fad036323e1c48f55287b7bbb7987b2fcdf3b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@@ -629,42 +803,51 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
checksum = "fde1bb55ae4ce76a597a8566d82c57432bc69c039449d61572a7a353da28f68c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
checksum = "1513e8d48365a78adad7322fd6b5e4c4e99d92a69db8df2d435b25b1f1f286d4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
checksum = "60587c0265d2b842298f5858e1a5d79d146f9ee0c37be5782e92a6eb5e1d7a83"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
checksum = "224fe0e0ffff5d2ea6a29f82026c8f43870038a0ffc247aa95a52b47df381ac4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
checksum = "62fc52a0f50a088de499712cbc012df7ebd94e2d6eb948435449d76a6287e7ad"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
checksum = "2093925509d91ea3d69bcd20238f4c2ecdb1a29d3c281d026a09705d0dd35f3d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
checksum = "b6ade45bc8bf02ae2aa34a9d54ba660a1a58204da34ba793c00d83ca3730b5f1"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d09770118a7eb1ccaf4a594a221334119a44a814fcb0d31c5b85e83e97227a97"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
@@ -14,4 +14,9 @@ lazy_static = "1.4.0"
|
||||
pest = "2.5.1"
|
||||
pest_derive = "2.5.1"
|
||||
rayon = "1.6.0"
|
||||
thiserror = "1.0"
|
||||
ntest = "0.9.0"
|
||||
approx = "0.5.1"
|
||||
num-traits = "0.2"
|
||||
ndarray = "0.15.0"
|
||||
ndarray-rand = "0.14.0"
|
||||
|
||||
@@ -24,7 +24,7 @@ run_linters || exit 1
|
||||
for RUNNER in "${RUNNERS[@]}"; do
|
||||
echo "Running with $RUNNER..."
|
||||
|
||||
TESTS=("--lib assignment11_grade")
|
||||
TESTS=("--lib assignment11")
|
||||
if [ $(run_tests) -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -24,7 +24,7 @@ run_linters || exit 1
|
||||
for RUNNER in "${RUNNERS[@]}"; do
|
||||
echo "Running with $RUNNER..."
|
||||
|
||||
TESTS=("--lib assignment12_grade")
|
||||
TESTS=("--lib assignment11")
|
||||
if [ $(run_tests) -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -5,22 +5,45 @@
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
|
||||
//! See `assignment08_grade.rs` and `/scripts/grade-08.sh` for the test script.
|
||||
|
||||
/// Returns an anonymous function that applies the given function `f` for `n` times.
|
||||
/// Repeat
|
||||
///
|
||||
/// Returns an anonymous function that applies the given function `f` for `n` times.
|
||||
/// For instance, `repeat(3, f)(x)` roughly translates to `f(f(f(x)))`.
|
||||
///
|
||||
/// Refer `test_repeat` in `assignment08_grade.rs` for detailed examples.
|
||||
pub fn repeat<T, F: FnMut(T) -> T>(n: usize, mut f: F) -> impl FnMut(T) -> T {
|
||||
todo!();
|
||||
f // This line has been added to prevent compile error. You can erase this line.
|
||||
}
|
||||
|
||||
/// Funny Map
|
||||
///
|
||||
/// Applies the given function `f` for `i` times for the `i`-th element of the given vector.
|
||||
///
|
||||
/// For instance, `funny_map(f, [v0, v1, v2, v3])` roughly translates to `[v0, f(v1), f(f(v2)), f(f(f(v3)))]`.
|
||||
///
|
||||
/// Refer `test_funny_map` in `assignment08_grade.rs` for detailed examples.
|
||||
pub fn funny_map<T, F: Fn(T) -> T>(f: F, vs: Vec<T>) -> Vec<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Count Repeat
|
||||
///
|
||||
/// Returns the number of the elements of the set
|
||||
/// {x, f(x), f(f(x)), f(f(f(x))), ...}.
|
||||
/// You may assume that the answer is finite and small enough.
|
||||
///
|
||||
/// Refer `test_count_repeat` in `assignment08_grade.rs` for detailed examples.
|
||||
pub fn count_repeat<T, F: Fn(T) -> T>(f: F, x: T) -> usize
|
||||
where
|
||||
T: PartialEq + Copy,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Either `T1`, or `T2`.
|
||||
///
|
||||
/// Fill out `map` method for this type.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Either2<T1, T2> {
|
||||
/// Case 1.
|
||||
@@ -39,6 +62,8 @@ impl<T1, T2> Either2<T1, T2> {
|
||||
/// Maps the inner value.
|
||||
///
|
||||
/// If the inner value is case 1, apply `f1`, and if it is case 2, apply `f2`.
|
||||
///
|
||||
/// Refer `test_either2_map` in `assignment08_grade.rs` for detailed examples.
|
||||
pub fn map<U1, U2, F1, F2>(self, f1: F1, f2: F2) -> Either2<U1, U2>
|
||||
where
|
||||
F1: FnOnce(T1) -> U1,
|
||||
|
||||
@@ -27,4 +27,21 @@ mod test {
|
||||
let u2 = Either2::<u32, f32>::Case2 { inner: 43.0 };
|
||||
assert_eq!(u2, v2.map(|i| i + 1, |f| f + 1.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_count_repeat() {
|
||||
let inc_mod_100 = |x| (x + 1) % 100;
|
||||
assert_eq!(count_repeat(inc_mod_100, 10), 100);
|
||||
assert_eq!(count_repeat(inc_mod_100, 12345), 101);
|
||||
|
||||
let p_lookup = |n| vec![1, 0, 2, 4, 5, 6, 7, 3][n];
|
||||
assert_eq!(count_repeat(p_lookup, 0), 2);
|
||||
assert_eq!(count_repeat(p_lookup, 1), 2);
|
||||
assert_eq!(count_repeat(p_lookup, 2), 1);
|
||||
assert_eq!(count_repeat(p_lookup, 3), 5);
|
||||
assert_eq!(count_repeat(p_lookup, 4), 5);
|
||||
assert_eq!(count_repeat(p_lookup, 5), 5);
|
||||
assert_eq!(count_repeat(p_lookup, 6), 5);
|
||||
assert_eq!(count_repeat(p_lookup, 7), 5);
|
||||
}
|
||||
}
|
||||
|
||||
202
src/assignments/assignment11/bst.rs
Normal file
202
src/assignments/assignment11/bst.rs
Normal file
@@ -0,0 +1,202 @@
|
||||
//! Binary Search Tree
|
||||
//!
|
||||
//! Refer `bst_grade.rs` for test cases.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
/// Node struct of tree
|
||||
#[derive(Debug, Clone)]
|
||||
struct Node<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
value: T,
|
||||
parent: Option<Weak<RefCell<Node<T>>>>,
|
||||
left: Option<Rc<RefCell<Node<T>>>>,
|
||||
right: Option<Rc<RefCell<Node<T>>>>,
|
||||
}
|
||||
|
||||
impl<T> Node<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
fn new(value: T) -> Rc<RefCell<Node<T>>> {
|
||||
Rc::new(RefCell::new(Node {
|
||||
value,
|
||||
parent: None,
|
||||
left: None,
|
||||
right: None,
|
||||
}))
|
||||
}
|
||||
|
||||
fn with_parent(value: T, parent: Weak<RefCell<Node<T>>>) -> Rc<RefCell<Node<T>>> {
|
||||
Rc::new(RefCell::new(Node {
|
||||
value,
|
||||
parent: Some(parent),
|
||||
left: None,
|
||||
right: None,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Minimum node starting from cursor
|
||||
fn min_node(mut cursor: Rc<RefCell<Node<T>>>) -> Rc<RefCell<Node<T>>> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Upgraded parent node.
|
||||
/// `None` if the node has no parent.
|
||||
fn parent(&self) -> Option<Rc<RefCell<Node<T>>>> {
|
||||
self.parent.as_ref().and_then(|p| p.upgrade())
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary Search Tree
|
||||
#[derive(Debug)]
|
||||
pub struct Tree<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
root: Option<Rc<RefCell<Node<T>>>>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<T: Ord> Default for Tree<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Tree<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
/// New tree
|
||||
pub fn new() -> Tree<T> {
|
||||
Tree { root: None, len: 0 }
|
||||
}
|
||||
|
||||
/// Length of the tree
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
/// Check if the tree is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
|
||||
/// Check if the tree contains the value.
|
||||
pub fn contains(&self, value: &T) -> bool {
|
||||
if let Some(mut cursor) = self.root.clone() {
|
||||
todo!();
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert the value into the tree.
|
||||
/// If there was no equal value in the tree, it returns `true`.
|
||||
/// Otherwise, it returns `false`.
|
||||
pub fn insert(&mut self, value: T) -> bool {
|
||||
self.len += 1;
|
||||
if let Some(mut cursor) = self.root.clone() {
|
||||
todo!();
|
||||
} else {
|
||||
self.root = Some(Node::new(value));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the node from the tree.
|
||||
/// Returns the value of the removed node.
|
||||
fn remove_node(&mut self, mut node: Rc<RefCell<Node<T>>>) -> T {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Remove the value from the tree.
|
||||
/// If there is an equal value in the tree, it returns `true`.
|
||||
/// Otherwise, it returns `false`.
|
||||
pub fn remove(&mut self, value: &T) -> Option<T> {
|
||||
let res = if let Some(root) = self.root.clone() {
|
||||
let mut cursor = root;
|
||||
|
||||
loop {
|
||||
let mut cursor_ref = cursor.deref().borrow_mut();
|
||||
let child = match value.cmp(&cursor_ref.value) {
|
||||
Ordering::Less => cursor_ref.left.clone(),
|
||||
Ordering::Greater => cursor_ref.right.clone(),
|
||||
Ordering::Equal => {
|
||||
drop(cursor_ref);
|
||||
break Some(self.remove_node(cursor));
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(child) = child {
|
||||
drop(cursor_ref);
|
||||
cursor = child;
|
||||
} else {
|
||||
break None;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.len -= res.is_some() as usize;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Tree<T>
|
||||
where
|
||||
T: Ord + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Tree {
|
||||
root: self.root.clone(),
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// IntoIterator for Tree
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
tree: Tree<T>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for Tree<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let len = self.len;
|
||||
IntoIter { tree: self, len }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Iterator for IntoIter<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
53
src/assignments/assignment11/bst_grade.rs
Normal file
53
src/assignments/assignment11/bst_grade.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
//! Test cases for assignment11/bst.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_bst {
|
||||
use super::super::bst::*;
|
||||
|
||||
#[test]
|
||||
fn bst_insert_test() {
|
||||
let mut tree = Tree::new();
|
||||
|
||||
let _ = tree.insert(1);
|
||||
let _ = tree.insert(5);
|
||||
let _ = tree.insert(3);
|
||||
let _ = tree.insert(7);
|
||||
|
||||
assert_eq!(tree.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bst_remove_test() {
|
||||
let mut tree = Tree::new();
|
||||
|
||||
let _ = tree.insert(1);
|
||||
let _ = tree.insert(5);
|
||||
let _ = tree.insert(3);
|
||||
let _ = tree.insert(7);
|
||||
let _ = tree.remove(&7);
|
||||
|
||||
assert_eq!(tree.into_iter().collect::<Vec<_>>(), vec![1, 3, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bst_complex_test() {
|
||||
let mut tree = Tree::new();
|
||||
|
||||
let _ = tree.insert(1);
|
||||
let _ = tree.insert(5);
|
||||
let _ = tree.insert(3);
|
||||
let _ = tree.insert(7);
|
||||
let _ = tree.remove(&7);
|
||||
let _ = tree.insert(7);
|
||||
let _ = tree.insert(6);
|
||||
let _ = tree.insert(8);
|
||||
let _ = tree.remove(&5);
|
||||
let _ = tree.remove(&1);
|
||||
let _ = tree.remove(&3);
|
||||
let _ = tree.remove(&7);
|
||||
let _ = tree.remove(&6);
|
||||
let _ = tree.remove(&8);
|
||||
|
||||
assert_eq!(tree.into_iter().collect::<Vec<_>>(), vec![]);
|
||||
}
|
||||
}
|
||||
101
src/assignments/assignment11/doubly_linked_list.rs
Normal file
101
src/assignments/assignment11/doubly_linked_list.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
//! Doubly Linked List.
|
||||
//!
|
||||
//! Refer `doubly_linked_list_grade.rs` for test cases.
|
||||
|
||||
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||
|
||||
type Link<T> = Option<Rc<RefCell<Node<T>>>>;
|
||||
|
||||
/// Node of a doubly-linked list.
|
||||
#[derive(Debug)]
|
||||
pub struct Node<T: Debug + Clone> {
|
||||
/// Value of current node.
|
||||
value: RefCell<T>,
|
||||
|
||||
/// Pointer to the next node. If it is `None`, there is no next node.
|
||||
next: Link<T>,
|
||||
|
||||
/// Pointer to the previous node. If it is `None`, there is no previous node.
|
||||
prev: Link<T>,
|
||||
}
|
||||
|
||||
impl<T: Debug + Clone> Node<T> {
|
||||
/// Creates a new node.
|
||||
fn new(value: T) -> Self {
|
||||
Self {
|
||||
value: RefCell::new(value),
|
||||
next: None,
|
||||
prev: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch the value contained in node
|
||||
pub fn get(&self) -> T {
|
||||
self.value.borrow().clone()
|
||||
}
|
||||
|
||||
/// Replace the data contained in the node
|
||||
pub fn replace(&self, new_value: T) -> T {
|
||||
self.value.replace(new_value)
|
||||
}
|
||||
|
||||
/// Fetch previous node
|
||||
pub fn prev(&self) -> Link<T> {
|
||||
self.prev.clone()
|
||||
}
|
||||
|
||||
/// Fetch next node
|
||||
pub fn next(&self) -> Link<T> {
|
||||
self.next.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// A doubly-linked list.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct DoublyLinkedList<T: Debug + Clone> {
|
||||
/// Head node of the list. If it is `None`, the list is empty.
|
||||
head: Link<T>,
|
||||
|
||||
/// Tail node of the list. If it is `None`, the list is empty.
|
||||
tail: Link<T>,
|
||||
}
|
||||
|
||||
impl<T: Debug + Clone> DoublyLinkedList<T> {
|
||||
/// Creates a new list.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
head: None,
|
||||
tail: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds the given node to the front of the list.
|
||||
pub fn push_front(&mut self, value: T) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Adds the given node to the back of the list.
|
||||
pub fn push_back(&mut self, value: T) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes and returns the node at the front of the list.
|
||||
pub fn pop_front(&mut self) -> Option<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes and returns the node at the back of the list.
|
||||
pub fn pop_back(&mut self) -> Option<T> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug + Clone> Drop for DoublyLinkedList<T> {
|
||||
fn drop(&mut self) {
|
||||
while let Some(node) = self.head.take() {
|
||||
let _ = node.borrow_mut().prev.take();
|
||||
self.head = node.borrow_mut().next.take();
|
||||
}
|
||||
let _unused = self.tail.take();
|
||||
}
|
||||
}
|
||||
43
src/assignments/assignment11/doubly_linked_list_grade.rs
Normal file
43
src/assignments/assignment11/doubly_linked_list_grade.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
//! Test cases for assignment11/doubly_linked_list.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_doubly_linked_list {
|
||||
use super::super::doubly_linked_list::*;
|
||||
|
||||
#[test]
|
||||
fn test_works() {
|
||||
let mut list = DoublyLinkedList::new();
|
||||
|
||||
list.push_back(3);
|
||||
list.push_back(4);
|
||||
assert_eq!(list.pop_front(), Some(3));
|
||||
|
||||
list.push_front(5);
|
||||
assert_eq!(list.pop_back(), Some(4));
|
||||
assert_eq!(list.pop_back(), Some(5));
|
||||
assert_eq!(list.pop_back(), None);
|
||||
assert_eq!(list.pop_front(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_push_back() {
|
||||
let mut list = DoublyLinkedList::new();
|
||||
assert_eq!(list.pop_back(), None);
|
||||
|
||||
list.push_back(3);
|
||||
list.push_back(4);
|
||||
list.push_back(5);
|
||||
assert_eq!(list.pop_back(), Some(5));
|
||||
|
||||
list.push_back(6);
|
||||
list.push_back(7);
|
||||
assert_eq!(list.pop_back(), Some(7));
|
||||
assert_eq!(list.pop_back(), Some(6));
|
||||
assert_eq!(list.pop_back(), Some(4));
|
||||
assert_eq!(list.pop_back(), Some(3));
|
||||
|
||||
list.push_back(2);
|
||||
assert_eq!(list.pop_back(), Some(2));
|
||||
assert_eq!(list.pop_back(), None);
|
||||
}
|
||||
}
|
||||
93
src/assignments/assignment11/graph.rs
Normal file
93
src/assignments/assignment11/graph.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
//! A small graph library.
|
||||
//!
|
||||
//! A node has a i32 value and (directed) edges to other nodes. A node does not have multiple edges
|
||||
//! to the same node. Nodes are not associated with a particular domain, and users can freely
|
||||
//! create nodes however they like. However, after a node is created, it can be added to a
|
||||
//! `SubGraph`, which form a subgraph of the graph of all nodes. A node can be added to multiple
|
||||
//! subgraphs. `SubGraph` has a method to check if the it has a cycle.
|
||||
//!
|
||||
//! The goal of this assignment is to learn how to deal with inherently shared mutable data in
|
||||
//! Rust. Design the types and fill in the `todo!()`s in methods. There are several possible
|
||||
//! approaches to this problem and you may import anything from the std library accordingly.
|
||||
//!
|
||||
//! Refer `graph_grade.rs` for test cases.
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
enum VisitStatus {
|
||||
Unvisited,
|
||||
Visiting,
|
||||
Visited,
|
||||
}
|
||||
|
||||
/// Handle to a graph node.
|
||||
/// `NodeHandle` should implement `Clone`, which clones the handle without cloning the underlying
|
||||
/// node. That is, there can be multiple handles to the same node.
|
||||
/// The user can access the node through a handle if it does not violate Rust's aliasing rules.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NodeHandle;
|
||||
|
||||
/// Error type for graph operations.
|
||||
#[derive(Debug)]
|
||||
pub struct GraphError;
|
||||
|
||||
/// Subgraph
|
||||
#[derive(Debug)]
|
||||
pub struct SubGraph;
|
||||
|
||||
impl NodeHandle {
|
||||
/// Creates a node and returns the handle to it.
|
||||
pub fn new(value: i32) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Adds an edge to `to`.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`.
|
||||
/// Returns `Ok(true)` if the edge is successfully added.
|
||||
/// Returns `Ok(false)` if an edge to `to` already exits.
|
||||
pub fn add_edge(&self, to: NodeHandle) -> Result<bool, GraphError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes the edge to `to`.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`.
|
||||
/// Returns `Ok(true)` if the edge is successfully removed.
|
||||
/// Returns `Ok(false)` if an edge to `to` does not exist.
|
||||
pub fn remove_edge(&self, to: &NodeHandle) -> Result<bool, GraphError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes all edges.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`.
|
||||
pub fn clear_edges(&self) -> Result<(), GraphError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SubGraph {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SubGraph {
|
||||
/// Creates a new subgraph.
|
||||
pub fn new() -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Adds a node to the subgraph. Returns true iff the node is newly added.
|
||||
pub fn add_node(&mut self, node: NodeHandle) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Adds a node to the subgraph. Returns true iff the node is successfully removed.
|
||||
pub fn remove_node(&mut self, node: &NodeHandle) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns true iff the subgraph contains a cycle. Nodes that do not belong to this subgraph
|
||||
/// are ignored. See https://en.wikipedia.org/wiki/Cycle_(graph_theory) for an algorithm.
|
||||
pub fn detect_cycle(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
63
src/assignments/assignment11/graph_grade.rs
Normal file
63
src/assignments/assignment11/graph_grade.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
//! Test cases for assignment11/graph.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_graph {
|
||||
use super::super::graph::*;
|
||||
|
||||
#[test]
|
||||
fn test_graph() {
|
||||
let mut nodes = (0..6).map(NodeHandle::new).collect::<Vec<_>>();
|
||||
let edges = [
|
||||
(0, 1),
|
||||
(0, 3),
|
||||
(1, 4),
|
||||
(2, 4),
|
||||
(2, 5),
|
||||
(3, 1),
|
||||
(4, 3),
|
||||
(5, 5),
|
||||
];
|
||||
|
||||
for (from, to) in edges {
|
||||
assert!(nodes[from].add_edge(nodes[to].clone()).unwrap());
|
||||
}
|
||||
|
||||
let mut graph1 = SubGraph::new();
|
||||
for n in 0..6 {
|
||||
assert!(graph1.add_node(nodes[n].clone()));
|
||||
}
|
||||
assert!(graph1.detect_cycle());
|
||||
assert!(!graph1.add_node(nodes[0].clone()));
|
||||
|
||||
let mut graph2 = SubGraph::new();
|
||||
for n in [0, 1, 3] {
|
||||
assert!(graph2.add_node(nodes[n].clone()));
|
||||
}
|
||||
assert!(!graph2.detect_cycle());
|
||||
|
||||
assert!(graph2.add_node(nodes[4].clone()));
|
||||
assert!(graph2.detect_cycle());
|
||||
|
||||
assert!(nodes[4].remove_edge(&nodes[3]).unwrap());
|
||||
assert!(!graph2.detect_cycle());
|
||||
|
||||
let mut graph3 = SubGraph::new();
|
||||
for n in [0, 1, 2, 3] {
|
||||
assert!(graph3.add_node(nodes[n].clone()));
|
||||
}
|
||||
assert!(!graph3.detect_cycle());
|
||||
|
||||
let more_edges = [(1, 2), (2, 3)];
|
||||
for (from, to) in more_edges {
|
||||
assert!(nodes[from].add_edge(nodes[to].clone()).unwrap());
|
||||
}
|
||||
assert!(graph3.detect_cycle());
|
||||
|
||||
assert!(graph3.remove_node(&nodes[2]));
|
||||
assert!(!graph3.detect_cycle());
|
||||
|
||||
for n in nodes {
|
||||
n.clear_edges().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
//! Singly linked list.
|
||||
//!
|
||||
//! Consult <https://doc.rust-lang.org/book/ch15-01-box.html>.
|
||||
//! Hint: Consult <https://doc.rust-lang.org/book/ch15-01-box.html>.
|
||||
//!
|
||||
//! Refer `linked_list_grade.rs` for test cases.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
||||
27
src/assignments/assignment11/linked_list_grade.rs
Normal file
27
src/assignments/assignment11/linked_list_grade.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
//! Test cases for assignment11/linked_list.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_linked_list {
|
||||
use super::super::linked_list::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct V(usize);
|
||||
|
||||
#[test]
|
||||
fn test_linked_list() {
|
||||
let mut list = SinglyLinkedList::new();
|
||||
list.push_back(V(3));
|
||||
list.push_front(V(2));
|
||||
list.push_back(V(4));
|
||||
list.push_front(V(1));
|
||||
list.push_back(V(5));
|
||||
|
||||
assert_eq!(list.pop_front(), Some(V(1)));
|
||||
assert_eq!(list.pop_back(), Some(V(5)));
|
||||
assert_eq!(list.pop_front(), Some(V(2)));
|
||||
assert_eq!(list.pop_back(), Some(V(4)));
|
||||
assert_eq!(list.pop_front(), Some(V(3)));
|
||||
assert_eq!(list.pop_back(), None);
|
||||
assert_eq!(list.pop_front(), None);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
//! Mock storage.
|
||||
//!
|
||||
//! Consult <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html#a-use-case-for-interior-mutability-mock-objects>.
|
||||
//! Hint: Consult <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html#a-use-case-for-interior-mutability-mock-objects>.
|
||||
//!
|
||||
//! Refer `mock_storage_grade.rs` for test cases.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
31
src/assignments/assignment11/mock_storage_grade.rs
Normal file
31
src/assignments/assignment11/mock_storage_grade.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
//! Test cases for assignment11/mock_storage.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_mock_storage {
|
||||
use super::super::mock_storage::*;
|
||||
|
||||
#[test]
|
||||
fn test_mock_storage() {
|
||||
let mock_storage = MockStorage::new(100);
|
||||
|
||||
let uploader1 = FileUploader::new(&mock_storage);
|
||||
let uploader2 = FileUploader::new(&mock_storage);
|
||||
|
||||
let usage_analyzer = UsageAnalyzer::new(&mock_storage, 0.75);
|
||||
|
||||
assert!(uploader1.upload("file1.txt", 20).is_ok());
|
||||
assert!(usage_analyzer.is_usage_under_bound());
|
||||
|
||||
assert!(uploader2.upload("file2.txt", 30).is_ok());
|
||||
assert!(usage_analyzer.is_usage_under_bound());
|
||||
|
||||
assert!(uploader1.upload("file3.txt", 40).is_ok());
|
||||
assert!(!usage_analyzer.is_usage_under_bound());
|
||||
|
||||
assert_eq!(uploader2.upload("file4.txt", 50), Err(40));
|
||||
assert!(!usage_analyzer.is_usage_under_bound());
|
||||
|
||||
assert!(uploader1.upload("file3.txt", 10).is_ok());
|
||||
assert!(usage_analyzer.is_usage_under_bound());
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,16 @@
|
||||
//! See `assignment11_grade.rs` and `/scripts/grade-11.sh` for the test script.
|
||||
//! Run `/scripts/prepare-submissions.sh` and submit `/target/assignment11.zip` to <https://gg.kaist.ac.kr>.
|
||||
|
||||
pub mod bst;
|
||||
pub mod bst_grade;
|
||||
pub mod doubly_linked_list;
|
||||
pub mod doubly_linked_list_grade;
|
||||
pub mod graph;
|
||||
pub mod graph_grade;
|
||||
pub mod linked_list;
|
||||
pub mod mock_storage;
|
||||
pub mod mock_storage_grade;
|
||||
pub mod turing_machine;
|
||||
pub mod turing_machine_grade;
|
||||
pub mod tv_room;
|
||||
pub mod tv_room_grade;
|
||||
|
||||
139
src/assignments/assignment11/turing_machine.rs
Normal file
139
src/assignments/assignment11/turing_machine.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
//! Simple Turing machien emulator
|
||||
//!
|
||||
//! Simple One-head, One-tape turing machine
|
||||
//! See <https://en.wikipedia.org/wiki/Turing_machine> that describes what turing machine is.
|
||||
//! See `test_turing_machine` module in `assignment11_grade.rs` for examples.
|
||||
//!
|
||||
//! Goal: To be accustomed with `RefCell`, `HashMap`
|
||||
//!
|
||||
//! Refer `turing_machine.rs` for test cases.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Formatter};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Error type for Turing machine
|
||||
/// <https://google.github.io/comprehensive-rust/error-handling/deriving-error-enums.html>
|
||||
#[derive(Debug, Error, PartialEq, Eq)]
|
||||
pub enum TuringMachineError {
|
||||
/// Invalid movement
|
||||
/// You can't move left from the leftmost location
|
||||
/// or move right from the rightmost location.
|
||||
#[error("Invalid movement")]
|
||||
InvalidMovement,
|
||||
|
||||
/// Exceeded maximum steps
|
||||
#[error("Exceeded maximum steps")]
|
||||
ExceedMaxSteps,
|
||||
|
||||
/// Invalid state or value
|
||||
/// Occurs when you cannot find instruction for the current state and value
|
||||
#[error("Invalid state or value")]
|
||||
InvalidStateOrValue,
|
||||
}
|
||||
|
||||
/// Turing Machine implementation
|
||||
#[derive(Debug)]
|
||||
pub struct TuringMachine<TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
/// Number of steps taken by the Turing machine
|
||||
pub steps: RefCell<usize>,
|
||||
|
||||
/// Table of instructions for the Turing machine
|
||||
pub table: HashMap<(TMState, TMValue), (TMState, Move, TMValue)>,
|
||||
|
||||
/// Tape of the Turing machine. Finite length
|
||||
pub tape: Vec<RefCell<TMValue>>,
|
||||
}
|
||||
|
||||
/// Implementation of the movement instructions of the head of the tape.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Move {
|
||||
/// Move Left
|
||||
L,
|
||||
/// Move Right
|
||||
R,
|
||||
/// Don't move
|
||||
N,
|
||||
}
|
||||
|
||||
/// Cursor for Turing machine
|
||||
#[derive(Debug)]
|
||||
pub struct Cursor<'a, TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
// Turing mahcine
|
||||
tm: &'a TuringMachine<TMState, TMValue>,
|
||||
// Index of the tape
|
||||
index: usize,
|
||||
// Current state of the Turing machine
|
||||
state: TMState,
|
||||
}
|
||||
|
||||
impl<'a, TMState, TMValue> Cursor<'a, TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
/// Generate new cursor
|
||||
pub fn new(tm: &'a TuringMachine<TMState, TMValue>, state: TMState, index: usize) -> Self {
|
||||
Cursor { tm, index, state }
|
||||
}
|
||||
|
||||
/// Run the Turing machine until it halts (if it halts). Print every step of that.
|
||||
pub fn run(&mut self, max_step: usize) -> Result<(TMValue, usize), TuringMachineError> {
|
||||
let mut steps = self.tm.steps.borrow_mut();
|
||||
while self.state != TMState::default() {
|
||||
*steps += 1;
|
||||
if *steps > max_step {
|
||||
return Err(TuringMachineError::ExceedMaxSteps);
|
||||
}
|
||||
self.step()?;
|
||||
// println!("{}", self);
|
||||
}
|
||||
Ok((self.get(), *steps))
|
||||
}
|
||||
|
||||
/// Set tape value at the current index with `value`
|
||||
/// You may need this function for `mov` function
|
||||
fn set(&mut self, value: TMValue) -> TMValue {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Step the Turing machine
|
||||
/// Look at the `run` function to see how this function is used.
|
||||
fn step(&mut self) -> Result<(), TuringMachineError> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Move the cursor while setting the value of the current index
|
||||
fn mov(&mut self, new_value: TMValue, movement: &Move) -> Result<(), TuringMachineError> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Get the value of the current index
|
||||
/// Look at the `run` function to see how this function is used.
|
||||
fn get(&self) -> TMValue {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
impl<TMState, TMValue> TuringMachine<TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
/// Generate new Turing machine
|
||||
pub fn new(
|
||||
table: HashMap<(TMState, TMValue), (TMState, Move, TMValue)>,
|
||||
tape: Vec<RefCell<TMValue>>,
|
||||
) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
309
src/assignments/assignment11/turing_machine_grade.rs
Normal file
309
src/assignments/assignment11/turing_machine_grade.rs
Normal file
@@ -0,0 +1,309 @@
|
||||
//! Test cases for assignment11/turing_machine.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_turing_machine {
|
||||
use super::super::turing_machine::*;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_movement() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![
|
||||
TMValue::One,
|
||||
TMValue::Zero,
|
||||
TMValue::One,
|
||||
TMValue::One,
|
||||
TMValue::One,
|
||||
TMValue::Zero,
|
||||
TMValue::One,
|
||||
]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Zero),
|
||||
(TMState::B, Move::R, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::A, TMValue::One),
|
||||
(TMState::B, Move::L, TMValue::Zero),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Zero),
|
||||
(TMState::A, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::One),
|
||||
(TMState::A, Move::R, TMValue::Zero),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
assert_eq!(result, Err(TuringMachineError::InvalidMovement));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_15_fail_move() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Zero; 10]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Zero),
|
||||
(TMState::B, Move::R, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::A, TMValue::One),
|
||||
(TMState::B, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Zero),
|
||||
(TMState::A, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::One),
|
||||
(TMState::Halt, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
assert_eq!(result, Err(TuringMachineError::InvalidMovement));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_15_pass() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Zero; 10]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Zero),
|
||||
(TMState::B, Move::R, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::A, TMValue::One),
|
||||
(TMState::B, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Zero),
|
||||
(TMState::A, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::One),
|
||||
(TMState::Halt, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 2);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
for (idx, val) in tm.tape.iter().enumerate() {
|
||||
if idx < 4 {
|
||||
assert_eq!(*val.borrow(), TMValue::One);
|
||||
} else {
|
||||
assert_eq!(*val.borrow(), TMValue::Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_zero_ones_fail_step() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Empty
|
||||
Empty,
|
||||
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Empty; 100]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Empty),
|
||||
(TMState::B, Move::R, TMValue::Zero),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Empty),
|
||||
(TMState::A, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(10);
|
||||
assert_eq!(result, Err(TuringMachineError::ExceedMaxSteps));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_zero_ones() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Empty
|
||||
Empty,
|
||||
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Empty; 100]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Empty),
|
||||
(TMState::B, Move::R, TMValue::Zero),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Empty),
|
||||
(TMState::A, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
assert_eq!(result, Err(TuringMachineError::InvalidMovement));
|
||||
for (idx, val) in tm.tape.iter().enumerate() {
|
||||
if idx % 2 == 0 {
|
||||
assert_eq!(*val.borrow(), TMValue::Zero);
|
||||
} else {
|
||||
assert_eq!(*val.borrow(), TMValue::One);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
//! Consult the following documentations:
|
||||
//! - <https://doc.rust-lang.org/book/ch15-04-rc.html#rct-the-reference-counted-smart-pointer>
|
||||
//! - <https://doc.rust-lang.org/book/ch15-05-interior-mutability.html#having-multiple-owners-of-mutable-data-by-combining-rct-and-refcellt>
|
||||
//!
|
||||
//! Refer `tv_room_grade.rs` for test cases.
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
|
||||
32
src/assignments/assignment11/tv_room_grade.rs
Normal file
32
src/assignments/assignment11/tv_room_grade.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
//! Test cases for assignment11/tv_room.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_tv_room {
|
||||
use super::super::tv_room::*;
|
||||
|
||||
#[test]
|
||||
fn test_tv_room() {
|
||||
let tv_room = TVRoom::new();
|
||||
assert!(!tv_room.is_opened());
|
||||
|
||||
// Turn on and add new guests.
|
||||
let manager = tv_room.open().unwrap();
|
||||
assert!(tv_room.is_opened());
|
||||
let guest1 = manager.new_guest();
|
||||
let guest2 = manager.new_guest();
|
||||
drop(manager);
|
||||
drop(guest1);
|
||||
assert!(tv_room.open().is_none());
|
||||
drop(guest2);
|
||||
assert!(!tv_room.is_opened());
|
||||
|
||||
// Turn on and add new guests.
|
||||
let manager = tv_room.open().unwrap();
|
||||
assert!(tv_room.is_opened());
|
||||
let guest3 = manager.new_guest();
|
||||
drop(guest3);
|
||||
assert!(tv_room.is_opened());
|
||||
drop(manager);
|
||||
assert!(!tv_room.is_opened());
|
||||
}
|
||||
}
|
||||
52
src/assignments/assignment12/card.rs
Normal file
52
src/assignments/assignment12/card.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
//! Flipping card game.
|
||||
//!
|
||||
//! For this assignment, you have to see `play` function in `card_grade.rs` file.
|
||||
//! Multiple threads will be created and they will run as enemy bots(`bot_threads`).
|
||||
//! Strategy of the enemy bots is implemented in the closure of the `thread::spawn` function.
|
||||
//! Your goal is to beat them so that there are more white cards than blue cards in the ground.
|
||||
//! Write your strategy in the `flip_card_strategy` function of the `Player` struct.
|
||||
//!
|
||||
//! Have fun!
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
/// Color represents the color of the card.
|
||||
/// The color of a card can be either Blue or White.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Color {
|
||||
/// blue
|
||||
Blue,
|
||||
|
||||
/// white
|
||||
White,
|
||||
}
|
||||
|
||||
/// Player struct represents a player in the card game.
|
||||
/// Each player has a memory which is represented as a HashMap.
|
||||
#[derive(Debug)]
|
||||
pub struct Player {
|
||||
memory: HashMap<isize, isize>,
|
||||
}
|
||||
|
||||
impl Default for Player {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Player {
|
||||
/// Creates a new player with an empty memory.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
memory: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// This function should return the index of the card to flip and the color to change to.
|
||||
pub fn flip_card_strategy(&mut self) -> (usize, Color) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
141
src/assignments/assignment12/card_grade.rs
Normal file
141
src/assignments/assignment12/card_grade.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
//! Test cases for assignment12/card.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_card {
|
||||
use super::super::card::*;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
const NUM_CARDS: usize = 10_000;
|
||||
const DURATION: u64 = 1;
|
||||
const NUM_ENEMIES: usize = 100;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Card {
|
||||
color: Arc<Mutex<Color>>,
|
||||
}
|
||||
|
||||
impl Card {
|
||||
fn new() -> Self {
|
||||
Card {
|
||||
color: Arc::new(Mutex::new(Color::Blue)),
|
||||
}
|
||||
}
|
||||
|
||||
fn flip(&self, new_color: Color) {
|
||||
let mut color = self.color.lock().unwrap();
|
||||
*color = new_color;
|
||||
}
|
||||
|
||||
fn get_color(&self) -> Color {
|
||||
let color = self.color.lock().unwrap();
|
||||
*color
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Ground {
|
||||
cards: Vec<Card>,
|
||||
}
|
||||
|
||||
impl Ground {
|
||||
fn new() -> Self {
|
||||
let cards: Vec<_> = (0..NUM_CARDS).map(|_| Card::new()).collect();
|
||||
Ground { cards }
|
||||
}
|
||||
|
||||
fn flip_card(&self, idx: usize, color: Color) {
|
||||
self.cards[idx % NUM_CARDS].flip(color);
|
||||
}
|
||||
|
||||
fn get_card_color(&self, idx: usize) -> Color {
|
||||
self.cards[idx % NUM_CARDS].get_color()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn play() {
|
||||
let ground = Ground::new();
|
||||
let barrier = Arc::new(Barrier::new(
|
||||
NUM_ENEMIES + 1 /*Player*/ + 1, /*Referee*/
|
||||
));
|
||||
let playing = Arc::new(AtomicBool::new(true));
|
||||
|
||||
// Create a thread for the student's strategy
|
||||
let mut player = Player::new();
|
||||
let player_thread = {
|
||||
let ground = ground.clone();
|
||||
let barrier = barrier.clone();
|
||||
let playing = playing.clone();
|
||||
|
||||
// The player's strategy thread
|
||||
thread::spawn(move || {
|
||||
// Get, Set, Ready, Go!
|
||||
let _ = barrier.wait();
|
||||
|
||||
// As long as the game is still playing...
|
||||
while playing.load(Ordering::SeqCst) {
|
||||
let (idx, color) = player.flip_card_strategy();
|
||||
ground.flip_card(idx, color);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// Create multiple threads for the computer's strategy
|
||||
let dist = NUM_CARDS / NUM_ENEMIES;
|
||||
let bot_threads: Vec<_> = (0..NUM_ENEMIES)
|
||||
.map(|i| {
|
||||
let ground = ground.clone();
|
||||
let barrier = barrier.clone();
|
||||
let playing = playing.clone();
|
||||
|
||||
let init = i * dist;
|
||||
let mut cnt = 0;
|
||||
|
||||
thread::spawn(move || {
|
||||
// Get, Set, Ready, Go!
|
||||
let _ = barrier.wait();
|
||||
|
||||
// As long as the game is still playing...
|
||||
while playing.load(Ordering::SeqCst) {
|
||||
let idx = init + (cnt % dist);
|
||||
match ground.get_card_color(idx) {
|
||||
Color::White => ground.flip_card(idx, Color::Blue),
|
||||
Color::Blue => thread::sleep(Duration::from_micros(1)),
|
||||
};
|
||||
cnt += 1;
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Get, Set, Ready, Go!
|
||||
let _ = barrier.wait();
|
||||
|
||||
// Wait for a while and stop the game
|
||||
thread::sleep(Duration::from_secs(DURATION));
|
||||
playing.store(false, Ordering::SeqCst);
|
||||
|
||||
// Wait for all threads to finish
|
||||
player_thread.join().unwrap();
|
||||
for bot_thread in bot_threads {
|
||||
bot_thread.join().unwrap();
|
||||
}
|
||||
|
||||
// Count the number of white and blue cards
|
||||
let mut white_cnt = 0;
|
||||
let mut blue_cnt = 0;
|
||||
for card in ground.cards {
|
||||
match card.get_color() {
|
||||
Color::White => white_cnt += 1,
|
||||
Color::Blue => blue_cnt += 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Print the winner
|
||||
println!("[White: {white_cnt}, Blue: {blue_cnt}]");
|
||||
assert!(white_cnt > blue_cnt, "You lose...",);
|
||||
}
|
||||
}
|
||||
37
src/assignments/assignment12/demux.rs
Normal file
37
src/assignments/assignment12/demux.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
//! Demultiplexing sender
|
||||
//!
|
||||
//! Implement demultiplexing sender
|
||||
//! Demultiplexer, `Demux` in short, is a device that has one input and many outputs.
|
||||
//! It distributes the input to the outputs according to the control signal.
|
||||
//! It is used when a circuit wishes to send a signal to one of many devices.
|
||||
//! For more information, refer <https://www.electronics-tutorials.ws/combination/comb_3.html>
|
||||
//!
|
||||
//! In this assignment, closure `f` will be given as an argument to `demux` function.
|
||||
//! This closure will be used to determine which destination to send the input data.
|
||||
//!
|
||||
//! Refer `demux_grade.rs` for test cases
|
||||
|
||||
use std::sync::mpsc::{channel, Receiver, SendError, Sender};
|
||||
use std::thread;
|
||||
|
||||
/// Sender for demux.
|
||||
#[derive(Debug)]
|
||||
pub struct DemuxSender<T, F: Fn(&T) -> bool> {
|
||||
tx_true: Sender<T>,
|
||||
tx_false: Sender<T>,
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<T, F: Fn(&T) -> bool> DemuxSender<T, F> {
|
||||
/// send
|
||||
///
|
||||
/// If `f(&value)` is true, send `value` to `tx_true`. Otherwise, send `value` to `tx_false`.
|
||||
pub fn send(&self, value: T) -> Result<(), SendError<T>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Demux.
|
||||
pub fn demux<T, F: Fn(&T) -> bool>(f: F) -> (DemuxSender<T, F>, Receiver<T>, Receiver<T>) {
|
||||
todo!()
|
||||
}
|
||||
36
src/assignments/assignment12/demux_grade.rs
Normal file
36
src/assignments/assignment12/demux_grade.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
//! Test cases for assignment12/demux.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_demux {
|
||||
use super::super::demux::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
#[timeout(5000)]
|
||||
fn test_demux() {
|
||||
let (tx, rx1, rx2) = demux::<u32, _>(|x| x % 2 == 0);
|
||||
|
||||
let thread_tx = thread::spawn(move || {
|
||||
for i in 0..100 {
|
||||
tx.send(i).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
let thread_rx1 = thread::spawn(move || {
|
||||
let sum: u32 = rx1.iter().sum();
|
||||
assert_eq!(sum, (0..100).filter(|x| x % 2 == 0).sum());
|
||||
});
|
||||
|
||||
let thread_rx2 = thread::spawn(move || {
|
||||
let sum: u32 = rx2.iter().sum();
|
||||
assert_eq!(sum, (0..100).filter(|x| x % 2 != 0).sum());
|
||||
});
|
||||
|
||||
thread_tx.join().unwrap();
|
||||
thread_rx1.join().unwrap();
|
||||
thread_rx2.join().unwrap();
|
||||
}
|
||||
}
|
||||
21
src/assignments/assignment12/funnel.rs
Normal file
21
src/assignments/assignment12/funnel.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
//! Funnel
|
||||
//!
|
||||
//! Spawn a thread that executes a funnel.
|
||||
//! Funnel will receive data from multiple receivers and send it to a single sender.
|
||||
//! Also, the funnel will filter out data that does not pass the filter function.
|
||||
//!
|
||||
//! Refer `funnel_grade.rs` for test cases
|
||||
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::thread::JoinHandle;
|
||||
|
||||
/// Spawn a thread that concurrently receive datas from `rxs`, send it to `tx` if it makes `f` true. Returns its handle.
|
||||
pub fn spawn_funnel<T, F>(rxs: Vec<Receiver<T>>, tx: Sender<T>, f: F) -> JoinHandle<()>
|
||||
where
|
||||
T: Send + 'static,
|
||||
F: Send + Sync + Fn(&T) -> bool + 'static,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
33
src/assignments/assignment12/funnel_grade.rs
Normal file
33
src/assignments/assignment12/funnel_grade.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
//! Test cases for assignment12/funnel.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_funnel {
|
||||
use super::super::funnel::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
#[timeout(5000)]
|
||||
fn test_funnel_concurrent() {
|
||||
let (txs, rxs): (Vec<_>, Vec<_>) = (0..10).map(|_| channel::<u32>()).unzip();
|
||||
let (tx, rx) = channel::<u32>();
|
||||
let filter = |x: &u32| x % 2 == 0;
|
||||
|
||||
let thread_txs_rx = thread::spawn(move || {
|
||||
for i in 0..100 {
|
||||
let idx = (i * 7) % 13 * 17 % 10;
|
||||
txs[idx].send(i as u32).unwrap();
|
||||
if i % 2 == 0 {
|
||||
let x = rx.recv().unwrap();
|
||||
assert_eq!(x, i as u32);
|
||||
}
|
||||
}
|
||||
});
|
||||
let thread_funnel = spawn_funnel(rxs, tx, filter);
|
||||
|
||||
thread_txs_rx.join().unwrap();
|
||||
thread_funnel.join().unwrap();
|
||||
}
|
||||
}
|
||||
15
src/assignments/assignment12/mod.rs
Normal file
15
src/assignments/assignment12/mod.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
//! Assignment 12: Concurrency.
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to concurrency.
|
||||
//!
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-12.sh` works fine.
|
||||
//! See `assignment12_grade.rs` and `/scripts/grade-12.sh` for the test script.
|
||||
|
||||
pub mod card;
|
||||
pub mod card_grade;
|
||||
pub mod demux;
|
||||
pub mod demux_grade;
|
||||
pub mod funnel;
|
||||
pub mod funnel_grade;
|
||||
pub mod small_exercises;
|
||||
pub mod small_exercises_grade;
|
||||
@@ -1,23 +1,25 @@
|
||||
#![allow(single_use_lifetimes)]
|
||||
|
||||
//! Assignment 12: Concurrency.
|
||||
//! Small exercises
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to concurrency.
|
||||
//!
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-12.sh` works fine.
|
||||
//! See `assignment12_grade.rs` and `/scripts/grade-12.sh` for the test script.
|
||||
//! Refer `small_exercises_grade.rs` for test cases
|
||||
|
||||
use std::sync::mpsc::{Receiver, RecvError, Sender};
|
||||
use std::thread;
|
||||
|
||||
use etrace::*;
|
||||
|
||||
/// The "pong" function (read the test script to figure out what it should do).
|
||||
/// The "pong" function
|
||||
///
|
||||
/// Data will be sent and received through `rx` and `tx`.
|
||||
/// Read the `test_ping_pong` function in `small_exercises_grade.rs` to figure out what it should do.
|
||||
pub fn pong(rx1: &mut Receiver<u32>, tx2: &mut Sender<u32>) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Executes the given functions (f1, f2) in concurrent and returns the results.
|
||||
///
|
||||
/// Read the `test_scoped_thread` function in `small_exercises_grade.rs` to figure out what it should do.
|
||||
pub fn use_scoped_thread<'scope, 'env, T1, T2, F1, F2>(
|
||||
s: &'scope thread::Scope<'scope, 'env>,
|
||||
f1: F1,
|
||||
86
src/assignments/assignment12/small_exercises_grade.rs
Normal file
86
src/assignments/assignment12/small_exercises_grade.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
//! Test cases for assignment12/small_exercises_grade.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_pingpong {
|
||||
use super::super::small_exercises::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
fn test_ping_pong() {
|
||||
let (tx1, mut rx1) = channel();
|
||||
let (mut tx2, rx2) = channel();
|
||||
|
||||
let thread_ping = thread::spawn(move || {
|
||||
for i in 0..100 {
|
||||
tx1.send(i).unwrap();
|
||||
let x = rx2.recv().unwrap();
|
||||
assert_eq!(x, i + 1);
|
||||
}
|
||||
});
|
||||
|
||||
let thread_pong = thread::spawn(move || while pong(&mut rx1, &mut tx2) {});
|
||||
|
||||
thread_ping.join().unwrap();
|
||||
thread_pong.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scoped_thread() {
|
||||
for i in 0..100 {
|
||||
let v = (0..i).collect::<Vec<u32>>();
|
||||
|
||||
thread::scope(|s| {
|
||||
let (r1, r2) = use_scoped_thread(
|
||||
s,
|
||||
|| v.iter().sum::<u32>(),
|
||||
|| v.windows(2).map(|x| x[0] * x[1]).sum::<u32>(),
|
||||
);
|
||||
|
||||
assert_eq!(r1, v.iter().sum());
|
||||
assert_eq!(r2, v.windows(2).map(|x| x[0] * x[1]).sum());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[timeout(5000)]
|
||||
fn test_scoped_thread_concurrent() {
|
||||
use std::sync::Mutex;
|
||||
|
||||
let m = Mutex::new(0);
|
||||
let (r1, r2) = thread::scope(|s| {
|
||||
use_scoped_thread(
|
||||
s,
|
||||
|| {
|
||||
for i in 0..100 {
|
||||
loop {
|
||||
let mut a = m.lock().unwrap();
|
||||
if *a == 2 * i {
|
||||
*a += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
thread::current().id()
|
||||
},
|
||||
|| {
|
||||
for i in 0..100 {
|
||||
loop {
|
||||
let mut a = m.lock().unwrap();
|
||||
if *a == 2 * i + 1 {
|
||||
*a += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
thread::current().id()
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
assert!(r1 != r2);
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,6 @@ mod assignment09_grade;
|
||||
pub mod assignment10;
|
||||
mod assignment10_grade;
|
||||
pub mod assignment11;
|
||||
mod assignment11_grade;
|
||||
pub mod assignment12;
|
||||
mod assignment12_grade;
|
||||
pub mod assignment13;
|
||||
mod assignment13_grade;
|
||||
|
||||
Reference in New Issue
Block a user