Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions code/후/src/main/java/ch4/memory1/Container.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ch4.memory1;

import java.util.*;

public class Container {

private List<Container> group;
private float amount;

public float getAmount() {
return amount;
}

public void connectTo(Container other) {
if (group == null) {
group = new ArrayList<>();
group.add(this);
}
if (other.group == null) {
other.group = new ArrayList<>();
other.group.add(other);
}
if (group == other.group) {
return;
}

int size1 = group.size();
int size2 = other.group.size();
float total1 = amount * size1;
float total2 = other.amount * size2;
float newAmount = (total1 + total2) / (size1 + size2);

group.addAll(other.group);
for (Container c : other.group) {
c.group = group;
}
for (Container c : group) {
c.amount = newAmount;
}
}

public void addWater(float amount) {
if (group == null) {
this.amount += amount;
return;
}
float amountPerContainer = amount / group.size();
for (Container c : group) {
c.amount += amountPerContainer;
}
}
}
56 changes: 56 additions & 0 deletions code/후/src/main/java/ch4/memory2/Container.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ch4.memory2;

import java.util.*;

public class Container {

private Container[] group;
private float amount;

public float getAmount() {
return amount;
}

public void connectTo(Container other) {
if (group == null) {
group = new Container[]{this};
}
if (other.group == null) {
other.group = new Container[]{other};
}
if (group == other.group) {
return;
}

int size1 = group.length;
int size2 = other.group.length;
float total1 = amount * size1;
float total2 = other.amount * size2;
float newAmount = (total1 + total2) / (size1 + size2);

Container[] newGroup = new Container[size1 + size2];

int i = 0;
for (Container c : group) {
c.group = newGroup;
c.amount = newAmount;
newGroup[i++] = c;
}
for (Container c : other.group) {
c.group = newGroup;
c.amount = newAmount;
newGroup[i++] = c;
}
}

public void addWater(float amount) {
if (group == null) {
this.amount += amount;
return;
}
float amountPerContainer = amount / group.length;
for (Container c : group) {
c.amount += amountPerContainer;
}
}
}
89 changes: 89 additions & 0 deletions code/후/src/main/java/ch4/memory3/Container.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package ch4.memory3;

import java.util.*;

public class Container {

private static int[] group = new int[0];
private static float[] amount = new float[0];

private Container() {
}

public static int newContainer() {
int nContainers = group.length;
int nGroups = amount.length;
amount = Arrays.copyOf(amount, nGroups + 1);
group = Arrays.copyOf(group, nContainers + 1);
group[nContainers] = nGroups;
return nContainers;
}

public static float getAmount(int containerId) {
int groupId = group[containerId];
return amount[groupId];
}

public static void connect(int containerId1, int containerId2) {
int groupId1 = group[containerId1];
int groupId2 = group[containerId2];
int size1 = groupSize(groupId1);
int size2 = groupSize(groupId2);

if (groupId1 == groupId2) {
return;
}

float amount1 = amount[groupId1] * size1;
float amount2 = amount[groupId2] * size2;
amount[groupId1] = (amount1 + amount2) / (size1 + size2);

for (int i = 0; i < group.length; i++) {
if (group[i] == groupId2) {
group[i] = groupId1;
}
}

removeGroupAndDefrag(groupId2);
}

private static int groupSize(int groupId) {
int size = 0;
for (int otherGroupId : group) {
if (otherGroupId == groupId) {
size++;
}
}
return size;
}

private static void removeGroupAndDefrag(int groupId) {
for (int containerId = 0; containerId < group.length; containerId++) {
if (group[containerId] == amount.length - 1) {
group[containerId] = groupId;
}
}

amount[groupId] = amount[amount.length - 1];
amount = Arrays.copyOf(amount, amount.length - 1);
}

public static void addWater(int containerId, float amount) {
int groupId = group[containerId];
int groupSize = groupSize(groupId);
Container.amount[groupId] += amount / groupSize;
}

public static void debugDump() {
System.out.print("group: [\t");
for (int c : group) {
System.out.print(c + ", \t");
}
System.out.println("]");
System.out.print("amount: [\t");
for (float a : amount) {
System.out.print(a + ", \t");
}
System.out.println("]");
}
}
113 changes: 113 additions & 0 deletions code/후/src/main/java/ch4/memory4/Container.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ch4.memory4;

import java.util.Arrays;

/**
* A system of water containers, identified by integer IDs (object-less API).
*
* @author Marco Faella
* @version 1.0
*/
public class Container {

/* When positive, it's the index of the next container in this group,
with a +1 bias.
When zero or negative, it's the opposite of the water amount
in each container of this group.
*/
private static float nextOrAmount[] = new float[0];

private Container() {
// Prevents instantiation
}

/**
* Returns the ID of a new empty container.
*/
public static int newContainer() {
int nContainers = nextOrAmount.length;
// the new cell is automatically initialized with zero
nextOrAmount = Arrays.copyOf(nextOrAmount, nContainers + 1);
return nContainers;
}

/**
* Returns the amount of water in the specified container.
*/
public static float getAmount(int containerID) {
while (nextOrAmount[containerID] > 0) {
containerID = (int) nextOrAmount[containerID] - 1;
}
return -nextOrAmount[containerID];
}

/**
* Adds the specified amount of water to the specified container.
*/
public static void addWater(int containerID, float amount) {
int firstOfGroup = findFirstOfGroup(containerID);
int[] lastAndSize = findLastOfGroupAndCount(firstOfGroup);
nextOrAmount[lastAndSize[0]] -= amount / lastAndSize[1];
}

/**
* Returns the index of the first container in the same group of containerID. Warning: quadratic
* time complexity.
*/
private static int findFirstOfGroup(int containerID) {
int current = containerID, i = 0;
do {
for (i = 0; i < nextOrAmount.length; i++) {
if (nextOrAmount[i] == current + 1) {
current = i;
break;
}
}
} while (i < nextOrAmount.length);
return current;
}

/**
* @return an array of two values: - the index of the last container in the same group of
* containerID - the number of steps from containerID to the last one (inclusive)
*/
private static int[] findLastOfGroupAndCount(int containerID) {
int[] result = new int[]{containerID, 1};
while (nextOrAmount[result[0]] > 0) {
result[0] = (int) nextOrAmount[result[0]] - 1;
result[1]++;
}
return result;
}

/**
* Connects the specified containers, so that water can flow from one to the other.
*/
public static void connect(int containerID1, int containerID2) {
int first1 = findFirstOfGroup(containerID1),
first2 = findFirstOfGroup(containerID2);
if (first1 == first2) {
return;
}

int[] lastAndSize1 = findLastOfGroupAndCount(first1),
lastAndSize2 = findLastOfGroupAndCount(first2);
int last1 = lastAndSize1[0],
last2 = lastAndSize2[0];
float amount1 = -nextOrAmount[last1],
amount2 = -nextOrAmount[last2],
newAmount = ((amount1 * lastAndSize1[1]) + (amount2 * lastAndSize2[1]))
/ (lastAndSize1[1] + lastAndSize2[1]);

nextOrAmount[last1] = first2 + 1; // concatenation
nextOrAmount[last2] = -newAmount;
}

public static void debugDump() {
System.out.print("[\t");
for (float c : nextOrAmount) {
System.out.print(c + ", \t");
}
System.out.println("]");
}
}
18 changes: 18 additions & 0 deletions code/후/src/main/java/ch4/multiset/LessDuplicationMultiSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ch4.multiset;

import java.util.*;

public class LessDuplicationMultiSet<T> implements MultiSet<T> {

private List<T> data = new ArrayList<>();

@Override
public void add(T elem) {
data.add(elem);
}

@Override
public long count(T elem) {
return data.stream().filter(x -> x.equals(elem)).count();
}
}
31 changes: 31 additions & 0 deletions code/후/src/main/java/ch4/multiset/ManyDuplicationMultiSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ch4.multiset;

import java.util.*;

public class ManyDuplicationMultiSet<T> implements MultiSet<T> {

private List<T> elements = new ArrayList<>();
private List<Long> repetitions = new ArrayList<>();

@Override
public void add(T elem) {
for (int i = 0; i < elements.size(); i++) {
if (elements.get(i).equals(elem)) {
repetitions.set(i, repetitions.get(i) + 1);
return;
}
}
elements.add(elem);
repetitions.add(1L);
}

@Override
public long count(T elem) {
for (int i = 0; i < elements.size(); i++) {
if (elements.get(i).equals(elem)) {
return repetitions.get(i);
}
}
return 0;
}
}
8 changes: 8 additions & 0 deletions code/후/src/main/java/ch4/multiset/MultiSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ch4.multiset;

public interface MultiSet<T> {

public void add(T elem);

public long count(T elem);
}
Loading