Finish course 3 week 1

master
Felix Martin 2021-02-02 14:26:50 -05:00
parent b69713fb5e
commit a13fae6ceb
6 changed files with 226 additions and 164 deletions

View File

@ -4,31 +4,32 @@ struct MinHeap<T> {
} }
fn parent_index(index: usize) -> usize { fn parent_index(index: usize) -> usize {
(index + 1) / 2 - 1 (index + 1) / 2 - 1
} }
fn child_indices(index: usize) -> (usize, usize) { 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<T: std::cmp::PartialOrd> MinHeap<T> { impl<T: std::cmp::PartialOrd> MinHeap<T> {
fn new() -> Self { fn new() -> Self {
Self { nodes: Vec::with_capacity(128) } Self {
nodes: Vec::with_capacity(128),
}
} }
fn smaller_than_parent(&self, index: usize) -> bool { fn smaller_than_parent(&self, index: usize) -> bool {
if index == 0 { if index == 0 {
false false
} else { } else {
self.nodes[index] < self.nodes[parent_index(index)]
self.nodes[index] < self.nodes[parent_index(index)] }
}
} }
fn bubble_up(&mut self, index: usize) -> usize { fn bubble_up(&mut self, index: usize) -> usize {
let parent_index = parent_index(index); let parent_index = parent_index(index);
self.nodes.swap(index, parent_index); self.nodes.swap(index, parent_index);
parent_index parent_index
} }
fn insert(&mut self, e: T) -> () { fn insert(&mut self, e: T) -> () {
@ -37,57 +38,57 @@ impl<T: std::cmp::PartialOrd> MinHeap<T> {
let mut bubble_index = last; let mut bubble_index = last;
while self.smaller_than_parent(bubble_index) { 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 { fn greater_than_children(&self, index: usize) -> bool {
let length = self.nodes.len(); let length = self.nodes.len();
let (left_index, right_index) = child_indices(index); let (left_index, right_index) = child_indices(index);
if left_index < length && self.nodes[index] > self.nodes[left_index] { if left_index < length && self.nodes[index] > self.nodes[left_index] {
true true
} else if right_index < length && self.nodes[index] > self.nodes[right_index] { } else if right_index < length && self.nodes[index] > self.nodes[right_index] {
true true
} else { } else {
false false
} }
} }
fn bubble_down(&mut self, index: usize) -> usize { fn bubble_down(&mut self, index: usize) -> usize {
let length = self.nodes.len(); let length = self.nodes.len();
let (left_index, right_index) = child_indices(index); let (left_index, right_index) = child_indices(index);
let mut target_index = index; let mut target_index = index;
if left_index < length && self.nodes[target_index] > self.nodes[left_index] { if left_index < length && self.nodes[target_index] > self.nodes[left_index] {
target_index = left_index; target_index = left_index;
} }
if right_index < length && self.nodes[right_index] < self.nodes[target_index] { if right_index < length && self.nodes[right_index] < self.nodes[target_index] {
target_index = right_index; target_index = right_index;
} }
self.nodes.swap(index, target_index); self.nodes.swap(index, target_index);
target_index target_index
} }
fn extract_min(&mut self) -> T { fn extract_min(&mut self) -> T {
if self.nodes.len() == 0 { if self.nodes.len() == 0 {
panic!("Cannot extract key from empty heap"); panic!("Cannot extract key from empty heap");
} }
let mut bubble_index = 0; let mut bubble_index = 0;
let last = self.nodes.len() - 1; let last = self.nodes.len() - 1;
self.nodes.swap(bubble_index, last); self.nodes.swap(bubble_index, last);
let result = self.nodes.pop().unwrap(); let result = self.nodes.pop().unwrap();
while self.greater_than_children(bubble_index) { while self.greater_than_children(bubble_index) {
bubble_index = self.bubble_down(bubble_index); bubble_index = self.bubble_down(bubble_index);
} }
result result
} }
fn size(&self) -> usize { fn size(&self) -> usize {
self.nodes.len() self.nodes.len()
} }
} }
@ -95,32 +96,32 @@ pub fn heap(v: &Vec<i64>) -> i64 {
let mut hl: MinHeap<i64> = MinHeap::new(); let mut hl: MinHeap<i64> = MinHeap::new();
let mut hh: MinHeap<i64> = MinHeap::new(); let mut hh: MinHeap<i64> = MinHeap::new();
let mut iter = v.into_iter(); let mut iter = v.into_iter();
let mut current_median = *iter.next().unwrap(); let mut current_median = *iter.next().unwrap();
let mut median_sum = current_median; let mut median_sum = current_median;
hl.insert(-current_median); hl.insert(-current_median);
for e in iter { for e in iter {
let e = *e; let e = *e;
if e < current_median { if e < current_median {
hl.insert(-e); hl.insert(-e);
} else { } else {
hh.insert(e); hh.insert(e);
} }
while hl.size() < hh.size() { while hl.size() < hh.size() {
let e = hh.extract_min(); let e = hh.extract_min();
hl.insert(-e); hl.insert(-e);
} }
while hl.size() > hh.size() + 1 { while hl.size() > hh.size() + 1 {
let e = -hl.extract_min(); let e = -hl.extract_min();
hh.insert(e); hh.insert(e);
} }
current_median = -hl.extract_min(); current_median = -hl.extract_min();
median_sum = (median_sum + current_median) % 10000; median_sum = (median_sum + current_median) % 10000;
hl.insert(-current_median); hl.insert(-current_median);
} }
median_sum median_sum

View File

@ -2,47 +2,47 @@ use std::cmp::Ordering;
#[derive(Debug)] #[derive(Debug)]
pub struct Job { pub struct Job {
pub weight: i64, pub weight: i64,
pub length: i64, pub length: i64,
} }
pub type Jobs = Vec<Job>; pub type Jobs = Vec<Job>;
fn weighted_completion_time(jobs: &Jobs) -> i64 { fn weighted_completion_time(jobs: &Jobs) -> i64 {
let mut time = 0; let mut time = 0;
let mut weighted_completion_time = 0; let mut weighted_completion_time = 0;
for job in jobs { for job in jobs {
let completion_time = time + job.length; let completion_time = time + job.length;
weighted_completion_time += completion_time * job.weight; weighted_completion_time += completion_time * job.weight;
time += job.length; time += job.length;
} }
weighted_completion_time weighted_completion_time
} }
fn compare_1(a: &Job, b: &Job) -> Ordering { fn compare_1(a: &Job, b: &Job) -> Ordering {
let da = a.weight - a.length; let da = a.weight - a.length;
let db = b.weight - b.length; let db = b.weight - b.length;
if da == db { if da == db {
b.weight.cmp(&a.weight) b.weight.cmp(&a.weight)
} else { } else {
db.cmp(&da) db.cmp(&da)
} }
} }
fn compare_2(a: &Job, b: &Job) -> Ordering { fn compare_2(a: &Job, b: &Job) -> Ordering {
let da: f64 = a.weight as f64 / a.length as f64; let da: f64 = a.weight as f64 / a.length as f64;
let db: f64 = b.weight as f64 / b.length as f64; let db: f64 = b.weight as f64 / b.length as f64;
db.partial_cmp(&da).unwrap() db.partial_cmp(&da).unwrap()
} }
pub fn jobs_1(jobs: &mut Jobs) -> i64 { pub fn jobs_1(jobs: &mut Jobs) -> i64 {
jobs.sort_by(compare_1); jobs.sort_by(compare_1);
weighted_completion_time(&jobs) weighted_completion_time(&jobs)
} }
pub fn jobs_2(jobs: &mut Jobs) -> i64 { pub fn jobs_2(jobs: &mut Jobs) -> i64 {
jobs.sort_by(compare_2); jobs.sort_by(compare_2);
weighted_completion_time(&jobs) weighted_completion_time(&jobs)
} }

View File

@ -1,25 +1,24 @@
mod dijkstra; mod dijkstra;
mod heap; mod heap;
mod jobs;
mod merge_sort; mod merge_sort;
mod min_cut; mod min_cut;
mod prims;
mod quick_sort; mod quick_sort;
mod ssc; mod ssc;
mod util;
mod two_sum; mod two_sum;
mod jobs; mod util;
mod prims;
use std::cmp::min;
use crate::dijkstra::dijkstra; use crate::dijkstra::dijkstra;
use crate::heap::heap; use crate::heap::heap;
use crate::jobs::{jobs_1, jobs_2};
use crate::merge_sort::merge_sort_inversions; use crate::merge_sort::merge_sort_inversions;
use crate::min_cut::min_cut; use crate::min_cut::min_cut;
use crate::prims::prims;
use crate::quick_sort::quick_sort; use crate::quick_sort::quick_sort;
use crate::ssc::ssc; use crate::ssc::ssc;
use crate::two_sum::find_two_sums; use crate::two_sum::find_two_sums;
use crate::jobs::{jobs_1, jobs_2}; use std::cmp::min;
use crate::prims::prims;
#[allow(dead_code)] #[allow(dead_code)]
fn c1a2() { fn c1a2() {
@ -86,20 +85,25 @@ fn c2a4() {
let mut v = util::read_to_vector("data/c2a4.txt").unwrap(); let mut v = util::read_to_vector("data/c2a4.txt").unwrap();
let r = find_two_sums(&mut v); let r = find_two_sums(&mut v);
println!("c2a4={:?}", r); println!("c2a4={:?}", r);
// c2a4=427 // c2a4=427
} }
#[allow(dead_code)] #[allow(dead_code)]
fn c3a1() { fn c3a1() {
let mut jobs = util::read_jobs("data/c3a1_jobs.txt").unwrap(); // belongs to c3a1
let r1 = jobs_1(&mut jobs); let mut jobs = util::read_jobs("data/c3a1_jobs.txt").unwrap();
let r2 = jobs_2(&mut jobs); 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(); // r1 = 69119377652; r2 = 67311454237; r3 = -3612829
let r3 = prims(&g); }
println!("r1 = {}; r2 = {}; r3 = {} ", r1, r2, r3); #[allow(dead_code)]
// r1 = 69119377652; r2 != 67311454237; fn c3a2() {
println!("let's go");
} }
fn main() { fn main() {
@ -110,5 +114,6 @@ fn main() {
// c2a2(); // c2a2();
// c2a3(); // c2a3();
// c2a4(); // c2a4();
c3a1(); // c3a1();
c3a2();
} }

View File

@ -1,14 +1,49 @@
#[derive(Debug, Clone)] use std::collections::HashSet;
#[derive(Debug, Clone, Copy)]
pub struct Edge { pub struct Edge {
pub node_a: u32, pub weight: i32,
pub node_b: u32, pub source_id: usize,
pub weight: u32, pub target_id: usize,
} }
pub type WeightedGraph = Vec<Edge>; #[derive(Debug, Clone)]
pub struct Vertex {
pub id: usize,
pub edges: Vec<Edge>,
}
pub fn prims(graph: &WeightedGraph) -> usize { pub type WeightedGraph = Vec<Vertex>;
println!("{:?}", graph);
42 pub fn prims(graph: &WeightedGraph) -> i32 {
} let mut x: HashSet<usize> = 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
}

View File

@ -1,44 +1,49 @@
use std::collections::HashSet; use std::collections::HashSet;
fn binary_search<T: std::cmp::PartialOrd>(min_i: usize, max_i: usize, xs: &Vec<T>, needle: T) -> usize { fn binary_search<T: std::cmp::PartialOrd>(
if min_i >= max_i { min_i: usize,
return max_i; max_i: usize,
} xs: &Vec<T>,
let half_i = min_i + (max_i - min_i) / 2; 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 { if xs[half_i] == needle {
return half_i; return half_i;
} }
if needle < xs[half_i] { if needle < xs[half_i] {
binary_search(min_i, half_i - 1, &xs, needle) binary_search(min_i, half_i - 1, &xs, needle)
} else { } else {
binary_search(half_i + 1, max_i, xs, needle) binary_search(half_i + 1, max_i, xs, needle)
} }
} }
pub fn find_two_sums(xs: &mut Vec<i64>) -> usize { pub fn find_two_sums(xs: &mut Vec<i64>) -> usize {
let mut found: HashSet<i64> = HashSet::new(); let mut found: HashSet<i64> = HashSet::new();
const T_MIN: i64 = -10000; const T_MIN: i64 = -10000;
const T_MAX: i64 = 10000; const T_MAX: i64 = 10000;
xs.sort(); xs.sort();
for i in 0..xs.len() { for i in 0..xs.len() {
let a: i64 = xs[i]; let a: i64 = xs[i];
let b_min = T_MIN - a; let b_min = T_MIN - a;
let b_max = T_MAX - a; let b_max = T_MAX - a;
let i_min = binary_search(i + 1, xs.len() - 1, &xs, b_min); 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); let i_max = binary_search(i + 1, xs.len() - 1, &xs, b_max);
for i in i_min..(i_max + 1) { for i in i_min..(i_max + 1) {
let b = xs[i]; let b = xs[i];
let t = a + b; let t = a + b;
if T_MIN <= t && t <= T_MAX { if T_MIN <= t && t <= T_MAX {
found.insert(t); found.insert(t);
} }
} }
} }
found.len() found.len()
} }
// fn two_sum(t: i64, xs: &Vec<i64>, ys: &HashSet<i64>) -> bool { // fn two_sum(t: i64, xs: &Vec<i64>, ys: &HashSet<i64>) -> bool {
@ -63,7 +68,7 @@ pub fn find_two_sums(xs: &mut Vec<i64>) -> usize {
// for t in -10000..10001 { // for t in -10000..10001 {
// if t % 10 == 0 { // if t % 10 == 0 {
// println!("{:?}", t); // println!("{:?}", t);
// } // }
// if two_sum(t, &xs_min, &xs_max_set) { // if two_sum(t, &xs_min, &xs_max_set) {
// r += 1 // r += 1
// } // }

View File

@ -1,9 +1,9 @@
use crate::jobs::{Job, Jobs};
use crate::prims::{Edge, Vertex, WeightedGraph};
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::{BufRead, BufReader, Error, ErrorKind}; use std::io::{BufRead, BufReader, Error, ErrorKind};
use std::vec::Vec; use std::vec::Vec;
use crate::jobs::{Job, Jobs};
use crate::prims::{WeightedGraph, Edge};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Graph { pub struct Graph {
@ -163,28 +163,44 @@ pub fn read_jobs(path: &str) -> Result<Jobs, io::Error> {
} }
pub fn read_weighted_graph(path: &str) -> Result<WeightedGraph, io::Error> { pub fn read_weighted_graph(path: &str) -> Result<WeightedGraph, io::Error> {
let g = Vec::new(); let mut g = Vec::new();
let file = File::open(path)?; let file = File::open(path)?;
let br = BufReader::new(file); let br = BufReader::new(file);
let mut lines = br.lines(); let mut lines = br.lines();
let line = lines.next().unwrap().unwrap(); let line = lines.next().unwrap().unwrap();
let mut nodes = line.split_whitespace(); let mut fields = line.split_whitespace();
let n_nodes: usize = nodes.next().unwrap().parse().unwrap(); let n_nodes: usize = fields.next().unwrap().parse().unwrap();
let n_edges: usize = nodes.next().unwrap().parse().unwrap(); // let n_edges: usize = fields.next().unwrap().parse().unwrap();
println!("{:?} {:?}", n_nodes, n_edges); for i in 0..n_nodes {
// lines.next(); let node = Vertex {
// for line in lines { id: i,
// let line = line?; edges: vec![],
// let mut nodes = line.split_whitespace(); };
// let weight = nodes.next().unwrap().parse().unwrap(); g.push(node);
// let length = nodes.next().unwrap().parse().unwrap(); }
// let job = Job {
// weight: weight, for line in lines {
// length: length, let line = line?;
// }; let mut nodes = line.split_whitespace();
// jobs.push(job); let id_a: usize = nodes.next().unwrap().parse::<usize>().unwrap() - 1;
// } let id_b: usize = nodes.next().unwrap().parse::<usize>().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) Ok(g)
} }