はじめに
paizaxQiitaコラボキャンペーンに参加して、対象問題をすべて解いてみました。
言語は全問題Rustで記述しました。
標準入力からの受け取りについて
Rustは標準入力の受け取りがめんどくさいと巷でよく言われています。
普段自分が遊んでいる競技プログラミングサイトではproconio
という偉大なるクレートを用いることができるためここら辺はストレスフリーなのですが、
残念ながらpaizaでは導入されていなかったため、proconioのソースから必要な一部分を拝借・修正して入力できるようにしています。(最小限のものだけとってきてるので簡易版です)
入力箇所のinputマクロは以下に記載しますが、問題の本質とはズレるので解答コードからは省略しています。
#!/usr/bin/env rust-script
use std::{collections::HashMap, io::Read};
macro_rules! input {
(source = $s:expr, $($r:tt)*) => {
let mut iter = $s.split_whitespace();
input_inner!{iter, $($r)*}
};
($($r:tt)*) => {
let mut s = {
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
s
};
let mut iter = s.split_whitespace();
input_inner!{iter, $($r)*}
};
}
macro_rules! input_inner {
($iter:expr) => {};
($iter:expr, ) => {};
($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
let $var = read_value!($iter, $t);
input_inner!{$iter $($r)*}
};
}
macro_rules! read_value {
($iter:expr, ( $($t:tt),* )) => {
( $(read_value!($iter, $t)),* )
};
($iter:expr, [ $t:tt ; $len:expr ]) => {
(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
};
($iter:expr, chars) => {
read_value!($iter, String).chars().collect::<Vec<char>>()
};
($iter:expr, usize1) => {
read_value!($iter, usize) - 1
};
($iter:expr, $t:ty) => {
$iter.next().unwrap().parse::<$t>().expect("Parse error")
};
}
宝くじ
私の解答
条件分岐の練習問題といったことでしょうか。
ちなみに、前後賞は当選番号の ±1 の番号ということで、100000 または 199999はコーナーケース考えなくちゃと思うかもしれませんが、
入力の制約といして100,000 ≦ a_i ≦ 199,999を満たしてくれているので特に何にも考えなくても大丈夫そうです。
fn main() {
input! {
b: usize,
n: usize,
a: [usize; n]
}
let b_second = &b.to_string()[2..];
let b_third = &b.to_string()[3..];
for &num in a.iter() {
let second = &num.to_string()[2..];
let third = &num.to_string()[3..];
if num == b {
println!("first");
} else if num - 1 == b || num + 1 == b {
println!("adjacent");
} else if b_second == second {
println!("second");
} else if b_third == third {
println!("third");
} else {
println!("blank");
}
}
}
野球の審判
私の解答
制約としては3 ≦ N ≦ 6と小さいので計算量のことを何も気にしなくて良い問題なのですが、
気づいたらmapでストライク数、ボール数を管理する実装にしていました。
後々考えればstrike_count
, ball_count
だけで管理すればより簡潔に書けそうですが手癖でmapを使用していました。
fn main() {
input! {
n: usize,
s: [String; n]
}
let mut map = HashMap::new();
for word in s.into_iter() {
let &count = map.get(&word).unwrap_or(&0usize);
if word == "ball".to_string() {
if count <= 2 {
map.insert(word, count + 1);
println!("ball!");
} else {
return println!("fourball!");
}
} else {
if count <= 1 {
map.insert(word, count + 1);
println!("strike!");
} else {
return println!("out!");
}
}
}
}
みかんの仕分け
私の解答
上の箱に入れるか、下の箱に入れるかはその数のnでの余りをとってあげてその値が小さい方に入れてあげれば良いです。
0gの箱はないこと、二つの箱の差が等しい時には大きい方にいれるということを考慮して実装しています。
fn main() {
input! {
n: usize,
m: usize,
w: [usize; m]
}
for &num in w.iter() {
let v1 = num % n;
let v2 = n - v1;
if v2 <= v1 || num - v1 == 0 {
println!("{}", num + v2);
} else {
println!("{}", num - v1);
}
}
}
Fizz Buzz
私の解答
有名なFizz Buzzですね。
rustではmatch文で(5の余り, 3の余り)で分岐してあげればスッキリかけます。
fn main() {
input! {
n: usize,
}
for i in 1..=n {
match (i % 3, i % 5) {
(0, 0) => println!("Fizz Buzz"),
(0, _) => println!("Fizz"),
(_, 0) => println!("Buzz"),
(_, _) => println!("{}", i),
}
}
}
残り物の量
私の解答
算数問題ですね。
回答に小数入るのでf64で入力とります。
fn main() {
input! {
m: f64,
p: f64,
q: f64
}
let rest = (1.0 - p / 100.0) * m;
let ans = (1.0 - q / 100.0) * rest;
println!("{}", ans);
}
まとめ・感想
この記事ではpaizaxQiitaコラボキャンペーン対象問題のCランク相当の問題5問を解きました。
CランクもDランクに引き続き易しい問題が多かったです。
プログラミング始めたての方とか新しい言語の始めの一歩にぴったりだなと思いました。
他のランクの問題も記事があるので併せて読んでいただけると嬉しいです!