"Des énigmes mathématiques qui entraînent davantage le cerveau du programme" _Q41 (code: Ruby) -> Rust

Je pensais que la réécriture "des puzzles mathématiques qui entraînent davantage le cerveau du programmeur" avec Rust peut être juste pour éviter le flou.

Q41: vignette du menu Démarrer

Quel genre d'idée pensez-vous d'un tel problème? Le problème du ciblage des chiffres est amusant.

Ruby

q41_2.rb


W, H = 10, 10

@memo = {}
def search(tile)
    return @memo[tile] if @memo[tile]
    return 1 if tile.min == H

    pos = tile.index(tile.min)
    cnt = 0
    [[1,1],[2,2],[4,2], [4,4]].each do |px,py|
        check = true
        px.times do |x|
            if (pos + x >= W) || (tile[pos + x] + py > H)
                check = false
            elsif tile[pos + x] != tile[pos]
                check = false
            end
        end
        next if !check

        px.times do |x|
            tile[pos + x] += py
        end
        cnt += search(tile)
        px.times do |x|
            tile[pos + x] -= py
        end
    end
    @memo[tile.clone] = cnt
end

puts search([0] * W)

Je trouve que c'est trop compressé. Comme il n'y a pas d'illustration de l'algorithme dans le livre, il est difficile à comprendre en raison de la pertinence du nom de la variable et de la structure de données exposée. À moins d'illustrer le type de jugement qui mènera à l'état suivant, vous ne pouvez pas obtenir une image de recherche récursive. Peut-être que je suis le seul.

Rust

main.rs


use std::collections::HashMap;

fn main() {
    let space_width = 10;
    let space_height = 10;
    let mut q41 = Q41 {
        memo: HashMap::new(),
    };
    let space = Space::new(space_width,space_height);
    println!(
        "{}",
        q41.patterns(&space, &vec![(1, 1), (2, 2), (4, 2), (4, 4)])
    );
}

struct Q41 {
    memo: HashMap<Space, u64>,
}

impl Q41 {
    pub fn patterns(&mut self, space: &Space, tiles: &Vec<(u64, u64)>) -> u64 {
        match self.memo.get(space) {
            Some(v) => *v,
            _ => {
                if space.is_filled() {
                    return 1;
                }
                let mut count = 0;
                for t in tiles {
                    if space.can_be_placed(t) {
                        let new_space = space.place(t);
                        count += self.patterns(&new_space.unwrap(), tiles);
                    }
                }
                self.memo.insert(space.clone(), count);
                return count;
            }
        }
    }
}

#[derive(Eq, Hash)]
struct Space {
    rows: Vec<u64>,
    width: usize,
}

impl PartialEq for Space {
    fn eq(&self, other: &Self) -> bool {
        self.rows == other.rows
    }
}

impl Space {

    pub fn new(width:u64, height:u64) -> Space {
        Space {
            rows: vec![0u64; height as usize],
            width: width as usize,
        }
    }

    pub fn height(&self) -> usize {
        self.rows.len()
    }

    pub fn min_value(&self) -> u64 {
        let mut min = std::u64::MAX;
        for i in 0..self.height() {
            if self.rows[i] < min {
                min = self.rows[i];
            }
        }
        min
    }

    pub fn index_of_min_value(&self) -> usize {
        let min_value: u64 = self.min_value();
        self.rows.iter().position(|&v| v == min_value).unwrap()
    }

    pub fn is_filled(&self) -> bool {
        for i in 0..self.height() {
            if self.rows[i] != self.width as u64 {
                return false;
            }
        }
        true
    }

    pub fn place(&self, tile: &(u64, u64)) -> Option<Space> {
        if !self.can_be_placed(tile) {
            return None;
        }

        let mut new_space: Space = self.clone();

        let py = self.index_of_min_value();
        for y in py..py + tile.1 as usize {
            new_space.rows[y] += tile.0;
        }

        return Some(new_space);
    }

    pub fn can_be_placed(&self, tile: &(u64, u64)) -> bool {
        let index_of_min = self.index_of_min_value();
        let (tw, th) = tile;
        if index_of_min + *th as usize > self.height() {
            // height over!
            return false;
        }
        for dh in 0..*th {
            let ih = index_of_min + dh as usize;
            if self.rows[ih] + tw > self.width as u64 || self.rows[ih] != self.rows[index_of_min] {
                return false;
            }
        }
        return true;
    }

    pub fn clone(&self) -> Space {
        Space {
            rows: self.rows.clone(),
            width: self.width,
        }
    }

    #[warn(dead_code)]
    pub fn to_string(&self) -> String {
        let mut str = String::new();
        for i in 0..self.height() {
            str.push_str(&self.rows[i].to_string());
            str.push_str(", ");
        }
        format!("rows=[{}],width={}",str, self.width)
    }
}

Puisqu'il existe une «méthode directement connectée à l'espace» qui intègre des tuiles, cette méthode est disposée du côté de la structure «Espace». Cela seul a peut-être rendu plus facile la compréhension des «patterns ()» de traitement du corps principal. Quand il s'agit de cette échelle, c'est un bon endroit pour étudier le design.

Recommended Posts

"Des énigmes mathématiques qui entraînent davantage le cerveau du programme" _Q41 (code: Ruby) -> Rust
"Puzzles mathématiques qui entraînent davantage le cerveau du programme" _Q18 (code: Ruby) -> Rust
"Puzzles mathématiques qui entraînent davantage le cerveau du programme" _Q61 (code: Ruby) -> Rust (& SQL)
"Puzzles mathématiques qui entraînent davantage le cerveau du programme" _Q39 (code: Ruby) -> Rust
"Puzzles mathématiques qui entraînent davantage le cerveau du programme" _Q02 (code: Ruby) -> Rust
"Des énigmes mathématiques qui entraînent davantage le cerveau du programme" _Q17 (code: Ruby) -> Rust
"Des énigmes mathématiques qui entraînent davantage le cerveau du programme" _Q01 (code: Ruby) -> Rust
"Puzzles mathématiques qui entraînent davantage le cerveau du programme" _pp.018-020 (code: Ruby) -> Rust
"Puzzle mathématique pour entraîner le cerveau du programme plus" _Q40 (code: Ruby) -> Rust inachevé
Une tentative de "puzzles mathématiques qui entraînent davantage le cerveau de Rust".