Skip to main content

ternary_spreadsheet/
sort.rs

1use crate::grid::Grid;
2
3/// Axis to sort by.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum SortAxis {
6    Row,
7    Column,
8}
9
10/// Sort rows or columns by their total fitness (descending = fittest first).
11pub fn sort_by_fitness(grid: &mut Grid, by: SortAxis) {
12    match by {
13        SortAxis::Row => {
14            let mut rows = std::mem::take(grid.rows_mut());
15            rows.sort_by(|a, b| {
16                let fa: f64 = a.iter().map(|c| c.fitness).sum();
17                let fb: f64 = b.iter().map(|c| c.fitness).sum();
18                fb.partial_cmp(&fa).unwrap_or(std::cmp::Ordering::Equal)
19            });
20            *grid.rows_mut() = rows;
21        }
22        SortAxis::Column => {
23            let (nrows, ncols) = grid.dimensions();
24            let mut col_fitness: Vec<(usize, f64)> = (0..ncols)
25                .map(|c| {
26                    let fitness: f64 = (0..nrows)
27                        .filter_map(|r| grid.get(r, c).map(|cell| cell.fitness))
28                        .sum();
29                    (c, fitness)
30                })
31                .collect();
32            col_fitness.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
33
34            let col_order: Vec<usize> = col_fitness.iter().map(|(c, _)| *c).collect();
35            let mut new_cells = Vec::with_capacity(nrows);
36            for r in 0..nrows {
37                let mut row = Vec::with_capacity(ncols);
38                for &c in &col_order {
39                    row.push(grid.get(r, c).cloned().unwrap_or_default());
40                }
41                new_cells.push(row);
42            }
43            *grid.rows_mut() = new_cells;
44        }
45    }
46}