Day 9, finally.
This commit is contained in:
1
inputs/day9
Normal file
1
inputs/day9
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,432,1027,1101,439,0,1026,1101,0,36,1010,1101,0,34,1018,1102,278,1,1029,1101,0,24,1002,1102,1,20,1016,1102,1,31,1011,1102,319,1,1024,1102,21,1,1012,1102,1,763,1022,1102,1,25,1007,1101,0,287,1028,1102,32,1,1008,1101,0,22,1013,1102,38,1,1001,1101,0,314,1025,1102,35,1,1009,1102,1,23,1015,1102,39,1,1019,1102,27,1,1000,1102,1,37,1003,1102,1,28,1017,1101,0,0,1020,1101,0,29,1004,1102,1,30,1006,1102,1,756,1023,1102,1,33,1005,1101,0,1,1021,1102,26,1,1014,109,13,2108,28,-7,63,1005,63,201,1001,64,1,64,1105,1,203,4,187,1002,64,2,64,109,8,21107,40,41,-3,1005,1018,225,4,209,1001,64,1,64,1105,1,225,1002,64,2,64,109,-3,1206,2,239,4,231,1105,1,243,1001,64,1,64,1002,64,2,64,109,-21,1201,6,0,63,1008,63,35,63,1005,63,267,1001,64,1,64,1105,1,269,4,249,1002,64,2,64,109,35,2106,0,-4,4,275,1001,64,1,64,1105,1,287,1002,64,2,64,109,-11,1205,-1,303,1001,64,1,64,1105,1,305,4,293,1002,64,2,64,109,8,2105,1,-5,4,311,1106,0,323,1001,64,1,64,1002,64,2,64,109,-7,21108,41,38,-6,1005,1016,339,1106,0,345,4,329,1001,64,1,64,1002,64,2,64,109,2,21102,42,1,-8,1008,1016,45,63,1005,63,369,1001,64,1,64,1105,1,371,4,351,1002,64,2,64,109,-14,21101,43,0,1,1008,1011,43,63,1005,63,397,4,377,1001,64,1,64,1106,0,397,1002,64,2,64,109,-8,21101,44,0,8,1008,1010,47,63,1005,63,417,1105,1,423,4,403,1001,64,1,64,1002,64,2,64,109,25,2106,0,0,1001,64,1,64,1105,1,441,4,429,1002,64,2,64,109,-20,2107,37,-6,63,1005,63,463,4,447,1001,64,1,64,1106,0,463,1002,64,2,64,109,8,2108,25,-8,63,1005,63,485,4,469,1001,64,1,64,1106,0,485,1002,64,2,64,109,-1,21107,45,44,-1,1005,1013,505,1001,64,1,64,1106,0,507,4,491,1002,64,2,64,109,-11,1207,-1,25,63,1005,63,529,4,513,1001,64,1,64,1106,0,529,1002,64,2,64,109,23,1206,-5,545,1001,64,1,64,1106,0,547,4,535,1002,64,2,64,109,-31,2102,1,5,63,1008,63,27,63,1005,63,569,4,553,1106,0,573,1001,64,1,64,1002,64,2,64,109,27,21102,46,1,-9,1008,1013,46,63,1005,63,595,4,579,1105,1,599,1001,64,1,64,1002,64,2,64,109,-26,2101,0,6,63,1008,63,24,63,1005,63,625,4,605,1001,64,1,64,1106,0,625,1002,64,2,64,109,5,1208,0,37,63,1005,63,645,1001,64,1,64,1105,1,647,4,631,1002,64,2,64,109,7,2102,1,-3,63,1008,63,31,63,1005,63,671,1001,64,1,64,1105,1,673,4,653,1002,64,2,64,109,2,1202,-5,1,63,1008,63,33,63,1005,63,699,4,679,1001,64,1,64,1105,1,699,1002,64,2,64,109,-4,2101,0,-3,63,1008,63,35,63,1005,63,719,1105,1,725,4,705,1001,64,1,64,1002,64,2,64,109,-5,1207,4,32,63,1005,63,741,1106,0,747,4,731,1001,64,1,64,1002,64,2,64,109,29,2105,1,-7,1001,64,1,64,1106,0,765,4,753,1002,64,2,64,109,-26,2107,36,5,63,1005,63,781,1105,1,787,4,771,1001,64,1,64,1002,64,2,64,109,10,1201,-6,0,63,1008,63,32,63,1005,63,809,4,793,1106,0,813,1001,64,1,64,1002,64,2,64,109,3,21108,47,47,-5,1005,1012,835,4,819,1001,64,1,64,1106,0,835,1002,64,2,64,109,-24,1202,9,1,63,1008,63,25,63,1005,63,859,1001,64,1,64,1106,0,861,4,841,1002,64,2,64,109,19,1205,9,875,4,867,1106,0,879,1001,64,1,64,1002,64,2,64,109,-3,1208,-1,32,63,1005,63,897,4,885,1106,0,901,1001,64,1,64,4,64,99,21102,27,1,1,21101,915,0,0,1105,1,922,21201,1,60043,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,22102,1,-2,-2,109,-3,2105,1,0
|
||||||
143
src/machine.rs
143
src/machine.rs
@@ -5,23 +5,40 @@ use std::ops::Range;
|
|||||||
use std::str;
|
use std::str;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
const ADD: i64 = 1;
|
const ADD: i64 = 1;
|
||||||
const MULTIPLY: i64 = 2;
|
const MULTIPLY: i64 = 2;
|
||||||
const INPUT: i64 = 3;
|
const INPUT: i64 = 3;
|
||||||
const OUTPUT: i64 = 4;
|
const OUTPUT: i64 = 4;
|
||||||
const JMPIF: i64 = 5;
|
const JMPIF: i64 = 5;
|
||||||
const JMPNIF: i64 = 6;
|
const JMPNIF: i64 = 6;
|
||||||
const LESS_THAN: i64 = 7;
|
const LESS_THAN: i64 = 7;
|
||||||
const EQUALS: i64 = 8;
|
const EQUALS: i64 = 8;
|
||||||
const HALT: i64 = 99;
|
const ADJUST_BASE: i64 = 9;
|
||||||
|
const HALT: i64 = 99;
|
||||||
|
|
||||||
const MODE_POSITION: i64 = 0;
|
#[derive(Debug,PartialEq)]
|
||||||
const MODE_IMMEDIATE: i64 = 1;
|
enum Mode {
|
||||||
|
Position,
|
||||||
|
Immediate,
|
||||||
|
Relative,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for Mode {
|
||||||
|
fn from(x: i64) -> Mode {
|
||||||
|
match x {
|
||||||
|
0 => Mode::Position,
|
||||||
|
1 => Mode::Immediate,
|
||||||
|
2 => Mode::Relative,
|
||||||
|
_ => panic!("Unknown mode value: {}", x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Computer {
|
pub struct Computer {
|
||||||
memory: Vec<i64>,
|
memory: Vec<i64>,
|
||||||
position: usize,
|
position: usize,
|
||||||
|
relative_base: i64,
|
||||||
done: bool
|
done: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +60,7 @@ impl Computer {
|
|||||||
memory.push(next);
|
memory.push(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
Computer{ memory, position, done: false }
|
Computer{ memory, position, relative_base: 0, done: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(&self) {
|
pub fn show(&self) {
|
||||||
@@ -53,34 +70,56 @@ impl Computer {
|
|||||||
println!("POSITION: {}", self.position);
|
println!("POSITION: {}", self.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self, idx: usize) -> i64 {
|
pub fn read(&mut self, idx: usize) -> i64 {
|
||||||
|
if idx >= self.memory.len() {
|
||||||
|
self.memory.resize(idx + 1, 0);
|
||||||
|
}
|
||||||
self.memory[idx]
|
self.memory[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_arg(&self, mode: i64, val: usize) -> i64 {
|
pub fn read_arg(&mut self, mode: Mode, val: usize) -> i64 {
|
||||||
match mode {
|
match mode {
|
||||||
MODE_POSITION => self.read(self.read(val) as usize),
|
Mode::Position => {
|
||||||
MODE_IMMEDIATE => self.read(val),
|
let ptr = self.read(val) as usize;
|
||||||
_ => panic!("Unknown argument mode: {}", mode)
|
self.read(ptr)
|
||||||
|
}
|
||||||
|
Mode::Immediate => self.read(val),
|
||||||
|
Mode::Relative => {
|
||||||
|
let ptr = self.read(val) + self.relative_base;
|
||||||
|
self.read(ptr as usize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_dest(&mut self, mode: Mode, val: usize) -> usize {
|
||||||
|
assert_ne!(mode, Mode::Immediate);
|
||||||
|
let mut base = self.read(val);
|
||||||
|
if mode == Mode::Relative {
|
||||||
|
base += self.relative_base;
|
||||||
|
}
|
||||||
|
assert!(base >= 0);
|
||||||
|
base as usize
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write(&mut self, idx: usize, val: i64) {
|
pub fn write(&mut self, idx: usize, val: i64) {
|
||||||
|
if idx >= self.memory.len() {
|
||||||
|
self.memory.resize(idx + 1, 0);
|
||||||
|
}
|
||||||
self.memory[idx] = val;
|
self.memory[idx] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self, input: &mut Receiver<i64>, output: &mut Sender<i64>) {
|
fn step(&mut self, input: &mut Receiver<i64>, output: &mut Sender<i64>) {
|
||||||
let next_instruction = self.read(self.position);
|
let next_instruction = self.read(self.position);
|
||||||
let opcode = next_instruction % 100;
|
let opcode = next_instruction % 100;
|
||||||
let arg1mode = (next_instruction / 100) % 10;
|
let arg1mode = Mode::from((next_instruction / 100) % 10);
|
||||||
let arg2mode = (next_instruction / 1000) % 10;
|
let arg2mode = Mode::from((next_instruction / 1000) % 10);
|
||||||
let _arg3mode = (next_instruction / 10000) % 10;
|
let arg3mode = Mode::from((next_instruction / 10000) % 10);
|
||||||
|
|
||||||
match opcode {
|
match opcode {
|
||||||
ADD => {
|
ADD => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
let dest = self.read(self.position + 3) as usize;
|
let dest = self.read_dest(arg3mode, self.position + 3) as usize;
|
||||||
|
|
||||||
self.write(dest, arg1 + arg2);
|
self.write(dest, arg1 + arg2);
|
||||||
self.position += 4;
|
self.position += 4;
|
||||||
@@ -88,25 +127,28 @@ impl Computer {
|
|||||||
MULTIPLY => {
|
MULTIPLY => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
let dest = self.read(self.position + 3) as usize;
|
let dest = self.read_dest(arg3mode, self.position + 3) as usize;
|
||||||
|
|
||||||
self.write(dest, arg1 * arg2);
|
self.write(dest, arg1 * arg2);
|
||||||
self.position += 4;
|
self.position += 4;
|
||||||
}
|
}
|
||||||
INPUT => {
|
INPUT => {
|
||||||
let dest = self.read(self.position + 1) as usize;
|
let dest = self.read_dest(arg1mode, self.position + 1) as usize;
|
||||||
let val = input.recv().expect("Failed to get input!");
|
let val = input.recv().expect("Failed to get input!");
|
||||||
|
|
||||||
self.write(dest, val);
|
self.write(dest, val);
|
||||||
self.position += 2;
|
self.position += 2;
|
||||||
}
|
}
|
||||||
OUTPUT => {
|
OUTPUT => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
|
|
||||||
output.send(arg1);
|
output.send(arg1);
|
||||||
self.position += 2;
|
self.position += 2;
|
||||||
}
|
}
|
||||||
JMPIF => {
|
JMPIF => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
|
|
||||||
if arg1 != 0 {
|
if arg1 != 0 {
|
||||||
self.position = arg2 as usize;
|
self.position = arg2 as usize;
|
||||||
} else {
|
} else {
|
||||||
@@ -116,6 +158,7 @@ impl Computer {
|
|||||||
JMPNIF => {
|
JMPNIF => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
|
|
||||||
if arg1 == 0 {
|
if arg1 == 0 {
|
||||||
self.position = arg2 as usize;
|
self.position = arg2 as usize;
|
||||||
} else {
|
} else {
|
||||||
@@ -125,7 +168,7 @@ impl Computer {
|
|||||||
LESS_THAN => {
|
LESS_THAN => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
let dest = self.read(self.position + 3) as usize;
|
let dest = self.read_dest(arg3mode, self.position + 3) as usize;
|
||||||
|
|
||||||
self.write(dest, if arg1 < arg2 { 1 } else { 0 });
|
self.write(dest, if arg1 < arg2 { 1 } else { 0 });
|
||||||
self.position += 4;
|
self.position += 4;
|
||||||
@@ -133,11 +176,17 @@ impl Computer {
|
|||||||
EQUALS => {
|
EQUALS => {
|
||||||
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
let arg2 = self.read_arg(arg2mode, self.position + 2);
|
||||||
let dest = self.read(self.position + 3) as usize;
|
let dest = self.read_dest(arg3mode,self.position + 3) as usize;
|
||||||
|
|
||||||
self.write(dest, if arg1 == arg2 { 1 } else { 0 });
|
self.write(dest, if arg1 == arg2 { 1 } else { 0 });
|
||||||
self.position += 4;
|
self.position += 4;
|
||||||
}
|
}
|
||||||
|
ADJUST_BASE => {
|
||||||
|
let arg1 = self.read_arg(arg1mode, self.position + 1);
|
||||||
|
|
||||||
|
self.relative_base += arg1;
|
||||||
|
self.position += 2;
|
||||||
|
}
|
||||||
HALT => {
|
HALT => {
|
||||||
output.conclude();
|
output.conclude();
|
||||||
self.done = true;
|
self.done = true;
|
||||||
@@ -244,13 +293,18 @@ impl Computer {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn run_example(computer: Vec<i64>, inputs: Vec<i64>, targets: Vec<i64>) {
|
fn run_example(computer: Vec<i64>, inputs: Vec<i64>, targets: Vec<i64>) {
|
||||||
let mut day5a = Computer{ memory: computer, position: 0, done: false };
|
let day5a = Computer{ memory: computer, position: 0, relative_base: 0, done: false };
|
||||||
|
run_computer(day5a, inputs, targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn run_computer(mut computer: Computer, inputs: Vec<i64>, targets: Vec<i64>) {
|
||||||
let ( mysend, mut corecv) = channel();
|
let ( mysend, mut corecv) = channel();
|
||||||
let (mut cosend, myrecv) = channel();
|
let (mut cosend, myrecv) = channel();
|
||||||
for i in inputs.iter() {
|
for i in inputs.iter() {
|
||||||
mysend.send(*i);
|
mysend.send(*i);
|
||||||
}
|
}
|
||||||
day5a.run(&mut corecv, &mut cosend);
|
computer.run(&mut corecv, &mut cosend);
|
||||||
let outputs: Vec<i64> = myrecv.collect();
|
let outputs: Vec<i64> = myrecv.collect();
|
||||||
assert_eq!(targets, outputs);
|
assert_eq!(targets, outputs);
|
||||||
}
|
}
|
||||||
@@ -259,35 +313,35 @@ fn run_example(computer: Vec<i64>, inputs: Vec<i64>, targets: Vec<i64>) {
|
|||||||
fn test_examples() {
|
fn test_examples() {
|
||||||
let (mut deadsend, mut deadrecv) = channel();
|
let (mut deadsend, mut deadrecv) = channel();
|
||||||
|
|
||||||
let mut example1 = Computer{ memory: vec![1,0,0,0,99], position: 0, done: false };
|
let mut example1 = Computer::from_string("1,0,0,0,99", 0);
|
||||||
let answer1 = Computer{ memory: vec![2,0,0,0,99], position: 4, done: false };
|
let answer1 = Computer{ memory: vec![2,0,0,0,99], position: 4, relative_base: 0, done: false };
|
||||||
example1.step(&mut deadrecv, &mut deadsend);
|
example1.step(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example1, answer1);
|
assert_eq!(example1, answer1);
|
||||||
|
|
||||||
let mut example2 = Computer{ memory: vec![2,3,0,3,99], position: 0, done: false };
|
let mut example2 = Computer::from_string("2,3,0,3,99", 0);
|
||||||
let answer2 = Computer{ memory: vec![2,3,0,6,99], position: 4, done: false };
|
let answer2 = Computer{ memory: vec![2,3,0,6,99], position: 4, relative_base: 0, done: false };
|
||||||
example2.step(&mut deadrecv, &mut deadsend);
|
example2.step(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example2, answer2);
|
assert_eq!(example2, answer2);
|
||||||
|
|
||||||
let mut example3 = Computer{ memory: vec![2,4,4,5,99,0], position: 0, done: false };
|
let mut example3 = Computer::from_string("2,4,4,5,99,0", 0);
|
||||||
let answer3 = Computer{ memory: vec![2,4,4,5,99,9801], position: 4, done: false };
|
let answer3 = Computer{ memory: vec![2,4,4,5,99,9801], position: 4, relative_base: 0, done: false };
|
||||||
example3.step(&mut deadrecv, &mut deadsend);
|
example3.step(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example3, answer3);
|
assert_eq!(example3, answer3);
|
||||||
|
|
||||||
let mut example4 = Computer{ memory: vec![1,1,1,4,99,5,6,0,99], position: 0, done: false };
|
let mut example4 = Computer::from_string("1,1,1,4,99,5,6,0,99", 0);
|
||||||
let answer4 = Computer{ memory: vec![30,1,1,4,2,5,6,0,99], position: 8, done: true };
|
let answer4 = Computer{ memory: vec![30,1,1,4,2,5,6,0,99], position: 8, relative_base: 0, done: true };
|
||||||
example4.run(&mut deadrecv, &mut deadsend);
|
example4.run(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example4, answer4);
|
assert_eq!(example4, answer4);
|
||||||
assert!(example4.halted());
|
assert!(example4.halted());
|
||||||
|
|
||||||
let mut example5 = Computer{ memory: vec![1002,4,3,4,33], position: 0, done: false };
|
let mut example5 = Computer::from_string("1002,4,3,4,33", 0);
|
||||||
let answer5 = Computer{ memory: vec![1002,4,3,4,99], position: 4, done: true };
|
let answer5 = Computer{ memory: vec![1002,4,3,4,99], position: 4, relative_base: 0, done: true };
|
||||||
example5.run(&mut deadrecv, &mut deadsend);
|
example5.run(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example5, answer5);
|
assert_eq!(example5, answer5);
|
||||||
assert!(example5.halted());
|
assert!(example5.halted());
|
||||||
|
|
||||||
let mut example6 = Computer::from_string("1101,100,-1,4,0", 0);
|
let mut example6 = Computer::from_string("1101,100,-1,4,0", 0);
|
||||||
let answer6 = Computer{ memory: vec![1101,100,-1,4,99], position: 4, done: true };
|
let answer6 = Computer{ memory: vec![1101,100,-1,4,99], position: 4, relative_base: 0, done: true };
|
||||||
example6.run(&mut deadrecv, &mut deadsend);
|
example6.run(&mut deadrecv, &mut deadsend);
|
||||||
assert_eq!(example6, answer6);
|
assert_eq!(example6, answer6);
|
||||||
assert!(example6.halted());
|
assert!(example6.halted());
|
||||||
@@ -353,4 +407,17 @@ fn test_examples() {
|
|||||||
let (example7fs, example7ft) = example7f.find_best_signal(5..10, |x| example7f.amplifier(x));
|
let (example7fs, example7ft) = example7f.find_best_signal(5..10, |x| example7f.amplifier(x));
|
||||||
assert_eq!(18216, example7fs);
|
assert_eq!(18216, example7fs);
|
||||||
assert_eq!(vec![9,7,8,5,6], example7ft);
|
assert_eq!(vec![9,7,8,5,6], example7ft);
|
||||||
|
|
||||||
|
run_example(vec![109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99],
|
||||||
|
vec![],
|
||||||
|
vec![109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99]);
|
||||||
|
run_example(vec![1102,34915192,34915192,7,4,7,99,0],
|
||||||
|
vec![],
|
||||||
|
vec![1219070632396864]);
|
||||||
|
run_example(vec![104,1125899906842624,99],
|
||||||
|
vec![],
|
||||||
|
vec![1125899906842624]);
|
||||||
|
|
||||||
|
run_computer(Computer::load("inputs/day9", 0), vec![1], vec![3063082071]);
|
||||||
|
run_computer(Computer::load("inputs/day9", 0), vec![2], vec![81348]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user