├── class-20210422 ├── .gitignore ├── src │ ├── lib.rs │ ├── borrow_iter │ │ └── index_graph.rs │ ├── borrow_iter.rs │ └── interior_mut.rs └── Cargo.toml ├── 04-ownership ├── src │ ├── lib.rs │ ├── bst.rs │ └── list_set.rs ├── Cargo.toml ├── .idea │ └── runConfigurations │ │ ├── Cargo_test.xml │ │ ├── Cargo_check.xml │ │ └── Cargo_clippy.xml └── Cargo.lock ├── README.md ├── 01-ub ├── Cargo.toml ├── Cargo.lock ├── examples │ ├── div_mul.rs │ ├── iterator.rs │ └── int_max.rs ├── cxx-src │ ├── array.cxx │ ├── uninitialized.cxx │ ├── div_mul.cpp │ ├── iterator.cxx │ └── int_max.cxx ├── CMakeLists.txt └── .idea │ └── runConfigurations │ ├── Run_div_mul.xml │ ├── Run_int_max.xml │ └── Run_iterator.xml ├── 03-rainfall ├── Cargo.toml ├── Cargo.lock ├── CMakeLists.txt ├── cxx-src │ └── rainfall.cxx └── src │ └── main.rs └── .gitignore /class-20210422/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /04-ownership/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod list_set; 2 | pub mod bst; 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code Samples 2 | 3 | Each subdirectory here is a separate project. 4 | -------------------------------------------------------------------------------- /01-ub/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ub" 3 | version = "0.1.0" 4 | authors = ["Jesse A. Tov "] 5 | edition = "2018" 6 | -------------------------------------------------------------------------------- /03-rainfall/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rainfall" 3 | version = "0.1.0" 4 | authors = ["Jesse A. Tov "] 5 | edition = "2018" 6 | -------------------------------------------------------------------------------- /01-ub/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ub" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /03-rainfall/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "rainfall" 5 | version = "0.1.0" 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CMake build directories: 2 | cmake-build-*/ 3 | build/ 4 | build.*/ 5 | 6 | # IDEA config 7 | .idea/ 8 | 9 | # Cargo/Rust build directory: 10 | target/ 11 | 12 | # Assembly output: 13 | *.s 14 | -------------------------------------------------------------------------------- /04-ownership/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ownership" 3 | version = "0.1.0" 4 | authors = ["Jesse A. Tov "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | quickcheck = { version = "0.8", optional = true } 9 | 10 | [dev-dependencies] 11 | quickcheck = "0.8" 12 | -------------------------------------------------------------------------------- /class-20210422/src/lib.rs: -------------------------------------------------------------------------------- 1 | ///! Examples from class on Thursday, 22 April. 2 | 3 | /// Example of a borrowing iterator. 4 | mod borrow_iter; 5 | pub use borrow_iter::*; 6 | 7 | /// Example of a linked list using interior mutability. 8 | mod interior_mut; 9 | pub use interior_mut::*; 10 | -------------------------------------------------------------------------------- /01-ub/examples/div_mul.rs: -------------------------------------------------------------------------------- 1 | fn identity(x: i32, y: i32) -> i32 { 2 | x * y / y 3 | } 4 | 5 | fn print_identity(x: i32, y: i32) { 6 | println!("identity({}, {}) == {}", x, y, identity(x, y)); 7 | } 8 | 9 | fn main() { 10 | print_identity(7, 5); 11 | print_identity(7, 0); 12 | } -------------------------------------------------------------------------------- /class-20210422/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "class-20210422" 3 | version = "0.1.0" 4 | authors = ["Jesse A. Tov "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /01-ub/cxx-src/array.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int f(int i) 4 | { 5 | // Try changing the size on the next line from 3 to 1. 6 | int array[3] = {0}; 7 | array[i] = 12; 8 | return array[i] + array[0]; 9 | } 10 | 11 | int main() 12 | { 13 | for (int i = 0; i < 8; ++i) 14 | std::cout << f(i) << '\n'; 15 | } -------------------------------------------------------------------------------- /01-ub/examples/iterator.rs: -------------------------------------------------------------------------------- 1 | fn double_repeat(v: &mut Vec) { 2 | let mut w = Vec::new(); 3 | 4 | for i in v.iter_mut() { 5 | *i *= 2; 6 | w.push(*i); 7 | } 8 | 9 | v.extend(w); 10 | } 11 | 12 | fn main() { 13 | let mut v = vec![1, 2, 3, 4, 5]; 14 | double_repeat(&mut v); 15 | println!("{:?}", v); 16 | } 17 | -------------------------------------------------------------------------------- /01-ub/cxx-src/uninitialized.cxx: -------------------------------------------------------------------------------- 1 | // You know what's faster than conditionally initializing a variable? 2 | // Unconditionally initializing a variable. 3 | 4 | #include 5 | 6 | int f(bool init) 7 | { 8 | int x; 9 | 10 | if (init) x = 4; 11 | 12 | return x; 13 | } 14 | 15 | int main() 16 | { 17 | std::cout << f(false) << "\n"; 18 | } -------------------------------------------------------------------------------- /03-rainfall/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(rainfall CXX) 3 | 4 | macro (add_program name) 5 | add_executable(${name} ${ARGN}) 6 | set_target_properties(${name} PROPERTIES 7 | CXX_STANDARD 17 8 | CXX_STANDARD_REQUIRED On 9 | CXX_EXTENSIONS Off) 10 | endmacro (add_program) 11 | 12 | add_program(rainfall cxx-src/rainfall.cxx) 13 | -------------------------------------------------------------------------------- /01-ub/examples/int_max.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | fn is_int_max(x: i32) -> bool { 4 | return x > x + 1; 5 | } 6 | 7 | fn better_is_int_max(x: i32) -> bool { 8 | return x > x.wrapping_add(1); 9 | } 10 | 11 | fn test_int(x: i32) { 12 | println!("{} is{} INT_MAX", x, 13 | if is_int_max(x) {""} else {"n't"}); 14 | } 15 | 16 | fn main() { 17 | test_int(5); 18 | test_int(std::i32::MAX); 19 | } 20 | -------------------------------------------------------------------------------- /01-ub/cxx-src/div_mul.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int identity(int x, int y) 5 | { 6 | return x * y / y; 7 | } 8 | 9 | void print_identity(int x, int y) 10 | { 11 | std::cout << "identity(" << x << ", " << y << ") == " 12 | << identity(x, y) << '\n'; 13 | } 14 | 15 | int main() 16 | { 17 | print_identity(7, 5); 18 | print_identity(7, INT_MAX); 19 | print_identity(7, 0); 20 | } -------------------------------------------------------------------------------- /01-ub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(ub CXX) 3 | 4 | macro (add_program name) 5 | add_executable(${name} ${ARGN}) 6 | set_target_properties(${name} PROPERTIES 7 | CXX_STANDARD 17 8 | CXX_STANDARD_REQUIRED On 9 | CXX_EXTENSIONS Off) 10 | endmacro (add_program) 11 | 12 | add_program(div_mul cxx-src/div_mul.cpp) 13 | add_program(int_max cxx-src/int_max.cxx) 14 | add_program(uninitialized cxx-src/uninitialized.cxx) 15 | add_program(array cxx-src/array.cxx) 16 | add_program(iterator cxx-src/iterator.cxx) 17 | -------------------------------------------------------------------------------- /01-ub/cxx-src/iterator.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void double_repeat(std::vector& v) 5 | { 6 | for (int& each: v) { 7 | each *= 2; 8 | v.push_back(each); 9 | } 10 | } 11 | 12 | template 13 | void print_vec(const std::vector& v) 14 | { 15 | std::cout << "{ "; 16 | for (const T& each: v) std::cout << each << ", "; 17 | std::cout << "}\n"; 18 | } 19 | 20 | int main () 21 | { 22 | std::vector v{1, 2, 3, 4, 5}; 23 | v.reserve(10); // comment out this line for different behavior 24 | double_repeat(v); 25 | print_vec(v); 26 | } -------------------------------------------------------------------------------- /class-20210422/src/borrow_iter/index_graph.rs: -------------------------------------------------------------------------------- 1 | pub trait IndexGraph<'a> { 2 | type Neighbors: Iterator; 3 | 4 | fn len(&self) -> usize; 5 | 6 | fn is_empty(&self) -> bool { 7 | self.len() == 0 8 | } 9 | 10 | fn new_vertex(&mut self) -> usize; 11 | 12 | fn set_edge(&mut self, u: usize, v: usize, present: bool); 13 | 14 | fn add_edge(&mut self, u: usize, v: usize) { 15 | self.set_edge(u, v, true); 16 | } 17 | 18 | fn remove_edge(&mut self, u: usize, v: usize) { 19 | self.set_edge(u, v, false); 20 | } 21 | 22 | fn has_edge(&self, u: usize, v: usize) -> bool; 23 | 24 | fn neighbors(&'a self, v: usize) -> Self::Neighbors; 25 | } 26 | -------------------------------------------------------------------------------- /04-ownership/.idea/runConfigurations/Cargo_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /04-ownership/.idea/runConfigurations/Cargo_check.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /04-ownership/.idea/runConfigurations/Cargo_clippy.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /01-ub/.idea/runConfigurations/Run_div_mul.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /01-ub/.idea/runConfigurations/Run_int_max.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /01-ub/.idea/runConfigurations/Run_iterator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /01-ub/cxx-src/int_max.cxx: -------------------------------------------------------------------------------- 1 | // This demonstates that integer overflow is undefined (but unsigned integers 2 | // wrap, which is defined). You will likely only observe the behavior if you 3 | // compile in release mode. 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | bool is_int_max(int x) 11 | { 12 | return x + 1 < x; 13 | } 14 | 15 | void test(int x) 16 | { 17 | cout << x << (is_int_max(x)? " is INT_MAX\n" : " isn't INT_MAX\n"); 18 | } 19 | 20 | bool is_uint_max(unsigned int x) 21 | { 22 | return x + 1u < x; 23 | } 24 | 25 | void test(unsigned int x) 26 | { 27 | cout << x << (is_uint_max(x)? " is UINT_MAX\n" : " isn't UINT_MAX\n"); 28 | } 29 | 30 | int main() 31 | { 32 | test(INT_MAX); 33 | test(UINT_MAX); 34 | } 35 | -------------------------------------------------------------------------------- /03-rainfall/cxx-src/rainfall.cxx: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // x1. Read from stdin. 6 | // x2. Split into lines. 7 | // x3. Detect sentinel "999". 8 | // x4. Convert strings to f64. 9 | // x5. Cull invalid input. 10 | // x6. Calculate mean 11 | // x7. Count intervals (second pass; requires storage) 12 | 13 | std::vector 14 | get_readings(std::istream& input) 15 | { 16 | std::vector result; 17 | std::string line; 18 | 19 | while (std::getline(input, line) && line != "999") { 20 | std::istringstream iss(line); 21 | if (double reading; iss >> reading && reading >= 0) { 22 | result.push_back(reading); 23 | } 24 | } 25 | 26 | return result; 27 | } 28 | 29 | double mean(std::vector const& readings) 30 | { 31 | double sum = 0.0; 32 | for (auto d : readings) sum += d; 33 | return sum / readings.size(); 34 | } 35 | 36 | std::pair 37 | count_ranges(double mean, 38 | std::vector const& readings) 39 | { 40 | size_t below = 0, above = 0; 41 | 42 | for (auto d : readings) { 43 | if (mean - 5 <= d && d < mean) ++below; 44 | if (mean < d && d <= mean + 5) ++above; 45 | } 46 | 47 | return {below, above}; 48 | } 49 | 50 | int main() 51 | { 52 | auto readings = get_readings(std::cin); 53 | auto m = mean(readings); 54 | auto counts = count_ranges(m, readings); 55 | 56 | std::cout 57 | << "Mean: " << m << "\n" 58 | << "Below: " << counts.first << "\n" 59 | << "Above: " << counts.second << "\n"; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /03-rainfall/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::BufRead; 2 | 3 | fn main() { 4 | let numbers = get_readings(std::io::stdin().lock()); 5 | println!("{:?}", numbers); 6 | } 7 | 8 | fn get_readings(input: impl BufRead) -> Vec { 9 | input.lines() 10 | .map(Result::unwrap) 11 | .take_while(|s| s != "999") 12 | .filter_map(|s| 13 | match s.parse() { 14 | Ok(f) if f >= 0.0 => Some(f), 15 | _ => None, 16 | }) 17 | .collect() 18 | } 19 | 20 | /* 21 | std::vector 22 | get_readings(std::istream& input) 23 | { 24 | std::vector result; 25 | std::string line; 26 | 27 | while (std::getline(input, line) && line != "999") { 28 | std::istringstream iss(line); 29 | if (double reading; iss >> reading && reading >= 0) { 30 | result.push_back(reading); 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | */ 37 | 38 | fn mean(readings: &[f64]) -> f64 { 39 | let mut sum = 0.0; 40 | 41 | for d in readings { 42 | sum += *d; 43 | } 44 | 45 | sum / readings.len() as f64 46 | } 47 | 48 | #[test] 49 | fn mean_works() { 50 | assert_eq!( mean(&[7.0, 8.0, 9.0]), 8.0 ); 51 | } 52 | 53 | fn count_ranges(mean: f64, readings: &[f64]) -> (usize, usize) { 54 | // let mut below = 0; 55 | // let mut above = 0; 56 | // 57 | // for &d in readings { 58 | // if mean - 5. <= d && d < mean { below += 1; } 59 | // if mean < d && d <= mean + 5. { above += 1; } 60 | // } 61 | // 62 | // (below, above); 63 | 64 | (readings.iter().copied().filter(|d| mean - 5. <= *d && *d < mean).count(), 65 | readings.iter().copied().filter(|d| mean < *d && *d <= mean + 5.).count()) 66 | } 67 | 68 | /* 69 | int main() 70 | { 71 | auto readings = get_readings(std::cin); 72 | auto m = mean(readings); 73 | auto counts = count_ranges(m, readings); 74 | 75 | std::cout 76 | << "Mean: " << m << "\n" 77 | << "Below: " << counts.first << "\n" 78 | << "Above: " << counts.second << "\n"; 79 | } 80 | 81 | */ -------------------------------------------------------------------------------- /04-ownership/src/bst.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering::*; 2 | use std::mem; 3 | 4 | #[derive(Debug)] 5 | pub struct BST(Link); 6 | 7 | #[derive(Debug)] 8 | struct Node { 9 | key: K, 10 | value: V, 11 | left: Link, 12 | right: Link, 13 | } 14 | 15 | type Link = Option>>; 16 | 17 | impl BST { 18 | pub fn new() -> Self { 19 | BST(None) 20 | } 21 | 22 | pub fn is_empty(&self) -> bool { 23 | self.0.is_none() 24 | } 25 | 26 | pub fn len(&self) -> usize { 27 | Node::len_iter(&self.0) 28 | } 29 | } 30 | 31 | impl Default for BST { 32 | fn default() -> Self { 33 | BST::new() 34 | } 35 | } 36 | 37 | impl BST { 38 | pub fn find(&self, key: &K) -> Option<&V> { 39 | Node::find_iter(&self.0, key) } 40 | 41 | pub fn find_mut(&mut self, key: &K) -> Option<&mut V> { 42 | Node::find_mut_iter(&mut self.0, key) 43 | } 44 | 45 | pub fn insert(&mut self, key: K, value: V) -> Option<(K, V)> { 46 | Node::insert_iter(&mut self.0, key, value) 47 | } 48 | } 49 | 50 | impl Node { 51 | fn new(key: K, value: V) -> Box { 52 | Box::new(Node { 53 | key, 54 | value, 55 | left: None, 56 | right: None, 57 | }) 58 | } 59 | 60 | #[allow(dead_code)] 61 | fn len_rec(ptr: &Link) -> usize { 62 | if let Some(ref node_ptr) = *ptr { 63 | 1 + Node::len_rec(&node_ptr.left) + Node::len_rec(&node_ptr.right) 64 | } else {0} 65 | } 66 | 67 | fn len_iter(ptr: &Link) -> usize { 68 | let mut result = 0; 69 | let mut stack = vec![ptr]; 70 | 71 | while let Some(each) = stack.pop() { 72 | if let Some(ref node_ptr) = *each { 73 | result += 1; 74 | stack.push(&node_ptr.left); 75 | stack.push(&node_ptr.right); 76 | } 77 | } 78 | 79 | result 80 | } 81 | } 82 | 83 | impl Node { 84 | #[allow(dead_code)] 85 | fn find_rec<'a, 'b>(ptr: &'a Link, key: &'b K) -> Option<&'a V> { 86 | if let Some(ref n) = *ptr { 87 | match key.cmp(&n.key) { 88 | Less => Node::find_rec(&n.left, key), 89 | Greater => Node::find_rec(&n.right, key), 90 | Equal => Some(&n.value), 91 | } 92 | } else {None} 93 | } 94 | 95 | fn find_iter<'a, 'b>(mut ptr: &'a Link, key: &'b K) 96 | -> Option<&'a V> 97 | { 98 | while let Some(ref n) = *ptr { 99 | match key.cmp(&n.key) { 100 | Less => { ptr = &n.left; } 101 | Greater => { ptr = &n.right; } 102 | Equal => { return Some(&n.value); } 103 | } 104 | } 105 | 106 | None 107 | } 108 | 109 | #[allow(dead_code)] 110 | fn find_mut_rec<'a, 'b>(ptr: &'a mut Link, key: &'b K) 111 | -> Option<&'a mut V> 112 | { 113 | if let Some(ref mut n) = *ptr { 114 | match key.cmp(&n.key) { 115 | Less => Node::find_mut_rec(&mut n.left, key), 116 | Greater => Node::find_mut_rec(&mut n.right, key), 117 | Equal => Some(&mut n.value), 118 | } 119 | } else {None} 120 | } 121 | 122 | 123 | fn find_mut_iter<'a, 'b>(ptr: &'a mut Link, key: &'b K) 124 | -> Option<&'a mut V> 125 | { 126 | let mut cur = ptr.as_mut(); 127 | 128 | loop { 129 | if let Some(node) = cur.map(|node| &mut **node) { 130 | match key.cmp(&node.key) { 131 | Less => cur = node.left.as_mut(), 132 | Greater => cur = node.right.as_mut(), 133 | Equal => return Some(&mut node.value), 134 | } 135 | } else { 136 | return None; 137 | } 138 | } 139 | } 140 | 141 | #[allow(dead_code)] 142 | fn insert_rec(ptr: &mut Link, key: K, value: V) -> Option<(K, V)> { 143 | match *ptr { 144 | None => { 145 | *ptr = Some(Node::new(key, value)); 146 | None 147 | } 148 | 149 | Some(ref mut node_ptr) => { 150 | match key.cmp(&node_ptr.key) { 151 | Less => Node::insert_rec(&mut node_ptr.left, key, value), 152 | Greater => Node::insert_rec(&mut node_ptr.right, key, value), 153 | Equal => Some((mem::replace(&mut node_ptr.key, key), 154 | mem::replace(&mut node_ptr.value, value))), 155 | } 156 | } 157 | } 158 | } 159 | 160 | fn insert_iter(mut ptr: &mut Link, key: K, value: V) -> Option<(K, V)> { 161 | while ptr.is_some() { 162 | let node = {ptr}.as_mut().unwrap(); 163 | match key.cmp(&node.key) { 164 | Less => ptr = &mut node.left, 165 | Greater => ptr = &mut node.right, 166 | Equal => return Some((mem::replace(&mut node.key, key), 167 | mem::replace(&mut node.value, value))), 168 | } 169 | } 170 | 171 | *ptr = Some(Node::new(key, value)); 172 | None 173 | } 174 | } 175 | 176 | #[test] 177 | fn bst_test() { 178 | let mut bst = BST::new(); 179 | assert_eq!( bst.insert("one", 1), None ); 180 | assert_eq!( bst.insert("two", 2), None ); 181 | assert_eq!( bst.insert("three", 3), None ); 182 | 183 | assert_eq!( bst.find(&"one"), Some(&1) ); 184 | assert_eq!( bst.find(&"two"), Some(&2) ); 185 | assert_eq!( bst.find(&"three"), Some(&3) ); 186 | assert_eq!( bst.find(&"four"), None ); 187 | 188 | *bst.find_mut(&"three").unwrap() = 4; 189 | 190 | assert_eq!( bst.find(&"three"), Some(&4) ); 191 | 192 | assert_eq!( bst.insert("four", 7), None ); 193 | assert_eq!( bst.insert("four", 8), Some(("four", 7)) ); 194 | } 195 | -------------------------------------------------------------------------------- /class-20210422/src/borrow_iter.rs: -------------------------------------------------------------------------------- 1 | mod index_graph; 2 | 3 | pub use index_graph::IndexGraph; 4 | 5 | use std::collections::HashSet; 6 | 7 | /// Make edges abstract to enforce a representation invariant that makes 8 | /// each edge representation unique. In particular, we want that 9 | /// `Edge::new(u, v) == Edge::new(v, u)`. 10 | mod edge { 11 | pub type Vertex = usize; 12 | 13 | #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 14 | /// Graph edge with invariant that `u <= v`. 15 | pub struct Edge { 16 | u: Vertex, 17 | v: Vertex, 18 | } 19 | 20 | impl Edge { 21 | pub fn new(mut u: usize, mut v: usize) -> Self { 22 | if v < u { 23 | std::mem::swap(&mut u, &mut v); 24 | } 25 | Edge { u, v } 26 | } 27 | } 28 | } 29 | 30 | use edge::{Edge, Vertex}; 31 | 32 | #[derive(Clone, Debug, Eq, PartialEq)] 33 | pub struct EdgeSetGraph { 34 | len: usize, 35 | edges: HashSet, 36 | } 37 | 38 | impl EdgeSetGraph { 39 | pub fn new() -> Self { 40 | Self::with_vertices(0) 41 | } 42 | 43 | pub fn with_vertices(len: usize) -> Self { 44 | Self { 45 | len, 46 | edges: HashSet::new(), 47 | } 48 | } 49 | 50 | pub fn from_edges(edges: I) -> Self 51 | where 52 | I: IntoIterator, 53 | { 54 | let mut len = 0; 55 | let edges = edges 56 | .into_iter() 57 | .map(|(u, v)| { 58 | len = len.max(u + 1).max(v + 1); 59 | Edge::new(u, v) 60 | }) 61 | .collect(); 62 | 63 | Self { len, edges } 64 | } 65 | 66 | /// Bounds checks the two vertices and then returns the 67 | /// canonicalized edge. 68 | fn edge(&self, u: usize, v: usize) -> Edge { 69 | self.bounds_check(u); 70 | self.bounds_check(v); 71 | Edge::new(u, v) 72 | } 73 | 74 | /// Bounds checks a vertex, panicking if out of bounds. 75 | fn bounds_check(&self, v: usize) { 76 | assert!( 77 | v < self.len(), 78 | "Vertex {} not in bounds for graph of size {}", 79 | v, 80 | self.len() 81 | ); 82 | } 83 | } 84 | 85 | impl<'a> IndexGraph<'a> for EdgeSetGraph { 86 | type Neighbors = Neighbors<'a>; 87 | 88 | fn len(&self) -> usize { 89 | self.len 90 | } 91 | 92 | fn new_vertex(&mut self) -> usize { 93 | let result = self.len; 94 | self.len = result + 1; 95 | result 96 | } 97 | 98 | fn set_edge(&mut self, u: usize, v: usize, present: bool) { 99 | let edge = self.edge(u, v); 100 | if present { 101 | self.edges.insert(edge); 102 | } else { 103 | self.edges.remove(&edge); 104 | } 105 | } 106 | 107 | fn has_edge(&self, u: usize, v: usize) -> bool { 108 | let edge = self.edge(u, v); 109 | self.edges.contains(&edge) 110 | } 111 | 112 | fn neighbors(&'a self, u: usize) -> Self::Neighbors { 113 | Neighbors { 114 | graph: self, 115 | vertex: u, 116 | next: 0, 117 | } 118 | } 119 | } 120 | 121 | impl std::default::Default for EdgeSetGraph { 122 | fn default() -> Self { 123 | Self::new() 124 | } 125 | } 126 | 127 | #[derive(Clone, Debug)] 128 | pub struct Neighbors<'a> { 129 | graph: &'a EdgeSetGraph, 130 | vertex: Vertex, 131 | next: Vertex, 132 | } 133 | 134 | impl Iterator for Neighbors<'_> { 135 | type Item = Vertex; 136 | 137 | fn next(&mut self) -> Option { 138 | while self.next < self.graph.len() { 139 | let candidate = self.next; 140 | self.next += 1; 141 | 142 | if self.graph.has_edge(self.vertex, candidate) { 143 | return Some(candidate); 144 | } 145 | } 146 | 147 | None 148 | } 149 | 150 | fn size_hint(&self) -> (usize, Option) { 151 | (0, Some(self.graph.len() - self.next)) 152 | } 153 | } 154 | 155 | #[cfg(test)] 156 | mod tests { 157 | use super::{EdgeSetGraph as Graph, IndexGraph, Vertex}; 158 | 159 | impl Graph { 160 | /// Helper function for asserting that the neighbors of `u` are 161 | /// `expected`. 162 | fn check_neighbors(&self, u: Vertex, expected: &[Vertex]) { 163 | use std::iter::FromIterator; 164 | 165 | let actual = Vec::from_iter(self.neighbors(u)); 166 | assert_eq!(actual, expected); 167 | } 168 | } 169 | 170 | #[test] 171 | fn neighbors() { 172 | let g = Graph::from_edges(vec![(5, 0), (0, 1), (0, 2), (1, 2), (2, 2), (1, 3), (2, 3)]); 173 | 174 | g.check_neighbors(0, &[1, 2, 5]); 175 | g.check_neighbors(1, &[0, 2, 3]); 176 | g.check_neighbors(2, &[0, 1, 2, 3]); 177 | g.check_neighbors(3, &[1, 2]); 178 | g.check_neighbors(4, &[]); 179 | g.check_neighbors(5, &[0]); 180 | } 181 | 182 | #[test] 183 | fn new_vertex_and_len() { 184 | let mut g = Graph::new(); 185 | assert_eq!(g.len(), 0); 186 | assert_eq!(g.new_vertex(), 0); 187 | assert_eq!(g.new_vertex(), 1); 188 | assert_eq!(g.len(), 2); 189 | } 190 | 191 | #[test] 192 | fn add_remove_has() { 193 | let mut g = Graph::new(); 194 | assert_eq!(g.len(), 0); 195 | for i in 0..5 { 196 | assert_eq!(g.new_vertex(), i); 197 | } 198 | 199 | assert!(!g.has_edge(0, 1)); 200 | g.add_edge(0, 1); 201 | assert!(g.has_edge(0, 1)); 202 | assert!(g.has_edge(1, 0)); 203 | assert!(!g.has_edge(0, 2)); 204 | } 205 | 206 | #[test] 207 | fn from_edges() { 208 | let edges = &[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (5, 2)]; 209 | let g = Graph::from_edges(edges.iter().copied()); 210 | 211 | for &(u, v) in edges { 212 | assert!(g.has_edge(u, v)); 213 | assert!(g.has_edge(v, u)); 214 | } 215 | 216 | assert!(!g.has_edge(0, 2)); 217 | assert!(!g.has_edge(0, 3)); 218 | assert!(!g.has_edge(1, 5)); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /class-20210422/src/interior_mut.rs: -------------------------------------------------------------------------------- 1 | // 2 | // Examples first! 3 | // 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | use super::{cons, List}; 8 | 9 | #[test] 10 | fn build_and_access() { 11 | let mut xs = List::new(); 12 | xs.cons(5).cons(6).cons(7); 13 | 14 | assert_eq!(xs.len(), 3); 15 | assert_eq!(xs.first_copied(), Some(7)); 16 | assert_eq!(xs.nth_copied(1), Some(6)); 17 | assert_eq!(xs.nth_copied(2), Some(5)); 18 | 19 | assert!(!xs.nth_rest(2).unwrap().empty()); 20 | assert!(xs.nth_rest(3).is_some()); 21 | assert!(xs.nth_rest(3).unwrap().empty()); 22 | assert!(xs.nth_rest(4).is_none()); 23 | } 24 | 25 | #[test] 26 | fn sharing() { 27 | let mut xs = List::new(); 28 | xs.cons(5).cons(6).cons(7); 29 | let ys = cons(4, xs.clone()); 30 | assert_eq!(xs.len(), 3); 31 | assert_eq!(ys.len(), 4); 32 | 33 | xs.cons(4).cons(3); 34 | assert_eq!(xs.len(), 5); 35 | assert_eq!(ys.len(), 4); 36 | } 37 | 38 | #[test] 39 | fn mutation() { 40 | let mut xs = List::new(); 41 | xs.cons(5).cons(6).cons(7); 42 | 43 | assert_eq!(xs.nth_copied(0), Some(7)); 44 | assert_eq!(xs.nth_copied(1), Some(6)); 45 | assert_eq!(xs.nth_copied(2), Some(5)); 46 | assert!(xs.nth_copied(3).is_none()); 47 | 48 | xs.map_nth_mut(1, |o| o.map(|r| *r = 12)); 49 | assert_eq!(xs.nth_copied(0), Some(7)); 50 | assert_eq!(xs.nth_copied(1), Some(12)); 51 | assert_eq!(xs.nth_copied(2), Some(5)); 52 | assert!(xs.nth_copied(3).is_none()); 53 | 54 | xs.rest().unwrap().rest_mut().unwrap().cons(55); 55 | assert_eq!(xs.nth_copied(0), Some(7)); 56 | assert_eq!(xs.nth_copied(1), Some(12)); 57 | assert_eq!(xs.nth_copied(2), Some(55)); 58 | assert_eq!(xs.nth_copied(3), Some(5)); 59 | assert!(xs.nth_copied(4).is_none()); 60 | } 61 | } 62 | 63 | use std::cell::{Ref, RefCell, RefMut}; 64 | use std::rc::Rc; 65 | 66 | // 67 | // Data definitions 68 | // 69 | 70 | /// A list is an optional, shared pointer to a mutable node: 71 | #[derive(Debug)] 72 | pub struct List(Option>>>); 73 | 74 | /// A node has an element and another list: 75 | #[derive(Debug)] 76 | struct Node { 77 | first: T, 78 | rest: List, 79 | } 80 | 81 | // 82 | // Free function 83 | // 84 | 85 | /// Creates a longer list from an element and an additional list. 86 | pub fn cons(first: T, rest: List) -> List { 87 | let node = Node { first, rest }; 88 | List(Some(Rc::new(RefCell::new(node)))) 89 | } 90 | 91 | // 92 | // Inherent method imps 93 | // 94 | 95 | impl List { 96 | /// Constructs an empty list. 97 | pub fn new() -> Self { 98 | List(None) 99 | } 100 | 101 | /// Modifies a list by adding a new element to the front of it. 102 | pub fn cons(&mut self, first: T) -> &mut Self { 103 | *self = cons(first, self.clone()); 104 | self 105 | } 106 | 107 | /// Checks whether a list is empty. 108 | pub fn empty(&self) -> bool { 109 | self.0.is_none() 110 | } 111 | 112 | /// Returns the length of a list. 113 | pub fn len(&self) -> usize { 114 | let mut count = 0; 115 | 116 | let mut current = self.clone(); 117 | while let Some(next) = current.rest() { 118 | current = next; 119 | count += 1; 120 | } 121 | 122 | count 123 | } 124 | 125 | /// Returns a guarded reference to the first element of a list. 126 | pub fn first(&self) -> Option> { 127 | self.map_ref(|node| &node.first) 128 | } 129 | 130 | /// Returns the rest of a list. 131 | pub fn rest(&self) -> Option> { 132 | self.0.as_ref().map(|rc| rc.borrow().rest.clone()) 133 | } 134 | 135 | /// Returns a guarded *mutable* reference to the first element of a 136 | /// list. 137 | pub fn first_mut(&self) -> Option> { 138 | self.map_ref_mut(|node| &mut node.first) 139 | } 140 | 141 | /// Returns a guarded *mutable* reference to the rest of a list. 142 | pub fn rest_mut(&self) -> Option>> { 143 | self.map_ref_mut(|node| &mut node.rest) 144 | } 145 | 146 | /// Returns a guarded reference to the rest of a list. Usually 147 | /// [`List::rest`] is easier to use, but this method avoids a 148 | /// reference count bump. 149 | pub fn rest_ref(&self) -> Option>> { 150 | self.map_ref(|node| &node.rest) 151 | } 152 | 153 | /// Applies the given function to an option containing a reference 154 | /// to the first element, returning the function’s result. 155 | pub fn map_first(&self, f: F) -> R 156 | where 157 | F: FnOnce(Option<&T>) -> R, 158 | { 159 | if let Some(rc) = self.0.as_ref() { 160 | f(Some(&rc.borrow().first)) 161 | } else { 162 | f(None) 163 | } 164 | } 165 | 166 | /// Applies the given function to an option containing a *mutable* 167 | /// reference to the first element, returning the function’s result. 168 | pub fn map_first_mut(&self, f: F) -> R 169 | where 170 | F: FnOnce(Option<&mut T>) -> R, 171 | { 172 | if let Some(rc) = self.0.as_ref() { 173 | f(Some(&mut rc.borrow_mut().first)) 174 | } else { 175 | f(None) 176 | } 177 | } 178 | 179 | /// Applies the given function to an option containing a reference 180 | /// to the `n`th element (if it exists), returning the function’s result. 181 | pub fn map_nth(&self, n: usize, f: F) -> R 182 | where 183 | F: FnOnce(Option<&T>) -> R, 184 | { 185 | if let Some(lst) = self.nth_rest(n) { 186 | lst.map_first(f) 187 | } else { 188 | f(None) 189 | } 190 | } 191 | 192 | /// Returns the `n`th `rest` of a list (if it exists), like calling 193 | /// [`List::rest`] `n` times. 194 | pub fn nth_rest(&self, n: usize) -> Option> { 195 | let mut current = self.clone(); 196 | for _ in 0..n { 197 | current = current.rest()?; 198 | } 199 | Some(current) 200 | } 201 | 202 | /// Applies the given function to an option containing a *mutable* 203 | /// reference to the `n`th element (if it exists), returning the 204 | /// function’s result. 205 | pub fn map_nth_mut(&self, n: usize, f: F) -> R 206 | where 207 | F: FnOnce(Option<&mut T>) -> R, 208 | { 209 | if let Some(lst) = self.nth_rest(n) { 210 | lst.map_first_mut(f) 211 | } else { 212 | f(None) 213 | } 214 | } 215 | 216 | // Helper 217 | fn map_ref(&self, f: impl FnOnce(&Node) -> &U) -> Option> { 218 | self.0.as_ref().map(|rc| Ref::map(rc.borrow(), f)) 219 | } 220 | 221 | // Helper 222 | fn map_ref_mut(&self, f: impl FnOnce(&mut Node) -> &mut U) -> Option> { 223 | self.0.as_ref().map(|rc| RefMut::map(rc.borrow_mut(), f)) 224 | } 225 | } 226 | 227 | // Methods for `Copy` elements. 228 | impl List { 229 | /// Returns a copy of the first element, if it is copyable. 230 | pub fn first_copied(&self) -> Option { 231 | self.first().map(|r| *r) 232 | } 233 | 234 | /// Returns a copy of the `n`th element if it exists. 235 | pub fn nth_copied(&self, n: usize) -> Option { 236 | self.nth_rest(n)?.first_copied() 237 | } 238 | } 239 | 240 | // Methods for `Clone` elements. 241 | impl List { 242 | /// Returns a clone of the first element, if it is cloneable. 243 | pub fn first_cloned(&self) -> Option { 244 | self.first().map(|r| T::clone(&r)) 245 | } 246 | 247 | /// Returns a clone of the `n`th element if it exists. 248 | pub fn nth_cloned(&self, n: usize) -> Option { 249 | self.nth_rest(n)?.first_cloned() 250 | } 251 | } 252 | 253 | // 254 | // Trait impls 255 | // 256 | 257 | impl Clone for List { 258 | /// A list is cloned by cloning the shared pointer inside, which 259 | /// means that the original and the result share their structure. 260 | fn clone(&self) -> Self { 261 | List(self.0.clone()) 262 | } 263 | } 264 | 265 | impl std::default::Default for List { 266 | fn default() -> Self { 267 | Self::new() 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /04-ownership/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.6" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "0.1.7" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "bitflags" 18 | version = "1.2.1" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "cfg-if" 23 | version = "0.1.10" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "cloudabi" 28 | version = "0.0.3" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | dependencies = [ 31 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 32 | ] 33 | 34 | [[package]] 35 | name = "env_logger" 36 | version = "0.6.2" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | dependencies = [ 39 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 40 | "regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 41 | ] 42 | 43 | [[package]] 44 | name = "fuchsia-cprng" 45 | version = "0.1.1" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | 48 | [[package]] 49 | name = "lazy_static" 50 | version = "1.4.0" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | 53 | [[package]] 54 | name = "libc" 55 | version = "0.2.66" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | 58 | [[package]] 59 | name = "log" 60 | version = "0.4.8" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | dependencies = [ 63 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 64 | ] 65 | 66 | [[package]] 67 | name = "memchr" 68 | version = "2.3.0" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | 71 | [[package]] 72 | name = "ownership" 73 | version = "0.1.0" 74 | dependencies = [ 75 | "quickcheck 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", 76 | ] 77 | 78 | [[package]] 79 | name = "quickcheck" 80 | version = "0.8.5" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | dependencies = [ 83 | "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 84 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 85 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 86 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 87 | ] 88 | 89 | [[package]] 90 | name = "rand" 91 | version = "0.6.5" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | dependencies = [ 94 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 95 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 96 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 97 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 98 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 99 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 100 | "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 101 | "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 105 | ] 106 | 107 | [[package]] 108 | name = "rand_chacha" 109 | version = "0.1.1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | dependencies = [ 112 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 113 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 114 | ] 115 | 116 | [[package]] 117 | name = "rand_core" 118 | version = "0.3.1" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | dependencies = [ 121 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 122 | ] 123 | 124 | [[package]] 125 | name = "rand_core" 126 | version = "0.4.2" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | 129 | [[package]] 130 | name = "rand_hc" 131 | version = "0.1.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | dependencies = [ 134 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 135 | ] 136 | 137 | [[package]] 138 | name = "rand_isaac" 139 | version = "0.1.1" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | dependencies = [ 142 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 143 | ] 144 | 145 | [[package]] 146 | name = "rand_jitter" 147 | version = "0.1.4" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | dependencies = [ 150 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 151 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 152 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 153 | ] 154 | 155 | [[package]] 156 | name = "rand_os" 157 | version = "0.1.3" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | dependencies = [ 160 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 161 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 162 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 163 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 164 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 165 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 166 | ] 167 | 168 | [[package]] 169 | name = "rand_pcg" 170 | version = "0.1.2" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | dependencies = [ 173 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 174 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 175 | ] 176 | 177 | [[package]] 178 | name = "rand_xorshift" 179 | version = "0.1.1" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | dependencies = [ 182 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 183 | ] 184 | 185 | [[package]] 186 | name = "rdrand" 187 | version = "0.4.0" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | dependencies = [ 190 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 191 | ] 192 | 193 | [[package]] 194 | name = "regex" 195 | version = "1.3.3" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | dependencies = [ 198 | "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", 199 | "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 200 | "regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 201 | "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 202 | ] 203 | 204 | [[package]] 205 | name = "regex-syntax" 206 | version = "0.6.13" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | 209 | [[package]] 210 | name = "thread_local" 211 | version = "1.0.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | dependencies = [ 214 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 215 | ] 216 | 217 | [[package]] 218 | name = "winapi" 219 | version = "0.3.8" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | dependencies = [ 222 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 223 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 224 | ] 225 | 226 | [[package]] 227 | name = "winapi-i686-pc-windows-gnu" 228 | version = "0.4.0" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | 231 | [[package]] 232 | name = "winapi-x86_64-pc-windows-gnu" 233 | version = "0.4.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | 236 | [metadata] 237 | "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" 238 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 239 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 240 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 241 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 242 | "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" 243 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 244 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 245 | "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" 246 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 247 | "checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" 248 | "checksum quickcheck 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9c35d9c36a562f37eca96e79f66d5fd56eefbc22560dacc4a864cabd2d277456" 249 | "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 250 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 251 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 252 | "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 253 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 254 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 255 | "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" 256 | "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" 257 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 258 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 259 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 260 | "checksum regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87" 261 | "checksum regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90" 262 | "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" 263 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 264 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 265 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 266 | -------------------------------------------------------------------------------- /04-ownership/src/list_set.rs: -------------------------------------------------------------------------------- 1 | //! Sets, represented as sorted, singly-linked lists. 2 | 3 | use std::cmp::Ordering::{self, Less, Equal, Greater}; 4 | use std::default::Default; 5 | use std::iter::{Extend, FromIterator}; 6 | use std::mem; 7 | 8 | /// A set of elements of type `T`. 9 | /// 10 | /// # Example 11 | /// 12 | /// ``` 13 | /// use ownership::list_set::Set; 14 | /// 15 | /// let mut set = Set::new(); 16 | /// 17 | /// set.insert("a"); 18 | /// set.insert("b"); 19 | /// 20 | /// if set.contains(&"a") { 21 | /// set.insert("c"); 22 | /// } 23 | /// ``` 24 | #[derive(Debug)] 25 | pub struct Set { 26 | head: Link, 27 | len: usize, 28 | } 29 | // Invariant: the elements must be sorted according to . 30 | 31 | type Link = Option>>; 32 | 33 | #[derive(Debug)] 34 | struct Node { 35 | data: T, 36 | link: Link, 37 | } 38 | 39 | impl Drop for Set { 40 | fn drop(&mut self) { 41 | let mut head = self.head.take(); 42 | 43 | while let Some(next) = head.take() { 44 | head = next.link; 45 | } 46 | } 47 | } 48 | 49 | impl Node { 50 | fn new(data: T, link: Link) -> Option> { 51 | Some(Box::new(Node { data, link })) 52 | } 53 | } 54 | 55 | impl Set { 56 | /// Creates a new, empty list-set. 57 | /// 58 | /// # Example 59 | /// 60 | /// ``` 61 | /// # use ownership::list_set::Set; 62 | /// let mut set = Set::new(); 63 | /// set.insert("hello"); 64 | /// ``` 65 | pub fn new() -> Self { 66 | Set { 67 | len: 0, 68 | head: None, 69 | } 70 | } 71 | 72 | /// Returns whether a set is empty. 73 | /// 74 | /// # Example 75 | /// 76 | /// ``` 77 | /// # use ownership::list_set::Set; 78 | /// let mut set = Set::new(); 79 | /// assert!(set.is_empty()); 80 | /// 81 | /// set.insert(5); 82 | /// assert!(!set.is_empty()); 83 | /// ``` 84 | pub fn is_empty(&self) -> bool { 85 | self.len == 0 86 | } 87 | 88 | /// Returns the number of elements in the set. 89 | /// 90 | /// # Example 91 | /// 92 | /// ``` 93 | /// # use ownership::list_set::Set; 94 | /// let mut set = Set::new(); 95 | /// assert_eq!(0, set.len()); 96 | /// 97 | /// set.insert(5); 98 | /// assert_eq!(1, set.len()); 99 | /// 100 | /// set.insert(6); 101 | /// assert_eq!(2, set.len()); 102 | /// 103 | /// set.insert(5); 104 | /// assert_eq!(2, set.len()); 105 | /// ``` 106 | pub fn len(&self) -> usize { 107 | self.len 108 | } 109 | 110 | /// Returns a borrowing iterator over the elements of the set. 111 | /// 112 | /// # Example 113 | /// 114 | /// ``` 115 | /// # use ownership::list_set::Set; 116 | /// use std::iter::FromIterator; 117 | /// 118 | /// let set = Set::from_iter(vec![1, 3, 5]); 119 | /// let mut result = Vec::new(); 120 | /// 121 | /// for elt in set.iter() { 122 | /// result.push(elt); 123 | /// } 124 | /// 125 | /// assert_eq!( result, &[&1, &3, &5] ); 126 | /// ``` 127 | pub fn iter(&self) -> Iter { 128 | self.into_iter() 129 | } 130 | 131 | /// Returns an iterator that removes and returns elements satisfying a predicate, leaving the 132 | /// rest in the set. 133 | pub fn drain_filter bool>(&mut self, pred: P) -> DrainFilter { 134 | let len = self.len; 135 | DrainFilter { 136 | cursor: CursorMut::new(self), 137 | pred, 138 | len, 139 | } 140 | } 141 | } 142 | 143 | impl Default for Set { 144 | fn default() -> Self { 145 | Set::new() 146 | } 147 | } 148 | 149 | impl Set { 150 | /// Checks whether the given set contains the given element. 151 | /// 152 | /// # Example 153 | /// 154 | /// ``` 155 | /// # use ownership::list_set::Set; 156 | /// use std::iter::FromIterator; 157 | /// 158 | /// let set = Set::from_iter(vec![3, 5, 4]); 159 | /// 160 | /// assert!(!set.contains(&2)); 161 | /// assert!( set.contains(&3)); 162 | /// assert!( set.contains(&4)); 163 | /// assert!( set.contains(&5)); 164 | /// assert!(!set.contains(&6)); 165 | /// ``` 166 | pub fn contains(&self, element: &T) -> bool { 167 | let mut current = &self.head; 168 | 169 | while let Some(ref node) = *current { 170 | match element.cmp(&node.data) { 171 | Less => return false, 172 | Equal => return true, 173 | Greater => current = &node.link, 174 | } 175 | } 176 | 177 | false 178 | } 179 | 180 | /// Adds the element to the set. 181 | /// 182 | /// Returns `true` if the set did not previously contain the 183 | /// element, and `false` if it did. 184 | /// 185 | /// # Example 186 | /// 187 | /// ``` 188 | /// # use ownership::list_set::Set; 189 | /// let mut set = Set::new(); 190 | /// set.insert(3); 191 | /// set.insert(5); 192 | /// set.insert(4); 193 | /// 194 | /// assert!(!set.contains(&2)); 195 | /// assert!( set.contains(&3)); 196 | /// assert!( set.contains(&4)); 197 | /// assert!( set.contains(&5)); 198 | /// assert!(!set.contains(&6)); 199 | /// ``` 200 | pub fn insert(&mut self, element: T) -> bool { 201 | let mut cur = CursorMut::new(self); 202 | 203 | while let Some(data) = cur.data() { 204 | match element.cmp(data) { 205 | Less => break, 206 | Equal => return false, 207 | Greater => cur.advance(), 208 | } 209 | } 210 | 211 | cur.insert(element); 212 | 213 | true 214 | } 215 | 216 | /// Adds the element to the set if absent, or replaces it if 217 | /// present. 218 | /// 219 | /// Returns `Some` of the old element if it was present. 220 | /// 221 | /// # Example 222 | /// 223 | /// ``` 224 | /// # use ownership::list_set::Set; 225 | /// let mut set = Set::new(); 226 | /// 227 | /// assert_eq!(None, set.replace(5)); 228 | /// assert_eq!(Some(5), set.replace(5)); 229 | /// ``` 230 | pub fn replace(&mut self, element: T) -> Option { 231 | let mut cur = CursorMut::new(self); 232 | 233 | while let Some(data) = cur.data_mut() { 234 | match element.cmp(data) { 235 | Less => break, 236 | Equal => { 237 | let old_data = mem::replace(data, element); 238 | return Some(old_data); 239 | } 240 | Greater => cur.advance(), 241 | } 242 | } 243 | 244 | cur.insert(element); 245 | 246 | None 247 | } 248 | 249 | /// Removes the given element from the set. 250 | /// 251 | /// Returns `Some(data)` where `data` was the element, if removed, 252 | /// or `None` if the element didn’t exist. 253 | /// 254 | /// # Example 255 | /// 256 | /// ``` 257 | /// # use ownership::list_set::Set; 258 | /// let mut set = Set::new(); 259 | /// 260 | /// assert_eq!(false, set.contains(&5)); 261 | /// assert_eq!(true, set.insert(5)); 262 | /// assert_eq!(true, set.contains(&5)); 263 | /// assert_eq!(false, set.insert(5)); 264 | /// assert_eq!(Some(5), set.remove(&5)); 265 | /// assert_eq!(false, set.contains(&5)); 266 | /// ``` 267 | pub fn remove(&mut self, element: &T) -> Option { 268 | let mut cur = CursorMut::new(self); 269 | 270 | while let Some(data) = cur.data() { 271 | match element.cmp(data) { 272 | Less => break, 273 | Equal => return cur.remove(), 274 | Greater => cur.advance(), 275 | } 276 | } 277 | 278 | None 279 | } 280 | } 281 | 282 | #[cfg(test)] 283 | mod stack_overflow_tests { 284 | use super::Set; 285 | 286 | fn iota(len: usize) -> Set { 287 | let mut result = Set::new(); 288 | 289 | for i in (0..len).into_iter().rev() { 290 | result.insert(i); 291 | } 292 | 293 | result 294 | } 295 | 296 | #[test] 297 | fn len_iota() { 298 | iota(100_000); 299 | } 300 | } 301 | 302 | #[derive(Debug)] 303 | struct CursorMut<'a, T: 'a> { 304 | link: Option<&'a mut Link>, 305 | len: &'a mut usize, 306 | } 307 | 308 | impl<'a, T: 'a> CursorMut<'a, T> { 309 | fn new(set: &'a mut Set) -> Self { 310 | CursorMut { 311 | link: Some(&mut set.head), 312 | len: &mut set.len, 313 | } 314 | } 315 | 316 | #[allow(dead_code)] 317 | fn is_empty(&self) -> bool { 318 | self.link.as_ref() 319 | .and_then(|o| o.as_ref()) 320 | .is_none() 321 | } 322 | 323 | fn data_mut(&mut self) -> Option<&mut T> { 324 | self.link.as_mut() 325 | .and_then(|link_ptr| link_ptr.as_mut()) 326 | .map(|node_ptr| &mut node_ptr.data) 327 | } 328 | 329 | fn data(&self) -> Option<&T> { 330 | self.link.as_ref() 331 | .and_then(|link_ptr| link_ptr.as_ref()) 332 | .map(|node_ptr| &node_ptr.data) 333 | } 334 | 335 | fn advance(&mut self) { 336 | self.link = self.link.take() 337 | .and_then(|link_ptr| link_ptr.as_mut()) 338 | .map(|node_ptr| &mut node_ptr.link); 339 | } 340 | 341 | fn remove(&mut self) -> Option { 342 | let link_ptr = self.link.as_mut()?; 343 | let Node { data, link } = *link_ptr.take()?; 344 | **link_ptr = link; 345 | *self.len -= 1; 346 | Some(data) 347 | } 348 | 349 | fn insert(&mut self, data: T) { 350 | let link_ptr = self.link.as_mut() 351 | .expect("CursorMut::insert: empty cursor"); 352 | **link_ptr = Node::new(data, link_ptr.take()); 353 | *self.len += 1; 354 | } 355 | } 356 | 357 | /// An immutable iterator over the elements of a `Set`. 358 | /// 359 | /// # Example 360 | /// 361 | /// ``` 362 | /// # use ownership::list_set::Set; 363 | /// let mut set = Set::new(); 364 | /// 365 | /// set.insert(2); 366 | /// set.insert(4); 367 | /// set.insert(3); 368 | /// 369 | /// let mut iter = (&set).into_iter(); 370 | /// 371 | /// assert_eq!(Some(&2), iter.next()); 372 | /// assert_eq!(Some(&3), iter.next()); 373 | /// assert_eq!(Some(&4), iter.next()); 374 | /// assert_eq!(None, iter.next()); 375 | /// ``` 376 | #[derive(Debug)] 377 | pub struct Iter<'a, T: 'a> { 378 | link: &'a Link, 379 | len: usize, 380 | } 381 | 382 | impl<'a, T> Iterator for Iter<'a, T> { 383 | type Item = &'a T; 384 | 385 | fn next(&mut self) -> Option<&'a T> { 386 | match *self.link { 387 | Some(ref node_ptr) => { 388 | self.link = &node_ptr.link; 389 | self.len -= 1; 390 | Some(&node_ptr.data) 391 | } 392 | None => None, 393 | } 394 | } 395 | 396 | fn size_hint(&self) -> (usize, Option) { 397 | (self.len, Some(self.len)) 398 | } 399 | } 400 | 401 | impl<'a, T> ExactSizeIterator for Iter<'a, T> { 402 | fn len(&self) -> usize { 403 | self.len 404 | } 405 | } 406 | 407 | impl<'a, T> IntoIterator for &'a Set { 408 | type Item = &'a T; 409 | type IntoIter = Iter<'a, T>; 410 | 411 | fn into_iter(self) -> Iter<'a, T> { 412 | Iter { 413 | link: &self.head, 414 | len: self.len, 415 | } 416 | } 417 | } 418 | 419 | /// An iterator that consumes a `Set` as it iterates. 420 | /// 421 | /// # Example 422 | /// 423 | /// ``` 424 | /// # use ownership::list_set::Set; 425 | /// let mut set = Set::new(); 426 | /// 427 | /// set.insert(2); 428 | /// set.insert(4); 429 | /// set.insert(3); 430 | /// 431 | /// let mut iter = set.into_iter(); 432 | /// 433 | /// assert_eq!(Some(2), iter.next()); 434 | /// assert_eq!(Some(3), iter.next()); 435 | /// assert_eq!(Some(4), iter.next()); 436 | /// assert_eq!(None, iter.next()); 437 | /// ``` 438 | #[derive(Debug)] 439 | pub struct IntoIter(Set); 440 | 441 | impl Iterator for IntoIter { 442 | type Item = T; 443 | 444 | fn next(&mut self) -> Option { 445 | CursorMut::new(&mut self.0).remove() 446 | } 447 | 448 | fn size_hint(&self) -> (usize, Option) { 449 | (self.0.len, Some(self.0.len)) 450 | } 451 | } 452 | 453 | impl ExactSizeIterator for IntoIter { 454 | fn len(&self) -> usize { 455 | self.0.len 456 | } 457 | } 458 | 459 | impl IntoIterator for Set { 460 | type Item = T; 461 | type IntoIter = IntoIter; 462 | 463 | fn into_iter(self) -> IntoIter { 464 | IntoIter(self) 465 | } 466 | } 467 | 468 | impl Extend for Set { 469 | fn extend>(&mut self, iter: I) { 470 | for elem in iter { 471 | self.insert(elem); 472 | } 473 | } 474 | } 475 | 476 | impl FromIterator for Set { 477 | fn from_iter>(iter: I) -> Self { 478 | let mut result = Set::new(); 479 | result.extend(iter); 480 | result 481 | } 482 | } 483 | 484 | impl Ord for Set { 485 | fn cmp(&self, other: &Set) -> Ordering { 486 | let mut i = self.into_iter(); 487 | let mut j = other.into_iter(); 488 | 489 | loop { 490 | match (i.next(), j.next()) { 491 | (None, None) => return Equal, 492 | (None, Some(_)) => return Less, 493 | (Some(_), None) => return Greater, 494 | (Some(a), Some(b)) => match a.cmp(b) { 495 | Less => return Less, 496 | Greater => return Greater, 497 | Equal => continue, 498 | } 499 | } 500 | } 501 | } 502 | } 503 | 504 | impl PartialOrd for Set { 505 | fn partial_cmp(&self, other: &Set) -> Option { 506 | Some(self.cmp(other)) 507 | } 508 | } 509 | 510 | impl PartialEq for Set { 511 | fn eq(&self, other: &Set) -> bool { 512 | self.cmp(other) == Equal 513 | } 514 | } 515 | 516 | impl Eq for Set {} 517 | 518 | impl Clone for Set { 519 | fn clone(&self) -> Self { 520 | let mut result = Set::new(); 521 | 522 | { 523 | let mut cur = &mut result.head; 524 | 525 | for each in self { 526 | *cur = Node::new(each.clone(), None); 527 | cur = &mut {cur}.as_mut().unwrap().link; 528 | } 529 | } 530 | 531 | result.len = self.len; 532 | result 533 | } 534 | } 535 | 536 | #[test] 537 | fn test_clone() { 538 | let set1: Set = vec![3, 5, 4].into_iter().collect(); 539 | let set2 = set1.clone(); 540 | assert_eq!(set2, set1); 541 | } 542 | 543 | impl Set { 544 | /// Returns whether two sets are disjoint. 545 | /// 546 | /// # Example 547 | /// 548 | /// ``` 549 | /// # use ownership::list_set::Set; 550 | /// use std::iter::FromIterator; 551 | /// 552 | /// let set1 = Set::from_iter(vec![1, 2]); 553 | /// let set2 = Set::from_iter(vec![3, 4]); 554 | /// let set3 = Set::from_iter(vec![1, 3]); 555 | /// 556 | /// assert!(!set1.is_disjoint(&set1)); 557 | /// assert!( set1.is_disjoint(&set2)); 558 | /// assert!(!set1.is_disjoint(&set3)); 559 | /// assert!( set2.is_disjoint(&set1)); 560 | /// assert!(!set2.is_disjoint(&set2)); 561 | /// assert!(!set2.is_disjoint(&set3)); 562 | /// assert!(!set3.is_disjoint(&set1)); 563 | /// assert!(!set3.is_disjoint(&set2)); 564 | /// assert!(!set3.is_disjoint(&set3)); 565 | /// ``` 566 | pub fn is_disjoint(&self, other: &Set) -> bool { 567 | let mut i = &self.head; 568 | let mut j = &other.head; 569 | 570 | while let (&Some(ref ilink), &Some(ref jlink)) = (i, j) { 571 | match ilink.data.cmp(&jlink.data) { 572 | Less => i = &ilink.link, 573 | Greater => j = &jlink.link, 574 | Equal => return false, 575 | } 576 | } 577 | 578 | true 579 | } 580 | 581 | /// Returns whether `self` is a subset of `other`. 582 | /// 583 | /// # Example 584 | /// 585 | /// ``` 586 | /// # use ownership::list_set::Set; 587 | /// use std::iter::FromIterator; 588 | /// 589 | /// let set1 = Set::from_iter(vec![2]); 590 | /// let set2 = Set::from_iter(vec![1, 2, 3]); 591 | /// let set3 = Set::from_iter(vec![1, 2, 3, 4]); 592 | /// 593 | /// assert!( set1.is_subset(&set1)); 594 | /// assert!( set1.is_subset(&set2)); 595 | /// assert!( set1.is_subset(&set3)); 596 | /// assert!(!set2.is_subset(&set1)); 597 | /// assert!( set2.is_subset(&set2)); 598 | /// assert!( set2.is_subset(&set3)); 599 | /// assert!(!set3.is_subset(&set1)); 600 | /// assert!(!set3.is_subset(&set2)); 601 | /// assert!( set3.is_subset(&set3)); 602 | /// ``` 603 | pub fn is_subset(&self, other: &Set) -> bool { 604 | let mut i = &self.head; 605 | let mut j = &other.head; 606 | 607 | while let (&Some(ref ilink), &Some(ref jlink)) = (i, j) { 608 | match ilink.data.cmp(&jlink.data) { 609 | Less => return false, 610 | Greater => j = &jlink.link, 611 | Equal => { 612 | i = &ilink.link; 613 | j = &jlink.link; 614 | } 615 | } 616 | } 617 | 618 | i.is_none() || j.is_some() 619 | } 620 | 621 | /// Returns whether `self` is a superset of `other`. 622 | pub fn is_superset(&self, other: &Set) -> bool { 623 | other.is_subset(self) 624 | } 625 | } 626 | 627 | impl Set { 628 | /// Returns the intersection of two sets. 629 | /// 630 | /// # Example 631 | /// 632 | /// ``` 633 | /// # use ownership::list_set::Set; 634 | /// use std::iter::FromIterator; 635 | /// 636 | /// let set1 = Set::from_iter(vec![1, 3, 5, 7]); 637 | /// let set2 = Set::from_iter(vec![1, 2, 3, 4]); 638 | /// 639 | /// let set3 = Set::from_iter(vec![1, 3]); 640 | /// 641 | /// assert_eq!(set3, set1.intersection(&set2)); 642 | /// assert_eq!(set3, set2.intersection(&set1)); 643 | /// ``` 644 | pub fn intersection(&self, other: &Set) -> Self { 645 | let mut result = Set::new(); 646 | 647 | { 648 | let mut cur = CursorMut::new(&mut result); 649 | 650 | let mut i = self.into_iter().peekable(); 651 | let mut j = other.into_iter().peekable(); 652 | 653 | while let (Some(&a), Some(&b)) = (i.peek(), j.peek()) { 654 | match a.cmp(b) { 655 | Less => { 656 | i.next(); 657 | } 658 | Greater => { 659 | j.next(); 660 | } 661 | Equal => { 662 | cur.insert(a.clone()); 663 | cur.advance(); 664 | i.next(); 665 | j.next(); 666 | } 667 | } 668 | } 669 | } 670 | 671 | result 672 | } 673 | 674 | /// Returns the union of two sets. 675 | /// 676 | /// # Example 677 | /// 678 | /// ``` 679 | /// # use ownership::list_set::Set; 680 | /// use std::iter::FromIterator; 681 | /// 682 | /// let set1 = Set::from_iter(vec![1, 3, 5, 7]); 683 | /// let set2 = Set::from_iter(vec![1, 2, 3, 4]); 684 | /// 685 | /// let set3 = Set::from_iter(vec![1, 2, 3, 4, 5, 7]); 686 | /// 687 | /// assert_eq!(set3, set1.union(&set2)); 688 | /// assert_eq!(set3, set2.union(&set1)); 689 | /// ``` 690 | pub fn union(&self, other: &Set) -> Self { 691 | let mut result = Set::new(); 692 | 693 | { 694 | let mut cur = CursorMut::new(&mut result); 695 | 696 | let mut i = self.into_iter().peekable(); 697 | let mut j = other.into_iter().peekable(); 698 | 699 | while let (Some(&a), Some(&b)) = (i.peek(), j.peek()) { 700 | match a.cmp(b) { 701 | Less => { 702 | cur.insert(a.clone()); 703 | cur.advance(); 704 | i.next(); 705 | } 706 | Greater => { 707 | cur.insert(b.clone()); 708 | cur.advance(); 709 | j.next(); 710 | } 711 | Equal => { 712 | cur.insert(a.clone()); 713 | cur.advance(); 714 | i.next(); 715 | j.next(); 716 | } 717 | } 718 | } 719 | 720 | for a in i { 721 | cur.insert(a.clone()); 722 | cur.advance(); 723 | } 724 | 725 | for b in j { 726 | cur.insert(b.clone()); 727 | cur.advance(); 728 | } 729 | } 730 | 731 | result 732 | } 733 | 734 | /// Returns the difference of two sets. 735 | /// 736 | /// # Example 737 | /// 738 | /// ``` 739 | /// # use ownership::list_set::Set; 740 | /// use std::iter::FromIterator; 741 | /// 742 | /// let set1 = Set::from_iter(vec![1, 3, 5, 7]); 743 | /// let set2 = Set::from_iter(vec![1, 2, 3, 4]); 744 | /// 745 | /// let set3 = Set::from_iter(vec![5, 7]); 746 | /// let set4 = Set::from_iter(vec![2, 4]); 747 | /// 748 | /// assert_eq!(set3, set1.difference(&set2)); 749 | /// assert_eq!(set4, set2.difference(&set1)); 750 | /// ``` 751 | pub fn difference(&self, other: &Set) -> Self { 752 | let mut result = Set::new(); 753 | 754 | { 755 | let mut cur = CursorMut::new(&mut result); 756 | 757 | let mut i = self.into_iter().peekable(); 758 | let mut j = other.into_iter().peekable(); 759 | 760 | while let (Some(&a), Some(&b)) = (i.peek(), j.peek()) { 761 | match a.cmp(b) { 762 | Less => { 763 | cur.insert(a.clone()); 764 | cur.advance(); 765 | i.next(); 766 | } 767 | Greater => { 768 | j.next(); 769 | } 770 | Equal => { 771 | i.next(); 772 | j.next(); 773 | } 774 | } 775 | } 776 | 777 | for a in i { 778 | cur.insert(a.clone()); 779 | cur.advance(); 780 | } 781 | } 782 | 783 | result 784 | } 785 | 786 | /// Returns the symmetric difference of two sets. 787 | /// 788 | /// # Example 789 | /// 790 | /// ``` 791 | /// # use ownership::list_set::Set; 792 | /// use std::iter::FromIterator; 793 | /// 794 | /// let set1 = Set::from_iter(vec![1, 3, 5, 7]); 795 | /// let set2 = Set::from_iter(vec![1, 2, 3, 4]); 796 | /// 797 | /// let set3 = Set::from_iter(vec![2, 4, 5, 7]); 798 | /// 799 | /// assert_eq!(set3, set1.symmetric_difference(&set2)); 800 | /// assert_eq!(set3, set2.symmetric_difference(&set1)); 801 | /// ``` 802 | pub fn symmetric_difference(&self, other: &Set) -> Self { 803 | let mut result = Set::new(); 804 | 805 | { 806 | let mut cur = CursorMut::new(&mut result); 807 | 808 | let mut i = self.into_iter().peekable(); 809 | let mut j = other.into_iter().peekable(); 810 | 811 | while let (Some(&a), Some(&b)) = (i.peek(), j.peek()) { 812 | match a.cmp(b) { 813 | Less => { 814 | cur.insert(a.clone()); 815 | cur.advance(); 816 | i.next(); 817 | } 818 | Greater => { 819 | cur.insert(b.clone()); 820 | cur.advance(); 821 | j.next(); 822 | } 823 | Equal => { 824 | i.next(); 825 | j.next(); 826 | } 827 | } 828 | } 829 | 830 | for a in i { 831 | cur.insert(a.clone()); 832 | cur.advance(); 833 | } 834 | 835 | for b in j { 836 | cur.insert(b.clone()); 837 | cur.advance(); 838 | } 839 | } 840 | 841 | result 842 | } 843 | } 844 | 845 | #[derive(Debug)] 846 | pub struct DrainFilter<'a, T: 'a, P> 847 | where P: FnMut(&T) -> bool 848 | { 849 | cursor: CursorMut<'a, T>, 850 | pred: P, 851 | len: usize, 852 | } 853 | 854 | impl<'a, T, P> Iterator for DrainFilter<'a, T, P> 855 | where P: FnMut(&T) -> bool 856 | { 857 | type Item = T; 858 | 859 | fn next(&mut self) -> Option { 860 | while let Some(data) = self.cursor.data() { 861 | self.len -= 1; 862 | 863 | if (self.pred)(data) { 864 | return self.cursor.remove(); 865 | } else { 866 | self.cursor.advance() 867 | } 868 | } 869 | 870 | None 871 | } 872 | 873 | fn size_hint(&self) -> (usize, Option) { 874 | (0, Some(self.len)) 875 | } 876 | } 877 | 878 | impl<'a, T, P> Drop for DrainFilter<'a, T, P> 879 | where P: FnMut(&T) -> bool 880 | { 881 | fn drop(&mut self) { 882 | for _ in self {} 883 | } 884 | } 885 | 886 | #[cfg(any(test, feature = "quickcheck"))] 887 | mod impl_arbitrary_for_set { 888 | use super::Set; 889 | use quickcheck::{Arbitrary, Gen}; 890 | use std::iter::FromIterator; 891 | 892 | impl Arbitrary for Set { 893 | fn arbitrary(g: &mut G) -> Self { 894 | FromIterator::from_iter(Vec::::arbitrary(g)) 895 | } 896 | 897 | fn shrink(&self) -> Box> { 898 | Box::new(Vec::from_iter(Set::clone(self)) 899 | .shrink() 900 | .map(FromIterator::from_iter)) 901 | } 902 | } 903 | } 904 | 905 | #[cfg(test)] 906 | mod random_tests { 907 | use super::Set; 908 | use quickcheck::quickcheck; 909 | 910 | quickcheck! { 911 | 912 | fn prop_member(vec: Vec, elems: Vec) -> bool { 913 | let set: Set = vec.iter().cloned().collect(); 914 | 915 | elems.iter() 916 | .all(|elem| vec.contains(elem) == set.contains(elem)) 917 | } 918 | 919 | fn prop_intersection(s1: Set, s2: Set) -> bool { 920 | let s3 = s1.intersection(&s2); 921 | 922 | s1.iter().all(|elem| s3.contains(elem) == s2.contains(elem)) 923 | 924 | && 925 | 926 | s2.iter().all(|elem| s3.contains(elem) == s1.contains(elem)) 927 | 928 | && 929 | 930 | s3.iter().all(|elem| s1.contains(elem) && s2.contains(elem)) 931 | 932 | } 933 | 934 | fn prop_union(s1: Set, s2: Set) -> bool { 935 | let s3 = s1.union(&s2); 936 | 937 | s1.iter().all(|elem| s3.contains(elem)) 938 | 939 | && 940 | 941 | s2.iter().all(|elem| s3.contains(elem)) 942 | 943 | && 944 | 945 | s3.iter().all(|elem| s1.contains(elem) || s2.contains(elem)) 946 | 947 | } 948 | 949 | } 950 | 951 | } 952 | 953 | --------------------------------------------------------------------------------