Skip to content

Commit 65632fe

Browse files
committed
Add examples for practice-B
1 parent f204639 commit 65632fe

File tree

5 files changed

+437
-0
lines changed

5 files changed

+437
-0
lines changed

examples/practice-b-naive.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// https://atcoder.jp/contests/practice/tasks/practice_2
2+
3+
use maplit::hashset;
4+
5+
use std::io;
6+
7+
fn main() {
8+
fn read_line() -> String {
9+
let mut input = "".to_owned();
10+
io::stdin().read_line(&mut input).unwrap();
11+
input
12+
}
13+
14+
fn query(l: u8, r: u8) -> bool {
15+
println!("? {} {}", l as char, r as char);
16+
read_line() == "<\n"
17+
}
18+
19+
let n = {
20+
let input = read_line();
21+
let mut input = input.split_whitespace();
22+
macro_rules! read(($ty:ty) => (input.next().unwrap().parse::<$ty>().unwrap()));
23+
read!(u32)
24+
};
25+
26+
let ans = match n {
27+
26 => on_26(query),
28+
5 => on_5(query),
29+
_ => unreachable!(),
30+
};
31+
println!("! {}", String::from_utf8(ans).unwrap());
32+
}
33+
34+
fn on_26(mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
35+
(b'B'..=b'Z').fold(vec![b'A'], |balls, ball| insort(balls, ball, &mut query))
36+
}
37+
38+
#[allow(clippy::many_single_char_names)]
39+
fn on_5(mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
40+
let (r, s, t, u) = {
41+
let (q1, q2) = (query(b'A', b'B'), query(b'C', b'D'));
42+
let (light1, heavy1) = if q1 { (b'A', b'B') } else { (b'B', b'A') };
43+
let (light2, heavy2) = if q2 { (b'C', b'D') } else { (b'D', b'C') };
44+
let q3 = query(light1, light2);
45+
if q3 {
46+
(light1, heavy1, light2, heavy2)
47+
} else {
48+
(light2, heavy2, light1, heavy1)
49+
}
50+
};
51+
52+
let v = (&hashset!(b'A', b'B', b'C', b'D', b'E') - &hashset!(r, s, t, u))
53+
.into_iter()
54+
.next()
55+
.unwrap();
56+
57+
let q4 = query(t, v);
58+
if q4 {
59+
let q5 = query(u, v);
60+
let (min_uv, max_uv) = if q5 { (u, v) } else { (v, u) };
61+
itertools::chain(vec![r], insort(vec![t, min_uv, max_uv], s, &mut query)).collect()
62+
} else {
63+
let q5 = query(r, v);
64+
if q5 {
65+
itertools::chain(vec![r], insort(vec![v, t, u], s, &mut query)).collect()
66+
} else {
67+
itertools::chain(vec![v, r], insort(vec![t, u], s, &mut query)).collect()
68+
}
69+
}
70+
}
71+
72+
fn insort(mut balls: Vec<u8>, ball: u8, mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
73+
let (mut min, mut max) = (0, balls.len());
74+
while min < max {
75+
let mid = (min + max) / 2;
76+
if query(balls[mid], ball) {
77+
min = mid + 1;
78+
} else {
79+
max = mid
80+
};
81+
}
82+
balls.insert(min, ball);
83+
balls
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use itertools::Itertools as _;
89+
90+
use std::str;
91+
92+
#[test]
93+
fn on_5() {
94+
for balls in (b'A'..=b'E').permutations(5) {
95+
let mut queries = 0;
96+
let ans = super::on_5(|l, r| {
97+
queries += 1;
98+
let wl = balls.iter().position(|&b| b == l).unwrap();
99+
let wr = balls.iter().position(|&b| b == r).unwrap();
100+
wl < wr
101+
});
102+
let ans = str::from_utf8(&ans).unwrap();
103+
let balls = str::from_utf8(&balls).unwrap();
104+
assert_eq!(ans, balls);
105+
assert!(queries <= 7);
106+
}
107+
}
108+
}

examples/practice-b-proconio.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// https://atcoder.jp/contests/practice/tasks/practice_2
2+
3+
use maplit::hashset;
4+
use proconio::input;
5+
use proconio::source::line::LineSource;
6+
7+
use std::io;
8+
9+
fn main() {
10+
let stdin = io::stdin();
11+
let mut stdin = stdin.lock();
12+
13+
input! {
14+
from LineSource::new(&mut stdin),
15+
n: u32,
16+
}
17+
18+
let query = |l: u8, r: u8| -> _ {
19+
println!("? {} {}", l as char, r as char);
20+
input! {
21+
from LineSource::new(&mut stdin),
22+
c: char,
23+
}
24+
c == '<'
25+
};
26+
27+
let ans = match n {
28+
26 => on_26(query),
29+
5 => on_5(query),
30+
_ => unreachable!(),
31+
};
32+
println!("! {}", String::from_utf8(ans).unwrap());
33+
}
34+
35+
fn on_26(mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
36+
(b'B'..=b'Z').fold(vec![b'A'], |balls, ball| insort(balls, ball, &mut query))
37+
}
38+
39+
#[allow(clippy::many_single_char_names)]
40+
fn on_5(mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
41+
let (r, s, t, u) = {
42+
let (q1, q2) = (query(b'A', b'B'), query(b'C', b'D'));
43+
let (light1, heavy1) = if q1 { (b'A', b'B') } else { (b'B', b'A') };
44+
let (light2, heavy2) = if q2 { (b'C', b'D') } else { (b'D', b'C') };
45+
let q3 = query(light1, light2);
46+
if q3 {
47+
(light1, heavy1, light2, heavy2)
48+
} else {
49+
(light2, heavy2, light1, heavy1)
50+
}
51+
};
52+
53+
let v = (&hashset!(b'A', b'B', b'C', b'D', b'E') - &hashset!(r, s, t, u))
54+
.into_iter()
55+
.next()
56+
.unwrap();
57+
58+
let q4 = query(t, v);
59+
if q4 {
60+
let q5 = query(u, v);
61+
let (min_uv, max_uv) = if q5 { (u, v) } else { (v, u) };
62+
itertools::chain(vec![r], insort(vec![t, min_uv, max_uv], s, &mut query)).collect()
63+
} else {
64+
let q5 = query(r, v);
65+
if q5 {
66+
itertools::chain(vec![r], insort(vec![v, t, u], s, &mut query)).collect()
67+
} else {
68+
itertools::chain(vec![v, r], insort(vec![t, u], s, &mut query)).collect()
69+
}
70+
}
71+
}
72+
73+
fn insort(mut balls: Vec<u8>, ball: u8, mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
74+
let (mut min, mut max) = (0, balls.len());
75+
while min < max {
76+
let mid = (min + max) / 2;
77+
if query(balls[mid], ball) {
78+
min = mid + 1;
79+
} else {
80+
max = mid
81+
};
82+
}
83+
balls.insert(min, ball);
84+
balls
85+
}
86+
87+
#[cfg(test)]
88+
mod tests {
89+
use itertools::Itertools as _;
90+
91+
use std::str;
92+
93+
#[test]
94+
fn on_5() {
95+
for balls in (b'A'..=b'E').permutations(5) {
96+
let mut queries = 0;
97+
let ans = super::on_5(|l, r| {
98+
queries += 1;
99+
let wl = balls.iter().position(|&b| b == l).unwrap();
100+
let wr = balls.iter().position(|&b| b == r).unwrap();
101+
wl < wr
102+
});
103+
assert_eq!(ans, balls);
104+
assert!(queries <= 7);
105+
}
106+
}
107+
}

examples/practice-b-text-io.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// https://atcoder.jp/contests/practice/tasks/practice_2
2+
3+
use maplit::hashset;
4+
use text_io::{read, try_read, try_scan};
5+
6+
use std::io;
7+
8+
#[allow(clippy::try_err)]
9+
fn main() {
10+
fn read_line() -> String {
11+
let mut input = "".to_owned();
12+
io::stdin().read_line(&mut input).unwrap();
13+
input
14+
}
15+
16+
let n: u32 = {
17+
let line = read_line();
18+
read!("{}", line.bytes())
19+
};
20+
21+
let query = |l: u8, r: u8| -> _ {
22+
println!("? {} {}", l as char, r as char);
23+
read_line() == "<\n"
24+
};
25+
26+
let ans = match n {
27+
26 => on_26(query),
28+
5 => on_5(query),
29+
_ => unreachable!(),
30+
};
31+
println!("! {}", String::from_utf8(ans).unwrap());
32+
}
33+
34+
fn on_26(mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
35+
(b'B'..=b'Z').fold(vec![b'A'], |balls, ball| insort(balls, ball, &mut query))
36+
}
37+
38+
#[allow(clippy::many_single_char_names)]
39+
fn on_5(mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
40+
let (r, s, t, u) = {
41+
let (q1, q2) = (query(b'A', b'B'), query(b'C', b'D'));
42+
let (light1, heavy1) = if q1 { (b'A', b'B') } else { (b'B', b'A') };
43+
let (light2, heavy2) = if q2 { (b'C', b'D') } else { (b'D', b'C') };
44+
let q3 = query(light1, light2);
45+
if q3 {
46+
(light1, heavy1, light2, heavy2)
47+
} else {
48+
(light2, heavy2, light1, heavy1)
49+
}
50+
};
51+
52+
let v = (&hashset!(b'A', b'B', b'C', b'D', b'E') - &hashset!(r, s, t, u))
53+
.into_iter()
54+
.next()
55+
.unwrap();
56+
57+
let q4 = query(t, v);
58+
if q4 {
59+
let q5 = query(u, v);
60+
let (min_uv, max_uv) = if q5 { (u, v) } else { (v, u) };
61+
itertools::chain(vec![r], insort(vec![t, min_uv, max_uv], s, &mut query)).collect()
62+
} else {
63+
let q5 = query(r, v);
64+
if q5 {
65+
itertools::chain(vec![r], insort(vec![v, t, u], s, &mut query)).collect()
66+
} else {
67+
itertools::chain(vec![v, r], insort(vec![t, u], s, &mut query)).collect()
68+
}
69+
}
70+
}
71+
72+
fn insort(mut balls: Vec<u8>, ball: u8, mut query: impl FnMut(u8, u8) -> bool) -> Vec<u8> {
73+
let (mut min, mut max) = (0, balls.len());
74+
while min < max {
75+
let mid = (min + max) / 2;
76+
if query(balls[mid], ball) {
77+
min = mid + 1;
78+
} else {
79+
max = mid
80+
};
81+
}
82+
balls.insert(min, ball);
83+
balls
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use itertools::Itertools as _;
89+
90+
use std::str;
91+
92+
#[test]
93+
fn on_5() {
94+
for balls in (b'A'..=b'E').permutations(5) {
95+
let mut queries = 0;
96+
let ans = super::on_5(|l, r| {
97+
queries += 1;
98+
let wl = balls.iter().position(|&b| b == l).unwrap();
99+
let wr = balls.iter().position(|&b| b == r).unwrap();
100+
wl < wr
101+
});
102+
assert_eq!(ans, balls);
103+
assert!(queries <= 7);
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)