use std::fs::File;
use std::io::prelude::*;
use std::iter::Iterator;

fn main() -> std::io::Result<()> {
    let input = File::open("list.txt")?;
    let mut reader = std::io::BufReader::new(input);

    let output = File::create("nodup.txt")?;
    let mut writer = std::io::BufWriter::new(output);

    loop {
        let mut linebuf = Vec::<u8>::with_capacity(1024);
        let mut elementsbuf = Vec::<Option<&[u8]>>::with_capacity(32);
        let mut sortbuf = Vec::<&mut Option<&[u8]>>::with_capacity(32);
        if reader.read_until('\n' as u8, &mut linebuf).is_err() || linebuf.is_empty() {
            break;
        }

        for element in linebuf.split(|v| *v == ';' as u8) {
            elementsbuf.push(Some(element));
        }
        elementsbuf.pop();
        for element in elementsbuf.iter_mut() {
            sortbuf.push(element);
        }

        sortbuf[3 ..].sort_by_key(|v| **v);
        let mut last: Option<&[u8]> = None;
        for element in sortbuf.iter_mut().skip(3) {
            let copy = element.clone();
            if **element == last {
                **element = None;
            }

            last = copy
        }

        let resultline: Vec<u8> = elementsbuf.iter()
            .flat_map(|v| v.unwrap_or(&[]).iter().chain(&[';' as u8][..]))
            .chain(&['\n' as u8][..])
            .map(|v| *v)
            .collect();
        writer.write(resultline.as_ref()).unwrap();
    }
    writer.flush().unwrap();
    Ok(())
}