AtCoder Beginner Contest 276 D

https://atcoder.jp/contests/abc276/tasks/abc276_d

AのgcdにAの各要素が何回割ってたどり着くかをカウントします。
reduceって無いんですね。foldだとgcdはちょっと面倒ですよね。

// Divide by 2 or 3
#![allow(non_snake_case)]

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect()
}

fn read_input() -> Vec<i32> {
    let _N: usize = read();
    let A = read_vec();
    A
}

fn gcd(a: i32, b: i32) -> i32 {
    if b == 0 { a } else { gcd(b, a % b) }
}

fn gcd_vec(A: &Vec<i32>) -> i32 {
    let mut iter = A.iter();
    match iter.next() {
        Some(&e0) => iter.fold(e0, |e, &f| gcd(e, f)),
        None      => 1
    }
}

fn num_divs23(e: i32) -> i32 {
    if e == 1 {
        0
    }
    else if e % 2 == 0 {
        num_divs23(e / 2) + 1
    }
    else if e % 3 == 0 {
        num_divs23(e / 3) + 1
    }
    else {
        -100    // 再帰でも負を返す
    }
}

fn f(A: Vec<i32>) -> i32 {
    let d = gcd_vec(&A);
    let mut counter: i32 = 0;
    for e in A.into_iter() {
        if e % d != 0 {
            return -1
        }
        else {
            let n = num_divs23(e / d);
            if n < 0 {
                return -1
            }
            else {
                counter += n
            }
        }
    }
    counter
}

fn main() {
    let A = read_input();
    println!("{}", f(A))
}