I have made an implementation of coin change problem solved with Dynamic Programming. Could you guys help with renaming some method and variables?
Here is my implementation -
public class CoinChange {
public int computeMinimumNumberOfCoins(int[] coins, int finalSum) {
Sum[] sums = new Sum[finalSum + 1];
for (int i = 0; i <= finalSum; i++) {
sums[i] = new Sum(i, coins);
}
for (int i = 1; i <= finalSum; i++) {
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
if (sums[i - coins[j]].getMinCoins() + 1 < sums[i].getMinCoins()) {
changeMinCoins(sums[i - coins[j]], sums[i]);
changeCoinCount(sums[i - coins[j]], sums[i], coins[j]);
}
}
}
}
return sums[finalSum].getMinCoins();
}
private void changeCoinCount(Sum from, Sum to, int coin) {
List<Coin> fromCoins = from.getCoins();
List<Coin> toCoins = to.getCoins();
for (int i = 0; i < fromCoins.size(); i++) {
Coin fromCoin = fromCoins.get(i);
Coin toCoin = toCoins.get(i);
if (toCoin.getValue() == coin) {
toCoin.setCount(fromCoin.getCount() + 1);
} else {
toCoin.setCount(fromCoin.getCount());
}
}
}
private void changeMinCoins(Sum from, Sum to) {
to.setMinCoins(from.getMinCoins() + 1);
}
}
the model classes Coin and Sum are as follows -
public class Coin {
private int value;
private int count;
Coin(int value, int count) {
this.value = value;
this.count = count;
}
public int getValue() {
return value;
}
void setValue(int value) {
this.value = value;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return "Value: " + value + ", count: " + count;
}
}
public class Sum {
private List<Coin> coins;
private int value;
private int minCoins;
public Sum(int value, int[] coins) {
this.value = value;
this.coins = new ArrayList<>(coins.length);
for (int i = 0; i < coins.length; i++) {
this.coins.add(i, new Coin(coins[i], 0));
}
if (value == 0) {
minCoins = 0;
} else {
minCoins = Integer.MAX_VALUE;
}
}
public int getValue() {
return value;
}
public int getMinCoins() {
return minCoins;
}
public void setMinCoins(int minCoins) {
this.minCoins = minCoins;
}
public List<Coin> getCoins() {
return coins;
}
}
I have tested it with this -
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.junit.MatcherAssert.assertThat;
@RunWith(JUnitParamsRunner.class)
public class CoinChangeTest {
CoinChange coinChange;
private Object[] coinChangeValues() {
return new Object[]{
new Object[]{new int[]{5, 10, 25}, 30, 2},
new Object[]{new int[]{9, 6, 5, 1}, 11, 2},
new Object[]{new int[]{1, 2, 3}, 5, 2},
new Object[]{new int[]{1, 3, 5}, 11, 3},
new Object[]{new int[]{1, 5, 10, 20, 25}, 40, 2},
new Object[]{new int[]{5, 10, 20, 25, 50}, 90, 3}
};
}
@Before
public void setUp() throws Exception {
coinChange = new CoinChange();
}
@Test
@Parameters(method = "coinChangeValues")
public void computeMinimumNumberOfCoins(int[] coins, int sum, int count) throws Exception {
assertThat(coinChange.computeMinimumNumberOfCoins(coins, sum), is(count));
}
}
and it seems to run fine. Here is the build.gradle file of the project above-
group 'org.yadavvi'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '2.0.0.0'
testCompile group: 'pl.pragmatists', name: 'JUnitParams', version: '1.0.6'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
I am not so sure about the names of the model classes being Coin and Sum. Also, I don't think that the changeCoinCount() and changeMinCoins() should have Sum from and Sum to as arguments.