Skip to content

Instantly share code, notes, and snippets.

@lxchurbakov
Last active November 1, 2022 11:16
Show Gist options
  • Save lxchurbakov/f235ea4e8d2b0ea4378e7ba083aec23b to your computer and use it in GitHub Desktop.
Save lxchurbakov/f235ea4e8d2b0ea4378e7ba083aec23b to your computer and use it in GitHub Desktop.
rust-basics
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)
}
}
#[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())
}
}
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;
}
}
#[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;
}
}
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