<commit_before>use std::mem;
use slsr_core::geom::{Geom, Move};
use slsr_core::puzzle::Puzzle;

use ::SolverResult;
use ::model::side_map::SideMap;
use ::model::theorem::{Pattern, Theorem, TheoremMatcher};

#[derive(Clone, Debug)]
pub struct TheoremPool {
    data: Vec<TheoremMatcher>
}

impl TheoremPool {
    pub fn new<'a, T>(theo_defs: T,
                      puzzle: &Puzzle,
                      sum_of_hint: u32,
                      side_map: &mut SideMap)
                      -> SolverResult<TheoremPool>
        where T: IntoIterator<Item=Theorem>
    {
        let it = theo_defs
            .into_iter()
            .flat_map(|theo| theo.all_rotations());

        let mut hint_theorem = [vec![], vec![], vec![], vec![], vec![]];
        let mut nonhint_theorem = vec![];

        for theo in it {
            match theo.head() {
                Pattern::Hint(h) => hint_theorem[h.hint() as usize].push(theo),
                _ => nonhint_theorem.push(theo)
            }
        }

        let mut data = vec![];

        for p in puzzle.points() {
            if let Some(x) = puzzle.hint(p) {
                for theo in &hint_theorem[x as usize] {
                    let o = match theo.head() {
                        Pattern::Hint(hint) => hint.point(),
                        _ => panic!()
                    };
                    let matcher = theo.clone().shift(p - o);
                    try!(matcher.matches(puzzle, sum_of_hint, side_map))
                        .update(side_map, &mut data);
                }
            }
        }

        for theo in nonhint_theorem {
            let sz = theo.size();
            for r in (1 - sz.0)..(puzzle.row() + sz.0 - 1) {
                for c in (1 - sz.1)..(puzzle.column() + sz.1 - 1) {
                    let matcher = theo.clone().shift(Move(r, c));
                    try!(matcher.matches(puzzle, sum_of_hint, side_map))
                        .update(side_map, &mut data);
                }
            }
        }

        let mut pool = TheoremPool { data: data };
        pool.merge_dup();

        Ok(pool)
    }

    pub fn apply_all(&mut self, side_map: &mut SideMap) -> SolverResult<()> {
        let cap = self.data.len();

        for matcher in mem::replace(&mut self.data, Vec::with_capacity(cap)) {
            try!(matcher.matches(side_map))
                .update(side_map, &mut self.data);
        }

        Ok(())
    }

    fn merge_dup(&mut self) {
        self.data.sort();
        // Merge elements that have same matchers.
        unsafe {
            let len = self.data.len();
            let p = self.data.as_mut_ptr();

            let mut w = 1;
            for r in 1..len {
                let read = p.offset(r as isize);
                let cmp = p.offset((w - 1) as isize);

                match (*cmp).merge(&*read) {
                    Ok(()) => {}
                    Err(()) => {
                        let write = cmp.offset(1);
                        mem::swap(&mut *write, &mut *read);
                        w += 1;
                    }
                }
            }

            self.data.truncate(w);
        }
    }
}
<commit_msg>solver: Reduce theorem numbers in pool<commit_after>use std::mem;
use slsr_core::geom::{Geom, Move};
use slsr_core::puzzle::Puzzle;

use ::SolverResult;
use ::model::side_map::SideMap;
use ::model::theorem::{Pattern, Theorem, TheoremMatcher};

#[derive(Clone, Debug)]
pub struct TheoremPool {
    data: Vec<TheoremMatcher>
}

impl TheoremPool {
    pub fn new<'a, T>(theo_defs: T,
                      puzzle: &Puzzle,
                      sum_of_hint: u32,
                      side_map: &mut SideMap)
                      -> SolverResult<TheoremPool>
        where T: IntoIterator<Item=Theorem>
    {
        let it = theo_defs
            .into_iter()
            .flat_map(|theo| theo.all_rotations());

        let mut hint_theorem = [vec![], vec![], vec![], vec![], vec![]];
        let mut nonhint_theorem = vec![];

        for theo in it {
            match theo.head() {
                Pattern::Hint(h) => hint_theorem[h.hint() as usize].push(theo),
                _ => nonhint_theorem.push(theo)
            }
        }

        let mut data = vec![];

        for p in puzzle.points() {
            if let Some(x) = puzzle.hint(p) {
                for theo in &hint_theorem[x as usize] {
                    let o = match theo.head() {
                        Pattern::Hint(hint) => hint.point(),
                        _ => panic!()
                    };
                    let matcher = theo.clone().shift(p - o);
                    try!(matcher.matches(puzzle, sum_of_hint, side_map))
                        .update(side_map, &mut data);
                }
            }
        }

        for theo in nonhint_theorem {
            let sz = theo.size();
            for r in (1 - sz.0)..(puzzle.row() + sz.0 - 1) {
                for c in (1 - sz.1)..(puzzle.column() + sz.1 - 1) {
                    let matcher = theo.clone().shift(Move(r, c));
                    try!(matcher.matches(puzzle, sum_of_hint, side_map))
                        .update(side_map, &mut data);
                }
            }
        }

        let mut pool = TheoremPool { data: data };
        let mut rev = side_map.revision();
        loop {
            try!(pool.apply_all(side_map));
            if side_map.revision() == rev {
                break
            }
            rev = side_map.revision();
        }

        pool.merge_dup();

        Ok(pool)
    }

    pub fn apply_all(&mut self, side_map: &mut SideMap) -> SolverResult<()> {
        let cap = self.data.len();

        for matcher in mem::replace(&mut self.data, Vec::with_capacity(cap)) {
            try!(matcher.matches(side_map))
                .update(side_map, &mut self.data);
        }

        Ok(())
    }

    fn merge_dup(&mut self) {
        self.data.sort();
        // Merge elements that have same matchers.
        unsafe {
            let len = self.data.len();
            let p = self.data.as_mut_ptr();

            let mut w = 1;
            for r in 1..len {
                let read = p.offset(r as isize);
                let cmp = p.offset((w - 1) as isize);

                match (*cmp).merge(&*read) {
                    Ok(()) => {}
                    Err(()) => {
                        let write = cmp.offset(1);
                        mem::swap(&mut *write, &mut *read);
                        w += 1;
                    }
                }
            }

            self.data.truncate(w);
        }
    }
}

{'fraction_non_alphanumeric': 0.13550340651021953, 'fraction_numerical': 0.004542013626040878, 'mean_word_length': 1.288981288981289, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4717393', 'n_tokens_mistral': 2059, 'n_tokens_neox': 1942, 'n_words': 447}