Skip to content

Commit ed54952

Browse files
committed
Enhance ATM solutions by addition of classes hierarchy to avoid code duplication
Adjust naming to satisfy Java code convention: use `Atm` instead of `ATM`
1 parent 31da636 commit ed54952

File tree

11 files changed

+195
-244
lines changed

11 files changed

+195
-244
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ they contain enough code which describes implementation in a natural way.
168168
| Поиск слова в матрице букв (leetcode) | [Youtube](https://youtu.be/FsKU04anMtE) | [Code](src/main/java/by/andd3dfx/search/wordsearch/WordSearch.java) |
169169
| Сжатие строки (Яндекс) | [Youtube](https://youtu.be/s3sGF7C6cV8) | [Code](src/main/java/by/andd3dfx/string/MakeStringCompact.java) |
170170
| Самодельный Stack | [Youtube](https://youtu.be/sZ-DrSHhrWc) | [Code](src/main/java/by/andd3dfx/collections/custom/CustomStack.java) |
171-
| Выдача купюр банкоматом (Яндекс) | [Youtube](https://youtu.be/LDKZtDevRRI) | [Code](src/main/java/by/andd3dfx/common/ATM.java) [Code2](src/main/java/by/andd3dfx/common/ATM2.java) |
171+
| Выдача купюр банкоматом (Яндекс) | [Youtube](https://youtu.be/LDKZtDevRRI) | [Code](src/main/java/by/andd3dfx/common/atm/AtmUsingLoop.java) [Code2](src/main/java/by/andd3dfx/common/atm/AtmUsingRecursion.java) |
172172
| Поиск набора слов в матрице букв (2 решения) (leetcode) | [Youtube](https://youtu.be/DTyMyr6bNGw) | [Code](src/main/java/by/andd3dfx/search/wordsearch/WordSearch_IIUsingWordSearch.java) [Code2](src/main/java/by/andd3dfx/search/wordsearch/WordSearch_IIUsingRecursion.java) |
173173
| Поиск набора слов в матрице букв 2: префиксное дерево (leetcode) | [Youtube](https://youtu.be/CLYbm21pvig) | [Code](src/main/java/by/andd3dfx/search/wordsearch/WordSearch_IIUsingPrefixTree.java) |
174174
| Поиск в строке наиболее длинной подстроки без повторений (leetcode) | [Youtube](https://youtu.be/Jj66XXja4LY) | [Code](src/main/java/by/andd3dfx/string/LongestWordWithoutRepeatingChars.java) |

Diff for: src/main/java/by/andd3dfx/common/ATM.java

-80
This file was deleted.

Diff for: src/main/java/by/andd3dfx/common/ATM2.java

-81
This file was deleted.
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package by.andd3dfx.common.atm;
2+
3+
import java.util.Comparator;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
public abstract class AbstractAtm implements IAtm {
9+
10+
protected Map<Integer, Integer> state;
11+
protected List<Integer> nominals;
12+
13+
public AbstractAtm(Map<Integer, Integer> state) {
14+
this.state = new HashMap<>(state);
15+
this.nominals = state.keySet().stream()
16+
.sorted(Comparator.reverseOrder()).toList();
17+
}
18+
19+
/**
20+
* Withdraw asked amount using banknotes of ATM
21+
*
22+
* @param amount sum asked to withdraw
23+
* @return map with solution - pairs {banknote nominal->quantity}
24+
*/
25+
@Override
26+
public Map<Integer, Integer> withdraw(int amount) {
27+
// Try to make withdraw using banknote of highest nominal,
28+
// in case of fail - try to start from next nominal
29+
for (int i = 0; i < nominals.size(); i++) {
30+
try {
31+
return withdraw(amount, i);
32+
} catch (IllegalStateException ex) {
33+
// do nothing
34+
}
35+
}
36+
37+
throw new IllegalStateException("Could not perform withdraw!");
38+
}
39+
40+
/**
41+
* Withdraw asked amount using banknotes of ATM starting from definite nominal (and its lower values)
42+
*
43+
* @param amount sum asked to withdraw
44+
* @return map with solution - pairs {banknote nominal->quantity}
45+
*/
46+
protected abstract Map<Integer, Integer> withdraw(int amount, int nominalIndex);
47+
48+
protected void mutateAtm(Map<Integer, Integer> result) {
49+
for (var nominal : result.keySet()) {
50+
state.put(nominal, state.get(nominal) - result.get(nominal));
51+
}
52+
}
53+
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package by.andd3dfx.common.atm;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* <pre>
8+
* Есть банкомат (ATM), который заряжают купюрами.
9+
* Надо реализовать метод withdraw() для выдачи заданной суммы amount имеющимися в банкомате купюрами.
10+
* Метод withdraw() - мутирующий, т.е. меняет состояние банкомата после вызова (кол-во купюр может уменьшиться).
11+
* </pre>
12+
*
13+
* @see <a href="https://youtu.be/LDKZtDevRRI">Video solution</a>
14+
*/
15+
public class AtmUsingLoop extends AbstractAtm {
16+
17+
public AtmUsingLoop(Map<Integer, Integer> state) {
18+
super(state);
19+
}
20+
21+
@Override
22+
protected Map<Integer, Integer> withdraw(int amount, int nominalIndex) {
23+
var result = new HashMap<Integer, Integer>();
24+
25+
for (var index = nominalIndex; index < nominals.size(); index++) {
26+
var nominal = nominals.get(index);
27+
if (nominal > amount || state.get(nominal) == 0) {
28+
continue;
29+
}
30+
31+
int count = amount / nominal;
32+
count = Math.min(count, state.get(nominal));
33+
result.put(nominal, count);
34+
amount -= nominal * count;
35+
36+
if (amount == 0) {
37+
break;
38+
}
39+
}
40+
41+
if (amount > 0) {
42+
throw new IllegalStateException("Could not perform withdraw!");
43+
}
44+
45+
mutateAtm(result);
46+
return result;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package by.andd3dfx.common.atm;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* <pre>
8+
* Есть банкомат (ATM), который заряжают купюрами.
9+
* Надо реализовать метод withdraw() для выдачи заданной суммы amount имеющимися в банкомате купюрами.
10+
* Метод withdraw() - мутирующий, т.е. меняет состояние банкомата после вызова (кол-во купюр может уменьшиться).
11+
* </pre>
12+
*
13+
* @see <a href="https://youtu.be/LDKZtDevRRI">Video solution</a>
14+
*/
15+
public class AtmUsingRecursion extends AbstractAtm {
16+
17+
public AtmUsingRecursion(Map<Integer, Integer> state) {
18+
super(state);
19+
}
20+
21+
@Override
22+
protected Map<Integer, Integer> withdraw(int amount, int nominalIndex) {
23+
if (amount == 0) {
24+
return Map.of();
25+
}
26+
if (nominalIndex >= nominals.size()) {
27+
throw new IllegalStateException("Could not perform withdraw!");
28+
}
29+
30+
var nominal = nominals.get(nominalIndex);
31+
if (nominal > amount || state.get(nominal) == 0) {
32+
return withdraw(amount, nominalIndex + 1);
33+
}
34+
35+
var result = new HashMap<Integer, Integer>();
36+
int count = amount / nominal;
37+
count = Math.min(count, state.get(nominal));
38+
result.put(nominal, count);
39+
amount -= nominal * count;
40+
41+
if (amount > 0) {
42+
result.putAll(withdraw(amount, nominalIndex + 1));
43+
return result;
44+
}
45+
46+
mutateAtm(result);
47+
return result;
48+
}
49+
}

Diff for: src/main/java/by/andd3dfx/common/atm/IAtm.java

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package by.andd3dfx.common.atm;
2+
3+
import java.util.Map;
4+
5+
public interface IAtm {
6+
7+
/**
8+
* Withdraw asked amount using banknotes of ATM
9+
*
10+
* @param amount sum asked to withdraw
11+
* @return map with solution - pairs {banknote nominal->quantity}
12+
*/
13+
Map<Integer, Integer> withdraw(int amount);
14+
}

0 commit comments

Comments
 (0)