Skip to content

Commit

Permalink
Add homework 3
Browse files Browse the repository at this point in the history
  • Loading branch information
1Git2Clone committed Nov 30, 2024
1 parent 8b0dbd9 commit 98a901d
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 2 deletions.
47 changes: 47 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
katexit = "0.1.4"
num-traits = "0.2.19"

[features]
Expand All @@ -19,3 +20,7 @@ hw1-task-3 = []
hw2-task-1 = []
hw2-task-2 = []
hw2-task-3 = []
# ---
# Homework 3
# ---
hw3-task-1 = []
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).
- [x] [Task 3](https://www.hackerrank.com/contests/citb106-f2024-hw1/challenges/discrete-mathematics-and-programming-hw-1-task-3)
([src](./src/hw1/task_3.rs))

## [Homework 2](https://www.hackerrank.com/contests/citb106-f2024-hw1/challenges)
## [Homework 2](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges)

<!-- prettier-ignore -->
- *23/11/2024*
Expand All @@ -39,4 +39,13 @@ algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).
- [x] [Task 2](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges/discrete-mathematics-and-programming-hw-2-task-2)
([src](./src/hw2/task_2.rs))
- [x] [Task 3](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges/discrete-mathematics-and-programming-hw-2-task-3)
([src](./src/hw2/task_3.rs))
([src](./src/hw2/task_3.rs))

## [Homework 3](https://www.hackerrank.com/contests/citb106-f2024-hw3/challenges)

<!-- prettier-ignore -->
- *30/11/2024*

- [x] [Task 1](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges/discrete-mathematics-and-programming-hw-2-task-1)
([src](./src/hw3/task_1.rs))

1 change: 1 addition & 0 deletions src/hw3/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod task_1;
150 changes: 150 additions & 0 deletions src/hw3/task_1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use crate::utils::{
gcd::ExtendedGcd,
input::{get_numeric_input, invalid_input, no_solution},
Error,
};

const MIN: i32 = 1;
const MAX: i32 = 100;

#[cfg_attr(doc, katexit::katexit)]
/// # HOMEWORK 3 | TASK 1
///
/// ## Input
///
/// 1. Three numbers (`a`, `b` and `c`).
///
/// ### Constaints
///
/// 2. The input should be in the inclusive range of: `[1;100]`.
///
/// ### Output
///
/// The values of `x` and `y` separated by new lines based on the Bezout's identity formula[1]:
///
/// $$
/// (a \times{x} + b \times{y}) \bmod{c} = 0
/// $$
///
///
/// [1]: https://en.wikipedia.org/wiki/B%C3%A9zout's_identity#Structure_of_solutions
///
/// ### Samples
///
/// #### Input Format
///
/// ```txt
/// 30
/// 18
/// 6
/// ```
///
/// #### Output Format
///
/// ```txt
/// -1
/// 2
/// ```
///
/// #### Input Format
///
/// ```txt
/// 30
/// 18
/// 4
/// ```
///
/// #### Output Format
///
/// ```txt
/// No solution!
/// ```
///
/// #### Explanation
///
/// (30, 18) = 6 => 6 % 4 != 0
///
/// #### Input Format
///
/// ```txt
/// 101
/// 25
/// 9
/// ```
///
/// #### Output Format
///
/// ```txt
/// Invalid input data!
/// ```
///
/// ### Error
///
/// If the input is invalid, return:
///
/// ```rust
/// String::from("Invalid input data!");
/// ```
///
/// If there's no solution, return:
///
/// ```rust
/// String::from("No solution!");
/// ```
///
/// ## Test cases
///
/// ```rust
/// use hackerrank::hw3::task_1::Solution;
///
/// assert_eq!(
/// Solution::main(30, 18, 6),
/// String::from("-1\n2")
/// );
/// assert_eq!(
/// Solution::main(30, 18, 4),
/// String::from("No solution!")
/// );
/// assert_eq!(
/// Solution::main(101, 25, 9),
/// String::from("Invalid input data!")
/// );
/// assert_eq!(
/// Solution::main(100, 50, 100),
/// String::from("0\n2")
/// );
/// assert_eq!(
/// Solution::main(99, 33, 66),
/// String::from("0\n2")
/// );
/// ```
pub struct Solution;

impl Solution {
pub fn main(a: i32, b: i32, c: i32) -> String {
if [a, b, c].iter().any(|item| !(MIN..=MAX).contains(item)) {
return invalid_input();
}
let ((mut x, mut y), d) = a.extended_gcd(b);

if c % d != 0 {
return no_solution();
}

let scale_to_c = c / d;
x *= scale_to_c;
y *= scale_to_c;

format!("{}\n{}", x, y)
}
}

pub fn main() -> Result<(), Error> {
let a = get_numeric_input::<i32>()?;
let b = get_numeric_input::<i32>()?;
let c = get_numeric_input::<i32>()?;

println!("{}", Solution::main(a, b, c));

Ok(())
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

pub mod hw1;
pub mod hw2;
pub mod hw3;
pub mod utils;
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod hw1;
mod hw2;
mod hw3;

mod utils;
use utils::Error;
Expand Down Expand Up @@ -42,5 +43,12 @@ fn main() -> Result<(), Error> {
HW_2[Task::Task3 as usize]()?;
}

#[cfg(feature = "hw3-task-1")]
{
const HW_3: [fn() -> Result<(), Error>; 1] = [hw3::task_1::main];

HW_3[Task::Task1 as usize]()?;
}

Ok(())
}
26 changes: 26 additions & 0 deletions src/utils/gcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,36 @@ where
}
}

/// Implemented based on this implementation[1].
///
/// [1]: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Pseudocode
pub trait ExtendedGcd: Gcd {
/// Returns: (Self::BezoutCoefficient, Self::Gcd)
/// where:
/// - Self::BezoutCoefficient = (Self, Self)
/// - Self::Gcd = Self
fn extended_gcd(self, other: Self) -> ((Self, Self), Self) {
let (mut prev_r, mut r) = (self, other);
let (mut prev_s, mut s) = (Self::one(), Self::zero());
let (mut prev_t, mut t) = (Self::zero(), Self::one());

let mut q;
while r != Self::zero() {
q = prev_r / r;
(prev_r, r) = (r, prev_r - q * r);
(prev_s, s) = (s, prev_s - q * s);
(prev_t, t) = (t, prev_t - q * t);
}

((prev_s, prev_t), prev_r)
}
}

macro_rules! gcd_impl {
($name:ident for $($x:ty)*) => ($(
impl $name for $x {}
)*)
}

gcd_impl!(Gcd for i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
gcd_impl!(ExtendedGcd for i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
6 changes: 6 additions & 0 deletions src/utils/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ where
Ok(tmp.trim().parse::<T>().unwrap())
}

#[must_use = "This function returns the 'Invalid input data!' value used for asserting tests."]
pub fn invalid_input() -> String {
String::from("Invalid input data!")
}

#[must_use = "This function returns the 'No solution!' value used for asserting tests."]
pub fn no_solution() -> String {
String::from("No solution!")
}

0 comments on commit 98a901d

Please sign in to comment.