#![feature(pattern, iter_array_chunks, round_char_boundary, iter_collect_into)] use std::{ io::{Read, Write}, str::pattern::Pattern, }; const BOOL_COUNT: usize = BOOLS.len(); const BOOLS: &[[&str; 2]] = &[ ["false", "true"], ["False", "True"], ["FALSE", "TRUE"], ["0", "1"], ["no", "yes"], ]; fn main() -> std::io::Result<()> { let mut input = String::new(); let mut stdin = std::io::stdin(); let mut stdout = std::io::stdout(); stdin.read_to_string(&mut input)?; let bool_locs = find_bools(&input); stdout.write_all(replace_bools(&mut input, bool_locs).as_bytes()) } type BoolLocs = [[Vec; 2]; BOOL_COUNT]; // you thought [`find_bools`] was stupid? this is *so* much worse!!! fn replace_bools(input: &str, mut bool_locs: BoolLocs) -> String { let mut result = String::with_capacity(input.len()); let mut intermediate = input; let mut flattened = bool_locs .iter_mut() .flatten() .map(|vec| { vec.reverse(); vec }) .enumerate() .collect::>(); let mut smallest = || { let min_idx = flattened .iter() .min_by(|va, vb| { va.1.last() .unwrap_or(&usize::MAX) .cmp(vb.1.last().unwrap_or(&usize::MAX)) })? .0; Some((min_idx, flattened[min_idx].1.pop()?)) }; let mut input_idx = 0; while let Some(item) = smallest() { let (a, b) = intermediate.split_at(item.1 - input_idx); input_idx += a.len(); result += a; let bool_ = &BOOLS[item.0 / 2]; input_idx += bool_[item.0 % 2].len(); result += bool_[if item.0 % 2 == 0 { 1 } else { 0 }]; let (_, b) = b.split_at(bool_[item.0 % 2].len()); intermediate = b; } result + intermediate } // this is so fucking stupid // it also would've been way easier using a regex crate lmao fn find_bools(input: &str) -> [[Vec; 2]; BOOL_COUNT] { let mut res = Vec::with_capacity(BOOL_COUNT); BOOLS .iter() .flatten() .map(|it| { input .match_indices(it) .filter_map(|it| { fn char_guard(c: char) -> bool { !(c.is_alphanumeric() || c.is_contained_in("-_")) } let last_idx = it.0 + it.1.len(); (it.0 > 0 && last_idx < input.len() && char_guard( input[it.1.floor_char_boundary(it.0 - 1)..it.0] .chars() .last()?, ) && char_guard( input[(last_idx)..(input.ceil_char_boundary(last_idx + 1))] .chars() .last()?, )) .then_some(it.0) }) .collect() }) .array_chunks::<2>() .collect_into(&mut res); res.try_into().unwrap() }