Advertisement
EeZotop

Non-param regression

May 29th, 2022
1,270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 8.71 KB | None | 0 0
  1. use std::{io, str::FromStr, f64::consts, cmp::Ordering};
  2.  
  3. fn main() {
  4.     let stdin = io::stdin();
  5.     let mut scan = Scanner::new(stdin.lock());
  6.  
  7.     let objs_cnt = scan.token();
  8.     let dims = scan.token();
  9.  
  10.     let objs: Vec<_> = (0..objs_cnt)
  11.         .map(|_| {
  12.             let obj: Vec<_> = (0..dims).map(|_| scan.token()).map(|el: i32| el as f64).collect();
  13.             let reduced: f64 = scan.token();
  14.             (obj, reduced)
  15.         })
  16.         .collect();
  17.  
  18.     let req: Vec<_> = (0..dims)
  19.         .map(|_| scan.token())
  20.         .map(|el: i32| el as f64)
  21.         .collect();
  22.  
  23.     let dist: Distance = scan.token();
  24.     let kern: Kernel = scan.token();
  25.     let wndw_prod: WindowProducer = scan.token();
  26.     let wndw = wndw_prod.window(scan.token());
  27.  
  28.     let dist = dist.as_func();
  29.     let kern = kern.as_func();
  30.  
  31.     let mut dists: Vec<_> = objs.iter()
  32.         .map(|(obj, red)| (dist(obj, &req), *red))
  33.         .collect();
  34.  
  35.     dists.sort_unstable_by(|(l_dist, _), (r_dist, _)| if l_dist < r_dist {
  36.         Ordering::Less
  37.     } else if r_dist < l_dist {
  38.         Ordering::Greater
  39.     } else {
  40.         if l_dist.is_nan() || r_dist.is_nan() {
  41.             panic!("NaN");
  42.         }
  43.         Ordering::Equal
  44.     });
  45.  
  46.     let max_dist = match wndw {
  47.         Window::Distance(max_dist) => max_dist,
  48.         Window::Count(count) => if count < dists.len() { dists[count].0 } else { dists.last().unwrap().0 },
  49.     };
  50.  
  51.  
  52.     let average = || dists.iter()
  53.         .map(|(_, red)| *red)
  54.         .sum::<f64>() / dists.len() as f64;
  55.  
  56.     let ans = if max_dist == 0. {
  57.         let (eq_sum, eq_cnt) = objs.iter()
  58.             .filter_map(|(obj, red)| if *obj == req {
  59.                 Some(*red)
  60.             } else { None })
  61.             .fold((0., 0), |(acc_sum, acc_cnt), reduced| (acc_sum + reduced, acc_cnt + 1));
  62.         Some((eq_sum, eq_cnt as f64))
  63.     } else {
  64.         dists.iter()
  65.             .copied()
  66.             .map(|(dist, red)| (kern(dist / max_dist), red))
  67.             .fold(None, |acc, (kern_dist, red)| {
  68.                 let num = kern_dist * red;
  69.                 let den = kern_dist;
  70.                 match acc {
  71.                     None => Some((num, den)),
  72.                     Some((acc_num, acc_den)) => Some((acc_num + num, acc_den + den)),
  73.                 }
  74.             })
  75.     }
  76.     .and_then(|(num, den)| if den != 0. { Some(num / den) } else { None })
  77.     .unwrap_or_else(average);
  78.  
  79.     println!("{ans}");
  80. }
  81.  
  82. #[derive(Debug, Clone, Copy)]
  83. pub enum Distance
  84. {
  85.     Euclid,
  86.     Manhattan,
  87.     Chebyshev,
  88. }
  89.  
  90. impl Distance
  91. {
  92.     fn euclid(lhs: &[f64], rhs: &[f64]) -> f64
  93.     {
  94.         assert_eq!(lhs.len(), rhs.len());
  95.         let squared: f64 = lhs.into_iter()
  96.             .zip(rhs)
  97.             .map(|(l, r)| *l - *r)
  98.             .map(|d| d * d)
  99.             .sum();
  100.         squared.sqrt()
  101.     }
  102.  
  103.     fn manhattan(lhs: &[f64], rhs: &[f64]) -> f64
  104.     {
  105.         assert_eq!(lhs.len(), rhs.len());
  106.         lhs.into_iter()
  107.             .zip(rhs)
  108.             .map(|(l, r)| *l - *r)
  109.             .map(f64::abs)
  110.             .sum()
  111.     }
  112.  
  113.     fn chebyshev(lhs: &[f64], rhs: &[f64]) -> f64
  114.     {
  115.         assert_eq!(lhs.len(), rhs.len());
  116.         lhs.into_iter()
  117.             .zip(rhs)
  118.             .map(|(l, r)| *l - *r)
  119.             .map(f64::abs)
  120.             .reduce(f64::max)
  121.             .unwrap()
  122.     }
  123.  
  124.     pub fn as_func(&self) -> fn(&[f64], &[f64]) -> f64
  125.     {
  126.         match self {
  127.             Distance::Euclid    => Self::euclid,
  128.             Distance::Manhattan => Self::manhattan,
  129.             Distance::Chebyshev => Self::chebyshev,
  130.         }
  131.     }
  132. }
  133.  
  134. impl FromStr for Distance
  135. {
  136.     type Err = String;
  137.  
  138.     fn from_str(s: &str) -> Result<Self, Self::Err>
  139.     {
  140.         match s {
  141.             "euclidean" => Ok(Distance::Euclid),
  142.             "manhattan" => Ok(Distance::Manhattan),
  143.             "chebyshev" => Ok(Distance::Chebyshev),
  144.             _           => Err(String::from(s)),
  145.         }
  146.     }
  147. }
  148.  
  149. #[derive(Debug, Clone, Copy)]
  150. pub enum Kernel
  151. {
  152.     Uniform,
  153.     Triangular,
  154.     Epanechnikov,
  155.     Quartic,
  156.     Triweight,
  157.     Tricube,
  158.     Gaussian,
  159.     Cosine,
  160.     Logistic,
  161.     Sigmoid
  162. }
  163.  
  164. impl Kernel
  165. {
  166.     fn uniform(x: f64) -> f64
  167.     { Self::guard(x).unwrap_or_else(|_| 0.5) }
  168.  
  169.     fn triangular(x: f64) -> f64
  170.     { Self::guard(x).unwrap_or_else(|x| 1. - x.abs()) }
  171.  
  172.     fn epanechnikov(x: f64) -> f64
  173.     { Self::guard(x).unwrap_or_else(|x| { 0.75 * (1. - x * x) }) }
  174.  
  175.     fn quartic(x: f64) -> f64
  176.     {
  177.         Self::guard(x)
  178.             .unwrap_or_else(|x| {
  179.                 let mul = 1. - x * x;
  180.                 (15. / 16.) * mul * mul
  181.             })
  182.     }
  183.  
  184.     fn triweight(x: f64) -> f64
  185.     {
  186.         Self::guard(x)
  187.             .unwrap_or_else(|x| {
  188.                 let mul = 1. - x * x;
  189.                 (35. / 32.) * mul * mul * mul
  190.             })
  191.     }
  192.  
  193.     fn tricube(x: f64) -> f64
  194.     {
  195.         Self::guard(x)
  196.             .unwrap_or_else(|x| {
  197.                 let x = x.abs();
  198.                 let mul = 1. - x * x * x;
  199.                 (70. / 81.) * mul * mul * mul
  200.             })
  201.     }
  202.  
  203.     fn gaussian(x: f64) -> f64
  204.     {
  205.         let e = (-0.5 * x * x).exp();
  206.         let coef = 1. / (consts::PI * 2.).sqrt();
  207.         coef * e
  208.     }
  209.  
  210.     fn cosine(x: f64) -> f64
  211.     {
  212.         Self::guard(x)
  213.             .unwrap_or_else(|x| {
  214.                 let angle = consts::FRAC_PI_2 * x;
  215.                 consts::FRAC_PI_4 * angle.cos()
  216.             })
  217.     }
  218.  
  219.     fn logistic(x: f64) -> f64
  220.     {
  221.         let den = x.exp() + (-x).exp() + 2.;
  222.         1. / den
  223.     }
  224.  
  225.     fn sigmoid(x: f64) -> f64
  226.     {
  227.         let den = x.exp() + (-x).exp();
  228.         consts::FRAC_2_PI / den
  229.     }
  230.  
  231.     fn guard(x: f64) -> Result<f64, f64>
  232.     {
  233.         if x.abs() >= 1. {
  234.             Ok(0.)
  235.         } else {
  236.             Err(x)
  237.         }
  238.     }
  239.  
  240.     fn as_func(&self) -> fn (f64) -> f64
  241.     {
  242.         match self {
  243.             Kernel::Uniform      => Self::uniform,
  244.             Kernel::Triangular   => Self::triangular,
  245.             Kernel::Epanechnikov => Self::epanechnikov,
  246.             Kernel::Quartic      => Self::quartic,
  247.             Kernel::Triweight    => Self::triweight,
  248.             Kernel::Tricube      => Self::tricube,
  249.             Kernel::Gaussian     => Self::gaussian,
  250.             Kernel::Cosine       => Self::cosine,
  251.             Kernel::Logistic     => Self::logistic,
  252.             Kernel::Sigmoid      => Self::sigmoid,
  253.         }
  254.     }
  255. }
  256.  
  257. impl FromStr for Kernel
  258. {
  259.     type Err = String;
  260.  
  261.     fn from_str(s: &str) -> Result<Self, Self::Err>
  262.     {
  263.         match s {
  264.             "uniform"      => Ok(Kernel::Uniform),
  265.             "triangular"   => Ok(Kernel::Triangular),
  266.             "epanechnikov" => Ok(Kernel::Epanechnikov),
  267.             "quartic"      => Ok(Kernel::Quartic),
  268.             "triweight"    => Ok(Kernel::Triweight),
  269.             "tricube"      => Ok(Kernel::Tricube),
  270.             "gaussian"     => Ok(Kernel::Gaussian),
  271.             "cosine"       => Ok(Kernel::Cosine),
  272.             "logistic"     => Ok(Kernel::Logistic),
  273.             "sigmoid"      => Ok(Kernel::Sigmoid),
  274.             _              => Err(String::from(s)),
  275.         }
  276.     }
  277. }
  278.  
  279. #[derive(Debug, Clone, Copy)]
  280. enum Window
  281. {
  282.     Distance(f64),
  283.     Count(usize),
  284. }
  285.  
  286. #[derive(Debug, Clone, Copy)]
  287. enum WindowProducer
  288. {
  289.     Distance,
  290.     Count,
  291. }
  292.  
  293. impl FromStr for WindowProducer
  294. {
  295.     type Err = String;
  296.  
  297.     fn from_str(s: &str) -> Result<Self, Self::Err>
  298.     {
  299.         match s {
  300.             "fixed"    => Ok(WindowProducer::Distance),
  301.             "variable" => Ok(WindowProducer::Count),
  302.             _          => Err(String::from(s)),
  303.         }
  304.     }
  305. }
  306.  
  307. impl WindowProducer
  308. {
  309.     fn window(&self, num: i32) -> Window
  310.     {
  311.         match self {
  312.             WindowProducer::Distance => Window::Distance(num as f64),
  313.             WindowProducer::Count    => Window::Count(num as usize),
  314.         }
  315.     }
  316. }
  317.  
  318. struct Scanner<R> {
  319.     reader: R,
  320.     buf_str: Vec<u8>,
  321.     buf_iter: std::str::SplitAsciiWhitespace<'static>,
  322. }
  323. impl<R: io::BufRead> Scanner<R> {
  324.    fn new(reader: R) -> Self {
  325.        Self { reader, buf_str: Vec::new(), buf_iter: "".split_ascii_whitespace() }
  326.    }
  327.    fn token<T: FromStr>(&mut self) -> T {
  328.        loop {
  329.            if let Some(token) = self.buf_iter.next() {
  330.                return token.parse().ok().expect("Failed parse");
  331.            }
  332.            self.buf_str.clear();
  333.            self.reader.read_until(b'\n', &mut self.buf_str).expect("Failed read");
  334.            self.buf_iter = unsafe {
  335.                let slice = std::str::from_utf8_unchecked(&self.buf_str);
  336.                std::mem::transmute(slice.split_ascii_whitespace())
  337.            }
  338.        }
  339.    }
  340. }
  341.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement