Outils pour utilisateurs

Outils du site


nsi:langages:rust:solutions:ghostleg

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Warning: Undefined array key 2 in /home/goupillf/wiki.goupill.fr/lib/plugins/codeprettify/syntax/code.php on line 214

Solution Ghostleg en Rust

Solution de ce problème.

// src/lib.rs

use std::fs::File;
use std::io::{ self, BufRead, BufReader };

fn transposition(line:&str, indice:usize) -> String {
    /* indice: rang d'un caractère
       fait la transpositon entre le rang voulu et le rang +1
       renvoie une copie de la ligne avec la modif faite */
    let n = line.len();
    if indice >= n-1 {
        panic!("dépassement d'indice !");
    }
    let mut out = String::new();
    let mut right = ' ';
    for (i,c) in line.chars().enumerate() {
        if i == indice {
            right = c;
        } else {
            out.push(c);
        }
        if i == indice + 1 {
            out.push(right);
        }
    }
    out
}

fn ghostleg_line(line:&str, gline:&str) -> String {
    /* partant d'une ligne, ex: "ABC"
       et d'une ligne de ghostleg, ex |--|  |
       calcule la ligne suivante, ex "BAC */
    let mut s = String::from(line);
    for (i,c) in gline.chars().enumerate() {
        if i % 3 == 1 && c == '-' {
            s = transposition(&s, i/3);
        }
    }
    s
}

fn get_head(line:&str) -> String {
    /* renvoie une copie de line sans les espace */
    let mut s = String::new();
    for c in line.chars() {
        if c != ' ' && c != '\n' {
            s.push(c);
        }
    }
    s
}

fn read_lines(filename: &str) -> io::Lines<BufReader<File>> {
    let file = match File::open(filename){
        Ok(f) => f,
        Err(erreur) => panic!("Erreur d'ouverture du fichier : {:?}", erreur),
    };
    return io::BufReader::new(file).lines(); 
}


pub fn ghostleg(filename: &str) -> String {
    /* text: ensemble du texte du ghostleg
       renvoie la chaîne finale          */
    let mut lines = read_lines(filename);
    let first_line = match lines.next() {
        Some(Ok(line)) => line,
        Some(Err(erreur)) => panic!("Erreur lecture première ligne : {:?}", erreur),
        None => panic!("Texte vide !"),
    };
    let mut s = get_head(&first_line);
    for getline in lines {
        let line = match getline {
            Ok(l) => l,
            Err(_erreur) => continue,
        };
        if line.starts_with('|') {
            s = ghostleg_line(&s, &line);
        }
    }
    s
}



#[cfg(test)]
mod tests {
    #[test]
    fn transposition_test() {
        let in_str = "ABCDEF";
        assert_eq!(crate::transposition(in_str, 3), String::from("ABCEDF"));
        assert_eq!(crate::transposition(in_str, 0), String::from("BACDEF"));
    }

    #[test]
    #[should_panic]
    fn transposition_panic_test() {
        let in_str = "ABCDEF";
        crate::transposition(in_str, 8);
    }

    #[test]
    fn ghostleg_line_test() {
        assert_eq!(crate::ghostleg_line("ABC", "|--|  |"), String::from("BAC"));
        assert_eq!(crate::ghostleg_line("ABCDEF", "|  |--|  |  |--|"), String::from("ACBDFE"));
    }

    #[test]
    fn get_head() {
        assert_eq!(crate::get_head("A  B    C   \n"), String::from("ABC"));
    }
}

Vous noterez la présence de match un peu lourds qui sont là pour palier à toute erreur possible, notamment en cours de lecture de la prochaine ligne. J'ai trouvé sur internet le système de Buffer utilisé pour la lecture de ligne. L'objet Lines produit des item compliqué puisqu'ils sont enveloppé dans Option (soit quelque chose Some, soit None) et une possibilité d'erreur Result (soit Ok soi Err).

// src/main.rs

use std::env;
use ghostleg::ghostleg;


fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        panic!("Usage : {} filename", args[0]);
    }
    let filename = &args[1];
    let s = ghostleg(filename);
    print!("{}\n", s);
}
nsi/langages/rust/solutions/ghostleg.txt · Dernière modification : de goupillwiki