Skip to content

Commit 98a901d

Browse files
committed
Add homework 3
1 parent 8b0dbd9 commit 98a901d

File tree

9 files changed

+255
-2
lines changed

9 files changed

+255
-2
lines changed

Cargo.lock

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7+
katexit = "0.1.4"
78
num-traits = "0.2.19"
89

910
[features]
@@ -19,3 +20,7 @@ hw1-task-3 = []
1920
hw2-task-1 = []
2021
hw2-task-2 = []
2122
hw2-task-3 = []
23+
# ---
24+
# Homework 3
25+
# ---
26+
hw3-task-1 = []

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).
2929
- [x] [Task 3](https://www.hackerrank.com/contests/citb106-f2024-hw1/challenges/discrete-mathematics-and-programming-hw-1-task-3)
3030
([src](./src/hw1/task_3.rs))
3131

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

3434
<!-- prettier-ignore -->
3535
- *23/11/2024*
@@ -39,4 +39,13 @@ algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).
3939
- [x] [Task 2](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges/discrete-mathematics-and-programming-hw-2-task-2)
4040
([src](./src/hw2/task_2.rs))
4141
- [x] [Task 3](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges/discrete-mathematics-and-programming-hw-2-task-3)
42-
([src](./src/hw2/task_3.rs))
42+
([src](./src/hw2/task_3.rs))
43+
44+
## [Homework 3](https://www.hackerrank.com/contests/citb106-f2024-hw3/challenges)
45+
46+
<!-- prettier-ignore -->
47+
- *30/11/2024*
48+
49+
- [x] [Task 1](https://www.hackerrank.com/contests/citb106-f2024-hw2/challenges/discrete-mathematics-and-programming-hw-2-task-1)
50+
([src](./src/hw3/task_1.rs))
51+

src/hw3/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod task_1;

src/hw3/task_1.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
use crate::utils::{
2+
gcd::ExtendedGcd,
3+
input::{get_numeric_input, invalid_input, no_solution},
4+
Error,
5+
};
6+
7+
const MIN: i32 = 1;
8+
const MAX: i32 = 100;
9+
10+
#[cfg_attr(doc, katexit::katexit)]
11+
/// # HOMEWORK 3 | TASK 1
12+
///
13+
/// ## Input
14+
///
15+
/// 1. Three numbers (`a`, `b` and `c`).
16+
///
17+
/// ### Constaints
18+
///
19+
/// 2. The input should be in the inclusive range of: `[1;100]`.
20+
///
21+
/// ### Output
22+
///
23+
/// The values of `x` and `y` separated by new lines based on the Bezout's identity formula[1]:
24+
///
25+
/// $$
26+
/// (a \times{x} + b \times{y}) \bmod{c} = 0
27+
/// $$
28+
///
29+
///
30+
/// [1]: https://en.wikipedia.org/wiki/B%C3%A9zout's_identity#Structure_of_solutions
31+
///
32+
/// ### Samples
33+
///
34+
/// #### Input Format
35+
///
36+
/// ```txt
37+
/// 30
38+
/// 18
39+
/// 6
40+
/// ```
41+
///
42+
/// #### Output Format
43+
///
44+
/// ```txt
45+
/// -1
46+
/// 2
47+
/// ```
48+
///
49+
/// #### Input Format
50+
///
51+
/// ```txt
52+
/// 30
53+
/// 18
54+
/// 4
55+
/// ```
56+
///
57+
/// #### Output Format
58+
///
59+
/// ```txt
60+
/// No solution!
61+
/// ```
62+
///
63+
/// #### Explanation
64+
///
65+
/// (30, 18) = 6 => 6 % 4 != 0
66+
///
67+
/// #### Input Format
68+
///
69+
/// ```txt
70+
/// 101
71+
/// 25
72+
/// 9
73+
/// ```
74+
///
75+
/// #### Output Format
76+
///
77+
/// ```txt
78+
/// Invalid input data!
79+
/// ```
80+
///
81+
/// ### Error
82+
///
83+
/// If the input is invalid, return:
84+
///
85+
/// ```rust
86+
/// String::from("Invalid input data!");
87+
/// ```
88+
///
89+
/// If there's no solution, return:
90+
///
91+
/// ```rust
92+
/// String::from("No solution!");
93+
/// ```
94+
///
95+
/// ## Test cases
96+
///
97+
/// ```rust
98+
/// use hackerrank::hw3::task_1::Solution;
99+
///
100+
/// assert_eq!(
101+
/// Solution::main(30, 18, 6),
102+
/// String::from("-1\n2")
103+
/// );
104+
/// assert_eq!(
105+
/// Solution::main(30, 18, 4),
106+
/// String::from("No solution!")
107+
/// );
108+
/// assert_eq!(
109+
/// Solution::main(101, 25, 9),
110+
/// String::from("Invalid input data!")
111+
/// );
112+
/// assert_eq!(
113+
/// Solution::main(100, 50, 100),
114+
/// String::from("0\n2")
115+
/// );
116+
/// assert_eq!(
117+
/// Solution::main(99, 33, 66),
118+
/// String::from("0\n2")
119+
/// );
120+
/// ```
121+
pub struct Solution;
122+
123+
impl Solution {
124+
pub fn main(a: i32, b: i32, c: i32) -> String {
125+
if [a, b, c].iter().any(|item| !(MIN..=MAX).contains(item)) {
126+
return invalid_input();
127+
}
128+
let ((mut x, mut y), d) = a.extended_gcd(b);
129+
130+
if c % d != 0 {
131+
return no_solution();
132+
}
133+
134+
let scale_to_c = c / d;
135+
x *= scale_to_c;
136+
y *= scale_to_c;
137+
138+
format!("{}\n{}", x, y)
139+
}
140+
}
141+
142+
pub fn main() -> Result<(), Error> {
143+
let a = get_numeric_input::<i32>()?;
144+
let b = get_numeric_input::<i32>()?;
145+
let c = get_numeric_input::<i32>()?;
146+
147+
println!("{}", Solution::main(a, b, c));
148+
149+
Ok(())
150+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33

44
pub mod hw1;
55
pub mod hw2;
6+
pub mod hw3;
67
pub mod utils;

src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod hw1;
22
mod hw2;
3+
mod hw3;
34

45
mod utils;
56
use utils::Error;
@@ -42,5 +43,12 @@ fn main() -> Result<(), Error> {
4243
HW_2[Task::Task3 as usize]()?;
4344
}
4445

46+
#[cfg(feature = "hw3-task-1")]
47+
{
48+
const HW_3: [fn() -> Result<(), Error>; 1] = [hw3::task_1::main];
49+
50+
HW_3[Task::Task1 as usize]()?;
51+
}
52+
4553
Ok(())
4654
}

src/utils/gcd.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,36 @@ where
4343
}
4444
}
4545

46+
/// Implemented based on this implementation[1].
47+
///
48+
/// [1]: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Pseudocode
49+
pub trait ExtendedGcd: Gcd {
50+
/// Returns: (Self::BezoutCoefficient, Self::Gcd)
51+
/// where:
52+
/// - Self::BezoutCoefficient = (Self, Self)
53+
/// - Self::Gcd = Self
54+
fn extended_gcd(self, other: Self) -> ((Self, Self), Self) {
55+
let (mut prev_r, mut r) = (self, other);
56+
let (mut prev_s, mut s) = (Self::one(), Self::zero());
57+
let (mut prev_t, mut t) = (Self::zero(), Self::one());
58+
59+
let mut q;
60+
while r != Self::zero() {
61+
q = prev_r / r;
62+
(prev_r, r) = (r, prev_r - q * r);
63+
(prev_s, s) = (s, prev_s - q * s);
64+
(prev_t, t) = (t, prev_t - q * t);
65+
}
66+
67+
((prev_s, prev_t), prev_r)
68+
}
69+
}
70+
4671
macro_rules! gcd_impl {
4772
($name:ident for $($x:ty)*) => ($(
4873
impl $name for $x {}
4974
)*)
5075
}
5176

5277
gcd_impl!(Gcd for i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
78+
gcd_impl!(ExtendedGcd for i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);

src/utils/input.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ where
1919
Ok(tmp.trim().parse::<T>().unwrap())
2020
}
2121

22+
#[must_use = "This function returns the 'Invalid input data!' value used for asserting tests."]
2223
pub fn invalid_input() -> String {
2324
String::from("Invalid input data!")
2425
}
26+
27+
#[must_use = "This function returns the 'No solution!' value used for asserting tests."]
28+
pub fn no_solution() -> String {
29+
String::from("No solution!")
30+
}

0 commit comments

Comments
 (0)