朋友不知道哪里搞来的那么久之前的原题(纯英文),我本来是一个不太在意Java位运算内容的人,但是做完这一题后对Java无符号位运算的实现有了比较深的理解,所以想写个博客记录一下。本题的part2没什么价值,就不说了。
题目翻译
以下为我对问题的翻译(只翻译关键部分):
现有一组导线和一组位运算门。每条导线都有一个标识符(一些小写字母),可以携带16位信号(0到65535之间的数字)。通过门、另一根导线或某个特定值将信号提供给每条导线。每条导线只能从一个源获得信号,但可以将其信号提供给多个端。位运算门不提供信号,直到它的所有输入都有信号为止。
例如:
123 -> x 表示信号123被提供给导线x。
x AND y -> z 表示将导线 x 和 y 连接到与门,然后将其输出连接到导线z。
p LSHIFT 2 -> q 意味着导线 p 的值左移2,然后提供给导线q。
NOT e -> f 表示将来自导线 e 的值的位补码提供给导线 f。
其他可能的门包括OR(按位OR)和RSHIFT(右移)。
比方说,这里有一个简单的电路:
123 -> x
456 -> y
x AND y -> d
x OR y -> e
x LSHIFT 2 -> f
y RSHIFT 2 -> g
NOT x -> h
NOT y -> i
运行后,这些是导线上的信号数值:
d: 72
e: 507
f: 492
g: 114
h: 65412
i: 65079
x: 123
y: 456
这为你的输入,那么最后导线 a 的信号值是多少呢?
代码
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
/**
* @author mango3y
* @version 1.0
*/
public class MyAnswer {
//保存结果 电线 : 数值
static HashMap<String, Integer> resultMap = new HashMap<>();
/*
我们用Integer,也就是int保存信号值,题目中强调“16位信号”,int为32位,使用它从空间上看是可行的。
但要注意本题有取反和左移操作。
对于int,我们真正要使用的是后16位,而对于前16位我们采用“清理”的操作,即对应方法clean()。
因为本质上我们此题是“无符号位运算”,所以对于取反运算,int中前16位被置为1了,我们得用 int & 0xffff 将前十六位重新置零。
而对于左移操作,本质上是舍弃了一些有效位,可能会有后16位的1移到前16位,此时也同样要clean()。
*/
//用来将文件的每一行保存,方便遍历、删除
static List<String> list = new ArrayList<>();
public static void main(String[] args) throws FileNotFoundException {
//将文件内容逐行保存到list中
Scanner s = new Scanner(new File("file.txt"));
while (s.hasNextLine(