use memra_tokenizer::Tokenizer;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut a = std::env::args().skip(1);
let (dir, inp, n, out) = (
a.next().expect("usage: tok-trim <hf_dir> <in.txt> <n_tokens> <out.txt>"),
a.next().expect("in.txt"),
a.next().expect("n_tokens").parse::<usize>()?,
a.next().expect("out.txt"),
);
let tok = Tokenizer::from_hf_dir(std::path::Path::new(&dir))?;
let text = std::fs::read_to_string(&inp)?;
let total = tok.encode(&text, true).len();
assert!(total >= n, "input encodes to {total} < requested {n} tokens");
let idx: Vec<usize> = text.char_indices().map(|(i, _)| i).chain([text.len()]).collect();
let (mut lo, mut hi) = (0usize, idx.len() - 1); while lo + 1 < hi {
let mid = (lo + hi) / 2;
if tok.encode(&text[..idx[mid]], true).len() <= n { lo = mid } else { hi = mid }
}
let mut cut = lo;
while cut > 0 && tok.encode(&text[..idx[cut]], true).len() > n { cut -= 1; }
let got = tok.encode(&text[..idx[cut]], true).len();
assert_eq!(got, n, "could not hit exactly {n} tokens (closest prefix = {got})");
std::fs::write(&out, &text[..idx[cut]])?;
println!("wrote {out}: {} chars = exactly {n} tokens", idx[cut]);
Ok(())
}