Translating a C++ program into Rust

I have a C++ program that is the competitive programming problem's solution. This program is entirely correct. I tried to rewrite it in Rust 1.49.0, but it does not behave as expected. The target platform is x86-64.

#include <bits/stdc++.h>
using namespace std;

const int MOD = 998244353;
 
int add(int x, const int y) {
	x += y;
	if (x < 0) {
	    x += MOD;
	} else if (x >= MOD) {
	    x -= MOD;
	}
	return x;
}
 
int main() {
	int n, m;
	cin >> n >> m;
	string a, b;
	cin >> a >> b;

	int pw = 1;
	int res = 0;
	int ans = 0;
	for (int i = 0; i < m; ++i) {
		if (i < n && a[n - i - 1] == '1') {
			res = add(res, pw);
		}
		if (b[m - i - 1] == '1') {
			ans = add(ans, res);
		}
		pw = add(pw, pw);
	}
	cout << ans << '\n';
}

I tried to make the Rust program as close as possible to the original one, and here is one of my attempts.

use std::*;
use io::{stdin, Read};

const MOD: i32 = 998_244_353;

fn add(x: i32, y: i32) -> i32 {
    let mut res = x.wrapping_add(y);
    if res < 0 {
        res += MOD;
    } else if res >= MOD {
        res -= MOD;
    }
    res
}

fn main() {
    let mut n_and_m = String::new();
    stdin().read_line(&mut n_and_m);

    let mut n_and_m: Vec<&str> = n_and_m.trim().split(" ").collect();
    let m = n_and_m.pop().unwrap().parse::<usize>().unwrap();
    let n = n_and_m.pop().unwrap().parse::<usize>().unwrap();
    drop(n_and_m);

    let mut a = vec![b'\0'; n];
    stdin().read(&mut a);
    stdin().read_line(&mut String::new());

    let mut b = vec![b'\0'; m];
    stdin().read(&mut b);

    let mut pw = 1 as i32;
    let mut res = 0 as i32;
    let mut ans = 0 as i32;
    for i in 0..m {
        if i < n && a[n - i - 1] == b'1' {
            res = add(res, pw);
        }
        if b[m - i - 1] == b'1' {
            ans = add(ans, res);
        }
        pw = add(pw, pw);
    }
    println!("{}", ans)
}

But, for some reason, it fails to pass all the tests.
It is guaranteed that the length of a string a is n and the length of a string b is m.
Here are my other attempts:
u64, cast to u128, rem_euclid
i128

Can anyone give me any advice, please?

Since new users can only put two links, I share some of my attempts here.
u64, rem_euclid
u128, rem_euclid

Does this work?

use std::io::{stdin, Read, Result};

const MOD: i32 = 998244353;

fn add(mut x: i32, y: i32) -> i32 {
    x += y;
    if x < 0 {
        x += MOD;
    } else if x >= MOD {
        x -= MOD;
    }
    x
}

fn main() -> Result<()> {
    let mut input = String::new();
    stdin().read_to_string(&mut input)?;
    let mut input = input.split_ascii_whitespace();

    let n: usize = input.next().unwrap().parse().unwrap();
    let m: usize = input.next().unwrap().parse().unwrap();

    let a = input.next().unwrap().as_bytes();
    let b = input.next().unwrap().as_bytes();

    assert!(a.len() == n);
    assert!(b.len() == m);

    let mut pw = 1;
    let mut res = 0;
    let mut ans = 0;
    for i in 0..m {
        if i < n && a[n - i - 1] == b'1' {
            res = add(res, pw);
        }
        if b[m - i - 1] == b'1' {
            ans = add(ans, res);
        }
        pw = add(pw, pw);
    }
    println!("{}", ans);

    Ok(())
}
2 Likes

This works perfectly, thank you!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.