Advertisement
krzysz00

Advent of code, day 18 (part b)

Dec 18th, 2017
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.94 KB | None | 0 0
  1. use std::io::{stdin, BufRead};
  2. use std::str::FromStr;
  3. use std::sync::{Arc};
  4. use std::sync::atomic::{Ordering,AtomicBool};
  5. use std::sync::mpsc::{channel,Sender,Receiver};
  6. use std::thread;
  7. use std::time::Duration;
  8.  
  9. type RegNum = u8;
  10. type RegVal = i64;
  11.  
  12. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
  13. enum RegImm {
  14.     Reg(RegNum),
  15.     Imm(RegVal),
  16. }
  17.  
  18. fn to_regnum(reg: &str) -> RegNum {
  19.     const A_BYTE: u8 = 97;
  20.     let byte = reg.as_bytes()[0];
  21.     if byte < A_BYTE || byte > A_BYTE + 26 {
  22.         panic!("Invalid register name");
  23.     }
  24.     byte - A_BYTE
  25. }
  26.  
  27. impl FromStr for RegImm {
  28.     type Err = ();
  29.  
  30.     fn from_str(input: &str) -> Result<Self, Self::Err> {
  31.         match input.parse::<RegVal>() {
  32.             Ok(n) => Ok(RegImm::Imm(n)),
  33.             Err(_) => Ok(RegImm::Reg(to_regnum(input))),
  34.         }
  35.     }
  36. }
  37.  
  38. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
  39. enum InstrType {
  40.     Snd,
  41.     Rcv,
  42.     Set(RegImm),
  43.     Add(RegImm),
  44.     Mul(RegImm),
  45.     Mod(RegImm),
  46.     Jgz(RegImm),
  47. }
  48.  
  49. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
  50. struct Instr {
  51.     arg1: RegImm,
  52.     effect: InstrType,
  53. }
  54.  
  55. impl FromStr for Instr {
  56.     type Err = ();
  57.  
  58.     fn from_str(input: &str) -> Result<Self, Self::Err> {
  59.         use InstrType::*;
  60.         type Variant1 = fn (RegImm) -> InstrType;
  61.  
  62.         let mut iter = input.split_whitespace();
  63.         let cmd = iter.next().expect("Must have a command");
  64.         let first_arg = iter.next().expect("Must have first arg").parse().expect("Valid first arg");
  65.         let second_arg = iter.next().map(|w| w.parse::<RegImm>().expect("Second arg must be valid"));
  66.         let effect = match second_arg {
  67.             Some(a2) =>
  68.                 (match cmd {
  69.                     "set" => Set as Variant1,
  70.                     "add" => Add as Variant1,
  71.                     "mul" => Mul as Variant1,
  72.                     "mod" => Mod as Variant1,
  73.                     "jgz" => Jgz as Variant1,
  74.                     _ => panic!("Unknown two-arg instruction"),
  75.                 })(a2),
  76.             None =>
  77.                 (match cmd {
  78.                     "snd" => Snd,
  79.                     "rcv" => Rcv,
  80.                     _ => panic!("Unknown one-arg instruction"),
  81.                 }),
  82.         };
  83.         Ok(Instr {arg1: first_arg, effect: effect })
  84.     }
  85. }
  86.  
  87. struct State {
  88.     regs: Vec<RegVal>,
  89.     instrs: Vec<Instr>,
  90.     pc: usize,
  91.     send_count: usize,
  92.  
  93.     recv_blocked: Arc<AtomicBool>,
  94.  
  95.     my_send: Sender<RegVal>,
  96.     my_recv: Receiver<RegVal>,
  97.     other_gone: bool,
  98. }
  99.  
  100. impl State {
  101.     pub fn new(program: Vec<Instr>, pid: RegVal,
  102.                chan_sender: Sender<RegVal>, chan_recver: Receiver<RegVal>,
  103.                recv_blocked: Arc<AtomicBool>) -> State {
  104.         let mut regs = vec![0; 26];
  105.         regs[15] = pid;
  106.         State { regs: regs,
  107.                 instrs: program,
  108.                 pc: 0, send_count: 0,
  109.                 my_send: chan_sender, my_recv: chan_recver,
  110.                 recv_blocked: recv_blocked,
  111.                 other_gone: false,
  112.         }
  113.     }
  114.  
  115.     fn get_value(&self, arg: RegImm) -> RegVal {
  116.         match arg {
  117.             RegImm::Imm(i) => i,
  118.             RegImm::Reg(r) => self.regs[r as usize]
  119.         }
  120.     }
  121.  
  122.     fn recv_if_possible(&self) -> Option<RegVal> {
  123.         loop {
  124.            match self.my_recv.recv_timeout(Duration::from_millis(100)) {
  125.                Ok(v) => {
  126.                    self.recv_blocked.store(false, Ordering::SeqCst);
  127.                    return Some(v);
  128.                }
  129.                Err(_) => if self.recv_blocked.swap(true, Ordering::SeqCst) {
  130.                    return None;
  131.                }
  132.            }
  133.         }
  134.     }
  135.  
  136.     fn step(&mut self) -> bool {
  137.         // boolean is halted
  138.         use InstrType::*;
  139.  
  140.         if self.pc >= self.instrs.len() { return false; }
  141.         let instr = self.instrs[self.pc];
  142.         let reg1_val = self.get_value(instr.arg1);
  143.         let new_reg1_val = match instr.effect {
  144.             Snd => {
  145.                 match self.my_send.send(reg1_val) {
  146.                     Ok(_) => { self.send_count += 1; },
  147.                     Err(_) => { self.other_gone = true; }
  148.                 };
  149.                 reg1_val
  150.             },
  151.             Rcv => {
  152.                 if self.other_gone { return false; }
  153.                 match self.recv_if_possible() {
  154.                     Some(v) => v,
  155.                     None => { return false; },
  156.                 }
  157.             },
  158.             Set(arg2) => self.get_value(arg2),
  159.             Add(arg2) => reg1_val + self.get_value(arg2),
  160.             Mul(arg2) => reg1_val * self.get_value(arg2),
  161.             Mod(arg2) => reg1_val % self.get_value(arg2),
  162.             Jgz(arg2) => {
  163.                 if reg1_val > 0 {
  164.                     self.pc = (self.pc as RegVal + self.get_value(arg2) - 1) as usize;
  165.                 }
  166.                 reg1_val
  167.             },
  168.         };
  169.         if let RegImm::Reg(r) = instr.arg1 {
  170.             self.regs[r as usize] = new_reg1_val;
  171.         }
  172.         self.pc += 1;
  173.         true
  174.     }
  175.  
  176.     pub fn run(mut self) -> usize {
  177.         while self.step() {};
  178.         self.send_count
  179.     }
  180. }
  181.  
  182. fn main() {
  183.     let stdin = stdin();
  184.     let handle = stdin.lock();
  185.     let program: Vec<Instr> = handle.lines()
  186.         .map(|l| l.expect("I/O error").parse().unwrap()).collect();
  187.  
  188.     let recv_blocked = Arc::new(AtomicBool::new(false));
  189.     let (send0, recv0) = channel();
  190.     let (send1, recv1) = channel();
  191.  
  192.     let core0 = State::new(program.clone(), 0, send0, recv1, recv_blocked.clone());
  193.     let core1 = State::new(program.clone(), 1, send1, recv0, recv_blocked.clone());
  194.  
  195.     let thread0 = thread::spawn(move || core0.run() );
  196.     let thread1 = thread::spawn(move || core1.run() );
  197.  
  198.     let sends0 = thread0.join().expect("Thread 0 not to crash");
  199.     let sends1 = thread1.join().expect("Thread 1 not to crash");
  200.     println!("Core 1 sent {} values (core 0 sent {})", sends1, sends0);
  201. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement