Permission Flags with Bits
Problem
Each user has four possible permissions: read, write, exec, admin. Store them in one small integer, one bit for each permission. Commands: grant USER PERM, revoke USER PERM, has USER PERM (print true or false), show USER (print the permissions the user has, in the order read, write, exec, admin, separated by commas; print none if the user has none). A user not seen before has no permissions.
Constraints
- 1 <= commands <= 100
- PERM is one of read, write, exec, admin
Examples
Input
grant ann read grant ann exec show ann
Output
read,exec
Solutions
One integer holds all four answers. OR sets a bit, AND with NOT clears it, and AND alone tests it. Granting a permission twice does no harm, because setting a set bit changes nothing.
/*
* Problem : Run the commands.
* Input : Command lines.
* Output : One line per answer.
* Approach: Bit flags
* Time : O(n)
* Space : O(users)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: One bit for each permission: read is bit 0, write is bit 1, exec is bit 2, admin is bit 3.
static class Permissions {
static final String[] NAMES = {"read", "write", "exec", "admin"};
private int bits = 0;
static int bitOf(String name) {
return 1 << java.util.Arrays.asList(NAMES).indexOf(name);
}
// Step 2: OR sets a bit. AND with the opposite (NOT) clears a bit. AND tests a bit.
void grant(String name) {
bits |= bitOf(name);
}
void revoke(String name) {
bits &= ~bitOf(name);
}
boolean has(String name) {
return (bits & bitOf(name)) != 0;
}
String text() {
StringBuilder sb = new StringBuilder();
for (String name : NAMES) {
if (has(name)) {
sb.append(sb.length() == 0 ? "" : ",").append(name);
}
}
return sb.length() == 0 ? "none" : sb.toString();
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
java.util.Map<String, Permissions> users = new java.util.HashMap<String, Permissions>();
java.util.List<String> out = new java.util.ArrayList<String>();
for (String line : lines) {
String[] part = line.split(" ");
Permissions user = users.computeIfAbsent(part[1], key -> new Permissions());
if (part[0].equals("grant")) {
user.grant(part[2]);
} else if (part[0].equals("revoke")) {
user.revoke(part[2]);
} else if (part[0].equals("has")) {
out.add(String.valueOf(user.has(part[2])));
} else {
out.add(user.text());
}
}
return out.toArray(new String[0]);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (2)
- What does bits &= ~mask do?
- Why is granting twice safe?