Last active
November 1, 2022 11:16
-
-
Save lxchurbakov/f235ea4e8d2b0ea4378e7ba083aec23b to your computer and use it in GitHub Desktop.
rust-basics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt; | |
struct Position { | |
longitude: f32, | |
latitude: f32, | |
} | |
impl fmt::Display for Position { | |
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
write!(f, "({}, {})", self.longitude, self.latitude) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug, Clone, Copy)] | |
enum Sign { | |
Plus, | |
Minus, | |
} | |
#[derive(Debug, Clone)] | |
struct BigInt { | |
sign: Sign, | |
digits: Vec<u8>, | |
} | |
impl std::fmt::Display for BigInt { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
let mut s = String::from(""); | |
if let Sign::Minus = self.sign { | |
s.push('-'); | |
} | |
for digit in self.digits.iter() { | |
s.push_str(&digit.to_string()); | |
} | |
f.write_str(&s) | |
} | |
} | |
impl BigInt { | |
fn new() -> BigInt { | |
BigInt { | |
sign: Sign::Plus, | |
digits: vec![0], | |
} | |
} | |
fn from_int (i: u32) -> BigInt { | |
let mut digits: Vec<u8> = vec![]; | |
let mut buffer = i; | |
while buffer > 0 { | |
digits.insert(0, (buffer % 10) as u8); | |
buffer /= 10; | |
} | |
BigInt { | |
sign: Sign::Plus, | |
digits: digits, | |
} | |
} | |
} | |
// impl Clone for BigInt { | |
// fn clone(&self) -> BigInt { | |
// BigInt { | |
// sign: self.sign.clone(), | |
// digits: self.digits.clone(), | |
// } | |
// } | |
// } | |
fn reverse<T> (v: Vec<T>) -> Vec<T> where T: Copy { | |
let mut result: Vec<T> = vec![]; | |
for element in v { | |
result.insert(0, element); | |
} | |
result | |
} | |
impl std::ops::Add for BigInt { | |
type Output = BigInt; | |
fn add(self, rhs: Self) -> Self::Output { | |
let mut result_digits = Vec::<u8>::new(); | |
let mut index = 0; | |
let mut carry = 0; | |
let self_digits: Vec<u8> = reverse(self.digits); | |
let rhs_digits: Vec<u8> = reverse(rhs.digits); | |
while index < self_digits.len() || index < rhs_digits.len() { | |
let mut sum = 0; | |
if index < self_digits.len() { | |
sum += self_digits[index]; | |
} | |
if index < rhs_digits.len() { | |
sum += rhs_digits[index]; | |
} | |
sum += carry; | |
result_digits.push(sum % 10); | |
carry = sum / 10; | |
index += 1; | |
} | |
if carry > 0 { | |
result_digits.push(carry as u8); | |
} | |
BigInt { | |
sign: Sign::Plus, | |
digits: reverse(result_digits), | |
} | |
} | |
} | |
struct Fibonacci { | |
current: BigInt, | |
next: BigInt, | |
} | |
impl Iterator for Fibonacci { | |
type Item = BigInt; | |
fn next(&mut self) -> Option<BigInt> { | |
// let new_next = self.current.checked_add(self.next)?; | |
let new_next = self.current.clone() + self.next.clone(); | |
self.current = self.next.clone(); | |
self.next = new_next; | |
Some(self.current.clone()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn find_largest<T: std::cmp::PartialOrd> (collection: &[T]) -> &T { | |
let mut largest = &collection[0]; | |
for item in collection.iter() { | |
if item > largest { | |
largest = item; | |
} | |
} | |
largest | |
} | |
enum CompareResult { | |
Equal, | |
More, | |
Less, | |
} | |
trait Comparable { | |
fn compare(&self, other: &Self) -> CompareResult; | |
} | |
impl Comparable for i32 { | |
fn compare (&self, other: &i32) -> CompareResult { | |
if self == other { | |
CompareResult::Equal | |
} else if self > other { | |
CompareResult::More | |
} else { | |
CompareResult::Less | |
} | |
} | |
} | |
fn sort_list (list: &mut [(impl Comparable + Copy)]) { | |
let mut index = 1; | |
while index < list.len() { | |
if let CompareResult::Less = list[index].compare(&list[index - 1]) { | |
let buffer = list[index]; | |
list[index] = list[index - 1]; | |
list[index - 1] = buffer; | |
index = std::cmp::max(2, index) - 2; | |
} | |
index += 1; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Debug, Clone)] | |
enum ListItem<T> where T: Clone { | |
Nil, | |
Value (T, Box<ListItem<T>>) | |
} | |
#[derive(Debug, Clone)] | |
struct List<T: std::clone::Clone> { | |
head: ListItem<T> | |
} | |
impl<T: std::clone::Clone> List<T> { | |
fn push (&mut self, item: T) { | |
let new_head = ListItem::Value(item, Box::new(self.head.clone())); | |
self.head = new_head; | |
} | |
fn pop (&mut self) -> Option<T> { | |
if let ListItem::Value(ref item, ref next) = self.head { | |
let value = item.clone(); | |
self.head = *next.clone(); | |
Some(value) | |
} else { | |
None | |
} | |
// let new_head | |
} | |
fn len (&self) -> usize { | |
let mut len = 0; | |
let mut current = &self.head; | |
loop { | |
match current { | |
ListItem::Nil => break len, | |
ListItem::Value(_, next) => { | |
len += 1; | |
current = next; | |
} | |
} | |
} | |
} | |
} | |
struct ListIterator<T> where T: Clone { | |
reference: ListItem<T> | |
} | |
impl<T: std::clone::Clone> IntoIterator for List<T> { | |
type Item = T; | |
type IntoIter = ListIterator<T>; | |
fn into_iter(self) -> Self::IntoIter { | |
ListIterator { reference: self.head } | |
} | |
} | |
impl<T: std::clone::Clone> Iterator for ListIterator<T> { | |
type Item = T; | |
fn next(&mut self) -> Option<Self::Item> { | |
if let ListItem::Value(ref value, ref next) = self.reference { | |
let v = value.clone(); | |
self.reference = *next.clone(); | |
Some(v) | |
} else { | |
None | |
} | |
} | |
} | |
// Another attempt | |
#[derive(Debug)] | |
enum LinkedListItem<T> { | |
Nil, | |
Value(T, Box<LinkedListItem<T>>), | |
} | |
#[derive(Debug)] | |
struct LinkedList<T> { | |
head: LinkedListItem<T>, | |
} | |
impl<T> std::ops::Index<usize> for LinkedList<T> { | |
type Output = LinkedListItem<T>; | |
fn index(&self, index: usize) -> &Self::Output { | |
let mut current = &self.head; | |
let mut current_index = index; | |
while current_index > 0 { | |
match current { | |
LinkedListItem::Nil => panic!("Index out of bounds"), | |
LinkedListItem::Value(_, next) => { | |
current = next; | |
current_index -= 1; | |
} | |
} | |
} | |
current | |
} | |
} | |
impl<T> std::ops::IndexMut<usize> for LinkedList<T> { | |
fn index_mut(&mut self, index: usize) -> &mut LinkedListItem<T> { | |
let mut current = &mut self.head; | |
let mut current_index = index; | |
while current_index > 0 { | |
match current { | |
LinkedListItem::Nil => panic!("Index out of bounds"), | |
LinkedListItem::Value(_, next) => { | |
current = next; | |
current_index -= 1; | |
} | |
} | |
} | |
current | |
} | |
} | |
// struct LinkedListIterator<T> { | |
// current: LinkedListItem<T>, | |
// } | |
// impl<T> IntoIterator for LinkedList<T> { | |
// type Item = T; | |
// type IntoIter = LinkedListIterator<T>; | |
// fn into_iter(self) -> Self::IntoIter { | |
// LinkedListIterator { | |
// current: self.head, | |
// } | |
// } | |
// } | |
impl<T> Iterator for LinkedList<T> where T: Copy, LinkedListItem<T>: Clone { | |
type Item = T; | |
fn next(&mut self) -> Option<T> { | |
if let LinkedListItem::Nil = self.head { | |
return None | |
} | |
let result = match &self.head { | |
LinkedListItem::Nil => None, | |
LinkedListItem::Value(value, _) => Some(*value), | |
}; | |
self.head = match &self.head { | |
LinkedListItem::Nil => LinkedListItem::Nil, | |
LinkedListItem::Value(_, next) => (**next).clone(), | |
}; | |
result | |
} | |
} | |
impl<T> ExactSizeIterator for LinkedList<T> where T: Copy, LinkedListItem<T>: Clone { | |
fn len(&self) -> usize { | |
let mut current = &self.head; | |
let mut result = 0; | |
while let LinkedListItem::Value(_, next) = current { | |
current = next; | |
result += 1; | |
} | |
result | |
} | |
} | |
impl Comparable for LinkedListItem<i32> { | |
fn compare (&self, other: &Self) -> CompareResult { | |
match (self, other) { | |
(LinkedListItem::Nil, LinkedListItem::Nil) => CompareResult::Equal, | |
(LinkedListItem::Value(_, _), LinkedListItem::Nil) => CompareResult::More, | |
(LinkedListItem::Nil, LinkedListItem::Value(_, _)) => CompareResult::Less, | |
(LinkedListItem::Value(a, _), LinkedListItem::Value(b, _)) => { | |
Comparable::compare(a, b) | |
} | |
} | |
} | |
} | |
// impl Copy for LinkedListItem<i32> {} | |
impl Clone for LinkedListItem<i32> { | |
fn clone(&self) -> Self { | |
match self { | |
LinkedListItem::Nil => LinkedListItem::Nil, | |
LinkedListItem::Value (value, next) => { | |
LinkedListItem::Value((*value).clone(), Box::new((**next).clone())) | |
} | |
} | |
} | |
} | |
impl LinkedList<i32> { | |
fn push (&mut self, value: i32) { | |
let old_head = self.head.clone(); | |
let new_head = LinkedListItem::Value(value, Box::new(old_head)); | |
self.head = new_head; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn create_cached_function_version<'a, T, R>(predicate: &'a dyn Fn (T) -> R) -> Box<dyn FnMut (T) -> R + 'a> where T: Eq + std::hash::Hash + Copy, R: Copy { | |
let mut cache = std::collections::HashMap::<T, R>::new(); | |
return Box::new(move |x: T| { | |
if let None = cache.get(&x) { | |
cache.insert(x, predicate(x)); | |
} | |
*cache.get(&x).unwrap() | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment