Last active
August 29, 2015 14:22
-
-
Save takawitter/080804d8b84869c2269d to your computer and use it in GitHub Desktop.
書いてみた。executeメソッドのみ。元ネタ: http://bufferings.hatenablog.com/entry/2015/06/03/082323
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public Result execute(Input in) throws IllegalArgumentException{ | |
assertNotNull(in, "In must not be null."); | |
try{ | |
Integer productId = in.getSelected(); | |
assertNotNull(productId, "ProductId must not be null."); | |
assertInRange(productId, 1, 10, "ProductId must be in the range 1-10."); | |
Product product = dao.findById(productId); | |
assertNotNull(product, "Product doesn't exist."); | |
List<Integer> coins = in.getCoins(); | |
assertNotNull(coins, "InputCoins must not be null."); | |
assertInRange(coins.size(), 1, 100, "The number of InputCoins must be in the range 1-100."); | |
List<Integer> supportedCoins = new ArrayList<Integer>(); | |
List<Integer> unsupportedCoins = new ArrayList<Integer>(); | |
filterUnsupportedCoins(coins, supportedCoins, unsupportedCoins); | |
int sum = sumUpCoins(supportedCoins); | |
int rest = sum - product.getPrice(); | |
assertTrue(rest >= 0, "Not enough money."); | |
List<Integer> restCoins = new ArrayList<Integer>(); | |
divideToCoins(rest, restCoins); | |
restCoins.addAll(unsupportedCoins); | |
return createSucceededResult(product, restCoins); | |
} catch(IllegalArgumentException | DaoException e){ | |
LOG.error(e); | |
return createCanceledResult(coins); | |
} | |
} | |
// 最適化版 | |
public Result execute2(Input in) throws IllegalArgumentException{ | |
assertNotNull(in, "In must not be null."); | |
try{ | |
Integer productId = in.getSelected(); | |
assertNotNull(productId, "ProductId must not be null."); | |
assertInRange(productId, 1, 10, "ProductId must be in the range 1-10."); | |
Product product = dao.findById(productId); | |
assertNotNull(product, "Product doesn't exist."); | |
List<Integer> coins = in.getCoins(); | |
assertNotNull(coins, "InputCoins must not be null."); | |
assertInRange(coins.size(), 1, 100, "The number of InputCoins must be in the range 1-100."); | |
List<Integer> changeCoins = new ArrayList<>(); | |
final LongAdder sum = new LongAdder(); | |
Collection<Integer> sumCalculator = new AbstractCollection<Integer>(){ | |
@Override | |
public Iterator<Integer> iterator() { | |
return null; | |
} | |
@Override | |
public int size() { | |
return 0; | |
} | |
@Override | |
public boolean add(Integer e) { | |
sum.add(e); | |
return true; | |
} | |
}; | |
filterUnsupportedCoins(coins, sumCalculator, changeCoins); | |
int rest = sum.intValue() - product.getPrice(); | |
assertTrue(rest >= 0, "Not enough money."); | |
divideToCoins(rest, changeCoins); | |
return createSucceededResult(product, changeCoins); | |
} catch(IllegalArgumentException | DaoException e){ | |
LOG.error(e); | |
return createCanceledResult(in.getCoins()); | |
} | |
} | |
private static void assertNotNull(Object value, String message) | |
throws IllegalArgumentException{ | |
if(value == null){ | |
throw new IllegalArgumentException(message); | |
} | |
} | |
private static void assertTrue(boolean value, String message) | |
throws IllegalArgumentException{ | |
if(!value){ | |
throw new IllegalArgumentException(message); | |
} | |
} | |
private static void assertInRange(int value, int min, int max, String message) | |
throws IllegalArgumentException{ | |
if(value < min || max < value){ | |
throw new IllegalArgumentException(message); | |
} | |
} | |
private static Set<Integer> unsupportedCoins = new HashSet<Integer>(){{ | |
add(1); | |
add(5); | |
}}; | |
private static void filterUnsupportedCoins( | |
Collection<Integer> coins, | |
Collection<Integer> supported, | |
Collection<Integer> unsupported) { | |
for(Integer c : coins){ | |
if(unsupportedCoins.contains(c)){ | |
unsupported.add(c); | |
} else{ | |
supported.add(c); | |
} | |
} | |
} | |
private static int sumUpCoins(Collection<Integer> coins) { | |
return coins.stream().mapToInt(Integer::intValue).sum(); | |
} | |
private static int[] coinKinds = {500, 100, 50, 10}; | |
private static void divideToCoins(int money, Collection<Integer> coins) { | |
for(int k : coinKinds){ | |
while(money >= k){ | |
coins.add(k); | |
} | |
} | |
if(money > 0){ | |
throw new RuntimeException("Invalid coin combination: " + money); | |
} | |
} | |
private static Result createSucceededResult(Product product, List<Integer> change){ | |
Result r = new Result(); | |
r.setProduct(product); | |
r.setCoins(change); | |
return r; | |
} | |
private static Result createCanceledResult(List<Integer> coins){ | |
Result r = new Result(); | |
r.setProduct(null); | |
r.setCoins(coins); | |
return r; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
方針的なもの