mod dijkstra;
mod heap;
mod huffman;
mod jobs;
mod k_clustering;
mod k_clustering_big;
mod mwis;
mod merge_sort;
mod min_cut;
mod prims;
mod quick_sort;
mod ssc;
mod two_sum;
mod util;
mod knapsack;

use crate::dijkstra::dijkstra;
use crate::heap::heap;
use crate::jobs::{jobs_1, jobs_2};
use crate::k_clustering::k_clustering;
use crate::k_clustering_big::k_clustering_big;
use crate::merge_sort::merge_sort_inversions;
use crate::min_cut::min_cut;
use crate::prims::prims;
use crate::quick_sort::quick_sort;
use crate::ssc::ssc;
use crate::two_sum::find_two_sums;
use crate::mwis::mwis;
use crate::knapsack::knapsack;
use std::cmp::min;

#[allow(dead_code)]
fn c1a2() {
    let vec = util::read_to_vector("data/c1a2.txt").unwrap();
    let (_sorted, inversions) = merge_sort_inversions(vec);
    println!("c1a2={:?}", inversions);
}

#[allow(dead_code)]
fn c1a3() {
    let mut vec = util::read_to_vector("data/c1a3.txt").unwrap();
    let mut comp_acc: usize = 0;
    quick_sort(&mut vec, &mut comp_acc);
    println!("c1a3={:?}", comp_acc);
    // 1: 162085, 2: 164123, 3: 138382
}

#[allow(dead_code)]
fn c1a4() {
    let g = util::read_to_graph("data/c1a4.txt").unwrap();
    let mut smallest_min_cut = u32::MAX;
    let iterations = g.nodes.len().pow(1);
    for _ in 0..iterations {
        let new_min_cut = min_cut(g.clone());
        if new_min_cut < smallest_min_cut {
            smallest_min_cut = new_min_cut;
        }
    }
    println!("c1a4={:?}", smallest_min_cut);
    // 17
}

#[allow(dead_code)]
fn c2a1() {
    // I have not checked in the graph file, because it has 70MB. This is a tiny test example.
    let g = util::read_to_directed_graph("data/c2a1_test.txt").unwrap();
    let sizes = ssc(g.0, g.1);
    let max_size = min(sizes.len(), 5);
    println!("{:?}", &sizes[0..max_size]);
    // [434821, 968, 459, 313, 211]
}

#[allow(dead_code)]
fn c2a2() {
    let mut requested_vertices: Vec<usize> = vec![7, 37, 59, 82, 99, 115, 133, 165, 188, 197];
    let mut g = util::read_to_directed_weighted_graph("data/c2a2.txt").unwrap();
    dijkstra(&mut g);
    for i in 0..requested_vertices.len() {
        requested_vertices[i] = g.distance[requested_vertices[i] - 1];
    }
    println!("{:?}", requested_vertices);
    // [2599, 2610, 2947, 2052, 2367, 2399, 2029, 2442, 2505, 3068]
}

#[allow(dead_code)]
fn c2a3() {
    let v = util::read_to_vector("data/c2a3.txt").unwrap();
    let r = heap(&v);
    println!("c2a3={:?}", r);
}

#[allow(dead_code)]
fn c2a4() {
    let mut v = util::read_to_vector("data/c2a4.txt").unwrap();
    let r = find_two_sums(&mut v);
    println!("c2a4={:?}", r);
    // c2a4=427
}

#[allow(dead_code)]
fn c3a1() {
    // belongs to c3a1
    let mut jobs = util::read_jobs("data/c3a1_jobs.txt").unwrap();
    let r1 = jobs_1(&mut jobs);
    let r2 = jobs_2(&mut jobs);
    let g = util::read_weighted_graph_prims("data/c3a1_edges.txt").unwrap();
    let r3 = prims(&g);
    println!("r1 = {}; r2 = {}; r3 = {} ", r1, r2, r3);

    // r1 = 69119377652; r2 = 67311454237; r3 = -3612829
}

#[allow(dead_code)]
fn c3a2() {
    let mut graph = util::read_weighted_graph_clustering("data/c3a2_clustering.txt").unwrap();
    let r1 = k_clustering(&mut graph);
    let graph = util::read_k_cluster_big("data/c3a2_clustering_big.txt").unwrap();
    let r2 = k_clustering_big(&graph);
    println!("r1 = {} r2 = {}", r1, r2);
    // r1 = 106 r2 = 6118
}

#[allow(dead_code)]
fn c3a3() {
    let h = util::read_huffman_alphabet("data/c3a3_huffman.txt").unwrap();
    let r = huffman::build_huffman_tree(&h);

    let s = util::read_max_weight_set("data/c3a3_mwis.txt").unwrap();
    let r3 = mwis(&s);
    println!("r1 = {} r2 = {} r3 = {:?}", r.1, r.0, r3);
    // r1 = 19 r2 = 9 r3 = [1, 0, 1, 0, 0, 1, 1, 0]
}

#[allow(dead_code)]
fn c3a4() {
	let k1 = util::read_knapsack("data/c3a4_knapsack1.txt").unwrap();
	let r1 = knapsack::knapsack(&k1);

	let k2 = util::read_knapsack("data/c3a4_knapsack_big.txt").unwrap();
	let r2 = knapsack::knapsack(&k2);
	println!("r1 = {} r2 = {}", r1, r2);
	// r1 = 2493893 r2 = 4243395
}

#[allow(dead_code)]
fn c4a4() {
	println!("Final course!");
}

fn main() {
    // c1a2();
    // c1a3();
    // c1a4();
    // c2a1();
    // c2a2();
    // c2a3();
    // c2a4();
    // c3a1();
    // c3a2();
    // c3a3();
    c3a4();
    c4a4();
}
