mirror of
https://github.com/kristoferssolo/customs-rs.git
synced 2025-10-21 19:20:33 +00:00
feat: pass all tests
This commit is contained in:
parent
a8311c5e0f
commit
941d905af8
@ -2,12 +2,22 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use crate::{error::InputError, utils::Time};
|
use crate::{error::InputError, utils::Time};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd)]
|
||||||
pub enum CitizenshipType {
|
pub enum CitizenshipType {
|
||||||
Citizen,
|
Citizen,
|
||||||
NonCitizen,
|
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 {
|
impl FromStr for CitizenshipType {
|
||||||
type Err = InputError;
|
type Err = InputError;
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
@ -21,13 +31,16 @@ impl FromStr for CitizenshipType {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Citizenship {
|
pub struct Citizenship {
|
||||||
pub id: Time,
|
pub arrival_time: Time,
|
||||||
pub type_: CitizenshipType,
|
pub type_: CitizenshipType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Citizenship {
|
impl Citizenship {
|
||||||
pub fn new(id: Time, type_: CitizenshipType) -> Self {
|
pub fn new(arrival_time: Time, type_: CitizenshipType) -> Self {
|
||||||
Self { id, type_ }
|
Self {
|
||||||
|
arrival_time,
|
||||||
|
type_,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +53,10 @@ impl FromStr for Citizenship {
|
|||||||
(Some(citizenship), Some(id)) => {
|
(Some(citizenship), Some(id)) => {
|
||||||
let id = id.parse::<Time>().map_err(|_| InputError::InvalidFormat)?;
|
let id = id.parse::<Time>().map_err(|_| InputError::InvalidFormat)?;
|
||||||
let type_ = CitizenshipType::from_str(citizenship)?;
|
let type_ = CitizenshipType::from_str(citizenship)?;
|
||||||
Ok(Self { id, type_ })
|
Ok(Self {
|
||||||
|
arrival_time: id,
|
||||||
|
type_,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
_ => Err(InputError::InvalidFormat),
|
_ => Err(InputError::InvalidFormat),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,5 +4,6 @@ pub mod customs_info;
|
|||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod officer;
|
pub mod officer;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
|
pub mod output_time;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|||||||
@ -6,10 +6,11 @@ use crate::{
|
|||||||
utils::{CustomsCount, Time},
|
utils::{CustomsCount, Time},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Officer {
|
pub struct Officer {
|
||||||
pub id: CustomsCount,
|
pub id: CustomsCount,
|
||||||
pub time: Time,
|
pub processing_time: Time,
|
||||||
|
pub departure_time: Time,
|
||||||
pub citizenship: CitizenshipType,
|
pub citizenship: CitizenshipType,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,10 +18,19 @@ impl Officer {
|
|||||||
pub fn new(id: CustomsCount, time: Time, citizenship: CitizenshipType) -> Self {
|
pub fn new(id: CustomsCount, time: Time, citizenship: CitizenshipType) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
time,
|
processing_time: time,
|
||||||
|
departure_time: 0,
|
||||||
citizenship,
|
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 {
|
impl PartialOrd for Officer {
|
||||||
@ -52,7 +62,8 @@ impl FromStr for Officer {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
id,
|
id,
|
||||||
citizenship,
|
citizenship,
|
||||||
time,
|
departure_time: 0,
|
||||||
|
processing_time: time,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(InputError::InvalidFormat),
|
_ => Err(InputError::InvalidFormat),
|
||||||
|
|||||||
@ -1,52 +1,44 @@
|
|||||||
use std::{cmp, fmt::Display};
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
citizenship::{Citizenship, CitizenshipType},
|
citizenship::{Citizenship, CitizenshipType},
|
||||||
customs::Customs,
|
|
||||||
officer::Officer,
|
officer::Officer,
|
||||||
utils::Time,
|
output_time::OutputTime,
|
||||||
|
utils::{Data, Time},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Output(Vec<OutputTime>);
|
pub struct Output(Vec<OutputTime>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct OutputTime {
|
|
||||||
input: Time,
|
|
||||||
output: Time,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Output {
|
impl Output {
|
||||||
pub fn new(mut customs: Customs, all_citizens: Vec<Citizenship>) -> Self {
|
pub fn sort(&mut self) {
|
||||||
customs.sort();
|
// first by departure time, then by CitizenshipType (citizens first), then by Officer id
|
||||||
dbg!(&customs);
|
self.0.sort_by(|a, b| {
|
||||||
let citizens = Self::from((&customs.citizens, &all_citizens, CitizenshipType::Citizen));
|
let departure_time_cmp = a.departure_time.cmp(&b.departure_time);
|
||||||
let noncitizens = Self::from((
|
if departure_time_cmp.is_ne() {
|
||||||
&customs.noncitizens,
|
return departure_time_cmp;
|
||||||
&all_citizens,
|
}
|
||||||
CitizenshipType::NonCitizen,
|
let citizenship_cmp = a.citizenship.cmp(&b.citizenship);
|
||||||
));
|
if citizenship_cmp.is_ne() {
|
||||||
let mut output = Vec::new();
|
return citizenship_cmp;
|
||||||
output.extend(citizens.0);
|
}
|
||||||
output.extend(noncitizens.0);
|
a.officer_id.cmp(&b.officer_id)
|
||||||
Self(output)
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(&Vec<Officer>, &Vec<Citizenship>, CitizenshipType)> for Output {
|
impl From<Data> for Output {
|
||||||
fn from(value: (&Vec<Officer>, &Vec<Citizenship>, CitizenshipType)) -> Self {
|
fn from(value: Data) -> Self {
|
||||||
let (customs, citizens, type_) = value;
|
|
||||||
let mut outputs = Vec::new();
|
let mut outputs = Vec::new();
|
||||||
for officer in customs {
|
let mut citizens = value.customs.citizens;
|
||||||
let mut prev = 0;
|
let mut noncitizens = value.customs.noncitizens;
|
||||||
for citizen in citizens {
|
|
||||||
if citizen.type_ == officer.citizenship && citizen.type_ == type_ {
|
for citizen in &value.citizens {
|
||||||
let output_ = officer.time + cmp::max(citizen.id, prev);
|
let time = match citizen.type_ {
|
||||||
let output = OutputTime::new(citizen.id, output_);
|
CitizenshipType::Citizen => foo(&citizen, &mut citizens),
|
||||||
outputs.push(output);
|
CitizenshipType::NonCitizen => foo(&citizen, &mut noncitizens),
|
||||||
prev = output_;
|
};
|
||||||
}
|
outputs.push(time);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Self(outputs)
|
Self(outputs)
|
||||||
}
|
}
|
||||||
@ -69,14 +61,37 @@ impl Into<String> for Output {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutputTime {
|
fn calculate_departure_time(officer: &mut Officer, arrival_time: Time) -> Time {
|
||||||
pub fn new(input: Time, output: Time) -> Self {
|
if arrival_time > officer.departure_time {
|
||||||
Self { input, output }
|
arrival_time + officer.processing_time
|
||||||
|
} else {
|
||||||
|
officer.potential_departure_time()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for OutputTime {
|
fn foo(citizen: &Citizenship, customs: &mut Vec<Officer>) -> OutputTime {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
let arrival_time = citizen.arrival_time;
|
||||||
write!(f, "{} {}", self.input, self.output)
|
|
||||||
}
|
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
48
src/output_time.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,15 +7,16 @@ use crate::{
|
|||||||
error::ParseError,
|
error::ParseError,
|
||||||
officer::Officer,
|
officer::Officer,
|
||||||
output::Output,
|
output::Output,
|
||||||
|
utils::Data,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn process(input: &str) -> String {
|
pub fn process(input: &str) -> String {
|
||||||
match parse_input(input) {
|
match parse_input(input) {
|
||||||
Ok(data) => data.into(),
|
Ok(mut data) => {
|
||||||
Err(e) => {
|
data.sort();
|
||||||
println!("Error: {e}");
|
data.into()
|
||||||
"nothing\n".into()
|
|
||||||
}
|
}
|
||||||
|
Err(_) => "nothing\n".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +50,6 @@ pub fn parse_input(input: &str) -> Result<Output, ParseError> {
|
|||||||
return Err(ParseError::NoCitizens);
|
return Err(ParseError::NoCitizens);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut citizen_customs_new = Vec::new();
|
|
||||||
for customs_id in 1..=first.citizen.count {
|
for customs_id in 1..=first.citizen.count {
|
||||||
if customs
|
if customs
|
||||||
.citizens
|
.citizens
|
||||||
@ -59,10 +59,9 @@ pub fn parse_input(input: &str) -> Result<Output, ParseError> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let new = Officer::new(customs_id, first.citizen.time, CitizenshipType::Citizen);
|
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 {
|
for customs_id in 1..=first.noncitizen.count {
|
||||||
if customs
|
if customs
|
||||||
.noncitizens
|
.noncitizens
|
||||||
@ -76,11 +75,9 @@ pub fn parse_input(input: &str) -> Result<Output, ParseError> {
|
|||||||
first.noncitizen.time,
|
first.noncitizen.time,
|
||||||
CitizenshipType::NonCitizen,
|
CitizenshipType::NonCitizen,
|
||||||
);
|
);
|
||||||
noncitizen_customs_new.push(new);
|
customs.noncitizens.push(new);
|
||||||
}
|
}
|
||||||
|
|
||||||
customs.citizens.extend(citizen_customs_new);
|
let data = Data::new(customs, citizens);
|
||||||
customs.noncitizens.extend(noncitizen_customs_new);
|
Ok(Output::from(data))
|
||||||
|
|
||||||
Ok(Output::new(customs, citizens))
|
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/utils.rs
14
src/utils.rs
@ -1,2 +1,16 @@
|
|||||||
|
use crate::{citizenship::Citizenship, customs::Customs};
|
||||||
|
|
||||||
pub type Time = u32;
|
pub type Time = u32;
|
||||||
pub type CustomsCount = u8;
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user