This commit is contained in:
Aadi Desai 2023-12-15 21:24:17 +00:00
parent 320360ac9e
commit e4a1d23e67
Signed by: supleed2
SSH key fingerprint: SHA256:CkbNRs0yVzXEiUp2zd0PSxsfRUMFF9bLlKXtE1xEbKM
4 changed files with 136 additions and 0 deletions

15
Cargo.lock generated
View file

@ -431,9 +431,11 @@ dependencies = [
"base64",
"chrono",
"image",
"regex",
"reqwest",
"serde",
"serde_json",
"sha256",
"shuttle-axum",
"shuttle-runtime",
"shuttle-shared-db",
@ -2541,6 +2543,19 @@ dependencies = [
"digest",
]
[[package]]
name = "sha256"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386"
dependencies = [
"async-trait",
"bytes",
"hex",
"sha2",
"tokio",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"

View file

@ -11,9 +11,11 @@ axum-extra = { version = "0.9.0", features = ["typed-header"] }
base64 = "0.21.5"
chrono = { version = "0.4.31", default-features = false, features = ["std"] }
image = "0.24.7"
regex = "1.10.2"
reqwest = { version = "0.11.22", features = ["json"] }
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
sha256 = "1.4.0"
shuttle-axum = { version = "0.35.0", default-features = false, features = ["axum-0-7"] }
shuttle-runtime = "0.35.0"
shuttle-shared-db = { version = "0.35.1", features = ["postgres"] }

117
src/cal/day15.rs Normal file
View file

@ -0,0 +1,117 @@
use axum::{http::StatusCode, response::IntoResponse, routing::post, Json, Router};
pub(crate) fn router() -> Router {
Router::new()
.route("/15/nice", post(nice))
.route("/15/game", post(game))
}
#[derive(serde::Deserialize)]
struct Nice {
input: String,
}
async fn nice(Json(Nice { input }): Json<Nice>) -> impl IntoResponse {
let vowels = input
.chars()
.filter(|&c| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y')
.count();
let repeat = input
.as_bytes()
.windows(2)
.any(|c| c[0].is_ascii_alphabetic() && c[0] == c[1]);
let substrs = input.contains("ab")
|| input.contains("cd")
|| input.contains("pq")
|| input.contains("xy");
if vowels > 2 && repeat && !substrs {
(StatusCode::OK, "{\"result\":\"nice\"}".to_string())
} else {
(
StatusCode::BAD_REQUEST,
"{\"result\":\"naughty\"}".to_string(),
)
}
}
#[derive(serde::Serialize)]
struct Game {
result: String,
reason: String,
}
async fn game(Json(Nice { input }): Json<Nice>) -> (StatusCode, Json<Game>) {
let code;
let result;
let reason;
let r1 = input.len() >= 8;
let r2 = input.chars().any(|c| c.is_ascii_uppercase())
&& input.chars().any(|c| c.is_ascii_lowercase())
&& input.chars().any(|c| c.is_ascii_digit());
let r3 = input.chars().filter(char::is_ascii_digit).count() >= 5;
let r4 = regex::Regex::new(r"\d+")
.expect("Regex should be valid")
.captures_iter(&input)
.map(|c| c.extract::<0>().0)
.map(|s| s.parse::<i32>().expect("All matches are only digits"))
.sum::<i32>()
== 2023;
let r5 = regex::Regex::new(r".*j.*o.*y.*")
.expect("Regex should be valid")
.is_match(&input)
&& input.chars().filter(|&c| c == 'j').count() == 1
&& input.chars().filter(|&c| c == 'o').count() == 1
&& input.chars().filter(|&c| c == 'y').count() == 1;
let r6 = input.as_bytes().windows(3).any(|c| {
c[0] != c[1] && c[0] == c[2] && c[0].is_ascii_alphabetic() && c[1].is_ascii_alphabetic()
});
let r7 = input
.chars()
.any(|c| ('\u{2980}'..='\u{2BFF}').contains(&c));
let r8 = regex::Regex::new(r"[\p{Emoji}--\p{Ascii}]")
.expect("Regex should be valid")
.is_match(&input);
let r9 = sha256::digest(input.clone()).ends_with('a');
if !r1 {
code = StatusCode::BAD_REQUEST;
result = "naughty".to_string();
reason = "8 chars".to_string();
} else if !r2 {
code = StatusCode::BAD_REQUEST;
result = "naughty".to_string();
reason = "more types of chars".to_string();
} else if !r3 {
code = StatusCode::BAD_REQUEST;
result = "naughty".to_string();
reason = "55555".to_string();
} else if !r4 {
code = StatusCode::BAD_REQUEST;
result = "naughty".to_string();
reason = "math is hard".to_string();
} else if !r5 {
code = StatusCode::NOT_ACCEPTABLE;
result = "naughty".to_string();
reason = "not joyful enough".to_string();
} else if !r6 {
code = StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS;
result = "naughty".to_string();
reason = "illegal: no sandwich".to_string();
} else if !r7 {
code = StatusCode::RANGE_NOT_SATISFIABLE;
result = "naughty".to_string();
reason = "outranged".to_string();
} else if !r8 {
code = StatusCode::UPGRADE_REQUIRED;
result = "naughty".to_string();
reason = "😳".to_string();
} else if !r9 {
code = StatusCode::IM_A_TEAPOT;
result = "naughty".to_string();
reason = "not a coffee brewer".to_string();
} else {
code = StatusCode::OK;
result = "nice".to_string();
reason = "that's a nice password".to_string();
}
(code, Json(Game { result, reason }))
}

View file

@ -8,6 +8,7 @@ mod day11;
mod day12;
mod day13;
mod day14;
mod day15;
pub(crate) fn router(pool: sqlx::PgPool) -> axum::Router {
axum::Router::new()
@ -21,4 +22,5 @@ pub(crate) fn router(pool: sqlx::PgPool) -> axum::Router {
.nest("/", day12::router())
.nest("/", day13::router(pool))
.nest("/", day14::router())
.nest("/", day15::router())
}