From e443fe6c811f70d273eda580b6c666e4be91107e Mon Sep 17 00:00:00 2001 From: static Date: Thu, 28 Nov 2024 15:28:47 +0000 Subject: [PATCH] Assignment 9 Done --- src/assignments/assignment09/bigint.rs | 75 ++++++- src/assignments/assignment09/matmul.rs | 30 ++- .../assignment09/small_exercises.rs | 183 ++++++++++++++++-- 3 files changed, 266 insertions(+), 22 deletions(-) diff --git a/src/assignments/assignment09/bigint.rs b/src/assignments/assignment09/bigint.rs index 95f2e2c..acf300a 100644 --- a/src/assignments/assignment09/bigint.rs +++ b/src/assignments/assignment09/bigint.rs @@ -38,7 +38,7 @@ pub struct BigInt { impl BigInt { /// Create a new `BigInt` from a `usize`. pub fn new(n: u32) -> Self { - todo!() + BigInt { carrier: vec![n] } } /// Creates a new `BigInt` from a `Vec`. @@ -48,7 +48,7 @@ impl BigInt { /// Panics if `carrier` is empty. pub fn new_large(carrier: Vec) -> Self { assert!(!carrier.is_empty()); - todo!() + BigInt { carrier } } } @@ -57,17 +57,52 @@ const SIGN_MASK: u32 = 1 << 31; impl BigInt { /// Extend `self` to `len` bits. fn sign_extension(&self, len: usize) -> Self { - todo!() + let mut carrier = vec![ + if self.carrier[0] & SIGN_MASK == 0 { + 0 + } else { + 0xFFFFFFFF + }; + (len + 31) / 32 - self.carrier.len() + ]; + carrier.extend_from_slice(&self.carrier); + + Self { carrier } } /// Compute the two's complement of `self`. fn two_complement(&self) -> Self { - todo!() + let mut one_complement = self.clone(); + + for v in &mut one_complement.carrier { + *v = !*v; + } + + one_complement + BigInt::new(1) } /// Truncate a `BigInt` to the minimum length. fn truncate(&self) -> Self { - todo!() + let sign = (self.carrier[0] & SIGN_MASK) != 0; + + for i in 0..(self.carrier.len() - 1) { + if (!sign + && (self.carrier[i] != 0 + || (self.carrier[i + 1] != 0 && (self.carrier[i + 1] & SIGN_MASK) != 0))) + || (sign + && (self.carrier[i] != u32::MAX + || (self.carrier[i + 1] != u32::MAX + && (self.carrier[i + 1] & SIGN_MASK) == 0))) + { + return Self { + carrier: self.carrier[i..].to_vec(), + }; + } + } + + Self { + carrier: self.carrier[self.carrier.len() - 1..].to_vec(), + } } } @@ -75,7 +110,33 @@ impl Add for BigInt { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - todo!() + let len = if self.carrier.len() > rhs.carrier.len() { + self.carrier.len() + } else { + rhs.carrier.len() + }; + let len = (len + 1) * 32; + let (lhs, rhs) = (self.sign_extension(len), rhs.sign_extension(len)); + + let mut carrier = vec![]; + let mut overflow = false; + + for (&l, &r) in lhs.carrier.iter().zip(rhs.carrier.iter()).rev() { + let (v, of) = l.overflowing_add(r); + if overflow { + let (v, of) = v.overflowing_add(1); + carrier.push(v); + overflow = of; + } else { + carrier.push(v); + overflow = of; + } + } + + let result = Self::Output { + carrier: carrier.iter().rev().copied().collect(), + }; + result.truncate() } } @@ -83,7 +144,7 @@ impl Sub for BigInt { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { - todo!() + self.add(rhs.two_complement()) } } diff --git a/src/assignments/assignment09/matmul.rs b/src/assignments/assignment09/matmul.rs index ec7c39a..ff2763b 100644 --- a/src/assignments/assignment09/matmul.rs +++ b/src/assignments/assignment09/matmul.rs @@ -15,7 +15,13 @@ use itertools::*; /// assert_eq!(res, vec![2.0, 4.0, 6.0, 8.0, 10.0]); /// ``` pub fn vec_add(lhs: &[f64], rhs: &[f64]) -> Vec { - todo!() + let mut result = vec![]; + + for (l, r) in lhs.iter().zip(rhs) { + result.push(l + *r); + } + + result } /// dot product of two arrays @@ -35,7 +41,13 @@ pub fn vec_add(lhs: &[f64], rhs: &[f64]) -> Vec { /// assert_eq!(res, 55.0); /// ``` pub fn dot_product(lhs: &[f64], rhs: &[f64]) -> f64 { - todo!() + let mut result = 0.0; + + for (l, r) in lhs.iter().zip(rhs) { + result += l * *r; + } + + result } /// Matrix multiplication @@ -68,5 +80,17 @@ pub fn dot_product(lhs: &[f64], rhs: &[f64]) -> f64 { /// assert_eq!(ans, res); /// ``` pub fn matmul(lhs: &[Vec], rhs: &[Vec]) -> Vec> { - todo!() + let mut result = vec![]; + + for (i, l) in lhs.iter().enumerate() { + let mut temp = vec![]; + + for (j, r) in rhs.iter().enumerate() { + temp.push(dot_product(l, r)); + } + + result.push(temp); + } + + result } diff --git a/src/assignments/assignment09/small_exercises.rs b/src/assignments/assignment09/small_exercises.rs index 9ff2123..1e0990f 100644 --- a/src/assignments/assignment09/small_exercises.rs +++ b/src/assignments/assignment09/small_exercises.rs @@ -18,7 +18,28 @@ use itertools::Itertools; /// assert_eq!(is_fibonacci([1, 1, 2, 3, 5, 8, 14].into_iter()), false); /// ``` pub fn is_fibonacci(inner: impl Iterator) -> bool { - todo!() + let mut inner = inner; + + let mut first = if let Some(v) = inner.next() { + v + } else { + return true; + }; + let mut second = if let Some(v) = inner.next() { + v + } else { + return true; + }; + + for third in inner { + if first + second == third { + first = second; + second = third; + } else { + return false; + } + } + true } /// Returns the sum of `f(v)` for all element `v` the given array. @@ -32,7 +53,7 @@ pub fn is_fibonacci(inner: impl Iterator) -> bool { /// assert_eq!(sigma([1, 2].into_iter(), |x| x * 4), 12); /// ``` pub fn sigma i64>(inner: impl Iterator, f: F) -> i64 { - todo!() + inner.map(f).sum() } /// Alternate elements from three iterators until they have run out. @@ -54,7 +75,22 @@ pub fn interleave3( list2: impl Iterator, list3: impl Iterator, ) -> Vec { - todo!() + let mut list1 = list1; + let mut list2 = list2; + let mut list3 = list3; + + let mut result = vec![]; + + for e1 in list1 { + let e2 = list2.next().unwrap(); + let e3 = list3.next().unwrap(); + + result.push(e1); + result.push(e2); + result.push(e3); + } + + result } /// Alternate elements from array of n iterators until they have run out. @@ -74,8 +110,20 @@ pub fn interleave3( pub fn interleave_n( mut iters: [impl Iterator; N], ) -> impl Iterator { - todo!(); - std::iter::empty() + struct MyIterator { + iters: [I; N], + counter: usize, + } + impl Iterator for MyIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + let item = self.iters[self.counter % N].next(); + self.counter += 1; + item + } + } + MyIterator { iters, counter: 0 } } /// Returns mean of k smallest value's mean. @@ -95,7 +143,14 @@ pub fn interleave_n( /// ); /// ``` pub fn k_smallest_mean(inner: impl Iterator, k: usize) -> f64 { - todo!() + let mut vec = inner.collect_vec(); + if vec.is_empty() { + return 0.0; + } + + let k = if k <= vec.len() { k } else { vec.len() }; + vec.sort(); + (vec[0..k].iter().sum::() as f64) / (k as f64) } /// Returns mean for each class. @@ -125,7 +180,24 @@ pub fn k_smallest_mean(inner: impl Iterator, k: usize) -> f64 { /// ); /// ``` pub fn calculate_mean(inner: impl Iterator) -> HashMap { - todo!() + let mut sum = HashMap::new(); + let mut count = HashMap::new(); + + for (class, score) in inner { + *sum.entry(class.clone()).or_insert(0) += score; + *count.entry(class).or_insert(0) += 1; + } + + let mut result = HashMap::new(); + + for (class, sum) in sum { + let _ = result.insert( + class.clone(), + (sum as f64) / (*count.get(&class).unwrap() as f64), + ); + } + + result } /// Among the cartesian product of input vectors, return the number of sets whose sum equals `n`. @@ -147,7 +219,31 @@ pub fn calculate_mean(inner: impl Iterator) -> HashMap>, n: i64) -> usize { - todo!() + let mut products = vec![vec![]]; + + for vec in inner { + let mut temp = vec![]; + + for v in vec { + for product in &products { + let mut new_product = product.clone(); + new_product.push(v); + temp.push(new_product); + } + } + + products = temp; + } + + let mut result = 0; + + for product in products { + if product.iter().sum::() == n { + result += 1; + } + } + + result } /// Returns a new vector that contains the item that appears `n` times in the input vector in @@ -164,7 +260,22 @@ pub fn sum_is_n(inner: Vec>, n: i64) -> usize { /// assert_eq!(find_count_n(vec![1, 2, 3, 4, 4], 1), vec![1, 2, 3]); /// ``` pub fn find_count_n(inner: Vec, n: usize) -> Vec { - todo!() + let mut map = HashMap::new(); + + for v in inner { + *map.entry(v).or_insert(0) += 1; + } + + let mut result = vec![]; + + for (key, value) in map { + if value == n { + result.push(key); + } + } + + result.sort(); + result } /// Return the position of the median element in the vector. @@ -188,7 +299,41 @@ pub fn find_count_n(inner: Vec, n: usize) -> Vec { /// assert_eq!(position_median(vec![1, 3, 3, 3]), Some(1)); /// ``` pub fn position_median(inner: Vec) -> Option { - todo!() + if inner.is_empty() { + return None; + } + + let mut vec = vec![]; + + for (i, v) in inner.iter().enumerate() { + vec.push((i, v)); + } + + vec.sort_by(|(i1, v1), (i2, v2)| match (**v1).cmp(*v2) { + std::cmp::Ordering::Equal => (*i1).cmp(i2), + r => r, + }); + + let mut result = 0; + let mut prev: Option<&T> = None; + + for (i, (j, v)) in vec.iter().enumerate() { + if let Some(prev) = prev { + if *prev != **v { + result = *j; + } + } else { + result = *j; + } + + prev = Some(*v); + + if i >= vec.len() / 2 { + return Some(result); + } + } + + unreachable!(); } /// Returns the sum of all elements in a two-dimensional array. @@ -203,7 +348,7 @@ pub fn position_median(inner: Vec) -> Option { /// ); /// ``` pub fn two_dimensional_sum(inner: impl Iterator>) -> i64 { - todo!() + inner.map(|iter| iter.sum::()).sum() } /// Returns whether the given string is palindrome or not. @@ -215,5 +360,19 @@ pub fn two_dimensional_sum(inner: impl Iterator /// /// Consult . pub fn is_palindrome(s: String) -> bool { - todo!() + if s.len() <= 1 { + return true; + } + + let mut front = s.chars().enumerate(); + let mut back = s.chars().rev(); + + for ((i, f), b) in front.zip(back) { + if i >= s.len() / 2 { + return true; + } else if f != b { + return false; + } + } + unreachable!(); }