Смятане на π

Краен срок
19.01.2023 17:00
Точки
4

Срокът за предаване на решения е отминал

use solution::*;
macro_rules! assert_close {
($eps:expr, $left:expr, $right:expr) => {
let left_str = $left;
let right_str = $right;
let eps_str = stringify!($eps);
assert!(($left - $right).abs() < $eps, "{left_str} was not {eps_str}-close to {right_str}");
}
}
#[test]
fn test_calculate_pi_using_wallis() {
let mut series = InfiniteSeries::new(1.0, (2.0, 1.0), |value, (n, d)| {
let value = value * (n * n / (d * (d + 2.0)));
let new_state = (n + 2.0, d + 2.0);
(value, new_state)
});
series.nth(200);
assert_close!(0.01, series.value, std::f64::consts::PI / 2.0);
series.nth(2000);
assert_close!(0.001, series.value, std::f64::consts::PI / 2.0);
}
#[test]
fn test_calculate_pi_using_leibniz() {
let mut series = InfiniteSeries::new(0.0, 1.0, |value, d| {
let value = value + (4.0 / d);
let new_state = -(d + d.signum() * 2.0);
(value, new_state)
});
series.nth(200);
assert_close!(0.01, series.value, std::f64::consts::PI);
series.nth(2000);
assert_close!(0.001, series.value, std::f64::consts::PI);
}
#[test]
fn test_calculate_pi_using_the_close_enough_method() {
let mut series = InfiniteSeries::new(3.1, 0.0, |value, state| (value, state));
series.nth(200);
assert_close!(0.01, series.value, 3.1);
series.nth(2000);
assert_close!(0.001, series.value, 3.1);
}

Този път ще ви улесним, като просто ви дадем теста, с който ще проверяваме. Ще ви затрудним, като не ви дадем почти нищо друго. Искаме да имплементирате структура, която да приеме някакво начално състояние и функция, и с всяка итерация да акумулира безкрайна сума/произведение. Конкретните формули сме взели оттук: https://www.codeproject.com/Articles/813185/Calculating-the-Number-PI-Through-Infinite-Sequenc

Ето как ще изглежда теста, който ще трябва да подкарате:

use solution::*;

macro_rules! assert_close {
    ($eps:expr, $left:expr, $right:expr) => {
        let left_str = $left;
        let right_str = $right;
        let eps_str = stringify!($eps);

        assert!(($left - $right).abs() < $eps, "{left_str} was not {eps_str}-close to {right_str}");
    }
}

#[test]
fn test_calculate_pi_using_wallis() {
    let mut series = InfiniteSeries::new(1.0, (2.0, 1.0), |value, (n, d)| {
        let value = value * (n * n / (d * (d + 2.0)));
        let new_state = (n + 2.0, d + 2.0);

        (value, new_state)
    });

    series.nth(200);
    assert_close!(0.01, series.value, std::f64::consts::PI / 2.0);

    series.nth(2000);
    assert_close!(0.001, series.value, std::f64::consts::PI / 2.0);
}

#[test]
fn test_calculate_pi_using_leibniz() {
    let mut series = InfiniteSeries::new(0.0, 1.0, |value, d| {
        let value = value + (4.0 / d);
        let new_state = -(d + d.signum() * 2.0);

        (value, new_state)
    });

    series.nth(200);
    assert_close!(0.01, series.value, std::f64::consts::PI);

    series.nth(2000);
    assert_close!(0.001, series.value, std::f64::consts::PI);
}

#[test]
fn test_calculate_pi_using_the_close_enough_method() {
    let mut series = InfiniteSeries::new(3.1, 0.0, |value, state| (value, state));

    series.nth(200);
    assert_close!(0.01, series.value, 3.1);

    series.nth(2000);
    assert_close!(0.001, series.value, 3.1);
}

Както виждате, има структура с конструктор, която имплементира Iterator (макар че използваме само .nth, така че 🤷). Всяка следваща стъпка на итерацията ще викне подадената функция с начална стойност и междинно състояние и ще получи следващата стойност и следващото междинно състояние. Стойността се чете през полето value, което е f64.

Какви точно generics ѝ трябват, за да може да приеме тези три параметъра, да си ги запази, и да извиква функцията за да си получи изчисленията -- измислете го с помощта на компилатора. Можехме да ви сложим и "скелет" на структурата както обикновено, но имайки пълен тест, не би трябвало да е проблем да имплементирате всичко, което ви липсва.

Решения

Андрей
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Андрей

pub struct InfiniteSeries<S: Clone, F: Fn(f64, S) -> (f64, S)> {
pub value: f64,
state: S,
calculator: F,
}
impl<S: Clone, F: Fn(f64, S) -> (f64, S)> InfiniteSeries<S, F> {
pub fn new(value: f64, state: S, calculator: F) -> Self {
InfiniteSeries { value, state, calculator }
}
}
impl<S: Clone, F: Fn(f64, S) -> (f64, S)> Iterator for InfiniteSeries<S, F> {
type Item = f64;
fn next(&mut self) -> Option<Self::Item> {
let (new_value, new_state) = (self.calculator)(self.value, self.state.clone());
self.state = new_state;
self.value = new_value;
Some(self.value)
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-gcjw0y/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.61s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Чудомир Ченков
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Чудомир Ченков

pub struct InfiniteSeries<S: Copy> {
pub value: f64,
pub state: S,
pub func: fn(f64, S) -> (f64, S)
}
impl<S: Copy> InfiniteSeries<S> {
pub fn new(value: f64, state: S, func: fn(f64, S) -> (f64, S)) -> Self {
InfiniteSeries {
value,
state,
func
}
}
}
impl<S: Copy> Iterator for InfiniteSeries<S> {
type Item = f64;
fn next(&mut self) -> Option<Self::Item> {
(self.value, self.state) = (self.func)(self.value, self.state);
Some(self.value)
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-es5ika/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.58s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Билян Хаджи
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Билян Хаджи

#[derive(Debug, Copy, Clone)]
pub enum State {
OneValue(f64),
TwoValues(f64, f64),
}
pub trait IntoState {
fn into(self) -> State;
}
impl State {
pub fn new<A>(args: A) -> State where A: IntoState {
args.into()
}
}
impl IntoState for f64 {
fn into(self) -> State {
State::OneValue(self)
}
}
impl IntoState for (f64, f64) {
fn into(self) -> State {
State::TwoValues(self.0, self.1)
}
}
#[derive(Copy, Clone)]
pub struct InfiniteSeries<S: IntoState + Copy, F: Fn(f64, S) -> (f64, S)> {
pub value: f64,
pub state: S,
func: F
}
impl<S: IntoState + Copy, F: Fn(f64, S) -> (f64, S)> InfiniteSeries<S, F> {
pub fn new(value: f64, state: S, func: F) -> Self {
InfiniteSeries { value, state, func }
}
}
impl<S: IntoState + Copy, F: Fn(f64, S) -> (f64, S)> Iterator for InfiniteSeries<S, F> {
type Item = f64;
fn next(&mut self) -> Option<Self::Item> {
let (new_value, new_state) = (self.func)(self.value, self.state);
self.value = new_value;
self.state = new_state;
Some(new_value)
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-1q23mju/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.59s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Николай Паев
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Николай Паев

pub struct InfiniteSeries<S, F> where F: Fn(f64, S) -> (f64, S), S: Copy {
pub value: f64,
state: S,
next_state: F,
}
impl<S, F> InfiniteSeries<S, F> where F: Fn(f64, S) -> (f64, S), S: Copy {
pub fn new(value: f64, state: S, next_state: F) -> InfiniteSeries<S, F> where F: Fn(f64, S) -> (f64, S), S: Copy {
InfiniteSeries { value, state, next_state }
}
}
impl<S, F> Iterator for InfiniteSeries<S, F> where F: Fn(f64, S) -> (f64, S), S: Copy {
type Item = f64;
fn next(&mut self) -> Option<Self::Item> {
(self.value, self.state) = (self.next_state)(self.value, self.state);
Some(self.value)
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-ed29w0/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.58s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Давид Петров
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Давид Петров

type ValT = f64;
type FnNext<V, T> = fn(V, T) -> (V, T);
pub struct InfiniteSeries<StateT: Copy> {
pub value: ValT,
pub state: StateT,
pub get_next: FnNext<ValT, StateT>
}
impl<StateT: Copy> InfiniteSeries<StateT> {
pub fn new(value: ValT, state: StateT, get_next: FnNext<ValT, StateT>) -> InfiniteSeries<StateT> {
InfiniteSeries { value, state, get_next }
}
}
impl<StateT: Copy> Iterator for InfiniteSeries<StateT> {
type Item = ValT;
fn next(&mut self) -> Option<Self::Item> {
let current = self.value;
(self.value, self.state) = (self.get_next)(current, self.state);
Some(current)
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! assert_close {
($eps:expr, $left:expr, $right:expr) => {
let left_str = $left;
let right_str = $right;
let eps_str = stringify!($eps);
assert!(($left - $right).abs() < $eps, "{left_str} was not {eps_str}-close to {right_str}");
}
}
#[test]
fn test_calculate_pi_using_wallis() {
let mut series = InfiniteSeries::new(1.0, (2.0, 1.0), |value, (n, d)| {
let value = value * (n * n / (d * (d + 2.0)));
let new_state = (n + 2.0, d + 2.0);
(value, new_state)
});
series.nth(200);
assert_close!(0.01, series.value, std::f64::consts::PI / 2.0);
series.nth(2000);
assert_close!(0.001, series.value, std::f64::consts::PI / 2.0);
}
#[test]
fn test_calculate_pi_using_leibniz() {
let mut series = InfiniteSeries::new(0.0, 1.0, |value, d| {
let value = value + (4.0 / d);
let new_state = -(d + d.signum() * 2.0);
(value, new_state)
});
series.nth(200);
assert_close!(0.01, series.value, std::f64::consts::PI);
series.nth(2000);
assert_close!(0.001, series.value, std::f64::consts::PI);
}
#[test]
fn test_calculate_pi_using_the_close_enough_method() {
let mut series = InfiniteSeries::new(3.1, 0.0, |value, state| (value, state));
series.nth(200);
assert_close!(0.01, series.value, 3.1);
series.nth(2000);
assert_close!(0.001, series.value, 3.1);
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-ryyqkh/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.66s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Климент Бербатов
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Климент Бербатов

pub struct InfiniteSeries<T: Copy>{
pub value: f64,
state: T,
func: Box<fn(f64,T) ->(f64,T)>,
}
impl<T: Copy> InfiniteSeries<T>{
pub fn new(value:f64, state:T,foo :fn(f64,T) ->(f64,T)) -> Self {
InfiniteSeries{
value:value,
state:state,
func:Box::new(foo),
}
}
}
impl<T: Copy> InfiniteSeries<T>{
pub fn nth(& mut self,ind:u16) -> (){
for _ in 0..ind{
let temp = (self.func)(self.value,self.state);
self.value = temp.0;
self.state = temp.1;
}
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-1l38tpy/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.62s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Йордан Илиев
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Йордан Илиев

type StatefulMapper<S> = fn(f64, S) -> (f64, S);
pub struct InfiniteSeries<S: Copy> {
pub value: f64,
state: S,
func: StatefulMapper<S>
}
impl<S: Copy> Iterator for InfiniteSeries<S> {
type Item = f64;
fn next(&mut self) -> Option<Self::Item> {
(self.value, self.state) = (self.func)(self.value, self.state);
Some(self.value)
}
}
impl<S : Copy> InfiniteSeries<S> {
pub fn new(value: f64, state: S, func: StatefulMapper<S>) -> InfiniteSeries<S> {
InfiniteSeries { value, state, func }
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-hcj0p0/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.58s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Александър Македонски
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Александър Македонски

#[derive(Clone, Copy)]
pub struct InfiniteSeries<F>
where F: Copy {
pub value: f64,
state: F,
function: fn(f64, F)-> (f64, F),
}
impl<F: std::marker::Copy> InfiniteSeries<F> {
pub fn new(value: f64, state: F, function: fn(f64, F)-> (f64, F)) -> InfiniteSeries<F>{
InfiniteSeries::<F>{
value,
state,
function,
}
}
}
impl<F:std::marker::Copy> Iterator for InfiniteSeries<F>{
type Item = f64;
fn next(&mut self) -> Option<f64>{
(self.value, self.state) = (self.function)(self.value, self.state);
Some(self.value)
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-32gshm/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.61s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_wallis ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Тодор Кюркчиев
  • Коректно
  • 3 успешни тест(а)
  • 0 неуспешни тест(а)
Тодор Кюркчиев

pub struct InfiniteSeries<T> {
pub value: f64,
pub state: T,
pub function: fn(f64, T) -> (f64, T),
}
impl<T> InfiniteSeries<T>
where T: Copy
{
pub fn new(initial_value: f64, initial_state: T, function: fn(f64, T) -> (f64, T)) -> InfiniteSeries<T> {
InfiniteSeries {
value: initial_value,
state: initial_state,
function,
}
}
pub fn nth(&mut self, n: usize) {
for _ in 0..n {
let (new_value, new_state) = (self.function)(self.value, self.state);
self.value = new_value;
self.state = new_state;
}
}
}
Compiling solution v0.1.0 (/tmp/d20230119-3772066-54psy4/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.60s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 3 tests
test solution_test::test_calculate_pi_using_the_close_enough_method ... ok
test solution_test::test_calculate_pi_using_leibniz ... ok
test solution_test::test_calculate_pi_using_wallis ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s