From a13fae6cebfbf57ea83358c57f597c2279d53458 Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Tue, 2 Feb 2021 14:26:50 -0500 Subject: [PATCH] Finish course 3 week 1 --- src/heap.rs | 127 +++++++++++++++++++++++++------------------------ src/jobs.rs | 48 +++++++++---------- src/main.rs | 37 +++++++------- src/prims.rs | 53 +++++++++++++++++---- src/two_sum.rs | 71 ++++++++++++++------------- src/util.rs | 54 +++++++++++++-------- 6 files changed, 226 insertions(+), 164 deletions(-) diff --git a/src/heap.rs b/src/heap.rs index 005ca85..c2364a6 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -4,31 +4,32 @@ struct MinHeap { } fn parent_index(index: usize) -> usize { - (index + 1) / 2 - 1 + (index + 1) / 2 - 1 } fn child_indices(index: usize) -> (usize, usize) { - ((index + 1) * 2 - 1, (index + 1) * 2 + 1 - 1) + ((index + 1) * 2 - 1, (index + 1) * 2 + 1 - 1) } impl MinHeap { fn new() -> Self { - Self { nodes: Vec::with_capacity(128) } + Self { + nodes: Vec::with_capacity(128), + } } fn smaller_than_parent(&self, index: usize) -> bool { - if index == 0 { - false - } else { - - self.nodes[index] < self.nodes[parent_index(index)] - } + if index == 0 { + false + } else { + self.nodes[index] < self.nodes[parent_index(index)] + } } fn bubble_up(&mut self, index: usize) -> usize { - let parent_index = parent_index(index); - self.nodes.swap(index, parent_index); - parent_index + let parent_index = parent_index(index); + self.nodes.swap(index, parent_index); + parent_index } fn insert(&mut self, e: T) -> () { @@ -37,57 +38,57 @@ impl MinHeap { let mut bubble_index = last; while self.smaller_than_parent(bubble_index) { - bubble_index = self.bubble_up(bubble_index); + bubble_index = self.bubble_up(bubble_index); } } fn greater_than_children(&self, index: usize) -> bool { - let length = self.nodes.len(); - let (left_index, right_index) = child_indices(index); - if left_index < length && self.nodes[index] > self.nodes[left_index] { - true - } else if right_index < length && self.nodes[index] > self.nodes[right_index] { - true - } else { - false - } + let length = self.nodes.len(); + let (left_index, right_index) = child_indices(index); + if left_index < length && self.nodes[index] > self.nodes[left_index] { + true + } else if right_index < length && self.nodes[index] > self.nodes[right_index] { + true + } else { + false + } } fn bubble_down(&mut self, index: usize) -> usize { - let length = self.nodes.len(); - let (left_index, right_index) = child_indices(index); - let mut target_index = index; + let length = self.nodes.len(); + let (left_index, right_index) = child_indices(index); + let mut target_index = index; - if left_index < length && self.nodes[target_index] > self.nodes[left_index] { - target_index = left_index; - } + if left_index < length && self.nodes[target_index] > self.nodes[left_index] { + target_index = left_index; + } - if right_index < length && self.nodes[right_index] < self.nodes[target_index] { - target_index = right_index; - } - self.nodes.swap(index, target_index); - target_index + if right_index < length && self.nodes[right_index] < self.nodes[target_index] { + target_index = right_index; + } + self.nodes.swap(index, target_index); + target_index } fn extract_min(&mut self) -> T { - if self.nodes.len() == 0 { - panic!("Cannot extract key from empty heap"); - } + if self.nodes.len() == 0 { + panic!("Cannot extract key from empty heap"); + } - let mut bubble_index = 0; - let last = self.nodes.len() - 1; - self.nodes.swap(bubble_index, last); - let result = self.nodes.pop().unwrap(); + let mut bubble_index = 0; + let last = self.nodes.len() - 1; + self.nodes.swap(bubble_index, last); + let result = self.nodes.pop().unwrap(); - while self.greater_than_children(bubble_index) { - bubble_index = self.bubble_down(bubble_index); - } + while self.greater_than_children(bubble_index) { + bubble_index = self.bubble_down(bubble_index); + } - result + result } fn size(&self) -> usize { - self.nodes.len() + self.nodes.len() } } @@ -95,32 +96,32 @@ pub fn heap(v: &Vec) -> i64 { let mut hl: MinHeap = MinHeap::new(); let mut hh: MinHeap = MinHeap::new(); - let mut iter = v.into_iter(); + let mut iter = v.into_iter(); let mut current_median = *iter.next().unwrap(); let mut median_sum = current_median; hl.insert(-current_median); for e in iter { - let e = *e; - if e < current_median { - hl.insert(-e); - } else { - hh.insert(e); - } + let e = *e; + if e < current_median { + hl.insert(-e); + } else { + hh.insert(e); + } - while hl.size() < hh.size() { - let e = hh.extract_min(); - hl.insert(-e); - } + while hl.size() < hh.size() { + let e = hh.extract_min(); + hl.insert(-e); + } - while hl.size() > hh.size() + 1 { - let e = -hl.extract_min(); - hh.insert(e); - } + while hl.size() > hh.size() + 1 { + let e = -hl.extract_min(); + hh.insert(e); + } - current_median = -hl.extract_min(); - median_sum = (median_sum + current_median) % 10000; - hl.insert(-current_median); + current_median = -hl.extract_min(); + median_sum = (median_sum + current_median) % 10000; + hl.insert(-current_median); } median_sum diff --git a/src/jobs.rs b/src/jobs.rs index ded07e5..73e2596 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -2,47 +2,47 @@ use std::cmp::Ordering; #[derive(Debug)] pub struct Job { - pub weight: i64, - pub length: i64, + pub weight: i64, + pub length: i64, } pub type Jobs = Vec; fn weighted_completion_time(jobs: &Jobs) -> i64 { - let mut time = 0; - let mut weighted_completion_time = 0; + let mut time = 0; + let mut weighted_completion_time = 0; - for job in jobs { - let completion_time = time + job.length; - weighted_completion_time += completion_time * job.weight; - time += job.length; - } + for job in jobs { + let completion_time = time + job.length; + weighted_completion_time += completion_time * job.weight; + time += job.length; + } - weighted_completion_time + weighted_completion_time } fn compare_1(a: &Job, b: &Job) -> Ordering { - let da = a.weight - a.length; - let db = b.weight - b.length; - if da == db { - b.weight.cmp(&a.weight) - } else { - db.cmp(&da) - } + let da = a.weight - a.length; + let db = b.weight - b.length; + if da == db { + b.weight.cmp(&a.weight) + } else { + db.cmp(&da) + } } fn compare_2(a: &Job, b: &Job) -> Ordering { - let da: f64 = a.weight as f64 / a.length as f64; - let db: f64 = b.weight as f64 / b.length as f64; - db.partial_cmp(&da).unwrap() + let da: f64 = a.weight as f64 / a.length as f64; + let db: f64 = b.weight as f64 / b.length as f64; + db.partial_cmp(&da).unwrap() } pub fn jobs_1(jobs: &mut Jobs) -> i64 { - jobs.sort_by(compare_1); - weighted_completion_time(&jobs) + jobs.sort_by(compare_1); + weighted_completion_time(&jobs) } pub fn jobs_2(jobs: &mut Jobs) -> i64 { - jobs.sort_by(compare_2); - weighted_completion_time(&jobs) + jobs.sort_by(compare_2); + weighted_completion_time(&jobs) } diff --git a/src/main.rs b/src/main.rs index 9072156..d890625 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,24 @@ mod dijkstra; mod heap; +mod jobs; mod merge_sort; mod min_cut; +mod prims; mod quick_sort; mod ssc; -mod util; mod two_sum; -mod jobs; -mod prims; +mod util; -use std::cmp::min; use crate::dijkstra::dijkstra; use crate::heap::heap; +use crate::jobs::{jobs_1, jobs_2}; use crate::merge_sort::merge_sort_inversions; use crate::min_cut::min_cut; +use crate::prims::prims; use crate::quick_sort::quick_sort; use crate::ssc::ssc; use crate::two_sum::find_two_sums; -use crate::jobs::{jobs_1, jobs_2}; -use crate::prims::prims; - +use std::cmp::min; #[allow(dead_code)] fn c1a2() { @@ -86,20 +85,25 @@ fn c2a4() { let mut v = util::read_to_vector("data/c2a4.txt").unwrap(); let r = find_two_sums(&mut v); println!("c2a4={:?}", r); - // c2a4=427 + // c2a4=427 } #[allow(dead_code)] fn c3a1() { - let mut jobs = util::read_jobs("data/c3a1_jobs.txt").unwrap(); - let r1 = jobs_1(&mut jobs); - let r2 = jobs_2(&mut jobs); + // belongs to c3a1 + let mut jobs = util::read_jobs("data/c3a1_jobs.txt").unwrap(); + let r1 = jobs_1(&mut jobs); + let r2 = jobs_2(&mut jobs); + let g = util::read_weighted_graph("data/c3a1_edges.txt").unwrap(); + let r3 = prims(&g); + println!("r1 = {}; r2 = {}; r3 = {} ", r1, r2, r3); - let g = util::read_weighted_graph("data/c3a1_edges.txt").unwrap(); - let r3 = prims(&g); + // r1 = 69119377652; r2 = 67311454237; r3 = -3612829 +} - println!("r1 = {}; r2 = {}; r3 = {} ", r1, r2, r3); - // r1 = 69119377652; r2 != 67311454237; +#[allow(dead_code)] +fn c3a2() { + println!("let's go"); } fn main() { @@ -110,5 +114,6 @@ fn main() { // c2a2(); // c2a3(); // c2a4(); - c3a1(); + // c3a1(); + c3a2(); } diff --git a/src/prims.rs b/src/prims.rs index 7d9f9ec..34deec5 100644 --- a/src/prims.rs +++ b/src/prims.rs @@ -1,14 +1,49 @@ -#[derive(Debug, Clone)] +use std::collections::HashSet; +#[derive(Debug, Clone, Copy)] pub struct Edge { - pub node_a: u32, - pub node_b: u32, - pub weight: u32, + pub weight: i32, + pub source_id: usize, + pub target_id: usize, } -pub type WeightedGraph = Vec; +#[derive(Debug, Clone)] +pub struct Vertex { + pub id: usize, + pub edges: Vec, +} -pub fn prims(graph: &WeightedGraph) -> usize { - println!("{:?}", graph); - 42 -} \ No newline at end of file +pub type WeightedGraph = Vec; + +pub fn prims(graph: &WeightedGraph) -> i32 { + let mut x: HashSet = HashSet::new(); + let mut t = Vec::new(); + + x.insert(0); + + while x.len() != graph.len() { + let mut min_edge = Edge { + weight: i32::MAX, + source_id: 0, + target_id: 0, + }; + + for node_id in &x { + for edge in &graph[*node_id].edges { + if edge.weight < min_edge.weight && !x.contains(&edge.target_id) { + min_edge = *edge; + } + } + } + + x.insert(min_edge.target_id); + t.push(min_edge); + } + + let mut result = 0; + for edge in &t { + result += edge.weight; + } + + result +} diff --git a/src/two_sum.rs b/src/two_sum.rs index 9f36c64..ff57766 100644 --- a/src/two_sum.rs +++ b/src/two_sum.rs @@ -1,44 +1,49 @@ use std::collections::HashSet; -fn binary_search(min_i: usize, max_i: usize, xs: &Vec, needle: T) -> usize { - if min_i >= max_i { - return max_i; - } - let half_i = min_i + (max_i - min_i) / 2; +fn binary_search( + min_i: usize, + max_i: usize, + xs: &Vec, + needle: T, +) -> usize { + if min_i >= max_i { + return max_i; + } + let half_i = min_i + (max_i - min_i) / 2; - if xs[half_i] == needle { - return half_i; - } + if xs[half_i] == needle { + return half_i; + } - if needle < xs[half_i] { - binary_search(min_i, half_i - 1, &xs, needle) - } else { - binary_search(half_i + 1, max_i, xs, needle) - } + if needle < xs[half_i] { + binary_search(min_i, half_i - 1, &xs, needle) + } else { + binary_search(half_i + 1, max_i, xs, needle) + } } pub fn find_two_sums(xs: &mut Vec) -> usize { - let mut found: HashSet = HashSet::new(); - const T_MIN: i64 = -10000; - const T_MAX: i64 = 10000; - xs.sort(); + let mut found: HashSet = HashSet::new(); + const T_MIN: i64 = -10000; + const T_MAX: i64 = 10000; + xs.sort(); - for i in 0..xs.len() { - let a: i64 = xs[i]; - let b_min = T_MIN - a; - let b_max = T_MAX - a; - let i_min = binary_search(i + 1, xs.len() - 1, &xs, b_min); - let i_max = binary_search(i + 1, xs.len() - 1, &xs, b_max); + for i in 0..xs.len() { + let a: i64 = xs[i]; + let b_min = T_MIN - a; + let b_max = T_MAX - a; + let i_min = binary_search(i + 1, xs.len() - 1, &xs, b_min); + let i_max = binary_search(i + 1, xs.len() - 1, &xs, b_max); - for i in i_min..(i_max + 1) { - let b = xs[i]; - let t = a + b; - if T_MIN <= t && t <= T_MAX { - found.insert(t); - } - } - } - found.len() + for i in i_min..(i_max + 1) { + let b = xs[i]; + let t = a + b; + if T_MIN <= t && t <= T_MAX { + found.insert(t); + } + } + } + found.len() } // fn two_sum(t: i64, xs: &Vec, ys: &HashSet) -> bool { @@ -63,7 +68,7 @@ pub fn find_two_sums(xs: &mut Vec) -> usize { // for t in -10000..10001 { // if t % 10 == 0 { // println!("{:?}", t); -// } +// } // if two_sum(t, &xs_min, &xs_max_set) { // r += 1 // } diff --git a/src/util.rs b/src/util.rs index 152d5af..48874b0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,9 +1,9 @@ +use crate::jobs::{Job, Jobs}; +use crate::prims::{Edge, Vertex, WeightedGraph}; use std::fs::File; use std::io; use std::io::{BufRead, BufReader, Error, ErrorKind}; use std::vec::Vec; -use crate::jobs::{Job, Jobs}; -use crate::prims::{WeightedGraph, Edge}; #[derive(Debug, Clone)] pub struct Graph { @@ -163,28 +163,44 @@ pub fn read_jobs(path: &str) -> Result { } pub fn read_weighted_graph(path: &str) -> Result { - let g = Vec::new(); + let mut g = Vec::new(); let file = File::open(path)?; let br = BufReader::new(file); let mut lines = br.lines(); let line = lines.next().unwrap().unwrap(); - let mut nodes = line.split_whitespace(); - let n_nodes: usize = nodes.next().unwrap().parse().unwrap(); - let n_edges: usize = nodes.next().unwrap().parse().unwrap(); + let mut fields = line.split_whitespace(); + let n_nodes: usize = fields.next().unwrap().parse().unwrap(); + // let n_edges: usize = fields.next().unwrap().parse().unwrap(); - println!("{:?} {:?}", n_nodes, n_edges); - // lines.next(); - // for line in lines { - // let line = line?; - // let mut nodes = line.split_whitespace(); - // let weight = nodes.next().unwrap().parse().unwrap(); - // let length = nodes.next().unwrap().parse().unwrap(); - // let job = Job { - // weight: weight, - // length: length, - // }; - // jobs.push(job); - // } + for i in 0..n_nodes { + let node = Vertex { + id: i, + edges: vec![], + }; + g.push(node); + } + + for line in lines { + let line = line?; + let mut nodes = line.split_whitespace(); + let id_a: usize = nodes.next().unwrap().parse::().unwrap() - 1; + let id_b: usize = nodes.next().unwrap().parse::().unwrap() - 1; + let weight = nodes.next().unwrap().parse().unwrap(); + + let edge = Edge { + weight: weight, + source_id: id_a, + target_id: id_b, + }; + g[id_a].edges.push(edge); + + let edge = Edge { + weight: weight, + source_id: id_b, + target_id: id_a, + }; + g[id_b].edges.push(edge); + } Ok(g) }