#![feature(iter_array_chunks)] #![feature(round_char_boundary)] #![feature(iter_collect_into)] #![feature(pattern)] use std::{ hint::black_box, 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() { let mut input = String::new(); let mut stdin = std::io::stdin(); let mut stdout = std::io::stdout(); stdin.read_to_string(&mut input).unwrap(); let bool_locs = find_bools(&input); stdout .write_all(replace_bools(&mut input, bool_locs).as_bytes()) .unwrap(); } 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| { let char_guard = |c: char| !(c.is_alphanumeric() || c.is_contained_in("-_")); let mut allow = true; if it.0 > 0 { allow &= char_guard( input[it.1.floor_char_boundary(it.0 - 1)..it.0] .chars() .last() .unwrap(), ); } let last_idx = it.0 + it.1.len(); if last_idx < input.len() { allow &= char_guard( input[(last_idx)..(input.ceil_char_boundary(last_idx + 1))] .chars() .last() .unwrap(), ); } allow.then_some(it.0) }) .collect() }) .array_chunks::<2>() .collect_into(&mut res); res.try_into().unwrap() }