11-2-23 Baseline

Experiments Set-up

  • C++ (src_lang) to Rust (tar_lang).
  • Code from code contests dataset
  • Test translation correctness by running I/O test cases
  • 100 C++ programs used as translation source in total
  • 10 Rust translations for each C++ program
  • Using chatGPT as LLM

Techniques used

  • Naive Translate
    • "Translate {src_lang} to {tar_lang}:{code}."
  • Polite Translation
    • "Please translate the following {src_lang} code to {tar_lang} code:{code}`"
  • Chain of Thought version 1
    • "First, understand the functionality of the following {src_lang} code. Then, translate the {src_lang} code to {tar_lang} while maintaining the same functionality, ensuring that the translated code can be successfully compiled. {code}
  • Chain of Thought version 2
    • Use problem description as summary to aid translation
      • Problem description: {summary}. Please translate to {tar_lang} according to the following {src_lang} code and the description of the coding problem it solved: {code}
  • One-Shot (TODO)

Result

  • Naive Translate
    • Compile success rate: 32.0%
    • Translation success rate: 21.8%
  • Polite Translation
    • Compile success rate: 33.0%
    • Translation success rate: 16.4%
  • Chain of Thought version 1
    • Compile success rate: 27.4%
    • Translation success rate: 18.4%
  • Chain of Thought version 2
    • Compile success rate: 40.9%
    • Translation success rate: 3.9%

Translation Examples

Problem

Let's call a string a phone number if it has length 11 and fits the pattern "8xxxxxxxxxx", where each "x" is replaced by a digit.

For example, "80123456789" and "80000000000" are phone numbers, while "8012345678" and "79000000000" are not.

You have n cards with digits, and you want to use them to make as many phone numbers as possible. Each card must be used in at most one phone number, and you don't have to use all cards. The phone numbers do not necessarily have to be distinct.

Input

The first line contains an integer n the number of cards with digits that you have (1 <= n <= 100).

The second line contains a string of n digits (characters "0", "1", ..., "9") s_1, s_2, ..., s_n. The string will not contain any other characters, such as leading or trailing spaces.

Output

If at least one phone number can be made from these cards, output the maximum number of phone numbers that can be made. Otherwise, output 0.

Source C++

#include <bits/stdc++.h>
using namespace std;
int main() {
  int i, n, cnt = 0, temp;
  scanf("%d", &n);
  for (i = 1; i <= n; i++) {
    scanf("%01d", &temp);
    if (temp == 8) cnt++;
  }
  printf("%d\n", min(cnt, n / 11));
}

C2Rust (syntactic translation)

#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
#![register_tool(c2rust)]
#![feature(register_tool)]
extern "C" {
    fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
    fn scanf(_: *const libc::c_char, _: ...) -> libc::c_int;
}
unsafe fn main_0() -> libc::c_int {
    let mut i: libc::c_int = 0;
    let mut n: libc::c_int = 0;
    let mut cnt: libc::c_int = 0 as libc::c_int;
    let mut temp: libc::c_int = 0;
    scanf(b"%d\0" as *const u8 as *const libc::c_char, &mut n as *mut libc::c_int);
    i = 1 as libc::c_int;
    while i <= n {
        scanf(
            b"%01d\0" as *const u8 as *const libc::c_char,
            &mut temp as *mut libc::c_int,
        );
        if temp == 8 as libc::c_int {
            cnt += 1;
        }
        i += 1;
    }
    printf(
        b"%d\n\0" as *const u8 as *const libc::c_char,
        min(cnt, n / 11 as libc::c_int),
    );
    return 0;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

Naive Translate

use std::cmp;

fn main() {
    let mut i: i32;
    let n: i32;
    let mut cnt: i32 = 0;
    let mut temp: i32;
    scanf("%d", &n);
    for i in 1..=n {
        scanf("%01d", &temp);
        if temp == 8 {
            cnt += 1;
        }
    }
    printf("%d\n", cmp::min(cnt, n / 11));
}

Error: printf not used in rust have to use print! macro. scanf is also not defined

Polite Translation (Does Not Compile)

use std::io::{self, Read};

fn main() -> io::Result<()> {
    let mut input = String::new();
    io::stdin().read_line(&mut input)?;
    let n: usize = input.trim().parse()?;
    
    let mut cnt = 0;
    let mut temp = String::new();
    for _ in 0..n {
        io::stdin().read_line(&mut temp)?;
        let temp: i32 = temp.trim().parse()?;
        if temp == 8 {
            cnt += 1;
        }
    }
    println!("{}", cnt.min(n / 11));
    
    Ok(())
}

Error: From return type only std::io::Error is accepted but parse()? will return ParseIntError which cannot be cast to std::io::Error

Chain of Thought version 1 (Compiles But Tests Failed)

use std::io::{self, Read};

fn main() {
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();
    
    let n: usize = input.trim().parse().unwrap();
    let mut cnt = 0;
    
    for _ in 0..n {
        let mut temp = String::new();
        io::stdin().read_line(&mut temp).unwrap();
        let temp: i32 = temp.trim().parse().unwrap();
        
        if temp == 8 {
            cnt += 1;
        }
    }
    
    println!("{}", cnt.min(n as i32 / 11));
}

Error: read_line instead of reading just one character.

Chain of Thought version 2 (success)

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines().map(|x| x.unwrap());
    
    let n: usize = lines.next().unwrap().parse().unwrap();
    let s: String = lines.next().unwrap();
    
    let mut cnt = 0;
    for ch in s.chars() {
        if ch == '8' {
            cnt += 1;
        }
    }
    
    let result = std::cmp::min(cnt, n / 11);
    println!("{}", result);
}