mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
Merge branch 'woojin' into 'main'
add church See merge request kaist-cp-class/cs220-private!23
This commit is contained in:
71
src/assignments/assignment08/church.rs
Normal file
71
src/assignments/assignment08/church.rs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
//! Church Numerals
|
||||||
|
//!
|
||||||
|
//! This exercise involves the use of "Church numerals", a
|
||||||
|
//! representation of natural numbers using lambda calculus, named after
|
||||||
|
//! Alonzo Church. Each Church numeral corresponds to a natural number `n`
|
||||||
|
//! and is represented as a higher-order function that applies a given function `f` `n` times.
|
||||||
|
//!
|
||||||
|
//! For more information, see:
|
||||||
|
//! - <https://en.wikipedia.org/wiki/Church_encoding>
|
||||||
|
//! - <https://opendsa-server.cs.vt.edu/OpenDSA/Books/PL/html/ChurchNumerals.html>
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
/// Church numerals are represented as higher-order functions that take a function `f`
|
||||||
|
pub type Church<T> = Rc<dyn Fn(Rc<dyn Fn(T) -> T>) -> Rc<dyn Fn(T) -> T>>;
|
||||||
|
|
||||||
|
/// This function returns a Church numeral equivalent of the natural number 1.
|
||||||
|
/// It takes a function `f` and applies it exactly once.
|
||||||
|
pub fn one<T: 'static>() -> Church<T> {
|
||||||
|
Rc::new(move |f| Rc::new(move |x| f(x)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function returns a Church numeral equivalent of the natural number 2.
|
||||||
|
/// It takes a function `f` and applies it twice.
|
||||||
|
pub fn two<T: 'static>() -> Church<T> {
|
||||||
|
Rc::new(move |f| Rc::new(move |x| f(f(x))))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function represents the Church numeral for zero. As zero applications
|
||||||
|
/// of `f` should leave the argument unchanged, the function simply returns the input.
|
||||||
|
pub fn zero<T: 'static>() -> Church<T> {
|
||||||
|
Rc::new(|_| Rc::new(|x| x))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a function to add 1 to a given Church numeral.
|
||||||
|
pub fn succ<T: 'static>(n: Church<T>) -> Church<T> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a function to add two Church numerals.
|
||||||
|
pub fn add<T: 'static>(n: Church<T>, m: Church<T>) -> Church<T> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a function to multiply (mult) two Church numerals.
|
||||||
|
pub fn mult<T: 'static>(n: Church<T>, m: Church<T>) -> Church<T> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a function to raise one Church numeral to the power of another.
|
||||||
|
/// This is the Church numeral equivalent of the natural number operation of exponentiation.
|
||||||
|
/// Given two natural numbers `n` and `m`, the function should return a Church numeral
|
||||||
|
/// that represents `n` to the power of `m`. The key is to convert `n` and `m` to Church numerals,
|
||||||
|
/// and then apply the Church numeral for `m` (the exponent) to the Church numeral for `n` (the base).
|
||||||
|
/// Note: This function should be implemented *WITHOUT* using the `to_usize` or any `pow`-like method.
|
||||||
|
pub fn exp<T: 'static>(n: usize, m: usize) -> Church<T> {
|
||||||
|
// ACTION ITEM: Uncomment the following lines and replace `todo!()` with your code.
|
||||||
|
// let n = from_usize(n);
|
||||||
|
// let m = from_usize(m);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a function to convert a Church numeral to a usize type.
|
||||||
|
pub fn to_usize<T: 'static + Default>(n: Church<T>) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implement a function to convert a usize type to a Church numeral.
|
||||||
|
pub fn from_usize<T: 'static>(n: usize) -> Church<T> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
73
src/assignments/assignment08/church_grade.rs
Normal file
73
src/assignments/assignment08/church_grade.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use crate::assignments::assignment08::church::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn you_must_pass_these_examples() {
|
||||||
|
let c_zero = zero::<usize>();
|
||||||
|
assert_eq!(to_usize(c_zero.clone()), 0);
|
||||||
|
|
||||||
|
let c_one = succ(c_zero.clone());
|
||||||
|
assert_eq!(to_usize(c_one.clone()), to_usize(one::<()>()));
|
||||||
|
|
||||||
|
let c_two = add(c_one.clone(), c_one.clone());
|
||||||
|
let c_three = add(c_one.clone(), c_two.clone());
|
||||||
|
assert_eq!(to_usize(c_three.clone()), 3);
|
||||||
|
|
||||||
|
let c_product = mult(c_three.clone(), c_two.clone());
|
||||||
|
assert_eq!(to_usize(c_product.clone()), 6);
|
||||||
|
|
||||||
|
let c_exponent = exp::<()>(6, 3);
|
||||||
|
assert_eq!(to_usize(c_exponent), 216);
|
||||||
|
|
||||||
|
let c_exponent2 = exp::<()>(3, 0);
|
||||||
|
assert_eq!(to_usize(c_exponent2), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(n: usize) -> usize {
|
||||||
|
to_usize(from_usize::<()>(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c_id(n: Church<usize>) -> Church<usize> {
|
||||||
|
from_usize(to_usize(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn engineering_isnt_just_mathematics() {
|
||||||
|
const N: usize = 77777;
|
||||||
|
assert_eq!(N, id(N));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test case is an optional challenge.
|
||||||
|
/// While it's not necessary to pass this test,
|
||||||
|
/// successfully doing so could provide a sense of satisfaction and achievement.
|
||||||
|
// #[test]
|
||||||
|
// fn i_said_engineering_isnt_just_mathematics() {
|
||||||
|
// const N: usize = 777777777777777;
|
||||||
|
// assert_eq!(N, id(N));
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn be_honest() {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
for _ in 0..77 {
|
||||||
|
let x = rng.gen_range(0..=7);
|
||||||
|
let y = rng.gen_range(0..=7);
|
||||||
|
|
||||||
|
let c_x = from_usize(x);
|
||||||
|
let c_y = from_usize(y);
|
||||||
|
|
||||||
|
let c_sum = add(c_x.clone(), c_y.clone());
|
||||||
|
assert_eq!(to_usize(c_id(c_sum)), x + y);
|
||||||
|
|
||||||
|
let c_prod = mult(c_x.clone(), c_y.clone());
|
||||||
|
assert_eq!(to_usize(c_id(c_prod)), x * y);
|
||||||
|
|
||||||
|
let c_exp = exp(x, y);
|
||||||
|
assert_eq!(to_usize(c_id(c_exp)), x.pow(y as u32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,10 @@
|
|||||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
|
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
|
||||||
//! See `assignment08/*_grade.rs` and `/scripts/grade-08.sh` for the test script.
|
//! See `assignment08/*_grade.rs` and `/scripts/grade-08.sh` for the test script.
|
||||||
|
|
||||||
|
pub mod church;
|
||||||
pub mod small_exercises;
|
pub mod small_exercises;
|
||||||
|
|
||||||
|
mod church_grade;
|
||||||
mod small_exercises_grade;
|
mod small_exercises_grade;
|
||||||
|
|
||||||
// TODO: add kyeongmin's church encoding asignment
|
// TODO: add kyeongmin's church encoding asignment
|
||||||
|
|||||||
Reference in New Issue
Block a user