Programming

CodeConvert 소개

steloflute 2024. 4. 20. 22:12

google에서 convert go to rust 라고 치면 맨 위에 나오는 사이트이다.

 

URL: Free Code Converter

 

CodeConvert AI - Convert code with a click of a button

Convert from ActionScript

www.codeconvert.ai

 

AI를 이용해서 프로그램 소스 코드를 다른 프로그래밍 언어로 변환해준다.

지원하는 언어는 C, C++, Common Lisp, Go, Rust, Racket, Java 등 다양하다.

 

예제로 MNIST를 Go에서 Rust로 변환해봤는데, csv 파일 읽는 공통 부분을 함수로 빼냈다! 대단하다.

let (answer, data) = (&line[0], &line[1..]); 부분도 원래 없는 answer 변수를 사용하고, 배열을 쪼개서 저장하는 한 줄로 묶었다.

 

다만, sumSqErr는 zip, map 등을 사용한 함수형 rust 코드로 바꿔서 더 느려졌다.

 

 

원본 Go:

// squared error, int
// accuracy: 0.9691

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

func square(x int) int {
	return x * x
}

func sumSqErr(x, y []int) int {
	l := len(x)
	if l != len(y) {
		log.Fatal("not same size")
	}
	sum := 0
	for i := range x {
		sum += square(x[i] - y[i])
	}
	return sum
}

func main() {
	fmt.Println("!")
	const fileNameTrain = "mnist_train.csv"
	const fileNameTest = "mnist_test.csv"

	// train
	file, err := os.Open(fileNameTrain)
	if err != nil {
		log.Fatal(err)
	}
	sin := bufio.NewScanner(file)
	trainData := [][]int{}
	for sin.Scan() {
		line := sin.Text()
		split := strings.Split(line, ",")
		data := []int{}
		for _, v := range split {
			n, err := strconv.ParseInt(v, 10, 64)
			if err != nil {
				log.Fatal(err)
			}
			data = append(data, int(n))
		}
		trainData = append(trainData, data)
	}
	file.Close()
	fmt.Println("train data loaded. rows:", len(trainData))

	// test
	file, err = os.Open(fileNameTest)
	if err != nil {
		log.Fatal(err)
	}
	sin = bufio.NewScanner(file)
	nRows := 0
	nCorrect := 0
	for sin.Scan() {
		nRows++
		line := sin.Text()
		split := strings.Split(line, ",")
		data := []int{}
		for _, v := range split {
			n, err := strconv.ParseInt(v, 10, 64)
			if err != nil {
				log.Fatal(err)
			}
			data = append(data, int(n))
		}
		// fmt.Println("data:", data)

		// predict
		best := 0
		minError := -1
		for i, d := range trainData {
			error := sumSqErr(data[1:], d[1:])
			if minError < 0 || error < minError {
				minError = error
				best = int(trainData[i][0])
			}
		}
		if best == int(data[0]) {
			nCorrect++
		}
		fmt.Println("predicted:", best, "answer:", data[0], "accuracy:", float64(nCorrect)/float64(nRows))
	}
	file.Close()
	fmt.Println("train data loaded. rows:", nRows, "accuracy:", float64(nCorrect)/float64(nRows))
}

 

변환 Rust:

use std::error::Error;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;

fn square(x: i32) -> i32 {
    x * x
}

fn sum_sq_err(x: &[i32], y: &[i32]) -> i32 {
    if x.len() != y.len() {
        panic!("not same size");
    }
    x.iter()
        .zip(y.iter())
        .map(|(a, b)| square(a - b))
        .sum()
}

fn main() -> Result<(), Box<dyn Error>> {
    println!("!");
    let file_name_train = "mnist_train.csv";
    let file_name_test = "mnist_test.csv";

    // train
    let train_data = read_csv(file_name_train)?;
    println!("train data loaded. rows: {}", train_data.len());

    // test
    let mut n_rows = 0;
    let mut n_correct = 0;
    for line in read_csv(file_name_test)? {
        n_rows += 1;
        let (answer, data) = (&line[0], &line[1..]);
        let mut best = 0;
        let mut min_error = -1;
        for row in &train_data {
            let error = sum_sq_err(&data, &row[1..]);
            if min_error < 0 || error < min_error {
                min_error = error;
                best = row[0];
            }
        }
        if best == *answer {
            n_correct += 1;
        }
        println!(
            "predicted: {}, answer: {}, accuracy: {}",
            best,
            answer,
            (n_correct as f64) / (n_rows as f64)
        );
    }
    println!(
        "train data loaded. rows: {}, accuracy: {}",
        n_rows,
        (n_correct as f64) / (n_rows as f64)
    );
    Ok(())
}

fn read_csv(file_name: &str) -> Result<Vec<Vec<i32>>, Box<dyn Error>> {
    let path = Path::new(file_name);
    let file = File::open(path)?;
    let reader = BufReader::new(file);
    let mut data = Vec::new();
    for line in reader.lines() {
        let line = line?;
        let values: Vec<i32> = line
            .split(',')
            .map(|s| i32::from_str(s).unwrap())
            .collect();
        data.push(values);
    }
    Ok(data)
}