use std::{collections::HashMap, process::exit}; use proconio::input_interactive; const K: usize = 100; fn main() { let query = |q: &Query| { match q { Query::Ask(register) => println!("? {register}"), Query::Add(src1, src2, dst) => println!("+ {src1} {src2} {dst}"), Query::Ans(register) => { println!("! {register}"); exit(0); } } input_interactive! { res: isize } assert_ne!(res, -1); res as usize }; let read = |register: char| { let mut counter = HashMap::new(); let read_query = Query::Ask(register); for _ in 0..K { let res = query(&read_query); *counter.entry(res).or_insert(0) += 1; } let &v = counter.iter().max_by_key(|t| t.1).unwrap().0; v }; let write = |src1: char, src2: char, dst: char, expected: usize| { let write_query = Query::Add(src1, src2, dst); loop { query(&write_query); let val = read(dst); if val == expected { break; } } }; let find_register = |ban1: char, ban2: char| { ['A', 'B', 'C'] .iter() .find(|&&c| c != ban1 && c != ban2) .copied() .unwrap() }; let x = read('A'); let mut y = read('B'); write('A', 'C', 'B', x); let mut ans_register = 'A'; let mut pow_register = 'B'; let mut ans = x; let mut pow = x; while y > 0 { if y & 1 == 1 { let dst = find_register(ans_register, pow_register); ans += pow; write(ans_register, pow_register, dst, ans); ans_register = dst; } let dst = find_register(ans_register, pow_register); pow += pow; write(pow_register, pow_register, dst, pow); pow_register = dst; y >>= 1; } let ans_query = Query::Ans(ans_register); query(&ans_query); } enum Query { Ask(char), Add(char, char, char), Ans(char), }