Программирование/Примеры программ на языке программирования Rust

Материал из Викиверситета

Вычисление факториала рекурсивным и итеративным методами[править]

// Ветви условия в данной функции демонстрируют необязательный вариант
// неявного возврата значений, что может быть удобно при использовании 
// "функционального" стиля. В отличие от C++ и других родственных языков, 
// в Rust if - это выражение, возвращающее значение, а не просто оператор. 
fn fac_recur(n: i32) -> i32 {
    if n <= 1 {
        1
    } else {
        n * fac_recur(n-1)
    }
}

fn fac_iter(n: i32) -> i32 {
    // Переменные объявляются с ключевым словом "let", по умолчанию
    // не изменяемые. Если нужна их изменяемость, добавляется ключевое
    // слово 'mut'.
    let mut i = 1;
    let mut result = 1;
    while i <= n {
        result *= i;
        i += 1;
    }
    return result;    // Пример явно возвращаемого значения.
}

fn fac_lambda(n: i32) -> i32 {
    // Итераторы включают множество методов трансформации.
    // "|accum, x|" - это определение анонимной функции.
    // Оптимизации компиляции преобразуют эту функцию 
    // в нечто, похожее на итеративный вариант.
    (1..=n).fold(1, |accum, x| accum * x)
}

fn fac_iter1(n: i32) -> i32 {
    (1..=n).product()
}
fn main() {
    let num = 10;
    println!("Recursive result: {}", fac_recur(num));
    println!("Iterative result: {}", fac_iter(num));
    println!("Iterative result: {}", fac_iter1(num));
    println!("Lambda result: {}", fac_lambda(num));
}

Вычисление чисел Фибоначчи рекурсивным и итеративным методами[править]

/// Классическая рекурсивная версия
/// без хвостовой рекурсии
fn fib_recursive(n: u64) -> u64 {
    match n {
        0 | 1 => n,
        n => fib_recursive(n - 1) + fib_recursive(n - 2),
    }
}

/// версия с хвостовой рекурсией
fn fib_tail_recursive(n: u64) -> u64 {
    fn in_fib(n: u64, current: u64, next: u64) -> u64 {
        match n {
            0 => current,
            n => in_fib(n - 1, next, current + next),
        }
    }
    in_fib(n, 0, 1)
}

/// итеративная версия
fn fib_iterative(n: u64) -> u64 {
    let (mut cur, mut next) = (0u64, 1u64);
    for _ in 0u64..n {
        let tmp = cur + next;
        cur = next;
        next = tmp;
    }
    cur
}

fn main() {
    let fns = vec![(fib_recursive as fn(u64) -> u64, "recursive"),
                   (fib_tail_recursive as fn(u64) -> u64, "tail recursive"),
                   (fib_iterative as fn(u64) -> u64, "iterative")];

    for (f, desc) in fns {
        let r = (0u64..10).map(f).collect::<Vec<u64>>();
        println!("{} implementation:\n{:?}\n", desc, r);
    }
}

Демонстрация возможностей параллельных вычислений в Rust[править]

use std::thread;

// Функция создаёт 10 "задач", которые выполняются параллельно.
// Чтобы убедиться в параллельности, запустите программу несколько раз,
// и обратите внимание на непостоянный порядок вывода результатов.
fn main() {
    // Эта строка неизменяемая, поэтому может безопасно использоваться
    // из нескольких задач.
    let greeting = "Привет";
    let mut threads = Vec::new();

    // Цикл for работает с любым типом, реализующим
    // интерфейс (trait) Iterator.
    for num in 0..10 {
        threads.push(thread::spawn(move || {
            // println! - это статический макрос, выполняющий форматирование
            // строки и её вывод. Макросы структурные (как в Scheme), а не
            // текстовые (как в Си).
            println!("{} из потока номер {}", greeting, num);
        }));
    }
    for thread in threads {
        let res = thread.join();
        if let Err(_) = res {
            println!("Произошла ошибка!");
        }
    }
}

Поиск подстроки в текстовом файле[править]

// поддержка метода lines()
use std::io::BufRead;

fn main() {
    // получает аргументы командной строки
    let pattern = std::env::args().nth(1).unwrap();
    let file_name = std::env::args().nth(2).unwrap();

    // открывает файл, разворачивает Result
    let file = std::fs::File::open(file_name).unwrap();
    let buffer = std::io::BufReader::new(file);

    // читает строку из файла
    for line_result in buffer.lines() {
        let line = line_result.unwrap();

        // ищет подстроку в строке
        if line.contains(&pattern) {
            println!("{}", line);
        }
    }
}

Факторизация чисел[править]

//функция факторизации чисел без знака
fn factorization_unsigned(mut a:u64)->Vec<u64>
{
	let mut arr:Vec<u64>=Vec::with_capacity(2);
	let mut g:u64=a/2;
	let mut i:u64=2u64;
	arr.push(1);
	while i<=g
	{
		g=a/i;
		while a%i==0
		{
			arr.push(i);
			a/=i;
		}
		i+=1;
	}
	if a != 1
	{
		arr.push(a);
	}
	return arr;
}
//функция факторизации чисел со знаком
fn factorization_signed(mut a:i64)->Vec<i64>
{
	let mut arr:Vec<i64>=Vec::with_capacity(2);
	if a<0
	{
		arr.push(-1);
		a = -a;
	}
	else
	{
		arr.push(1);
	}
	let mut g:i64=a/2;
	let mut i:i64=2i64;
	while i<=g
	{
		g=a/i;
		while a%i==0
		{
			arr.push(i);
			a/=i;
		}
		i+=1;
	}
	if a != 1
	{
		arr.push(a);
	}
	return arr;
}


fn main()
{
	let num1=-9;
	{
		let arr=factorization_signed(num1);
		print!("factorization_signed({}) = [", num1);
		for _i in &arr[..arr.len()-1]
		{
			print!("{}, ", _i);
		}
		println!("{}]", arr[arr.len()-1]);
	}
	
	let num2=9;
	{
		let arr=factorization_unsigned(num2);
		print!("factorization_unsigned({}) = [", num2);
		for _i in &arr[..arr.len()-1]
		{
			print!("{}, ", _i);
		}
		println!("{}]", arr[arr.len()-1]);
	}
}

Поиск совершенных чисел[править]

use std::time::Instant;
static mut TIME:Option<Instant>=None;

#[allow(non_camel_case_types)]
type perfnum_numb_type = u32;
fn perfnum(x : perfnum_numb_type)-> Vec<perfnum_numb_type>
{
	let mut arr=Vec::new();
	let width={(x).to_string().len()+1};
	
	let mut i0=1;
	while i0<=x
	{
		let mut acc : perfnum_numb_type=1;
		let mut i1=2;
		while i1<=i0/2
		{
			if i0%i1==0
			{
				acc+=i1;
			}
			i1+=1;
		}
		if acc==i0
		{
			unsafe
			{
				if let Some(t) = TIME
				{
					let time=Instant::now().duration_since(t);
					arr.push(i0);
					println!("number: {:<width$} time: {:?}", format!("{},", i0), time, width=width);
				}
			}
		}
		i0+=1;
	}
	return arr;
}

fn perfnum1(n : perfnum_numb_type) -> Vec<perfnum_numb_type>
{
	let mut arr=Vec::new();
	let width={(x).to_string().len()+1};
	for item in (1..=n).filter(|x| (2..=*x/2).filter(|n| x%n==0).sum::<perfnum_numb_type>()+1==*x)
	{
		unsafe
		{
			if let Some(t) = TIME
			{
				let time=Instant::now().duration_since(t);
				arr.push(item);
				println!("number: {:<width$} time: {:?}", format!("{},", item), time, width=width);
			}
		}
	}
	arr
}

fn main()
{
	unsafe{TIME=Some(Instant::now());}
	/*let arr=*/perfnum(8128);
	let time_end=Instant::now();
	unsafe
	{
		if let Some(t) = TIME
		{
			let time=time_end.duration_since(t);
			println!("time: {:?}", time);
		}
	}
	
	unsafe{TIME=Some(Instant::now());}
	/*let arr=*/perfnum1(8128);
	let time_end=Instant::now();
	unsafe
	{
		if let Some(t) = TIME
		{
			let time=time_end.duration_since(t);
			println!("time: {:?}", time);
		}
	}
}

Сортировка пузырьком[править]

#[allow(non_camel_case_types)]
type tupe=i64;
fn bubble_sort(a:&mut Vec<tupe>)
{
	if a.len()<2 {return ();}
	loop
	{
		let mut flag = true;
		for _i in 0..a.len()-1
		{
			if a[_i]>a[_i+1]
			{
				let temp = a[_i];
				a[_i] = a[_i+1];
				a[_i+1] = temp;
				flag = false;
			}
		}
		if flag
		{
			break;
		}
	}
}

fn main()
{
	let mut list = vec![10,29,14,4,35,6];
	println!("{:?}", list);
	bubble_sort(&mut list);
	println!("{:?}", list);
}

Быстрая сортировка[править]

#[allow(non_camel_case_types)]
type tupe=i64;
fn quicksort(a:&mut Vec<tupe>)
{
	if a.len()<=1
	{return ();}
	let mut amin=Vec::new();
	let mut amax=Vec::new();
	for _i in &a[1..]
	{
		if *_i>a[0]
		{
			amax.push(*_i);
		}
		else
		{
			amin.push(*_i);
		}
	}
	quicksort(&mut amin);
	quicksort(&mut amax);
	amin.push(a[0]);
	amin.extend(amax);
	for (_num, _i) in amin.iter().enumerate()
	{
		a[_num]=*_i;
	}
}

fn quicksort1(s_arr:&mut [tupe])
{
	if s_arr.len() < 2 {
		return ();
	}
	let last = s_arr.len()-1;
	if 0 < last
	{
		let mut left = 0;
		let mut right = last;
		let middle = s_arr[ last / 2];
		loop
		{
			while s_arr[left] < middle {left+=1};
			while s_arr[right] > middle {right-=1};
			if left < right
			{
				let tmp = s_arr[left];
				s_arr[left] = s_arr[right];
				s_arr[right] = tmp;
				left+=1;
				right-=1;
			}
			else {break;}
		}
		right-=1;
		left+=1;
		
		quicksort1(&mut s_arr[0..=right]);
		quicksort1(&mut s_arr[left..=last]);
	}
}

fn main()
{
	let listfir = vec![10,29,14,4,35,6];
	let mut list = listfir.clone();
	println!("{:?}", list);
	quicksort(&mut list);
	println!("{:?}", list);
	
	let mut list = listfir.clone();
	println!("{:?}", list);
	quicksort1(&mut list[..]);
	println!("{:?}", list);

}

Нахождение наибольшего общего делителя алгоритмом Евклида и наименьшего общего кратного, двух и более чисел[править]

//Наибольший общий делитель
fn euclidean_algorithm(arr: &mut [i64]) -> Option<i64>
{
	let mut a_len = arr.len();
	let mut temp : i64;
	while a_len > 1
	{
		let len = a_len-1;
		temp = arr[len-1] %  arr[len];
		*arr[len-1]= *arr[len];
		*arr[len] = temp;
		if  *arr[len] == 0
		{
			a_len -= 1;
		}
	}
	return Some(arr[0]);
}

fn euclidean_algorithm1(arr: &[i64]) -> std::option::Option<i64>
{
	let mut arr : Vec<i64> = arr.to_vec();
	let mut temp : i64;
	while arr.len() > 1
	{
		
		temp = arr.iter().rev().skip(1).next().unwrap() %  arr.iter().last().unwrap();
		*arr.iter_mut().rev().skip(1).next().unwrap() = *arr.iter().last().unwrap();
		*arr.iter_mut().last().unwrap() = temp;
		if  *arr.iter().last().unwrap() == 0
		{
			arr.pop();
		}
	}
	return arr.pop();
}

//Наименьшее общее кратное
fn nok(arr: &[i64]) -> std::option::Option<i64>
{
  match arr.len()
  {
    0 | 1 => None,
    _ => {
            let mut arr = arr.to_vec();
            let mut acc = 1;
            for index in 0..arr.len()-1
            {
              for index1 in 1..arr.len()
              {
                if index == index1
                {
                  continue;
                }
                acc *= euclidean_algorithm(&[arr[index], arr[index1]]).unwrap();
              }
            }
            Some(arr.iter().product::<i64>().abs() / acc)
          }
  }
}

fn main() {
    let arr = vec![10, 45, 95];

    println!("{} {}", euclidean_algorithm(&arr).unwrap(), nok(&arr).unwrap());
}