traversing a tree in a different way - java

I currently have done this so far: I tried to traverse the tree so that I can add up everything underneath a person.
Every person has int points, and an ArrayList of Friends. Imagine everyone in the tree is in a team. So the biggest team is the whole tree, but B also leads a sub team of D and E, while C leads F.
I want to calculate the biggest average of points per team. My current code tries to loop through the tree iteratively, but I have no idea how to get the sub totals of each team instead of the whole team. Do I need to do this recursively?
What I really need is a way to trasverse this tree on the basis of teams.
I would like the average points of a team with A,B,C,D,E,F and a team of B,D,E and the team with C and F.
A
/ \
B C
/ \ |
D E F
public static void main(String[] args) {
Person a = new Person(5);
Person b = new Person(3);
Person c = new Person(2);
ArrayList<Person> list1 = new ArrayList<>();
list1.add(b);
list1.add(c);
a.friends = list1;
mostPoints(a);
}
public static Employee mostPoints(Person start) {
int topFriend = 1;
for (Person person: start.friends) {
if (person.friends.size() > 1) {
topFriend++;
}
}
System.out.println(topFriend);
int total = 0;
for (Person under: start.friends) {
total = total + under.points;
}
return total / start.friends.size();
}

The simplest, but least efficient way: Traverse the tree, average each node (invoke mostPoints method), put it in an array, and take its biggest.
public class StackOverflowSolve {
private List<Integer> list = new ArrayList<>();
public int slove(Person person) {
dfs(person);
return list.stream().reduce(Integer::max).get();
}
public void dfs(Person person) {
if (person == null) {
return;
}
list.add(average(person));
if (person.friends != null && person.friends.size() > 0) {
person.friends.forEach(child -> {
dfs(child);
});
}
}
public int average(Person person) {
return sum(person) / teamSize(person);
}
public int sum(Person person) {
if (person == null) {
return 0;
}
if (person.friends == null || person.friends.size() == 0) {
return person.points;
}
int friendPonits = 0;
for (Person friend : person.friends) {
friendPonits += sum(friend);
}
return friendPonits + person.points;
}
public int teamSize(Person person) {
if (person == null) {
return 0;
}
if (person.friends == null || person.friends.size() == 0) {
return 1;
}
int friendSize = 0;
for (Person friend : person.friends) {
friendSize += teamSize(friend);
}
return friendSize + 1;
}
private static class Person {
public int points;
public List<Person> friends;
}
}

Related

Referring to an instance that refers to an instance

I am not sure if the title to this question is correct.
I have this school assignment where we have to create two classes.
In one class, we define relationships between people e.g. A knows B, and in the other class we ask questions about that, e.g. does A know B?
The first class below defines relationships and gives methods, the second class inquires about them.
I am sure that my mistake lies somewhere in the public boolean 'knowsWithDegree'. Are you able to help?
public class SocialGraph {
private HashMap<String, List<String>> map = new HashMap<String, List<String>>();
public SocialGraph() { // empty constructor
map = new HashMap<String, List<String>>();
}
public void addIndividual(String a) {
if (!map.containsKey(a)) {
map.put(a, new ArrayList<String>());
} else {
}
}
public boolean hasKnowsArrow(String a, String b) {
if (map.containsKey(a)) {
return map.get(a).contains(b);
} else {
return false;
}
}
public void addKnowsArrow(String a, String b) {
if ((!map.containsKey(a) || !map.containsKey(b)) || (hasKnowsArrow(a, b))) {
} else {
map.get(a).add(b);
}
}
public void removeKnowsArrow(String a, String b) {
if ((!map.containsKey(a) || !map.containsKey(b)) || (!hasKnowsArrow(a, b))) {
} else {
map.get(a).remove(b);
}
}
public boolean knowsWithDegree(String a, String b, int x) {
Object[] keys = map.keySet().toArray();
int y;
y = 0;
if (map.get(a).contains(b)) {
y = 1;
} else {
if ((map.get(a).contains(map.get(keys[0]).contains(b))) || (map.get(a).contains(map.get(keys[1]).contains(b))) ||
(map.get(a).contains(map.get(keys[2]).contains(b))) || (map.get(a).contains(map.get(keys[3]).contains(b)))) {
y = 2;
}
}
if (x == y) {
return true;
} else
return false;
}
}
public class SocialGraphTest {
public static void main(String[] args) {
SocialGraph socialGraph = new SocialGraph();
socialGraph.addIndividual("Anne");
socialGraph.addIndividual("Daisy");
socialGraph.addIndividual("Bob");
socialGraph.addIndividual("Charlie");
socialGraph.addKnowsArrow("Anne", "Bob");
socialGraph.addKnowsArrow("Anne", "Daisy");
socialGraph.addKnowsArrow("Bob", "Daisy");
socialGraph.addKnowsArrow("Bob", "Charlie");
System.out.println(socialGraph.hasKnowsArrow("Anne", "Bob")); //should be true
System.out.println(socialGraph.hasKnowsArrow("Anne", "Daisy"));//should be true
System.out.println(socialGraph.hasKnowsArrow("Bob", "Daisy"));//should be true
System.out.println(socialGraph.hasKnowsArrow("Bob", "Charlie"));//should be true
System.out.println(socialGraph.hasKnowsArrow("Anne", "Charlie")); //should be false
System.out.println ();
System.out.println (socialGraph.knowsWithDegree ("Anne", "Daisy", 1));
System.out.println (socialGraph.knowsWithDegree ("Anne", "Charlie", 2));
System.out.println (socialGraph.knowsWithDegree ("Anne", "Daisy", 3));
}
}
}
Here is an example using recursion:
public boolean knowsWithDegree(String a, String b, int x) {
return knowsWithDegreeRecursive(a, b, x, new HashSet<>());
}
private boolean knowsWithDegreeRecursive(String a, String b, int x, Set<String> visited) {
if (x < 1) {
// x must be at least 1
return false;
}
if (map.get(a).contains(b)) {
// If a knows b, then the number of degrees should be 1
return x == 1;
}
if (x == 1) {
// Since the degree is 1 and a does not know b, then a does not know b to the specified degree
return false;
}
// Go through each person that a knows
for (String c : map.get(a)) {
if (visited.contains(c)) {
// We've already checked this person
continue;
}
// Mark c as visited so we don't check them again
visited.add(c);
// See if this person knows b, with one fewer degree
// e.g. if we're seeing if a knows b with a degree of 2, then c should know b with a degree of 1
boolean knowsWithDegree = knowsWithDegreeRecursive(c, b, x - 1, visited);
// If c knows b with the degree minus 1, then a knows b with the specified degree
if (knowsWithDegree) {
return true;
}
}
// a does not know b to the specified degree
return false;
}
If the order of the knowsArrows doesn't matter, I would recommend using HashSet in your map over ArrayList.

Can we use java stream in the below scenario?

I have a class say Student that have a field marks of type Double. I am creating a list of Student objects. Each student object may have marks field set to null or set with same value in different student objects. I have a problem where I want to return a single student object from this list based on below conditions:
when all students have same marks then return null.
else return student that have highest marks.
I wonder if there is a better approach using java stream api to get it done. Thank you in advance.
Student class:
public class Student {
private Double marks;
public Double getMarks() {
return marks;
}
public void setMarks(Double marks) {
this.marks = marks;
}
#Override
public String toString() {
return "Student [marks=" + marks + "]";
}
public Student(Double marks) {
super();
this.marks = marks;
}
}
Using Streams, you can do it while collecting to TreeMap and verifying the lastEntry as in:
private Student highestMarkUniqueStudent(List<Student> studentList) {
if(studentList.size() == 0) return null;
if(studentList.size() == 1) return studentList.get(0);
TreeMap<Integer, List<Student>> map = new TreeMap<>(studentList.stream()
.collect(Collectors.groupingBy(Student::getMarks)));
List<Student> highestMarkStudents = map.lastEntry().getValue();
// only one highest or all same marks or more than one with highest mark
return highestMarkStudents.size() == 1 ? highestMarkStudents.get(0) : null;
}
You can do like this:
Indeed by using TreeMap you have the highest marks in the first entry. so by checking its value, you can return desire result. if all marks have the same value so the first entry has to value more than one and if you have two or more highest marks then the first entry has still more than one student object in the list.
TreeMap<Integer, List<Student>> map = list.stream()
.collect(Collectors.groupingBy(
Student::getMarks,
() -> new TreeMap<Integer, List<Student>>(Comparator.reverseOrder()),
Collectors.mapping(Function.identity(), Collectors.toList())));
Map.Entry<Integer, List<Student>> firstEntry = map.firstEntry();
if (firstEntry.getValue().size() <= 1) {
result = firstEntry.getValue().get(0);
}
You can work with streams, but you'd need a helper object which would be able to collect your data.
The work now either can be done with redution or with collection.
With reduction, you'd do
students.stream().reduce(
new Helper(),
(helper, student) -> new Helper(helper, student));
class Helper {
private Student bestStudent = null;
private boolean different = false;
public Helper() {
}
public Helper(Helper oldHelper, Student newStudent) {
if (oldHelper.bestStudent == null) {
bestStudent = newStudent;
} else if (student.getMark() > oldHelper.bestStudent.getMark()) {
different = true;
bestStudent = student;
} else if (student.getMark() < oldHelper.bestStudent.getMark()) {
different = true;
}
}
public Student getResult() {
return different ? bestStudent : null;
}
}
but that creates a new Helper object for every Student.
With collection, we'd do
students.stream().collect(Helper::new, Helper::accept, Helper::combine);
class Helper {
private Student bestStudent = null;
private boolean different = false;
public Helper() {
}
public void accept(Student newStudent) {
if (bestStudent == null) {
bestStudent = newStudent;
} else if (newStudent.getMark() > bestStudent.getMark()) {
different = true;
bestStudent = newStudent;
} else if (newStudent.getMark() < bestStudent.getMark()) {
different = true;
}
}
public void combine() (Helper other) {
if (bestStudent == null) {
bestStudent = other.bestStudent;
different = other.different;
} else if (other.bestStudent != null && other.bestStudent.getMark() > bestStudent.getMark()) {
different = true;
bestStudent = other.bestStudent;
} else if (other.bestStudent != null && other.bestStudent.getMark() < bestStudent.getMark()) {
different = true;
}
}
public Student getResult() {
return different ? bestStudent : null;
}
}
(Note: 1. Code not tested, 2. parts of the basic logic taken from another answer.)
You might not need streams. Sort the list highest mark firsts, if the first 2 are same, return null, otherwise return the first student.
students.sort(Comparator.comparing(Student::getMarks).reversed());
boolean firstTwoHaveSameMarks = students.get(0).getMarks().equals(students.get(1).getMarks());
return firstTwoHaveSameMarks ? null : students.get(0);
If 2 or more students have the same highest mark, it returns null, otherwise it returns the student.

Java: Dividing a single array by a object element value in to 2 arrays

Edit. thank you.
I have an array of 'normal' vehicles and 'large' vehicles. I have an assignment requiring me to divide them up to contribute to a far larger app.
One array for the large vehicles, one for the normal vehicles containing all the info for each element. ArrayLists are not permitted as my instructor is teaching us fundamentals.
Sample of the array
27723 4/09/61 large 7337
28507 22-02-1983 large 7055
28558 1/05/70 normal 3518
//On button press
//recieve single item from array from main and test it
//array in main will be looped for all elements.
public String loadVehicle(Vehicle v) {
String res = Constants.OK;
boolean normBool = false;
boolean largeBool = false;
//if both arrays are full , stop the method call in the main form
if (normBool && largeBool){return Constants.ERROR;}
//if vehicle size is normal, fill the normal veh array
if(v.getSize().equals(Constants.NORMAL_SIZE))
{
for(int i = 0; i<normalVehicles.length; i++)
{
//if norm veh array element is null, add the appropriate value to it
if(normalVehicles[i] == null){normalVehicles[i] = v;}
else{normBool = true;}
}
}
//if veh size is large put it in the large veh array
else if(v.getSize().equals(Constants.LARGE_SIZE))
{
for(int iL = 0; iL<largeVehicles.length; iL++)
{
if(largeVehicles[iL] == null){largeVehicles[iL] = v;}
else{largeBool = true;}
}
}
return res;
}//end method
Seems you cannot use builtin LinkedList class too, then do this:
Add the following code in your Vehicle class:
class Vehicle(){
//YOUR OTHER PIECES OF CODES ...
private static Vehicle firstLargeVehicle;
private Vehicle nextLargeVehicle;
private int index;
public void setIndex(int index){
this.index = index;
if(index == 0) Vehicle.firstLargeVehicle = this;
}
public int getIndex(){
return index;
}
public void setNextLargeVehicle(Vehicle nextLargeVehicle){
this.nextLargeVehicle = nextLargeVehicle;
}
public Vehicle getNextLargeVehicle(){
return nextLargeVehicle;
}
public addLargeVehicle(Vehicle newVehicle){
this.nextLargeVehicle = newVehicle;
newVehicle.setIndex(index + 1);
}
public getListSize(){
Vehicle lastOne = this;
while (lastOne.getNextLargeVehicle() != null){
lastOne = lastOne.getNextLargeVehicle();
}
return lastOne.getIndex() + 1;
}
public static Vehicle[] largeVehiclesToArray(){
Vehicle[] result = new Vehicle[firstLargeVehicle.getListSize()]();
Vehicle pointer = firstLargeVehicle;
for (int counter = 0; pointer != null; counter ++){
result[counter] = pointer;
pointer = pointer.getNextLargeVehicle();
}
return result;
}
}
And in your main loop, do something like the following code:
Vehicle vehicle = null;
for(Vehicle newVehicle : allVehicles) {
if (newVehicle.isLarge()){
if (vehicle == null) {
vehicle = newVehicle;
vehicle.setIndex(0);
}else{
vehicle.addLargeVehicle(newVehicle));
}
}
}
Vehicle[] largeVehicles = Vehicle.largeVehiclesToArray();
And the same story goes for normal vehicles.
Any question ?
You can write your loops like this:
for(int i = 0; i < normalVehicles.length; i++)
{
if(normalVehicles[i] == null)
{
normalVehicles[i] = v;
break;
}
}
// if last slot isn't null then it's full
normBool = normalVehicles[normalVehicles.length-1] != null;

How to check if all employee in hashmap have name?

I have a HashMap of employees:
Employee{
String name;
String id;
String Salary;
}
Map<String,Employee> emps = new HashMap<>();
emps.put("1",employee1);
emps.put("2",employee2);
emps.put("3",employee3);
I want have following scenarios:
All employees have name ==> Pass
All employess dont have name(name=null) ==> Pass
3. Other cases must throw an exception.
Example: employee2 does not have a name, but employee1 and employee3 do.
How can I write such scenario?
You can use Streams to filter employees that have or don't have a name, count them and compare the result to the size of the list.
long count = emps.values()
.stream()
.filter(employee -> employee.getName() != null)
.count();
/**
* count == 0 => All employess dont have name
* count == size => All employees have name
*/
return count == 0 || count == employees.size();
You can iterate over the values of the map by calling (map.values()) ,which give you Collection .Then apply your logic.
Collection<Employee> values = emps.values();
int count = 0;
for (Employee employee : values) {
if(null != employee.name){
count ++;
}
}
return count == 0 || count == emps.size();
1) Get list of employees
Collection<Employee> employees = employeesMap.values();
testEmployees(employees);
The program will stop with an exception if employees do not pass the test. This is how to test them
public void testEmployees(List<Employee> employees) {
int nullNameEmployeeCount = 0;
int size = employes.size();
for (Employee employee : employees) {
if (employee.getName() == null) {
nullNameEmployeeCount++;
}
}
if (nullNameEmployeeCount == 0 || nullNameEmployeeCount == size) {
System.out.println("All employees name are not nulls or nulls");
} else {
throw new EmployeesNotPassException();
}
}
And
public class EmployeesNotPassException extends RuntimeException {}
public class Pass {
public static void main(String[] args) {
List<Employee> list = new ArrayList<>();
boolean res = true;
for (Employee e : list) {
res = res && isPass(e);
}
System.out.println(res);
}
public static boolean isPass(Employee employee) {
if (employee == null)
return false;
if (employee.getName() == null)
return true;
if (employee.getName() != null && !StringUtils.isEmpty(employee.getName())) {
return true;
}
return false;
}
}

Correct heap implementation in a priority queue

My issue is more semantic than functional, As the code does seem to implement the deQueue and enQueue functions correctly.
The reheapDown and reheapUp functions are being used incorrectly, And i believe the issue lies in my heap function
package priqueue;
public class Hosheap{
private Patient[] elements;
private int numElements;
public Hosheap(int maxSize)
{
elements= new Patient[maxSize];
numElements=maxSize;
}
public void ReheapDown(int root,int bottom)
{
int maxChild;
int rightChild;
int leftChild;
leftChild=root*2+1;
rightChild=root*2+2;
if (leftChild<=bottom)
{
if(leftChild==bottom)
maxChild=leftChild;
else
{
if(elements[leftChild].getPriority() <= elements[rightChild].getPriority())
maxChild=rightChild;
else
maxChild=leftChild;
}
if(elements[root].getPriority()<elements[maxChild].getPriority())
{
Swap(root,maxChild);
ReheapDown(maxChild,bottom);
}
}
}
public void ReheapUp(int root,int bottom)
{
int parent;
if(bottom>root)
{
parent=(bottom-1)/2;
if(elements[parent].getPriority()<elements[bottom].getPriority())
{
Swap(parent,bottom);
ReheapUp(root,parent);
}
}
}
public void Swap(int Pos1, int Pos2)
{
Patient temp;
temp = elements[Pos1];
elements[Pos1]=elements[Pos2];
elements[Pos2]=temp;
}
public Patient getElement(int e)
{
return elements[e];
}
public void setElement(Patient p, int n)
{
elements[n]=p;
}
}
The idea is to rearrange a simple priority queue system so when a patient object is removed, ReheapUp or down correctly rearranges the queue, Which the code does not accomplish. Should i also include the priority queue code, Or is this already too lengthy?
I am using NetBeans IDE 6.0.1, If that helps.
Depending on your usage requirements, the answer relating to TreeSets will most probably do what you want.
However if you really need a queue, as opposed to a sorted collection, then the inbuilt PriorityQueue may be of use.
Not exactly answering your question, but with Java you may want to look into the built-in Collection classes. You can get priority queue behavior but using a TreeSet (a type of ordered-set) and implementing a custom Comparator for Patient instances. Depending what you're trying to achieve, this may be preferable. It would look something like this:
In Patient.java ...
class Patient implements Comparator {
...
public int compareTo(Patient other) {
return getPriority() > other.getPriority() ? 1 : 0;
}
Then in the place you want to use the queue
Set<Patient> queue = new TreeSet<Patient>();
queue.add(p1);
queue.add(p2);
//traverse in order of priority
for(Patient p : queue) {
doStuff();
}
Here is a simple implementation of a PriorityHeap. I coded it up pretty quick so it may have some flaws but I have implemented the pushUp() and pushDown() logic.
import java.util.Random;
public class Heap {
private Double[] data;
private int lastItem;
public Heap(int initialSize) {
// to simplify child/parent math leave the first index empty
// and use a lastItem that gives us the size
data = new Double[initialSize];
lastItem = 0;
}
public void insert(Double d) {
// double size if needed
// should have a matching shrink but this is example code
if (lastItem + 1 >= data.length) {
Double[] doubled = new Double[data.length * 2];
System.arraycopy(data, 0, doubled, 0, data.length);
data = doubled;
}
data[lastItem + 1] = d;
lastItem++;
pushUp(lastItem);
}
public void pushDown(int index) {
if (lastItem > 1) {
int leftChildIndex = index * 2;
int rightChildIndex = leftChildIndex + 1;
// assume that neither child will dominate (in priority)
// the item at index
int indexToPromote = index;
// there may not be a left child
if (leftChildIndex <= lastItem) {
Double leftChild = data[leftChildIndex];
Double tmp = data[index];
if (tmp.compareTo(leftChild) < 0) {
indexToPromote = leftChildIndex;
}
// there might not be a right child
if (rightChildIndex <= lastItem) {
Double rightChild = data[rightChildIndex];
tmp = data[indexToPromote];
if (tmp.compareTo(rightChild) < 0) {
indexToPromote = rightChildIndex;
}
}
}
// did either child dominate the item at index
// if so swap and push down again
if (indexToPromote != index) {
swap(index, indexToPromote);
pushDown(indexToPromote);
}
}
}
public void pushUp(int index) {
if (index > 1) {
// equivalent to floor((double)index/2.0d);
// if item at index is greater than its parent
// push the item up to until if finds a home
int parentIndex = index >>> 1;
Double parent = data[parentIndex];
Double item = data[index];
if (item.compareTo(parent) > 0) {
swap(parentIndex, index);
pushUp(parentIndex);
}
}
}
public Double removeTop() {
// assume size is zero then examine other cases
Double top = null;
if (lastItem > 1) {
// save the top item and take the bottom item and place it
// at the top the push the new top item down until it
// finds a home
top = data[1];
Double bottom = data[lastItem];
lastItem--;
data[1] = bottom;
pushDown(1);
} else if (lastItem == 1) {
top = data[1];
lastItem--;
}
return top;
}
public int size() {
return lastItem;
}
private void swap(int index1, int index2) {
Double temp = data[index1];
data[index1] = data[index2];
data[index2] = temp;
}
public static void main(String[] args) {
Heap heap = new Heap(4);
Random r = new Random();
for (int i = 0; i < 100000; i++) {
Double d = Double.valueOf(r.nextDouble() * 100.0d);
heap.insert(d);
}
double max = Double.MAX_VALUE;
while (heap.size() > 0) {
Double top = heap.removeTop();
if (top.doubleValue() > max) {
System.out.println("bad ordering...");
}
max = top.doubleValue();
System.out.println(max);
}
System.out.println("done...");
}
}

Categories

Resources