Files
HackerRank-Solutions/Java/Advanced/Java Visitor Pattern/Solution.java
T

243 lines
6.3 KiB
Java
Raw Normal View History

2017-03-05 00:26:42 -06:00
// Author: Rodney Shaghoulian
2018-07-27 16:45:56 -07:00
// Github: github.com/RodneyShag
// HackerRank: hackerrank.com/RodneyShag
2017-03-05 00:26:42 -06:00
import java.util.ArrayList;
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
import java.util.ArrayList;
import java.util.Scanner;
enum Color {
RED, GREEN
}
abstract class Tree {
private int value;
private Color color;
private int depth;
public Tree(int value, Color color, int depth) {
this.value = value;
this.color = color;
this.depth = depth;
}
public int getValue() {
return value;
}
public Color getColor() {
return color;
}
public int getDepth() {
return depth;
}
public abstract void accept(TreeVis visitor);
}
class TreeNode extends Tree {
private ArrayList<Tree> children = new ArrayList<>();
public TreeNode(int value, Color color, int depth) {
super(value, color, depth);
}
public void accept(TreeVis visitor) {
visitor.visitNode(this);
for (Tree child : children) {
child.accept(visitor);
}
}
public void addChild(Tree child) {
children.add(child);
}
}
class TreeLeaf extends Tree {
public TreeLeaf(int value, Color color, int depth) {
super(value, color, depth);
}
public void accept(TreeVis visitor) {
visitor.visitLeaf(this);
}
}
abstract class TreeVis {
public abstract int getResult();
public abstract void visitNode(TreeNode node);
public abstract void visitLeaf(TreeLeaf leaf);
}
// Useful tutorial for Visitor Pattern:
// https://www.tutorialspoint.com/design_pattern/visitor_pattern.htm
//
// I recommend skipping this problem since it's more about creating a
// tree in an obscure format than it is about Visitor patterns.
class SumInLeavesVisitor extends TreeVis {
private int result = 0;
public int getResult() {
return result;
}
public void visitNode(TreeNode node) {
// do nothing
}
public void visitLeaf(TreeLeaf leaf) {
result += leaf.getValue();
}
}
class ProductOfRedNodesVisitor extends TreeVis {
private long result = 1;
private final int M = 1000000007;
public int getResult() {
return (int) result;
}
public void visitNode(TreeNode node) {
if (node.getColor() == Color.RED) {
result = (result * node.getValue()) % M;
}
}
public void visitLeaf(TreeLeaf leaf) {
if (leaf.getColor() == Color.RED) {
result = (result * leaf.getValue()) % M;
}
}
}
class FancyVisitor extends TreeVis {
private int nonLeafEvenDepthSum = 0;
private int greenLeavesSum = 0;
public int getResult() {
return Math.abs(nonLeafEvenDepthSum - greenLeavesSum);
}
public void visitNode(TreeNode node) {
if (node.getDepth() % 2 == 0) {
nonLeafEvenDepthSum += node.getValue();
}
}
public void visitLeaf(TreeLeaf leaf) {
if (leaf.getColor() == Color.GREEN) {
greenLeavesSum += leaf.getValue();
}
}
}
public class Solution {
private static int [] values;
private static Color [] colors;
private static HashMap<Integer, HashSet<Integer>> map;
public static Tree solve() {
Scanner scan = new Scanner(System.in);
int numNodes = scan.nextInt();
2017-04-26 16:15:39 -07:00
/* Save nodes and colors */
2017-03-05 00:26:42 -06:00
values = new int[numNodes];
colors = new Color[numNodes];
map = new HashMap<>(numNodes);
for (int i = 0; i < numNodes; i++) {
values[i] = scan.nextInt();
}
for (int i = 0; i < numNodes; i++) {
colors[i] = scan.nextInt() == 0 ? Color.RED : Color.GREEN;
}
/* Save edges */
for (int i = 0; i < numNodes - 1; i++) {
int u = scan.nextInt();
int v = scan.nextInt();
/* Edges are undirected: Add 1st direction */
HashSet<Integer> uNeighbors = map.get(u);
if (uNeighbors == null) {
uNeighbors = new HashSet<>();
2017-03-24 00:02:30 -05:00
map.put(u, uNeighbors);
2017-03-05 00:26:42 -06:00
}
uNeighbors.add(v);
/* Edges are undirected: Add 2nd direction */
HashSet<Integer> vNeighbors = map.get(v);
if (vNeighbors == null) {
vNeighbors = new HashSet<>();
2017-03-24 00:02:30 -05:00
map.put(v, vNeighbors);
2017-03-05 00:26:42 -06:00
}
vNeighbors.add(u);
}
scan.close();
2017-04-26 16:15:39 -07:00
/* Handle 1-node tree */
if (numNodes == 1) {
return new TreeLeaf(values[0], colors[0], 0);
}
2017-03-05 00:26:42 -06:00
/* Create Tree */
TreeNode root = new TreeNode(values[0], colors[0], 0);
addChildren(root, 1);
return root;
}
/* Recursively adds children of a TreeNode */
private static void addChildren(TreeNode parent, Integer parentNum) {
/* Get HashSet of children and loop through them */
for (Integer treeNum : map.get(parentNum)) {
map.get(treeNum).remove(parentNum); // removes the opposite arrow direction
/* Add child */
HashSet<Integer> grandChildren = map.get(treeNum);
boolean childHasChild = (grandChildren != null && !grandChildren.isEmpty());
Tree tree;
if (childHasChild) {
tree = new TreeNode(values[treeNum - 1], colors[treeNum - 1], parent.getDepth() + 1);
} else {
tree = new TreeLeaf(values[treeNum - 1], colors[treeNum - 1], parent.getDepth() + 1);
}
parent.addChild(tree);
/* Recurse if necessary */
if (tree instanceof TreeNode) {
addChildren((TreeNode) tree, treeNum);
}
}
}
public static void main(String[] args) {
Tree root = solve();
SumInLeavesVisitor vis1 = new SumInLeavesVisitor();
ProductOfRedNodesVisitor vis2 = new ProductOfRedNodesVisitor();
FancyVisitor vis3 = new FancyVisitor();
root.accept(vis1);
root.accept(vis2);
root.accept(vis3);
int res1 = vis1.getResult();
int res2 = vis2.getResult();
int res3 = vis3.getResult();
System.out.println(res1);
System.out.println(res2);
System.out.println(res3);
}
}