feat: pass all tests

This commit is contained in:
Kristofers Solo 2024-03-17 21:14:08 +02:00
parent a8311c5e0f
commit 941d905af8
7 changed files with 165 additions and 63 deletions

View File

@ -2,12 +2,22 @@ use std::str::FromStr;
use crate::{error::InputError, utils::Time};
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd)]
pub enum CitizenshipType {
Citizen,
NonCitizen,
}
impl Ord for CitizenshipType {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(CitizenshipType::Citizen, CitizenshipType::NonCitizen) => std::cmp::Ordering::Less,
(CitizenshipType::NonCitizen, CitizenshipType::Citizen) => std::cmp::Ordering::Greater,
_ => std::cmp::Ordering::Equal,
}
}
}
impl FromStr for CitizenshipType {
type Err = InputError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
@ -21,13 +31,16 @@ impl FromStr for CitizenshipType {
#[derive(Debug)]
pub struct Citizenship {
pub id: Time,
pub arrival_time: Time,
pub type_: CitizenshipType,
}
impl Citizenship {
pub fn new(id: Time, type_: CitizenshipType) -> Self {
Self { id, type_ }
pub fn new(arrival_time: Time, type_: CitizenshipType) -> Self {
Self {
arrival_time,
type_,
}
}
}
@ -40,7 +53,10 @@ impl FromStr for Citizenship {
(Some(citizenship), Some(id)) => {
let id = id.parse::<Time>().map_err(|_| InputError::InvalidFormat)?;
let type_ = CitizenshipType::from_str(citizenship)?;
Ok(Self { id, type_ })
Ok(Self {
arrival_time: id,
type_,
})
}
_ => Err(InputError::InvalidFormat),
}

View File

@ -4,5 +4,6 @@ pub mod customs_info;
pub mod error;
pub mod officer;
pub mod output;
pub mod output_time;
pub mod process;
pub mod utils;

View File

@ -6,10 +6,11 @@ use crate::{
utils::{CustomsCount, Time},
};
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Officer {
pub id: CustomsCount,
pub time: Time,
pub processing_time: Time,
pub departure_time: Time,
pub citizenship: CitizenshipType,
}
@ -17,10 +18,19 @@ impl Officer {
pub fn new(id: CustomsCount, time: Time, citizenship: CitizenshipType) -> Self {
Self {
id,
time,
processing_time: time,
departure_time: 0,
citizenship,
}
}
pub fn potential_departure_time(&self) -> Time {
self.processing_time + self.departure_time
}
pub fn filter_departure_time(&self, num: Time) -> bool {
self.departure_time == 0 || self.departure_time == num
}
}
impl PartialOrd for Officer {
@ -52,7 +62,8 @@ impl FromStr for Officer {
Ok(Self {
id,
citizenship,
time,
departure_time: 0,
processing_time: time,
})
}
_ => Err(InputError::InvalidFormat),

View File

@ -1,52 +1,44 @@
use std::{cmp, fmt::Display};
use std::fmt::Display;
use crate::{
citizenship::{Citizenship, CitizenshipType},
customs::Customs,
officer::Officer,
utils::Time,
output_time::OutputTime,
utils::{Data, Time},
};
#[derive(Debug)]
pub struct Output(Vec<OutputTime>);
#[derive(Debug)]
pub struct OutputTime {
input: Time,
output: Time,
}
impl Output {
pub fn new(mut customs: Customs, all_citizens: Vec<Citizenship>) -> Self {
customs.sort();
dbg!(&customs);
let citizens = Self::from((&customs.citizens, &all_citizens, CitizenshipType::Citizen));
let noncitizens = Self::from((
&customs.noncitizens,
&all_citizens,
CitizenshipType::NonCitizen,
));
let mut output = Vec::new();
output.extend(citizens.0);
output.extend(noncitizens.0);
Self(output)
pub fn sort(&mut self) {
// first by departure time, then by CitizenshipType (citizens first), then by Officer id
self.0.sort_by(|a, b| {
let departure_time_cmp = a.departure_time.cmp(&b.departure_time);
if departure_time_cmp.is_ne() {
return departure_time_cmp;
}
let citizenship_cmp = a.citizenship.cmp(&b.citizenship);
if citizenship_cmp.is_ne() {
return citizenship_cmp;
}
a.officer_id.cmp(&b.officer_id)
});
}
}
impl From<(&Vec<Officer>, &Vec<Citizenship>, CitizenshipType)> for Output {
fn from(value: (&Vec<Officer>, &Vec<Citizenship>, CitizenshipType)) -> Self {
let (customs, citizens, type_) = value;
impl From<Data> for Output {
fn from(value: Data) -> Self {
let mut outputs = Vec::new();
for officer in customs {
let mut prev = 0;
for citizen in citizens {
if citizen.type_ == officer.citizenship && citizen.type_ == type_ {
let output_ = officer.time + cmp::max(citizen.id, prev);
let output = OutputTime::new(citizen.id, output_);
outputs.push(output);
prev = output_;
}
}
let mut citizens = value.customs.citizens;
let mut noncitizens = value.customs.noncitizens;
for citizen in &value.citizens {
let time = match citizen.type_ {
CitizenshipType::Citizen => foo(&citizen, &mut citizens),
CitizenshipType::NonCitizen => foo(&citizen, &mut noncitizens),
};
outputs.push(time);
}
Self(outputs)
}
@ -69,14 +61,37 @@ impl Into<String> for Output {
}
}
impl OutputTime {
pub fn new(input: Time, output: Time) -> Self {
Self { input, output }
fn calculate_departure_time(officer: &mut Officer, arrival_time: Time) -> Time {
if arrival_time > officer.departure_time {
arrival_time + officer.processing_time
} else {
officer.potential_departure_time()
}
}
impl Display for OutputTime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {}", self.input, self.output)
}
fn foo(citizen: &Citizenship, customs: &mut Vec<Officer>) -> OutputTime {
let arrival_time = citizen.arrival_time;
let officer = customs
.iter_mut()
.filter(|officer| officer.departure_time == 0 || arrival_time >= officer.departure_time)
.min_by_key(|officer| officer.id);
let officer = match officer {
Some(x) => x,
None => customs
.iter_mut()
.min_by_key(|officer| (officer.departure_time, officer.id))
.unwrap(),
};
let departure_time = calculate_departure_time(officer, arrival_time);
officer.departure_time = departure_time;
OutputTime::new(
arrival_time,
departure_time,
officer.citizenship,
officer.id,
)
}

48
src/output_time.rs Normal file
View File

@ -0,0 +1,48 @@
use std::fmt::Display;
use crate::{
citizenship::CitizenshipType,
utils::{CustomsCount, Time},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OutputTime {
pub arrival_time: Time,
pub departure_time: Time,
pub citizenship: CitizenshipType,
pub officer_id: CustomsCount,
}
impl OutputTime {
pub fn new(
input: Time,
output: Time,
citizenship: CitizenshipType,
officer_id: CustomsCount,
) -> Self {
Self {
arrival_time: input,
departure_time: output,
citizenship,
officer_id,
}
}
}
impl PartialOrd for OutputTime {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.departure_time.partial_cmp(&other.departure_time)
}
}
impl Ord for OutputTime {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.departure_time.cmp(&other.departure_time)
}
}
impl Display for OutputTime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {}", self.arrival_time, self.departure_time)
}
}

View File

@ -7,15 +7,16 @@ use crate::{
error::ParseError,
officer::Officer,
output::Output,
utils::Data,
};
pub fn process(input: &str) -> String {
match parse_input(input) {
Ok(data) => data.into(),
Err(e) => {
println!("Error: {e}");
"nothing\n".into()
Ok(mut data) => {
data.sort();
data.into()
}
Err(_) => "nothing\n".into(),
}
}
@ -49,7 +50,6 @@ pub fn parse_input(input: &str) -> Result<Output, ParseError> {
return Err(ParseError::NoCitizens);
}
let mut citizen_customs_new = Vec::new();
for customs_id in 1..=first.citizen.count {
if customs
.citizens
@ -59,10 +59,9 @@ pub fn parse_input(input: &str) -> Result<Output, ParseError> {
continue;
}
let new = Officer::new(customs_id, first.citizen.time, CitizenshipType::Citizen);
citizen_customs_new.push(new);
customs.citizens.push(new);
}
let mut noncitizen_customs_new = Vec::new();
for customs_id in 1..=first.noncitizen.count {
if customs
.noncitizens
@ -76,11 +75,9 @@ pub fn parse_input(input: &str) -> Result<Output, ParseError> {
first.noncitizen.time,
CitizenshipType::NonCitizen,
);
noncitizen_customs_new.push(new);
customs.noncitizens.push(new);
}
customs.citizens.extend(citizen_customs_new);
customs.noncitizens.extend(noncitizen_customs_new);
Ok(Output::new(customs, citizens))
let data = Data::new(customs, citizens);
Ok(Output::from(data))
}

View File

@ -1,2 +1,16 @@
use crate::{citizenship::Citizenship, customs::Customs};
pub type Time = u32;
pub type CustomsCount = u8;
#[derive(Debug)]
pub struct Data {
pub customs: Customs,
pub citizens: Vec<Citizenship>,
}
impl Data {
pub fn new(customs: Customs, citizens: Vec<Citizenship>) -> Self {
Self { customs, citizens }
}
}