Wrote program for Day 19

This commit is contained in:
Mariano Riefolo 2024-08-13 14:26:33 +02:00
parent ed0187db74
commit 4a71624acc
4 changed files with 150 additions and 1 deletions

View File

@ -65,7 +65,7 @@ We encourage you to share your progress and ask questions in the Discussions sec
| Day #16 | [Nim Game](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-16_Nim-Game) | :white_check_mark: | | Day #16 | [Nim Game](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-16_Nim-Game) | :white_check_mark: |
| Day #17 | [Prison Break](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-17_Prison-Break) | :white_check_mark: | | Day #17 | [Prison Break](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-17_Prison-Break) | :white_check_mark: |
| Day #18 | [Unique Paths](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-18_Unique-Paths) | :white_check_mark: | | Day #18 | [Unique Paths](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-18_Unique-Paths) | :white_check_mark: |
| Day #19 | [URL Shortener](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-19_URL-Shortener) | :white_large_square: | | Day #19 | [URL Shortener](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-19_URL-Shortener) | :white_check_mark: |
| Day #20 | [API Challenge](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-20_API-Challenge) | :white_large_square: | | Day #20 | [API Challenge](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-20_API-Challenge) | :white_large_square: |
| Day #21 | [Random Maze Generator](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-21_Random-Maze-Generator) | :white_large_square: | | Day #21 | [Random Maze Generator](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-03/Day-21_Random-Maze-Generator) | :white_large_square: |
| Day #22 | [Marcio Mellos Challenge](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-22_Marcio-Mellos-Challenge) | :white_large_square: | | Day #22 | [Marcio Mellos Challenge](https://github.com/LiveGray/100-Days-Of-Rust/tree/main/Week-04/Day-22_Marcio-Mellos-Challenge) | :white_large_square: |

View File

@ -0,0 +1,6 @@
[package]
name = "day19"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -0,0 +1,98 @@
use std::time::{SystemTime, UNIX_EPOCH};
fn valid_url(url: &str) -> Result<(), &str> {
if !url.starts_with("http://") && !url.starts_with("https://") {
Err("URL should start with either http:// or https://")
} else if url.contains(' ') {
Err("URL should not contain spaces")
} else if url.len() < 12 {
Err("URL should be at least 12 characters long")
} else if url.len() > 2048 {
Err("URL should not be longer than 2048 characters")
} else if url.contains('\n') {
Err("URL should not contain newlines")
} else {
Ok(())
}
}
pub fn url_shortener(url: &str, custom: Option<String>, rng: Option<Rng>) -> Result<String, &str> {
valid_url(url)?;
let domain = "https://shortener.rs/";
if let Some(custom) = custom {
Ok(format!("{}{}", domain, custom))
} else if let Some(mut rng) = rng {
Ok(format!("{}{}", domain, rng.random_string()))
} else {
Err("Either custom or rng should be provided")
}
}
pub struct Rng {
seed: u128,
}
impl Rng {
pub fn new() -> Rng {
let time_since_epoch = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Error in getting time")
.as_millis();
Rng {
seed: time_since_epoch,
}
}
pub fn random_string(&mut self) -> String {
let random_number = self.linear_congruent_generator(1103515245, 12345, 2u128.pow(31));
let binding = random_number.to_string();
let bytes = binding.as_bytes();
let (bytes, padding) = Rng::split_bits(bytes);
let alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".as_bytes();
let mut result = String::new();
for b in bytes {
result.push(alphabet[b as usize] as char);
}
for _ in (0..padding).step_by(2) {
result.push('=');
}
result
}
fn split_bits(bytes: &[u8]) -> (Vec<u8>, usize) {
let mut bits = Vec::new();
for &byte in bytes {
for i in (0..8).rev() {
bits.push((byte >> i) & 1);
}
}
let mut result = Vec::new();
let mut padding = 0;
for chunk in bits.chunks(6) {
let mut byte = 0;
for (i, &bit) in chunk.iter().enumerate() {
byte |= bit << (5 - i);
}
result.push(byte);
if chunk.len() < 6 {
padding = 6 - chunk.len();
}
}
(result, padding)
}
fn linear_congruent_generator(&mut self, a: u128, c: u128, m: u128) -> u128 {
let result = (a * self.seed + c) % m;
self.seed = result;
result
}
}
impl Default for Rng {
fn default() -> Self {
Self::new()
}
}

View File

@ -0,0 +1,45 @@
use day19::{url_shortener, Rng};
use std::io::{self, Write};
fn main() {
let rng = Rng::new();
let mut buffer = String::new();
print!("Enter the URL to shorten: ");
io::stdout().flush().expect("Failed to flush stdout");
io::stdin()
.read_line(&mut buffer)
.expect("Failed to read from stdin");
let url = buffer.trim().to_owned();
buffer = String::new();
print!("Do you want to provide a custom short URL? (y/n): ");
io::stdout().flush().expect("Failed to flush stdout");
io::stdin()
.read_line(&mut buffer)
.expect("Failed to read from stdin");
let short_url = if buffer.trim() == "y" {
buffer = String::new();
print!("Enter the custom short URL: ");
io::stdout().flush().expect("Failed to flush stdout");
io::stdin()
.read_line(&mut buffer)
.expect("Failed to read from stdin");
let custom = Some(buffer.trim().to_string());
url_shortener(&url, custom, None)
} else {
url_shortener(&url, None, Some(rng))
};
match short_url {
Ok(short_url) => println!("Shortened URL: {}", short_url),
Err(e) => eprintln!("Error: {}", e),
}
}