diff options
| author | olivia <olivia@fastmail.com> | 2018-04-26 21:29:11 +0200 |
|---|---|---|
| committer | olivia <olivia@fastmail.com> | 2018-04-26 21:29:11 +0200 |
| commit | 5e89d1e888a8fafc39096afce36d02e313f349c2 (patch) | |
| tree | 97b13f8223012d1db88d510cd79ea0e49570d1f7 /old_curriculum | |
| parent | 32ac403da5c49b002ba420186d3122501196ff89 (diff) | |
move old files to a separate directory
Diffstat (limited to 'old_curriculum')
53 files changed, 3093 insertions, 0 deletions
diff --git a/old_curriculum/.travis.yml b/old_curriculum/.travis.yml new file mode 100644 index 0000000..684b265 --- /dev/null +++ b/old_curriculum/.travis.yml @@ -0,0 +1,19 @@ +language: rust + +branches: + only: + - master + +cache: + cargo: true + +script: + - cargo run --bin generate_readme + - git config user.name "Carol (Nichols || Goulding)" + - git config user.email "carol.nichols@gmail.com" + - git commit -am "Regenerate README" && git remote add upstream "https://$GH_TOKEN@github.com/carols10cents/rustlings.git" && git push -q upstream HEAD:master > /dev/null 2>&1 || true + +notifications: + email: + on_success: never + diff --git a/old_curriculum/Cargo.lock b/old_curriculum/Cargo.lock new file mode 100644 index 0000000..7bff901 --- /dev/null +++ b/old_curriculum/Cargo.lock @@ -0,0 +1,456 @@ +[[package]] +name = "aho-corasick" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "atty" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dtoa" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "handlebars" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pest" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pest_derive" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "prlink" +version = "0.1.0" +source = "git+https://github.com/btbytes/prlink#f0536ed3b322072d65c42da2fc2a817b77d77308" +dependencies = [ + "clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_syscall" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustlings" +version = "0.1.0" +dependencies = [ + "handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prlink 0.1.0 (git+https://github.com/btbytes/prlink)", + "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_json" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "url" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" +"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07af2ff31f66f39a5c8b8b8a5dc02734a453110146763e3a2323f4931a915a76" +"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3c2bd9b9d21e48e956b763c9f37134dc62d9e95da6edb3f672cacb6caf3cd3" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" +"checksum pest_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6453faedc5c9980a3c278f28b1df33344a79cc6d4a2fd96e2b56288374dc822a" +"checksum prlink 0.1.0 (git+https://github.com/btbytes/prlink)" = "<none>" +"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57781ed845b8e742fc2bf306aba8e3b408fe8c366b900e3769fbc39f49eb8b39" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/old_curriculum/Cargo.toml b/old_curriculum/Cargo.toml new file mode 100644 index 0000000..d82b8a1 --- /dev/null +++ b/old_curriculum/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rustlings" +version = "0.1.0" +authors = ["Carol (Nichols || Goulding) <carol.nichols@gmail.com>"] + +[dependencies] +handlebars = "0.32.0" +serde_json = "1.0.10" +prlink = { git = "https://github.com/btbytes/prlink" } diff --git a/old_curriculum/README-template.hbs b/old_curriculum/README-template.hbs new file mode 100644 index 0000000..5cfec7f --- /dev/null +++ b/old_curriculum/README-template.hbs @@ -0,0 +1,190 @@ +<!-- +{{ autogenerated_notice }} +--> + +# rustlings + +Small exercises to get you used to reading and writing Rust code. Includes practice reading and +responding to compiler messages! + +This repo is very much the smallest thing that could possibly work :) + +## To do these exercises + +Thanks to [btbytes'](https://twitter.com/btbytes) [prlinks](https://github.com/btbytes/prlink), you +can now click on the links below to load the exercises in the rust playground! + +There are infinite correct answers-- the exercises are sometimes left very open-ended. Scroll down +in the playground to find comments that have hints. + +If you need more help or would like to compare solutions, you can ask in [#rust-beginners on +irc.mozilla.org](https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-beginners ), the +[user forum](https://users.rust-lang.org/), or [the subreddit](https://reddit.com/r/rust). If an +exercise could be improved in any way, please [create an +issue](https://github.com/carols10cents/rustlings/issues/new) or submit a pull request! + +### Variable bindings + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html) + +{{ playground_link "variables/variables1.rs" }} +{{ playground_link "variables/variables2.rs" }} +{{ playground_link "variables/variables3.rs" }} +{{ playground_link "variables/variables4.rs" }} + +### Functions + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html) + +{{ playground_link "functions/functions1.rs" }} +{{ playground_link "functions/functions2.rs" }} +{{ playground_link "functions/functions3.rs" }} +{{ playground_link "functions/functions4.rs" }} +{{ playground_link "functions/functions5.rs" }} + +### Primitive types + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html) + +{{ playground_link "primitive_types/primitive_types1.rs" }} +{{ playground_link "primitive_types/primitive_types2.rs" }} +{{ playground_link "primitive_types/primitive_types3.rs" }} +{{ playground_link "primitive_types/primitive_types4.rs" }} +{{ playground_link "primitive_types/primitive_types5.rs" }} +{{ playground_link "primitive_types/primitive_types6.rs" }} + +### Tests + +Going out of order from the book to cover tests-- many of the following exercises will ask you to +make tests pass! + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch11-01-writing-tests.html) + +{{ playground_link "tests/tests1.rs" }} +{{ playground_link "tests/tests2.rs" }} +{{ playground_link "tests/tests3.rs" }} +{{ playground_link "tests/tests4.rs" }} + +### If + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch03-05-control-flow.html) + +{{ playground_link "if/if1.rs" }} + +### Strings + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch08-02-strings.html) + +{{ playground_link "strings/strings1.rs" }} +{{ playground_link "strings/strings2.rs" }} +{{ playground_link "strings/strings3.rs" }} + +### Move semantics + +These exercises are adapted from [pnkfelix]()'s [Rust +Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- thank you Felix!!! + +Relevant chapters in the book: + +- [Ownership](https://doc.rust-lang.org/book/second-edition/ch04-01-what-is-ownership.html) +- [References and borrowing](https://doc.rust-lang.org/book/second-edition/ch04-02-references-and-borrowing.html) + +Note that the exercises in this section may look similar to each other but they are subtly +different :) + +{{ playground_link "move_semantics/move_semantics1.rs" }} +{{ playground_link "move_semantics/move_semantics2.rs" }} +{{ playground_link "move_semantics/move_semantics3.rs" }} +{{ playground_link "move_semantics/move_semantics4.rs" }} + +### Modules + +[Relevant chapter in The Rust Programming +Language](https://doc.rust-lang.org/book/second-edition/ch07-01-mod-and-the-filesystem.html) + +{{ playground_link "modules/modules1.rs" }} +{{ playground_link "modules/modules2.rs" }} + +### Macros + +Check out: + +- [The Macros section of the first edition of the book + book](https://doc.rust-lang.org/book/first-edition/macros.html) +- [The Macros appendix of the second edition of the + book](https://doc.rust-lang.org/book/second-edition/appendix-04-macros.html) +- [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html) + +{{ playground_link "macros/macros1.rs" }} +{{ playground_link "macros/macros2.rs" }} +{{ playground_link "macros/macros3.rs" }} +{{ playground_link "macros/macros4.rs" }} + +### Error Handling + +The [Error +Handling](https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html) +and [Generics](https://doc.rust-lang.org/book/second-edition/ch10-01-syntax.html) sections are +relevant. + +{{ playground_link "error_handling/option1.rs" }} +{{ playground_link "error_handling/result1.rs" }} +{{ playground_link "error_handling/errors1.rs" }} +{{ playground_link "error_handling/errors2.rs" }} +{{ playground_link "error_handling/errors3.rs" }} +{{ playground_link "error_handling/errorsn.rs" }} + +### Standard library types + +#### `Arc` + +The [Concurrency](https://doc.rust-lang.org/book/second-edition/ch16-03-shared-state.html) section +is relevant. + +{{ playground_link "standard_library_types/arc1.rs" }} + +#### Iterators + +Do not adjust your monitors-- iterators 1 and 2 are indeed missing. Iterator 3 is a bit challenging +so we're leaving space for some exercises to lead up to it! + +Check out the [Iterators chapter of the +book](https://doc.rust-lang.org/book/second-edition/ch13-02-iterators.html) and the [Iterator +docs](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html). + +{{ playground_link "standard_library_types/iterator3.rs" }} +{{ playground_link "standard_library_types/iterators4.rs" }} + +### Threads + +See [the Dining Philosophers +example](https://doc.rust-lang.org/1.4.0/book/first-edition/dining-philosophers.html) and the +[Concurrency Chapter](https://doc.rust-lang.org/book/second-edition/ch16-01-threads.html) from the +book. + +{{ playground_link "threads/threads1.rs" }} + +### Uncategorized + +A few exercises based on things I've encountered or had trouble with getting used to. + +{{ playground_link "ex1.rs" }} +{{ playground_link "ex2.rs" }} +{{ playground_link "ex3.rs" }} +{{ playground_link "ex4.rs" }} +{{ playground_link "ex5.rs" }} + +## To help with this repo/TODO list + +* File issues for problems or suggestions! +* Contribute more exercises! Anything that took you time to get used to, or that you had trouble + with, or that deserves practice would be a good exercise! +* How could the process of doing these exercises work better? This is an open-ended question :) Are + the playground links good enough? Are there ways that we could make going to the next exercise + easier without forking the playground?? diff --git a/old_curriculum/error_handling/errors1.rs b/old_curriculum/error_handling/errors1.rs new file mode 100644 index 0000000..14ed574 --- /dev/null +++ b/old_curriculum/error_handling/errors1.rs @@ -0,0 +1,73 @@ +// errors1.rs +// This function refuses to generate text to be printed on a nametag if +// you pass it an empty string. It'd be nicer if it explained what the problem +// was, instead of just sometimes returning `None`. The 2nd test currently +// does not compile or pass, but it illustrates the behavior we would like +// this function to have. +// Scroll down for hints!!! + +pub fn generate_nametag_text(name: String) -> Option<String> { + if name.len() > 0 { + Some(format!("Hi! My name is {}", name)) + } else { + // Empty names aren't allowed. + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // This test passes initially if you comment out the 2nd test. + // You'll need to update what this test expects when you change + // the function under test! + #[test] + fn generates_nametag_text_for_a_nonempty_name() { + assert_eq!( + generate_nametag_text("Beyoncé".into()), + Some("Hi! My name is Beyoncé".into()) + ); + } + + #[test] + fn explains_why_generating_nametag_text_fails() { + assert_eq!( + generate_nametag_text("".into()), + Err("`name` was empty; it must be nonempty.".into()) + ); + } +} + + + + + + + + + + + + + + + + + + + + +// `Err` is one of the variants of `Result`, so what the 2nd test is saying +// is that `generate_nametag_text` should return a `Result` instead of an +// `Option`. + +// To make this change, you'll need to: +// - update the return type in the function signature to be a Result that +// could be the variants `Ok(String)` and `Err(String)` +// - change the body of the function to return `Ok(stuff)` where it currently +// returns `Some(stuff)` +// - change the body of the function to return `Err(error message)` where it +// currently returns `None` +// - change the first test to expect `Ok(stuff)` where it currently expects +// `Some(stuff)`. diff --git a/old_curriculum/error_handling/errors2.rs b/old_curriculum/error_handling/errors2.rs new file mode 100644 index 0000000..05824c1 --- /dev/null +++ b/old_curriculum/error_handling/errors2.rs @@ -0,0 +1,72 @@ +// errors2.rs +// Say we're writing a game where you can buy items with tokens. All items cost +// 5 tokens, and whenever you purchase items there is a processing fee of 1 +// token. A player of the game will type in how many items they want to buy, +// and the `total_cost` function will calculate the total number of tokens. +// Since the player typed in the quantity, though, we get it as a string-- and +// they might have typed anything, not just numbers! + +// Right now, this function isn't handling the error case at all (and isn't +// handling the success case properly either). What we want to do is: +// if we call the `parse` function on a string that is not a number, that +// function will return a `ParseIntError`, and in that case, we want to +// immediately return that error from our function and not try to multiply +// and add. + +// There are at least two ways to implement this that are both correct-- but +// one is a lot shorter! Scroll down for hints to both ways. + +use std::num::ParseIntError; + +pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> { + let processing_fee = 1; + let cost_per_item = 5; + let qty = item_quantity.parse::<i32>(); + + Ok(qty * cost_per_item + processing_fee) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn item_quantity_is_a_valid_number() { + assert_eq!( + total_cost("34"), + Ok(171) + ); + } + + #[test] + fn item_quantity_is_an_invalid_number() { + assert_eq!( + total_cost("beep boop").unwrap_err().to_string(), + "invalid digit found in string" + ); + } +} + + + + + + + + + + + + + + + + + +// One way to handle this is using a `match` statement on +// `item_quantity.parse::<i32>()` where the cases are `Ok(something)` and +// `Err(something)`. This pattern is very common in Rust, though, so there's +// a `try!` macro that does pretty much what you would make that match statement +// do for you! Take a look at this section of the Error Handling chapter: +// https://doc.rust-lang.org/stable/book/error-handling.html#the-try-macro +// and give it a `try!` diff --git a/old_curriculum/error_handling/errors3.rs b/old_curriculum/error_handling/errors3.rs new file mode 100644 index 0000000..9b285e0 --- /dev/null +++ b/old_curriculum/error_handling/errors3.rs @@ -0,0 +1,67 @@ +// errors3.rs +// This is a program that is trying to use a completed version of the +// `total_cost` function from the previous exercise. It's not working though-- +// we can't call the `try!` macro in the `main()` function! Why not? +// What should we do instead? Scroll for hints! + +use std::num::ParseIntError; + +fn main() { + let mut tokens = 100; + let pretend_user_input = "8"; + + let cost = try!(total_cost(pretend_user_input)); + + if cost > tokens { + println!("You can't afford that many!"); + } else { + tokens -= cost; + println!("You now have {} tokens.", tokens); + } +} + +pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> { + let processing_fee = 1; + let cost_per_item = 5; + let qty = try!(item_quantity.parse::<i32>()); + + Ok(qty * cost_per_item + processing_fee) +} + + + + + + + + + + + + + + + + + + +// Since the `try!` macro returns an `Err` early if the thing it's trying to +// do fails, you can only use the `try!` macro in functions that have a +// `Result` as their return type. + +// The error that you get if you run this code is: + +// ``` +// error: mismatched types: +// expected `()`, +// found `std::result::Result<_, _>` +// ``` + +// which is saying that the expected return type of the `main` function is +// the empty tuple, but we tried to return a `Result`-- and that's happening +// in the implementation of `try!`. The `main` function never has a return type, +// so we have to use another way of handling a `Result` within `main`. + +// Decide what we should do if `pretend_user_input` has a string value that does +// not parse to an integer, and implement that instead of calling the `try!` +// macro. diff --git a/old_curriculum/error_handling/errorsn.rs b/old_curriculum/error_handling/errorsn.rs new file mode 100644 index 0000000..ee1179d --- /dev/null +++ b/old_curriculum/error_handling/errorsn.rs @@ -0,0 +1,138 @@ +// errorsn.rs +// This is a bigger error exercise than the previous ones! +// You can do it! :) +// +// Edit the `read_and_validate` function so that it compiles and +// passes the tests... so many things could go wrong! +// +// - Reading from stdin could produce an io::Error +// - Parsing the input could produce a num::ParseIntError +// - Validating the input could produce a CreationError (defined below) +// +// How can we lump these errors into one general error? That is, what +// type goes where the question marks are, and how do we return +// that type from the body of read_and_validate? +// +// Scroll down for hints :) + +use std::error; +use std::fmt; +use std::io; + +// PositiveNonzeroInteger is a struct defined below the tests. +fn read_and_validate(b: &mut io::BufRead) -> Result<PositiveNonzeroInteger, ???> { + let mut line = String::new(); + b.read_line(&mut line); + let num: i64 = line.trim().parse(); + let answer = PositiveNonzeroInteger::new(num); + answer +} + +// This is a test helper function that turns a &str into a BufReader. +fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<error::Error>> { + let mut b = io::BufReader::new(s.as_bytes()); + read_and_validate(&mut b) +} + +#[test] +fn test_success() { + let x = test_with_str("42\n"); + assert_eq!(PositiveNonzeroInteger(42), x.unwrap()); +} + +#[test] +fn test_not_num() { + let x = test_with_str("eleven billion\n"); + assert!(x.is_err()); +} + +#[test] +fn test_non_positive() { + let x = test_with_str("-40\n"); + assert!(x.is_err()); +} + +#[test] +fn test_ioerror() { + struct Broken; + impl io::Read for Broken { + fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { + Err(io::Error::new(io::ErrorKind::BrokenPipe, "uh-oh!")) + } + } + let mut b = io::BufReader::new(Broken); + assert!(read_and_validate(&mut b).is_err()); + assert_eq!("uh-oh!", read_and_validate(&mut b).unwrap_err().to_string()); +} + +#[derive(PartialEq,Debug)] +struct PositiveNonzeroInteger(u64); + +impl PositiveNonzeroInteger { + fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { + if value == 0 { + Err(CreationError::Zero) + } else if value < 0 { + Err(CreationError::Negative) + } else { + Ok(PositiveNonzeroInteger(value as u64)) + } + } +} + +#[test] +fn test_positive_nonzero_integer_creation() { + assert!(PositiveNonzeroInteger::new(10).is_ok()); + assert_eq!(Err(CreationError::Negative), PositiveNonzeroInteger::new(-10)); + assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0)); +} + +#[derive(PartialEq,Debug)] +enum CreationError { + Negative, + Zero, +} + +impl fmt::Display for CreationError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str((self as &error::Error).description()) + } +} + +impl error::Error for CreationError { + fn description(&self) -> &str { + match *self { + CreationError::Negative => "Negative", + CreationError::Zero => "Zero", + } + } +} + +// First hint: To figure out what type should go where the ??? is, take a look +// at the test helper function `test_with_str`, since it returns whatever +// `read_and_validate` returns and`test_with_str` has its signature fully +// specified. + +// Next hint: There are three places in `read_and_validate` that we call a +// function that returns a `Result` (that is, the functions might fail). +// Wrap those calls in a `try!` macro call so that we return immediately from +// `read_and_validate` if those function calls fail. + +// Another hint: under the hood, the `try!` macro calls `From::from` +// on the error value to convert it to a boxed trait object, a Box<error::Error>, +// which is polymorphic-- that means that lots of different kinds of errors +// can be returned from the same function because all errors act the same +// since they all implement the `error::Error` trait. +// Check out this section of the book: +// https://doc.rust-lang.org/stable/book/error-handling.html#standard-library-traits-used-for-error-handling + +// Another another hint: Note that because the `try!` macro returns +// the *unwrapped* value in the `Ok` case, if we want to return a `Result` from +// `read_and_validate` for *its* success case, we'll have to rewrap a value +// that we got from the return value of a `try!` call in an `Ok`-- this will +// look like `Ok(something)`. + +// Another another another hint: `Result`s must be "used", that is, you'll +// get a warning if you don't handle a `Result` that you get in your +// function. Read more about that in the `std::result` module docs: +// https://doc.rust-lang.org/std/result/#results-must-be-used diff --git a/old_curriculum/error_handling/option1.rs b/old_curriculum/error_handling/option1.rs new file mode 100644 index 0000000..9cf0bc9 --- /dev/null +++ b/old_curriculum/error_handling/option1.rs @@ -0,0 +1,45 @@ +// option1.rs +// This example panics because the second time it calls `pop`, the `vec` +// is empty, so `pop` returns `None`, and `unwrap` panics if it's called +// on `None`. Handle this in a more graceful way than calling `unwrap`! +// Scroll down for hints :) + +fn main() { + let mut list = vec![3]; + + let last = list.pop().unwrap(); + println!("The last item in the list is {:?}", last); + + let second_to_last = list.pop().unwrap(); + println!("The second-to-last item in the list is {:?}", second_to_last); +} + + + + + + + + + + + + + + + + + + + + + + + + + +// Try using a `match` statement where the arms are `Some(thing)` and `None`. +// Or set a default value to print out if you get `None` by using the +// function `unwrap_or`. +// Or use an `if let` statement on the result of `pop()` to both destructure +// a `Some` value and only print out something if we have a value! diff --git a/old_curriculum/error_handling/result1.rs b/old_curriculum/error_handling/result1.rs new file mode 100644 index 0000000..851ab45 --- /dev/null +++ b/old_curriculum/error_handling/result1.rs @@ -0,0 +1,43 @@ +// result1.rs +// Make this test pass! Scroll down for hints :) + +#[derive(PartialEq,Debug)] +struct PositiveNonzeroInteger(u64); + +#[derive(PartialEq,Debug)] +enum CreationError { + Negative, + Zero, +} + +impl PositiveNonzeroInteger { + fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { + Ok(PositiveNonzeroInteger(value as u64)) + } +} + +#[test] +fn test_creation() { + assert!(PositiveNonzeroInteger::new(10).is_ok()); + assert_eq!(Err(CreationError::Negative), PositiveNonzeroInteger::new(-10)); + assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0)); +} + + + + + + + + + + + + + + + + +// `PositiveNonzeroInteger::new` is always creating a new instance and returning an `Ok` result. +// It should be doing some checking, returning an `Err` result if those checks fail, and only +// returning an `Ok` result if those checks determine that everything is... okay :) diff --git a/old_curriculum/ex1.rs b/old_curriculum/ex1.rs new file mode 100644 index 0000000..dc5f9ca --- /dev/null +++ b/old_curriculum/ex1.rs @@ -0,0 +1,6 @@ +// ex1.rs +// Make me compile! :) + +fn main() { + println(); +} diff --git a/old_curriculum/ex2.rs b/old_curriculum/ex2.rs new file mode 100644 index 0000000..0fd714d --- /dev/null +++ b/old_curriculum/ex2.rs @@ -0,0 +1,10 @@ +// ex2.rs +// Make me compile! + +fn something() -> String { + "hi!" +} + +fn main() { + println!("{}", something()); +} diff --git a/old_curriculum/ex3.rs b/old_curriculum/ex3.rs new file mode 100644 index 0000000..db27ad2 --- /dev/null +++ b/old_curriculum/ex3.rs @@ -0,0 +1,10 @@ +// ex3.rs +// Make me compile! + +struct Foo { + capacity: i32, +} + +fn main() { + println!("{:?}", Foo { capacity: 3 }); +} diff --git a/old_curriculum/ex4.rs b/old_curriculum/ex4.rs new file mode 100644 index 0000000..362a557 --- /dev/null +++ b/old_curriculum/ex4.rs @@ -0,0 +1,14 @@ +// ex4.rs +// Make me compile! + +fn something() -> Result<i32, std::num::ParseIntError> { + let x:i32 = "3".parse(); + Ok(x * 4) +} + +fn main() { + match something() { + Ok(..) => println!("You win!"), + Err(e) => println!("Oh no something went wrong: {}", e), + } +} diff --git a/old_curriculum/ex5.rs b/old_curriculum/ex5.rs new file mode 100644 index 0000000..2eb8cfd --- /dev/null +++ b/old_curriculum/ex5.rs @@ -0,0 +1,22 @@ +// ex5.rs +// Make me compile! + +enum Reaction<'a> { + Sad(&'a str), + Happy(&'a str), +} + +fn express(sentiment: Reaction) { + match sentiment { + Reaction::Sad(s) => println!(":( {}", s), + Reaction::Happy(s) => println!(":) {}", s), + } +} + +fn main () { + let x = Reaction::Happy("It's a great day for Rust!"); + express(x); + express(x); + let y = Reaction::Sad("This code doesn't compile yet."); + express(y); +} diff --git a/old_curriculum/functions/functions1.rs b/old_curriculum/functions/functions1.rs new file mode 100644 index 0000000..396dd56 --- /dev/null +++ b/old_curriculum/functions/functions1.rs @@ -0,0 +1,44 @@ +// functions1.rs +// Make me compile! Scroll down for hints :) + +fn main() { + call_me(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// This main function is calling a function that it expects to exist, but the +// function doesn't exist. It expects this function to have the name `call_me`. +// It expects this function to not take any arguments and not return a value. +// Sounds a lot like `main`, doesn't it? diff --git a/old_curriculum/functions/functions2.rs b/old_curriculum/functions/functions2.rs new file mode 100644 index 0000000..1cf95c3 --- /dev/null +++ b/old_curriculum/functions/functions2.rs @@ -0,0 +1,42 @@ +// functions2.rs +// Make me compile! Scroll down for hints :) + +fn main() { + call_me(3); +} + +fn call_me(num) { + for i in 0..num { + println!("Ring! Call number {}", i + 1); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Rust requires that all parts of a function's signature have type annotations, +// but `call_me` is missing the type annotation of `num`. diff --git a/old_curriculum/functions/functions3.rs b/old_curriculum/functions/functions3.rs new file mode 100644 index 0000000..b17543b --- /dev/null +++ b/old_curriculum/functions/functions3.rs @@ -0,0 +1,42 @@ +// functions3.rs +// Make me compile! Scroll down for hints :) + +fn main() { + call_me(); +} + +fn call_me(num: i32) { + for i in 0..num { + println!("Ring! Call number {}", i + 1); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// This time, the function *declaration* is okay, but there's something wrong +// with the place where we're calling the function. diff --git a/old_curriculum/functions/functions4.rs b/old_curriculum/functions/functions4.rs new file mode 100644 index 0000000..5baca0e --- /dev/null +++ b/old_curriculum/functions/functions4.rs @@ -0,0 +1,44 @@ +// functions4.rs +// Make me compile! Scroll down for hints :) + +// This store is having a sale where if the price is an even number, you get +// 10 (money unit) off, but if it's an odd number, it's 3 (money unit) less. + +fn main() { + let original_price = 51; + println!("Your sale price is {}", sale_price(original_price)); +} + +fn sale_price(price: i32) -> { + if is_even(price) { + price - 10 + } else { + price - 3 + } +} + +fn is_even(num: i32) -> bool { + num % 2 == 0 +} + + + + + + + + + + + + + + + + + + + +// The error message points to line 12 and says it expects a type after the +// `->`. This is where the function's return type should be-- take a look at +// the `is_even` function for an example! diff --git a/old_curriculum/functions/functions5.rs b/old_curriculum/functions/functions5.rs new file mode 100644 index 0000000..f8fac5d --- /dev/null +++ b/old_curriculum/functions/functions5.rs @@ -0,0 +1,44 @@ +// functions5.rs +// Make me compile! Scroll down for hints :) + +fn main() { + let answer = square(3); + println!("The answer is {}", answer); +} + +fn square(num: i32) -> i32 { + num * num; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// This is a really common error that can be fixed by removing one character. +// It happens because Rust distinguishes between expressions and statements: expressions return +// a value and statements don't. We want to return a value from the `square` function, but it +// isn't returning one right now... diff --git a/old_curriculum/if/if1.rs b/old_curriculum/if/if1.rs new file mode 100644 index 0000000..5118657 --- /dev/null +++ b/old_curriculum/if/if1.rs @@ -0,0 +1,58 @@ +// if1.rs + +pub fn bigger(a: i32, b:i32) -> i32 { + // Complete this function to return the bigger number! + // Do not use: + // - return + // - another function call + // - additional variables + // Scroll down for hints. +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ten_is_bigger_than_eight() { + assert_eq!(10, bigger(10, 8)); + } + + #[test] + fn fortytwo_is_bigger_than_thirtytwo() { + assert_eq!(42, bigger(32, 42)); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + +// It's possible to do this in one line if you would like! +// Some similar examples from other languages: +// - In C(++) this would be: `a > b ? a : b` +// - In Python this would be: `a if a > b else b` +// Remember in Rust that: +// - the `if` condition does not need to be surrounded by parentheses +// - `if`/`else` conditionals are expressions +// - Each condition is followed by a `{}` block. diff --git a/old_curriculum/macros/macros1.rs b/old_curriculum/macros/macros1.rs new file mode 100644 index 0000000..a7c78a5 --- /dev/null +++ b/old_curriculum/macros/macros1.rs @@ -0,0 +1,64 @@ +// macros1.rs +// Make me compile! Scroll down for hints :) + +macro_rules! my_macro { + () => { + println!("Check out my macro!"); + }; +} + +fn main() { + my_macro(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// When you call a macro, you need to add something special compared to a +// regular function call. If you're stuck, take a look at what's inside +// `my_macro`. diff --git a/old_curriculum/macros/macros2.rs b/old_curriculum/macros/macros2.rs new file mode 100644 index 0000000..bc2e56b --- /dev/null +++ b/old_curriculum/macros/macros2.rs @@ -0,0 +1,73 @@ +// macros2.rs +// Make me compile! Scroll down for hints :) + +fn main() { + my_macro!(); +} + +macro_rules! my_macro { + () => { + println!("Check out my macro!"); + }; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Macros don't quite play by the same rules as the rest of Rust, in terms of +// what's available where. + + + + + + + + +// Unlike other things in Rust, the order of "where you define a macro" versus +// "where you use it" actually matters. diff --git a/old_curriculum/macros/macros3.rs b/old_curriculum/macros/macros3.rs new file mode 100644 index 0000000..84c4308 --- /dev/null +++ b/old_curriculum/macros/macros3.rs @@ -0,0 +1,75 @@ +// macros3.rs +// Make me compile, without taking the macro out of the module! Scroll down for hints :) + +mod macros { + macro_rules! my_macro { + () => { + println!("Check out my macro!"); + }; + } +} + +fn main() { + my_macro!(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// In order to use a macro outside of its module, you need to do something +// special to the module to lift the macro out into its parent. + + + + + + + + +// The same trick also works on "extern crate" statements for crates that have +// exported macros, if you've seen any of those around. diff --git a/old_curriculum/macros/macros4.rs b/old_curriculum/macros/macros4.rs new file mode 100644 index 0000000..d844bb0 --- /dev/null +++ b/old_curriculum/macros/macros4.rs @@ -0,0 +1,77 @@ +// macros4.rs +// Make me compile! Scroll down for hints :) + +macro_rules! my_macro { + () => { + println!("Check out my macro!"); + } + ($val:expr) => { + println!("Look at this other macro: {}", $val); + } +} + +fn main() { + my_macro!(); + my_macro!(7777); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// You only need to add a single character to make this compile. + + + + + + + + + +// The way macros are written, it wants to see something between each +// "macro arm", so it can separate them. diff --git a/old_curriculum/modules/modules1.rs b/old_curriculum/modules/modules1.rs new file mode 100644 index 0000000..0e092c5 --- /dev/null +++ b/old_curriculum/modules/modules1.rs @@ -0,0 +1,43 @@ +// modules1.rs +// Make me compile! Scroll down for hints :) + +mod sausage_factory { + fn make_sausage() { + println!("sausage!"); + } +} + +fn main() { + sausage_factory::make_sausage(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Everything is private in Rust by default-- but there's a keyword we can use +// to make something public! The compiler error should point to the thing that +// needs to be public. diff --git a/old_curriculum/modules/modules2.rs b/old_curriculum/modules/modules2.rs new file mode 100644 index 0000000..164dfb0 --- /dev/null +++ b/old_curriculum/modules/modules2.rs @@ -0,0 +1,45 @@ +// modules2.rs +// Make me compile! Scroll down for hints :) + +mod us_presidential_frontrunners { + use self::democrats::HILLARY_CLINTON as democrat; + use self::republicans::DONALD_TRUMP as republican; + + mod democrats { + pub const HILLARY_CLINTON: &'static str = "Hillary Clinton"; + pub const BERNIE_SANDERS: &'static str = "Bernie Sanders"; + } + + mod republicans { + pub const DONALD_TRUMP: &'static str = "Donald Trump"; + pub const JEB_BUSH: &'static str = "Jeb Bush"; + } +} + +fn main() { + println!("candidates: {} and {}", + us_presidential_frontrunners::democrat, + us_presidential_frontrunners::republican); +} + + + + + + + + + + + + + + + + + +// The us_presidential_frontrunners module is trying to present an external +// interface (the `democrat` and `republican` constants) that is different than +// its internal structure (the `democrats` and `republicans` modules and +// associated constants). It's almost there except for one keyword missing for +// each constant. diff --git a/old_curriculum/move_semantics/move_semantics1.rs b/old_curriculum/move_semantics/move_semantics1.rs new file mode 100644 index 0000000..73dc0ab --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics1.rs @@ -0,0 +1,43 @@ +// move_semantics1.rs +// Make me compile! Scroll down for hints :) + +pub fn main() { + let vec0 = Vec::new(); + + let vec1 = fill_vec(vec0); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + + vec1.push(88); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + +} + +fn fill_vec(vec: Vec<i32>) -> Vec<i32> { + let mut vec = vec; + + vec.push(22); + vec.push(44); + vec.push(66); + + vec +} + + + + + + + + + + + + + + + +// So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 11, +// right? The fix for this is going to be adding one keyword, and the addition is NOT on line 11 +// where the error is. diff --git a/old_curriculum/move_semantics/move_semantics2.rs b/old_curriculum/move_semantics/move_semantics2.rs new file mode 100644 index 0000000..bc42d8e --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics2.rs @@ -0,0 +1,54 @@ +// move_semantics2.rs +// Make me compile without changing line 10! Scroll down for hints :) + +pub fn main() { + let vec0 = Vec::new(); + + let mut vec1 = fill_vec(vec0); + + // Do not change the following line! + println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0); + + vec1.push(88); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + +} + +fn fill_vec(vec: Vec<i32>) -> Vec<i32> { + let mut vec = vec; + + vec.push(22); + vec.push(44); + vec.push(66); + + vec +} + + + + + + + + + + + + + + +// So `vec0` is being *moved* into the function `fill_vec` when we call it on +// line 7, which means it gets dropped at the end of `fill_vec`, which means we +// can't use `vec0` again on line 10 (or anywhere else in `main` after the +// `fill_vec` call for that matter). We could fix this in a few ways, try them +// all! +// 1. Make another, separate version of the data that's in `vec0` and pass that +// to `fill_vec` instead. +// 2. Make `fill_vec` borrow its argument instead of taking ownership of it, +// and then copy the data within the function in order to return an owned +// `Vec<i32>` +// 3. Make `fill_vec` *mutably* borrow its argument (which will need to be +// mutable), modify it directly, then not return anything. Then you can get rid +// of `vec1` entirely -- note that this will change what gets printed by the +// first `println!` diff --git a/old_curriculum/move_semantics/move_semantics3.rs b/old_curriculum/move_semantics/move_semantics3.rs new file mode 100644 index 0000000..7805d44 --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics3.rs @@ -0,0 +1,46 @@ +// move_semantics3.rs +// Make me compile without adding new lines-- just changing existing lines! +// (no lines with multiple semicolons necessary!) +// Scroll down for hints :) + +pub fn main() { + let vec0 = Vec::new(); + + let mut vec1 = fill_vec(vec0); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + + vec1.push(88); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + +} + +fn fill_vec(vec: Vec<i32>) -> Vec<i32> { + vec.push(22); + vec.push(44); + vec.push(66); + + vec +} + + + + + + + + + + + + + + + + + +// The difference between this one and the previous ones is that the first line +// of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can, +// instead of adding that line back, add `mut` in one place that will change +// an existing binding to be a mutable binding instead of an immutable one :) diff --git a/old_curriculum/move_semantics/move_semantics4.rs b/old_curriculum/move_semantics/move_semantics4.rs new file mode 100644 index 0000000..2b1ed8a --- /dev/null +++ b/old_curriculum/move_semantics/move_semantics4.rs @@ -0,0 +1,48 @@ +// move_semantics4.rs +// Refactor this code so that instead of having `vec0` and creating the vector +// in `fn main`, we instead create it within `fn fill_vec` and transfer the +// freshly created vector from fill_vec to its caller. Scroll for hints! + +pub fn main() { + let vec0 = Vec::new(); + + let mut vec1 = fill_vec(vec0); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + + vec1.push(88); + + println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + +} + +fn fill_vec(vec: Vec<i32>) -> Vec<i32> { + let mut vec = vec; + + vec.push(22); + vec.push(44); + vec.push(66); + + vec +} + + + + + + + + + + + + +// Stop reading whenever you feel like you have enough direction :) Or try +// doing one step and then fixing the compiler errors that result! +// So the end goal is to: +// - get rid of the first line in main that creates the new vector +// - so then `vec0` doesn't exist, so we can't pass it to `fill_vec` +// - we don't want to pass anything to `fill_vec`, so its signature should +// reflect that it does not take any arguments +// - since we're not creating a new vec in `main` anymore, we need to create +// a new vec in `fill_vec`, similarly to the way we did in `main` diff --git a/old_curriculum/primitive_types/primitive_types1.rs b/old_curriculum/primitive_types/primitive_types1.rs new file mode 100644 index 0000000..c3d11fe --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types1.rs @@ -0,0 +1,17 @@ +// primitive_types1.rs +// Fill in the rest of the line that has code missing! +// No hints, there's no tricks, just get used to typing these :) + +fn main() { + // Booleans (`bool`) + + let is_morning = true; + if is_morning { + println!("Good morning!"); + } + + let // Finish the rest of this line like the example! Or make it be false! + if is_evening { + println!("Good evening!"); + } +} diff --git a/old_curriculum/primitive_types/primitive_types2.rs b/old_curriculum/primitive_types/primitive_types2.rs new file mode 100644 index 0000000..f5c8f87 --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types2.rs @@ -0,0 +1,27 @@ +// primitive_types2.rs +// Fill in the rest of the line that has code missing! +// No hints, there's no tricks, just get used to typing these :) + +fn main() { + // Characters (`char`) + + let my_first_initial = 'C'; + if my_first_initial.is_alphabetic() { + println!("Alphabetical!"); + } else if my_first_initial.is_numeric() { + println!("Numerical!"); + } else { + println!("Neither alphabetic nor numeric!"); + } + + let // Finish this line like the example! What's your favorite character? + // Try a letter, try a number, try a special character, try a character + // from a different language than your own, try an emoji! + if your_character.is_alphabetic() { + println!("Alphabetical!"); + } else if your_character.is_numeric() { + println!("Numerical!"); + } else { + println!("Neither alphabetic nor numeric!"); + } +} diff --git a/old_curriculum/primitive_types/primitive_types3.rs b/old_curriculum/primitive_types/primitive_types3.rs new file mode 100644 index 0000000..a2f9b3b --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types3.rs @@ -0,0 +1,46 @@ +// primitive_types3.rs +// Create an array with at least 100 elements in it where the ??? is. +// Scroll down for hints! + +fn main() { + let a = ??? + + if a.len() >= 100 { + println!("Wow, that's a big array!"); + } else { + println!("Meh, I eat arrays like that for breakfast."); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +// There's a shorthand to initialize Arrays with a certain size that does not +// require you to type in 100 items (but you certainly can if you want!) +// Check out the Primitive Types -> Arrays section of the book: +// https://doc.rust-lang.org/stable/book/second-edition/ch03-02-data-types.html#arrays +// Bonus: what are some other things you could have that would return true +// for `a.len() >= 100`? diff --git a/old_curriculum/primitive_types/primitive_types4.rs b/old_curriculum/primitive_types/primitive_types4.rs new file mode 100644 index 0000000..c20b63b --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types4.rs @@ -0,0 +1,49 @@ +// primitive_types4.rs +// Get a slice out of Array a where the ??? is so that the `if` statement +// returns true. Scroll down for hints!! + +fn main() { + let a = [1, 2, 3, 4, 5]; + + let nice_slice = ??? + + if nice_slice == [2, 3, 4] { + println!("Nice slice!"); + } else { + println!("Not quite what I was expecting... I see: {:?}", nice_slice); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + +// Take a look at the Primitive Types -> Slices section of the book: +// http://doc.rust-lang.org/stable/book/primitive-types.html#slices +// and use the starting and ending indices of the items in the Array +// that you want to end up in the slice. + +// If you're curious why the right hand of the `==` comparison does not +// have an ampersand for a reference since the left hand side is a +// reference, take a look at the Deref coercions chapter: +// http://doc.rust-lang.org/stable/book/deref-coercions.html diff --git a/old_curriculum/primitive_types/primitive_types5.rs b/old_curriculum/primitive_types/primitive_types5.rs new file mode 100644 index 0000000..14c2fd2 --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types5.rs @@ -0,0 +1,45 @@ +// primitive_types5.rs +// Destructure the `cat` tuple so that the println will work. +// Scroll down for hints! + +fn main() { + let cat = ("Furry McFurson", 3.5); + let /* your pattern here */ = cat; + + println!("{} is {} years old.", name, age); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Take a look at the Primitive Types -> Tuples section of the book: +// http://doc.rust-lang.org/stable/book/primitive-types.html#tuples +// Particularly the part about "destructuring lets". You'll need to +// make a pattern to bind `name` and `age` to the appropriate parts +// of the tuple. You can do it!! diff --git a/old_curriculum/primitive_types/primitive_types6.rs b/old_curriculum/primitive_types/primitive_types6.rs new file mode 100644 index 0000000..d016642 --- /dev/null +++ b/old_curriculum/primitive_types/primitive_types6.rs @@ -0,0 +1,44 @@ +// primitive_types6.rs +// Use a tuple index to access the second element of `numbers`. +// You can put this right into the `println!` where the ??? is. +// Scroll down for hints! + +fn main() { + let numbers = (1, 2, 3); + println!("The second number is {}", ???); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// While you could use a destructuring `let` for the tuple here, try +// indexing into it instead, as explained here: +// http://doc.rust-lang.org/stable/book/primitive-types.html#tuple-indexing +// Now you have another tool in your toolbox! diff --git a/old_curriculum/src/bin/generate_readme.rs b/old_curriculum/src/bin/generate_readme.rs new file mode 100644 index 0000000..a502fea --- /dev/null +++ b/old_curriculum/src/bin/generate_readme.rs @@ -0,0 +1,49 @@ +// This script reads README-template.md and generates the playground links +// from the Rust source files in the various directories. + +// To add a new exercise, add it to the appropriate place in README-template.md +// and then make sure to recompile this script (because the template gets +// included at compile time and then run it to generate a new version of +// README.md. + +extern crate handlebars; +extern crate prlink; +#[macro_use] +extern crate serde_json; + +use handlebars::{Handlebars, Helper, RenderContext, RenderError}; + +use std::fs::File; +use std::io::prelude::*; +use std::path::PathBuf; + +fn main() { + let mut template_file = File::open("README-template.hbs").unwrap(); + let mut template = String::new(); + template_file.read_to_string(&mut template).unwrap(); + + let autogenerated_notice = "This file was autogenerated by the script in src/bin/generate_readme.rs. +Please edit either the script or the template in README-template.md in +order to make changes here rather than committing the changes directly."; + + let mut generated_readme = File::create("README.md").unwrap(); + + let mut hbs = Handlebars::new(); + hbs.register_helper("playground_link", Box::new(playground_link_helper)); + + write!( + generated_readme, + "{}", + hbs.render_template( + &template, + &json!({ "autogenerated_notice": autogenerated_notice }), + ).unwrap() + ).unwrap(); +} + +fn playground_link_helper(h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> { + let filename = PathBuf::from(h.param(0).unwrap().value().as_str().unwrap()); + let link = prlink::linkify_file(&filename); + rc.writer.write(link.into_bytes().as_ref())?; + Ok(()) +} diff --git a/old_curriculum/standard_library_types/arc1.rs b/old_curriculum/standard_library_types/arc1.rs new file mode 100644 index 0000000..c744a10 --- /dev/null +++ b/old_curriculum/standard_library_types/arc1.rs @@ -0,0 +1,56 @@ +// arc1.rs +// Make this code compile by filling in a value for `shared_numbers` where the +// TODO comment is and creating an initial binding for `child_numbers` +// somewhere. Try not to create any copies of the `numbers` Vec! +// Scroll down for hints :) + +use std::sync::Arc; +use std::thread; + +fn main() { + let numbers: Vec<_> = (0..100u32).collect(); + let shared_numbers = // TODO + let mut joinhandles = Vec::new(); + + for offset in 0..8 { + joinhandles.push( + thread::spawn(move || { + let mut i = offset; + let mut sum = 0; + while i < child_numbers.len() { + sum += child_numbers[i]; + i += 5; + } + println!("Sum of offset {} is {}", offset, sum); + })); + } + for handle in joinhandles.into_iter() { + handle.join().unwrap(); + } +} + + + + + + + + + + + + + + + + + + + + +// Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order +// to avoid creating a copy of `numbers`, you'll need to create `child_numbers` +// inside the loop but still in the main thread. + +// `child_numbers` should be a clone of the Arc of the numbers instead of a +// thread-local copy of the numbers. diff --git a/old_curriculum/standard_library_types/iterator3.rs b/old_curriculum/standard_library_types/iterator3.rs new file mode 100644 index 0000000..e973ac6 --- /dev/null +++ b/old_curriculum/standard_library_types/iterator3.rs @@ -0,0 +1,145 @@ +// iterator3.rs +// This is a bigger exercise than most of the others! You can do it! +// Here is your mission, should you choose to accept it: +// 1. Complete the divide function to get the first four tests to pass +// 2. Uncomment the last two tests and get them to pass by filling in +// values for `x` using `division_results`. +// Scroll down for a minor hint for part 2, and scroll down further for +// a major hint. +// Have fun :-) + +#[derive(Debug, PartialEq, Eq)] +pub enum DivisionError { + NotDivisible(NotDivisibleError), + DivideByZero, +} + +#[derive(Debug, PartialEq, Eq)] +pub struct NotDivisibleError { + dividend: i32, + divisor: i32, +} + +// This function should calculate `a` divided by `b` if `a` is +// evenly divisible by b. +// Otherwise, it should return a suitable error. +pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> { +} + +#[cfg(test)] +mod tests { + use super::*; + + // Tests that verify your `divide` function implementation + #[test] + fn test_success() { + assert_eq!(divide(81, 9), Ok(9)); + } + + #[test] + fn test_not_divisible() { + assert_eq!( + divide(81, 6), + Err(DivisionError::NotDivisible(NotDivisibleError{ + dividend: 81, + divisor: 6 + })) + ); + } + + #[test] + fn test_divide_by_0() { + assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero)); + } + + #[test] + fn test_divide_0_by_something() { + assert_eq!(divide(0, 81), Ok(0)); + } + + // Iterator exercises using your `divide` function + /* + #[test] + fn result_with_list() { + let numbers = vec![27, 297, 38502, 81]; + let division_results = numbers.into_iter().map(|n| divide(n, 27)); + let x //... Fill in here! + assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])"); + } + + #[test] + fn list_of_results() { + let numbers = vec![27, 297, 38502, 81]; + let division_results = numbers.into_iter().map(|n| divide(n, 27)); + let x //... Fill in here! + assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]"); + } + */ +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Minor hint: In each of the two cases in the match in main, you can create x with either a 'turbofish' or by hinting the type of x to the compiler. You may try both. + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Major hint: Have a look at the Iter trait and at the explanation of its collect function. Especially the part about Result is interesting. diff --git a/old_curriculum/standard_library_types/iterators4.rs b/old_curriculum/standard_library_types/iterators4.rs new file mode 100644 index 0000000..13613a6 --- /dev/null +++ b/old_curriculum/standard_library_types/iterators4.rs @@ -0,0 +1,61 @@ +// iterators4.rs + +pub fn factorial(num: u64) -> u64 { + // Complete this function to return factorial of num + // Do not use: + // - return + // For extra fun don't use: + // - imperative style loops (for, while) + // - additional variables + // For the most fun don't use: + // - recursion + // Scroll down for hints. +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn factorial_of_1() { + assert_eq!(1, factorial(1)); + } + #[test] + fn factorial_of_2() { + assert_eq!(2, factorial(2)); + } + + #[test] + fn factorial_of_4() { + assert_eq!(24, factorial(4)); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + +// In an imperative language you might write a for loop to iterate through +// multiply the values into a mutable variable. Or you might write code more +// functionally with recursion and a match clause. But you can also use ranges +// and iterators to solve this in rust. diff --git a/old_curriculum/strings/strings1.rs b/old_curriculum/strings/strings1.rs new file mode 100644 index 0000000..2e5088f --- /dev/null +++ b/old_curriculum/strings/strings1.rs @@ -0,0 +1,46 @@ +// strings1.rs +// Make me compile without changing the function signature! Scroll down for hints :) + +fn main() { + let answer = current_favorite_color(); + println!("My current favorite color is {}", answer); +} + +fn current_favorite_color() -> String { + "blue" +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// The `current_favorite_color` function is currently returning a string slice with the `'static` +// lifetime. We know this because the data of the string lives in our code itself -- it doesn't +// come from a file or user input or another program -- so it will live as long as our program +// lives. But it is still a string slice. There's one way to create a `String` by converting a +// string slice covered in the Strings chapter of the book, and another way that uses the `From` +// trait. diff --git a/old_curriculum/strings/strings2.rs b/old_curriculum/strings/strings2.rs new file mode 100644 index 0000000..c77e16f --- /dev/null +++ b/old_curriculum/strings/strings2.rs @@ -0,0 +1,44 @@ +// strings2.rs +// Make me compile without changing the function signature! Scroll down for hints :) + +fn main() { + let word = String::from("green"); // Try not changing this line :) + if is_a_color_word(word) { + println!("That is a color word I know!"); + } else { + println!("That is not a color word I know."); + } +} + +fn is_a_color_word(attempt: &str) -> bool { + attempt == "green" || attempt == "blue" || attempt == "red" +} + + + + + + + + + + + + + + + + + + + + + + + + + + +// Yes, it would be really easy to fix this by just changing the value bound to `word` to be a +// string slice instead of a `String`, wouldn't it?? There is a way to add one character to line +// 6, though, that will coerce the `String` into a string slice. diff --git a/old_curriculum/strings/strings3.rs b/old_curriculum/strings/strings3.rs new file mode 100644 index 0000000..b6f6a1e --- /dev/null +++ b/old_curriculum/strings/strings3.rs @@ -0,0 +1,21 @@ +// strings3.rs +// Ok, here are a bunch of values-- some are `Strings`, some are `&strs`. Your +// task is to call one of these two functions on each value depending on what +// you think each value is. That is, add either `string_slice` or `string` +// before the parentheses on each line. If you're right, it will compile! + +fn string_slice(arg: &str) { println!("{}", arg); } +fn string(arg: String) { println!("{}", arg); } + +fn main() { + ("blue"); + ("red".to_string()); + (String::from("hi")); + ("rust is fun!".to_owned()); + ("nice weather".into()); + (format!("Interpolation {}", "Station")); + (&String::from("abc")[0..1]); + (" hello there ".trim()); + ("Happy Monday!".to_string().replace("Mon", "Tues")); + ("mY sHiFt KeY iS sTiCkY".to_lowercase()); +} diff --git a/old_curriculum/tests/tests1.rs b/old_curriculum/tests/tests1.rs new file mode 100644 index 0000000..959ed85 --- /dev/null +++ b/old_curriculum/tests/tests1.rs @@ -0,0 +1,49 @@ +// tests1.rs +// Tests are important to ensure that your code does what you think it should do. +// Tests can be run on this file with the following command: +// rustc --test tests1.rs + +// This test has a problem with it -- make the test compile! Make the test +// pass! Make the test fail! Scroll down for hints :) + +#[cfg(test)] +mod tests { + #[test] + fn you_can_assert() { + assert!(); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// You don't even need to write any code to test -- you can just test values and run that, even +// though you wouldn't do that in real life :) `assert!` is a macro that needs an argument. +// Depending on the value of the argument, `assert!` will do nothing (in which case the test will +// pass) or `assert!` will panic (in which case the test will fail). So try giving different values +// to `assert!` and see which ones compile, which ones pass, and which ones fail :) diff --git a/old_curriculum/tests/tests2.rs b/old_curriculum/tests/tests2.rs new file mode 100644 index 0000000..6775d61 --- /dev/null +++ b/old_curriculum/tests/tests2.rs @@ -0,0 +1,44 @@ +// tests2.rs +// This test has a problem with it -- make the test compile! Make the test +// pass! Make the test fail! Scroll down for hints :) + +#[cfg(test)] +mod tests { + #[test] + fn you_can_assert_eq() { + assert_eq!(); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Like the previous exercise, you don't need to write any code to get this test to compile and +// run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two +// values that are equal! Try giving it two arguments that are different! Try giving it two values +// that are of different types! Try switching which argument comes first and which comes second! diff --git a/old_curriculum/tests/tests3.rs b/old_curriculum/tests/tests3.rs new file mode 100644 index 0000000..e041f38 --- /dev/null +++ b/old_curriculum/tests/tests3.rs @@ -0,0 +1,43 @@ +// tests3.rs +// This test isn't testing our function -- make it do that in such a way that +// the test passes. Then write a second test that tests that we get the result +// we expect to get when we call `is_even(5)`. Scroll down for hints! + +pub fn is_even(num: i32) -> bool { + num % 2 == 0 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn is_true_when_even() { + assert!(false); + } +} + + + + + + + + + + + + + + + + + + + + + + +// You can call a function right where you're passing arguments to `assert!` -- so you could do +// something like `assert!(having_fun())`. If you want to check that you indeed get false, you +// can negate the result of what you're doing using `!`, like `assert!(!having_fun())`. diff --git a/old_curriculum/tests/tests4.rs b/old_curriculum/tests/tests4.rs new file mode 100644 index 0000000..23d444a --- /dev/null +++ b/old_curriculum/tests/tests4.rs @@ -0,0 +1,19 @@ +// tests4.rs +// This test isn't testing our function -- make it do that in such a way that +// the test passes. Then write a second test that tests that we get the result +// we expect to get when we call `times_two` with a negative number. +// No hints, you can do this :) + +pub fn times_two(num: i32) -> i32 { + num * 2 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn returns_twice_of_positive_numbers() { + assert_eq!(4, 4); + } +} diff --git a/old_curriculum/threads/threads1.rs b/old_curriculum/threads/threads1.rs new file mode 100644 index 0000000..b4a5dc9 --- /dev/null +++ b/old_curriculum/threads/threads1.rs @@ -0,0 +1,95 @@ +// threads1.rs +// Make this compile! Scroll down for hints :) The idea is the thread +// spawned on line 19 is completing jobs while the main thread is +// monitoring progress until 10 jobs are completed. If you see 6 lines +// of "waiting..." and the program ends without timing out the playground, +// you've got it :) + +use std::sync::Arc; +use std::thread; +use std::time::Duration; + +struct JobStatus { + jobs_completed: u32, +} + +fn main() { + let status = Arc::new(JobStatus { jobs_completed: 0 }); + let status_shared = status.clone(); + thread::spawn(move || { + for _ in 0..10 { + thread::sleep(Duration::from_millis(250)); + status_shared.jobs_completed += 1; + } + }); + while status.jobs_completed < 10 { + println!("waiting... "); + thread::sleep(Duration::from_millis(500)); + } +} + + + + + + + + + + + + + + +// `Arc` is an Atomic Reference Counted pointer that allows safe, shared access +// to **immutable** data. But we want to *change* the number of `jobs_completed` +// so we'll need to also use another type that will only allow one thread to +// mutate the data at a time. Take a look at this section of the book: +// https://doc.rust-lang.org/stable/book/concurrency.html#safe-shared-mutable-state +// and keep scrolling if you'd like more hints :) + + + + + + + + + + +// Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: +// `let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` +// Similar to the code in the example in the book that happens after the text +// that says "We can use Arc<T> to fix this.". If not, give that a try! If you +// do and would like more hints, keep scrolling!! + + + + + + + + + + + + +// Make sure neither of your threads are holding onto the lock of the mutex +// while they are sleeping, since this will prevent the other thread from +// being allowed to get the lock. Locks are automatically released when +// they go out of scope. + +// Ok, so, real talk, this was actually tricky for *me* to do too. And +// I could see a lot of different problems you might run into, so at this +// point I'm not sure which one you've hit :) Please see a few possible +// answers on https://github.com/carols10cents/rustlings/issues/3 -- +// mine is a little more complicated because I decided I wanted to see +// the number of jobs currently done when I was checking the status. + +// Please open an issue if you're still running into a problem that +// these hints are not helping you with, or if you've looked at the sample +// answers and don't understand why they work and yours doesn't. + +// If you've learned from the sample solutions, I encourage you to come +// back to this exercise and try it again in a few days to reinforce +// what you've learned :) diff --git a/old_curriculum/variables/variables1.rs b/old_curriculum/variables/variables1.rs new file mode 100644 index 0000000..1cdd270 --- /dev/null +++ b/old_curriculum/variables/variables1.rs @@ -0,0 +1,42 @@ +// variables1.rs +// Make me compile! Scroll down for hints :) + +fn main() { + x = 5; + println!("x has the value {}", x); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Hint: The declaration on line 5 is missing a keyword that is needed in Rust +// to create a new variable binding. diff --git a/old_curriculum/variables/variables2.rs b/old_curriculum/variables/variables2.rs new file mode 100644 index 0000000..a0b4a37 --- /dev/null +++ b/old_curriculum/variables/variables2.rs @@ -0,0 +1,47 @@ +// variables2.rs +// Make me compile! Scroll down for hints :) + +fn main() { + let x; + if x == 10 { + println!("Ten!"); + } else { + println!("Not ten!"); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// The compiler message is saying that Rust cannot infer the type that the +// variable binding `x` has with what is given here. +// What happens if you annotate line 5 with a type annotation? +// What if you give x a value? +// What if you do both? +// What type should x be, anyway? +// What if x is the same type as 10? What if it's a different type? diff --git a/old_curriculum/variables/variables3.rs b/old_curriculum/variables/variables3.rs new file mode 100644 index 0000000..165a277 --- /dev/null +++ b/old_curriculum/variables/variables3.rs @@ -0,0 +1,43 @@ +// variables3.rs +// Make me compile! Scroll down for hints :) + +fn main() { + let x = 3; + println!("Number {}", x); + x = 5; + println!("Number {}", x); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// In Rust, variable bindings are immutable by default. But here we're trying +// to reassign a different value to x! There's a keyword we can use to make +// a variable binding mutable instead. diff --git a/old_curriculum/variables/variables4.rs b/old_curriculum/variables/variables4.rs new file mode 100644 index 0000000..71ebf0f --- /dev/null +++ b/old_curriculum/variables/variables4.rs @@ -0,0 +1,45 @@ +// variables4.rs +// Make me compile! Scroll down for hints :) + +fn main() { + let x: i32; + println!("Number {}", x); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Oops! In this exercise, we have a variable binding that we've created on +// line 5, and we're trying to use it on line 6, but we haven't given it a +// value. We can't print out something that isn't there; try giving x a value! +// This is an error that can cause bugs that's very easy to make in any +// programming language -- thankfully the Rust compiler has caught this for us! |
