Learning Java (and Programming) on Udemy. Need help to understand logic - java

I am currently watching a video on recursion, and I need some help with the logic in it.
I don't understand the return "moment" of the algorithm.
Here is the code:
public class App {
public static void main(String[] args) {
// E.g. 4! = 4*3*2*1 (factorial 4)
System.out.println(factorial(5));
}
private static int factorial(int value) {
//System.out.println(value);
if(value == 1) {
return 1;
}
return factorial(value - 1) * value;
}
}
What I don't understand is the return 1; part.
When the method is calculating the factorial of 4, it recalls it self until value becomes 1.
But when value == 1, the method is supposed to return 1 to the caller of the method.
Doesn't this return 1 overrides return factorial(value - 1) * value;??
Clearly, I don't completely understand how return works.
Thanks in advance :)

The point of every recursion is "stop point", the condition, when recursion does not continue, but instead returns value. If this point does not exist, the recursion nevers ends.
This is how it will be called :
System.out.println(factorial(5))
-return factorial(4)*5
--return factorial(3)*4
---return factorial(2)*3
----return factorial(1)*2
-----return 1
----return 1*2
---return 2*3
--return 6*4
-return 24*5
System.out.println(120)
I think it is more clear, when you put "return" outside the recursive counting, because you are doing more stuff in one line.
I made this program, ignore "doMinuses" method, it only makes minuses to make output more readable. It does the same thing as your program. You do not have to read it, just look to output first.
public class App {
public static int origValue = 5;
public static void main(String[] args) {
System.out.println(factorial(origValue));
}
private static int factorial(int value) {
doMinuses(origValue-value);
System.out.println("Entered factorial("+value+")");
if(value == 1) {
doMinuses(origValue-value);
System.out.println("Returning 1");
return 1;
}
doMinuses(origValue-value);
System.out.println("Start countin factorial("+(value-1)+")*"+value);
int factorialResult = factorial(value - 1) * value;
doMinuses(origValue-value);
System.out.println("Returning result for factorial("+(value-1)+")*"+value + " = " + factorialResult);
return factorialResult;
}
private static void doMinuses(int count){
for (int i = 0; i < count; i++) {
System.out.print('-');
}
}
}
The output is
Entered factorial(5)
Start countin factorial(4)*5
-Entered factorial(4)
-Start countin factorial(3)*4
--Entered factorial(3)
--Start countin factorial(2)*3
---Entered factorial(2)
---Start countin factorial(1)*2
----Entered factorial(1)
----Returning 1
---Returning result for factorial(1)*2 = 2
--Returning result for factorial(2)*3 = 6
-Returning result for factorial(3)*4 = 24
Returning result for factorial(4)*5 = 120
120
The only difference outside printing out code is to change this line
return factorial(value - 1) * value;
to two lines, because it is, what is really happening (especially the order of what is happening).
int factorialResult = factorial(value - 1) * value;
return factorialResult;
I edited function even more for BEST output ever :)
public class App {
public static int origValue = 5;
public static void main(String[] args) {
System.out.println(factorial(origValue));
}
private static int factorial(int value) {
doMinuses(origValue - value);
System.out.println("Entered factorial(" + value + ")");
if (value == 1) {
doMinuses(origValue - value);
System.out.println("Returning 1");
return 1;
}
doMinuses(origValue - value);
System.out.println("Start countin factorial(" + (value - 1) + ")*" + value);
int factorialResult = factorial(value - 1);
doMinuses(origValue - value);
System.out.println("Finished counting factorial(" + (value - 1) + ") = " + factorialResult);
doMinuses(origValue - value);
System.out.println("Returning result for factorial(" + (value - 1) + ")*" + value + " = " + factorialResult + "*" + value + " = " + (factorialResult * value));
return factorialResult * value;
}
private static void doMinuses(int count) {
for (int i = 0; i < count; i++) {
System.out.print('-');
}
}
}
Has this output :
Entered factorial(5)
Start countin factorial(4)*5
-Entered factorial(4)
-Start countin factorial(3)*4
--Entered factorial(3)
--Start countin factorial(2)*3
---Entered factorial(2)
---Start countin factorial(1)*2
----Entered factorial(1)
----Returning 1
---Finished counting factorial(1) = 1
---Returning result for factorial(1)*2 = 1*2 = 2
--Finished counting factorial(2) = 2
--Returning result for factorial(2)*3 = 2*3 = 6
-Finished counting factorial(3) = 6
-Returning result for factorial(3)*4 = 6*4 = 24
Finished counting factorial(4) = 24
Returning result for factorial(4)*5 = 24*5 = 120
120

Return 1 does override the return factorial(value - 1) * value;
But what this function is doing is calling itself, up until the value hits 1.
Once the value hits one, the if condition is met and the return 1 part is called, completely ending the function (kind of like a break; would, to put it simply), so it will stop executing the return factorial(value - 1) * value;

Returned value '1' comes from this expression
return factorial(value - 1) * value;
and is used only here, previous lines will never be evaluated.
In this case, recursion works similarly to a loop. To understand how it works, you may use debugger, or try to write down each instruction (statement, expression) in order in which it will be evaluated.
for factorial(3)
it will look like this
factorial(3)
if(3==1) //false
factorial(2) //to return factorial(2) * 3 when function becomes evaluated
if(2==1) //false
factorial(1) // //to return factorial(1) * 2 when function becomes evaluated
if(1==1) //true
return 1;
return /*factorial(1) = */ 1 * 2;
return /*factorial(2) = */ 2 * 3; //return 6 - result of your top call of factorial(3) from the main call

Related

Recursion in Java - print string permutations

I'm trying to write a method that prints all of the permutations of a string using recursion. For now, I have this code that works:
private static void printPermutations(String in, String out) {
if (in.length() == 0) System.out.println(out);
else {
for (int i = 0 ; i < in.length() ; i++) {
printPermutations(in.substring(0, i) + in.substring(i + 1), out + in.charAt(i));
}
}
}
It prints the right result, but I'm trying to solve it without using loops at all, including the one in line 4. Is it possible? If so, how would you solve it? Thank you!
I tried to add a third parameter called index and write index+1 inside the recursive call in line 5 but it didn't work. I think adding the third parameter is a good idea, I'm just not sure how to use it.
So I am not sure why you are trying to do that.. this is kind of the setup you would be doing for recursion, you need to not return void otherwise it's not really recursion. w3schools is a good resource.
public class Main {
public static void main(String[] args) {
int result = sum(10);
System.out.println(result);
}
public static int sum(int k) {
if (k > 0) {
return k + sum(k - 1);
} else {
return 0;
}
}
}
This would return something like
10 + sum(9)
10 + ( 9 + sum(8) )
10 + ( 9 + ( 8 + sum(7) ) )
...
10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + sum(0)
10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
I hope that kind of helps you put together what you need. You have to have a return so the Recursive method can see its previous call, it takes information then like a rubberband once it reaches a certain point it returns all of your iterations. Personally, I like loops more, easier to read and easier to code.
An implementation for what you are trying to do would be:
public class Main {
public static void main(String[] args) {
String result = Variations("test");
System.out.println(result);
}
public static String Variations(String k) {
if (k.length() > 0) {
return k + k.substring(0, k.lenth() - 1);
} else {
return "";
}
}
}
That would be the variation of what you are looking to do I believe.

I have some problems with ArrayList (quiz of head first java)

I've just started learning java since last week. I'm using book called 'head first java' and i'm struggling with solving problems about ArrayList. Error says "The method setLocationCells(ArrayList) in the type DotCom is not applicable for the
arguments (int[])" and I haven't found the solution :( help me..!
enter image description here
This looks like a Locate & Conquer type game similar to the game named Battleship with the exception that this game is a single player game played with a single hidden ship in a single horizontal row of columnar characters. Rather simplistic but kind of fun to play I suppose. The hard part is to locate the hidden ship but once you've located it, conquering (sinking) it becomes relatively easy. I'm sure this isn't the games' intent since it is after all named "The Dot Com Game" but the analogy could be possibly helpful.
There are several issues with your code but there are two major ones that just can not be there for the game to work:
Issue #1: The call to the DotCom.setLocationCells() method:
The initial problem is located within the DotComGame class on code line 13 (as the Exception indicates) where the call is made to the DotCom.setLocationCells() method. As already mentioned in comments the wrong parameter type is passed to this method. You can not pass an int[] Array to the setLocationCell() method when this method contains a parameter signature that stipulates it requires an ArrayList object. The best solution in my opinion would be to satisfy the setLocationCells() method parameter requirement...supply an ArrayList to this method.
The reason I say this is because all methods within the DotCom class work with an established ArrayList and one of the tasks of one of these methods (the checkYourself() method) actually removes elements from the ArrayList which is easy to do from a collection but very cumbersome to do the same from an Array.
To fix this problem you will need to change the data type for the locations variable located within the DotComGame class. Instead of using:
int[] locations = {randomNum, randomNum + 1, randomNum + 2};
you should have:
ArrayList<Integer> locations = new ArrayList<>(
Arrays.asList(random, randomNum + 1, randomNum + 2));
or you could do it this way:
ArrayList<Integer> locations = new ArrayList<>();
locations.add(randomNum);
locations.add(randomNum + 1);
locations.add(randomNum + 2);
There are other ways but these will do for now. Now, when the call to the setLocationCells() method is made you ahouldn't get an exception this issue should now be resolved.
Issue #2: The call to the DotCom.checkYourself() method:
Again, this particular issue is located within the DotComGame class on code line 18 where the call is made to the DotCom.checkYourself() method. Yet another parameter data type mismatch. You are trying to pass a variable of type String (named guess) to this method whereas its signature stipulates that it requires an integer (int) value. That again is a no go.
To fix this problem you will need to convert the string numerical value held by the guess variable to an Integer (int) value. So instead of having this:
while(isAlive) {
String guess = helper.getUserInput("Enter a Number: ");
String result = theDotCom.checkYourself(guess);
// ... The rest of your while loop code ...
}
you should have something like:
while(isAlive) {
String guess = helper.getUserInput("Enter a Number: ");
/* Validate. Ensure guess holds a string representation
of a Integer numerical value. */
if (!guess.matches("\\d+")) {
System.err.println("Invalid Value (" + guess
+ ") Supplied! Try again...");
continue;
}
int guessNum = Integer.parseInt(guess);
String result = theDotCom.checkYourself(guessNum);
numOfGuesses++;
if (result.equals("kill")) {
isAlive = false;
System.out.println(numOfGuesses + " guesses!");
}
else if (result.equals("hit")) {
// Do Something If You Like
System.out.println("HIT!");
}
else {
System.out.println("Missed!");
}
}
Below is a game named Simple Battleship which I based off of your code images (please don't use images for code anymore - I hate using online OCR's ;)
BattleshipGame.java - The application start class:
import java.awt.Toolkit;
public class BattleshipGame {
public static int gameLineLength = 10;
public static void main(String[] args) {
GameHelper helper = new GameHelper();
Battleship theDotCom = new Battleship();
int score = 0; // For keeping an overall score
// Display About the game...
System.out.println("Simple Battleship Game");
System.out.println("======================");
System.out.println("In this game you will be displayed a line of dashes.");
System.out.println("Each dash has the potential to hide a section of a");
System.out.println("hidden Battleship. The size of this ship is randomly");
System.out.println("chosen by the game engine and can be from 1 to 5 sections");
System.out.println("(characters) in length. The score for each battle is based");
System.out.println("on the length of the game line that will be displayed to");
System.out.println("you (default is a minimum of 10 charaters). You now have");
System.out.println("the option to supply the game line length you want to play");
System.out.println("with. If you want to use the default then just hit ENTER:");
System.out.println();
// Get the desire game line length
String length = helper.getUserInput("Desired Game Line Length: --> ", "Integer", true, 10, 10000);
if (!length.isEmpty()) {
gameLineLength = Integer.parseInt(length);
}
System.out.println();
// Loop to allow for continuous play...
boolean alwaysReplay = true;
while (alwaysReplay) {
int numOfGuesses = 0;
/* Create a random ship size to hide within the line.
It could be a size from 1 to 5 characters in length. */
int shipSize = new java.util.Random().nextInt((5 - 1) + 1) + 1;
int randomNum = (int) (Math.random() * (gameLineLength - (shipSize - 1)));
int[] locations = new int[shipSize];
for (int i = 0; i < locations.length; i++) {
locations[i] = randomNum + i;
}
System.out.println("Destroy the " + shipSize + " character ship hidden in the");
System.out.println("displayed line below:");
System.out.println();
String gameLine = String.join("", java.util.Collections.nCopies(gameLineLength, "-"));
theDotCom.setLocationCells(locations);
// Play current round...
boolean isAlive = true;
while (isAlive == true) {
System.out.println(gameLine);
String guess = helper.getUserInput("Enter a number from 1 to " + gameLineLength
+ " (0 to quit): --> ", "Integer", 1, gameLineLength);
int idx = Integer.parseInt(guess);
if (idx == 0) {
System.out.println("Quiting with an overall score of: " + score + " ... Bye-Bye");
alwaysReplay = false;
break;
}
idx = idx - 1;
String result = theDotCom.checkYourself(idx);
numOfGuesses++;
System.out.println(result);
if (result.equalsIgnoreCase("kill")) {
Toolkit.getDefaultToolkit().beep();
isAlive = false;
/* Tally the score dependent upon the gameLineLength... */
if (gameLineLength <= 10) { score += 5; }
else if (gameLineLength > 10 && gameLineLength <= 20) { score += 10; }
else if (gameLineLength > 20 && gameLineLength <= 30) { score += 15; }
else if (gameLineLength > 30 && gameLineLength <= 40) { score += 20; }
else { score += 25; }
gameLine = gameLine.substring(0, idx) + "x" + gameLine.substring(idx + 1);
System.out.println(gameLine);
System.out.println(numOfGuesses + " guesses were made to sink the hidden ship.");
System.out.println("Your overall score is: " + (score < 0 ? 0 : score));
}
else if (result.equalsIgnoreCase("hit")) {
gameLine = gameLine.substring(0, idx) + "x" + gameLine.substring(idx + 1);
}
if (result.equalsIgnoreCase("miss")) {
score -= 1;
}
System.out.println();
}
// Play Again? [but only if 'alwaysReplay' holds true]
if (alwaysReplay) {
String res = helper.getAnything("<< Press ENTER to play again >>\n"
+ "<< or enter 'q' to quit >>");
if (res.equalsIgnoreCase("q")) {
System.out.println("Quiting with an overall score of: " + score + " ... Bye-Bye");
break;
}
System.out.println();
}
}
}
}
GameHelper.java - The GameHelper class:
import java.util.Scanner;
public class GameHelper {
private final Scanner in = new Scanner(System.in);
public String getUserInput(String prompt, String responseType, int... minMAX) {
int min = 0, max = 0;
if (minMAX.length == 2) {
min = minMAX[0];
max = minMAX[1];
}
if (minMAX.length > 0 && min < 1 || max < 1) {
throw new IllegalArgumentException("\n\ngetUserInput() Method Error! "
+ "The optional parameters 'min' and or 'max' can not be 0!\n\n");
}
String response = "";
while (response.isEmpty()) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
response = in.nextLine().trim();
if (responseType.matches("(?i)\\b(int|integer|float|double)\\b")) {
if (!response.matches("-?\\d+(\\.\\d+)?") ||
(responseType.toLowerCase().startsWith("int") && response.contains("."))) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
continue;
}
}
// Check entry range value if the entry is to be an Integer
if (responseType.toLowerCase().startsWith("int")) {
int i = Integer.parseInt(response);
if (i != 0 && (i < min || i > max)) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
}
}
}
return response;
}
public String getUserInput(String prompt, String responseType, boolean allowNothing, int... minMAX) {
int min = 0, max = 0;
if (minMAX.length == 2) {
min = minMAX[0];
max = minMAX[1];
}
if (minMAX.length > 0 && min < 1 || max < 1) {
throw new IllegalArgumentException("\n\ngetUserInput() Method Error! "
+ "The optional parameters 'min' and or 'max' can not be 0!\n\n");
}
String response = "";
while (response.isEmpty()) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
response = in.nextLine().trim();
if (response.isEmpty() && allowNothing) {
return "";
}
if (responseType.matches("(?i)\\b(int|integer|float|double)\\b")) {
if (!response.matches("-?\\d+(\\.\\d+)?") ||
(responseType.toLowerCase().startsWith("int") && response.contains("."))) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
continue;
}
}
// Check entry range value if the entry is to be an Integer
if (responseType.toLowerCase().startsWith("int")) {
int i = Integer.parseInt(response);
if (i != 0 && (i < min || i > max)) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
}
}
}
return response;
}
public String getAnything(String prompt) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
return in.nextLine().trim();
}
}
Battleship.java - The Battleship class:
import java.util.ArrayList;
public class Battleship {
private ArrayList<Integer> locationCells;
public void setLocationCells(java.util.ArrayList<Integer> loc) {
locationCells = loc;
}
// Overload Method (Java8+)
public void setLocationCells(int[] loc) {
locationCells = java.util.stream.IntStream.of(loc)
.boxed()
.collect(java.util.stream.Collectors
.toCollection(java.util.ArrayList::new));
}
/*
// Overload Method (Before Java8)
public void setLocationCells(int[] loc) {
// Clear the ArrayList in case it was previously loaded.
locationCells.clear();
// Fill the ArrayList with integer elements from the loc int[] Array
for (int i = 0; i < loc.length; i++) {
locationCells.add(loc[i]);
}
}
*/
/**
* Completely removes one supplied Integer value from all elements
* within the supplied Integer Array if it exist.<br><br>
*
* <b>Example Usage:</b><pre>
*
* {#code int[] a = {103, 104, 100, 10023, 10, 140, 2065};
* a = removeFromArray(a, 104);
* System.out.println(Arrays.toString(a);
*
* // Output will be: [103, 100, 10023, 10, 140, 2065]}</pre>
*
* #param srcArray (Integer Array) The Integer Array to remove elemental
* Integers from.<br>
*
* #param intToDelete (int) The Integer to remove from elements within the
* supplied Integer Array.<br>
*
* #return A Integer Array with the desired elemental Integers removed.
*/
public static int[] removeFromArray(int[] srcArray, int intToDelete) {
int[] arr = {};
int cnt = 0;
boolean deleteIt = false;
for (int i = 0; i < srcArray.length; i++) {
if (srcArray[i] != intToDelete) {
arr[cnt] = srcArray[i];
cnt++;
}
}
return arr;
}
public String checkYourself(int userInput) {
String result = "MISS";
int index = locationCells.indexOf(userInput);
if (index >= 0) {
locationCells.remove(index);
if (locationCells.isEmpty()) {
result = "KILL";
}
else {
result = "HIT";
}
}
return result;
}
}

Java beginner question: Method for finding next available ID in an ArrayList

ive been given this Exercise: Make a method for finding the next available member ID in an ArrayList of member objects. I create the member ID's manually when creating a new member, and i can always assume that the members have been arranged in order by ID.
For example: If i have 4 members with ID's from 0-3, and i remove the 2nd member, the method should return 1.
Here is the messy part i have for now:
public int getNextID (){
int i;
for(i = 0; i < members.size(); i++){
if(i == members.get(i).getID()){
i++;
}
else if(i != members.get(i).getID()){
System.out.println("Next available ID: " + i);
} else {
System.out.println("Next available ID: " + members.size());
break;
}
}
return i;
}
This solution provides a new Member ID from a List, where all MemberItems are sorted by ID. Item 0 in the List, must have the ID 0. Item 1 -> ID 1.
The new ID will always be the lowest available ID which is currently not assigned.
Solution 1
public int getNextID (){
for(int i = 0; i < members.size(); i++){
if(i < members.get(i).getID()){
System.out.println("Next available ID: " + i);
// at this point we know this is the next id.
// we can leave the method and return the next ID.
return i;
}
}
// we did not leave the loop (and method), because all id's are assigned.
System.out.println("Next available ID: " + members.size());
return members.size();
}
Solution 2 (Java 1.8+ Stream)
If you prefer a 2 line java 8 stream solution you could also use this:
public int getNextID() {
Member m = members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().orElse(null);
return (m != null ? members.indexOf(m) : members.size());
}
Solution 3 (Java 1.8+ Stream)
or a 1 line stream solution:
public int getNextID() {
return members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().map(m2 -> members.indexOf(m2)).orElse(members.size());
}
To say something about your code:
You are increasing i twice.
Once in the for statement at the end with i++ and two lines below with i++ again.
This way, you are skipping the index 1. if the first member has the same id like index.
Timings and testing
For anyone who is interested into the comparision of timings between the 3 solutions. This are the Timings from my maschine with java1.8:
|----------------------------------------------------------------------|
| 10000 Items, Free Position 9998 | 10000 Items, Free Position 1 |
|----------------------------------------------------------------------|
| Solution1: ~2ms | Solution1: ~0.005ms |
| Solution2: ~65ms | Solution2: ~0.05ms |
| Solution3: ~60ms | Solution3: ~0.06ms |
|----------------------------------------------------------------------|
Code to execute it on your maschine. will definitly result in different timing results, but the proportion should stay about the same.
import java.util.ArrayList;
import java.util.List;
public class Test {
private static List<Member> members = new ArrayList<>();
public static void main(String[] args) {
members = getTestList(10000);
warmUp();
members.remove(9998);
testSolutions();
members.remove(1);
testSolutions();
}
private static void warmUp() {
for (int i = 0; i < 5; i++) {
for (Member m : members) {
// warm up cpu for iteration
}
members.forEach(Member::getID);
}
}
private static void testSolutions() {
long start = System.nanoTime();
int result1 = getNextID();
System.out.println("#1 Iterative result: " + result1 + " | in " + (System.nanoTime() - start) / 1000000.0 + "ms");
start = System.nanoTime();
Member m = members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().orElse(null);
int result2 = m != null ? members.indexOf(m) : members.size();
System.out.println("#2 Stream Result: " + result2 + " | in " + ((System.nanoTime() - start) / 1000000.0) + "ms");
start = System.nanoTime();
int result3 = members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().map(m2 -> members.indexOf(m2)).orElse(members.size());
System.out.println("#3 Stream Result: " + result3 + " | in " + ((System.nanoTime() - start) / 1000000.0) + "ms");
}
private static int getNextID() {
for (int i = 0; i < members.size(); i++) {
if (i < members.get(i).getID()) {
return i;
}
}
return members.size();
}
private static List<Member> getTestList(int count) {
List<Member> members = new ArrayList<>();
for (int i = 0; i < count; i++) {
members.add(new Member(i));
}
return members;
}
private static class Member {
private int id;
public Member(int id) {
this.id = id;
}
private int getID() {
return id;
}
}
}
For List, use size() to get the number of elements.(also it's give you the last but 1 index used).
Index is starting from 0 and is automatically adjusted when adding or removing elements.
So you do not need to keep tracking manually for indexes.
Note, when you add on list with method add(index, element) index should always be less then or equal to size()_methods return.
List<String> l = new ArrayList<String>();
l.add("a"); //auto index 0
l.add("b"); //auto index 1
l.add("c"); //auto index 2
System.out.println(l.size()); //3 and it's also next_available for add at bottom
l.remove(1);
l.forEach(System.out::println); //a c
System.out.println(l.size()); // 2
System.out.println(l.get(0)); //a
System.out.println(l.get(1)); //c adjusted index from 2 to 1 after remove
l.add(2,"d");
System.out.println(l.size()); //3
l.add(4,"e"); //error java.lang.IndexOutOfBoundsException: Index: 4, Size: 3
Kindly see #Sunchezz and #Evan answers for a full solution.

Validate routing number

How to validate bank routing number in java ?
can any one help me out.
for example
void boolean validate(String str){
// some code
return true; //if valid otherwise return false
}
Please find who needs a routing number validator.
routing-number.validator.ts
import { AbstractControl, ValidationErrors } from '#angular/forms';
export const routingNumberValidator = (): ((AbstractControl) => ValidationErrors | null) => {
return (control: AbstractControl): ValidationErrors | null => {
const targetValue = control.value;
if (!targetValue) {
return null;
}
const digits = targetValue.split('').map(d => parseInt(d, 10));
const checksum = 3 * (digits[0] + digits[3] + digits[6]) + 7 * (digits[1] + digits[4] + digits[7]) + (digits[2] + digits[5] + digits[8]);
return (checksum % 10 === 0) ? null : { routingnumber: true };
};
};
In your yourComponent.component.ts:
this.yourForm = this.fb.group({
routingNumber: [null, Validators.compose([
Validators.required,
routingNumberValidator()
])]
});
And in your yourComponent.component.html:
<nz-form-control [nzErrorTip]="routingNumberErrorTemplate">
<input
nz-input
formControlName="routingNumber"
id="routingNumber">
</nz-form-control>
<ng-template
#routingNumberErrorTemplate
let-control>
<span data-cy="routing-number-input-error">
<ng-container *ngIf="control.hasError('required')">The routing number is required</ng-container>
<ng-container *ngIf="control.hasError('routingnumber')">The routing number is invalid</ng-container>
</span>
</ng-template>
I got the solution. Bank Routing Number is validate by using this simple method.
public boolean validateRoutingNumber(String s) {
int checksum=0, len=0, sum=0, mod = 0;
len = s.length();
if(len != 9){
return false;
}else {
String newString = s.substring(s.length()-1);
checksum = Integer.parseInt(newString);
sum = (7*(Integer.parseInt(""+s.charAt(0))+Integer.parseInt(""+s.charAt(3))+ Integer.parseInt(""+s.charAt(6)))) +
(3*(Integer.parseInt(""+s.charAt(1))+Integer.parseInt(""+s.charAt(4))+ Integer.parseInt(""+s.charAt(7))))+
(9*(Integer.parseInt(""+s.charAt(2))+Integer.parseInt(""+s.charAt(5))));
mod = sum % 10;
if(mod == checksum)
return true;
else
return false;
}
}
Just for fun, I wrote a Angular js directive for doing this same thing:
angular.module('ldPortal.directives')
.directive('routingnumber', function(){
return {
// only use as an attribute
restrict: 'A',
require: 'ngModel',
link: function(scope, elem, attr, ctrl){
var regex = new RegExp('^[0-9]{9}$','');
var num_at = function(str, index){
try {
return parseInt(str.charAt(index))
}catch (execption){
console.write(execption);
}
};
var validate = function(value){
if(! (value)){
return false;
}
var strVal = value.toString();
if (!regex.test(strVal)){
return false;
}
var checksum = parseInt(strVal.substr(strVal.length-1));
var sum = 0;
sum += 7 * (num_at(strVal, 0)+num_at(strVal, 3)+num_at(strVal,6));
sum += 3 * (num_at(strVal, 1)+num_at(strVal, 4)+num_at(strVal, 7));
sum += 9 * (num_at(strVal, 2)+num_at(strVal, 5));
var mod = sum % 10;
return checksum == mod;
};
ctrl.$parsers.push(function(value){
var is_valid = validate(value);
ctrl.$setValidity('routingnumber', is_valid);
return is_valid ? value : undefined;
});
ctrl.$formatters.push(function(value){
var is_valid = validate(value);
ctrl.$setValidity('routingnumber', is_valid);
return value;
});
}
};
});
I created a simple Routing Validator, hope this works.
RoutingNumberValidator:
import static java.lang.Character.getNumericValue;
public static class RoutingNumberValidator {
public boolean isValid(String value) {
boolean isValid = value != null && value.matches("[0-9]{9}");
if (isValid) {
int check = 0;
for ( int index = 0; index < 3; index++ ) {
int pos = index * 3;
check += getNumericValue(value.charAt(pos)) * 3;
check += getNumericValue(value.charAt(pos + 1)) * 7;
check += getNumericValue(value.charAt(pos + 2));
}
isValid = check != 0 && check % 10 == 0;
}
return isValid;
}
}
RoutingNumberValidatorTest:
public class RoutingNumberValidatorTest {
private List<String> validRoutingNumbers = Arrays.asList("122105155", "082000549");
private List<String> invalidRoutingNumbers = Arrays.asList("1232101155", "032000549");
#Test
public void isValid() throws Exception {
RoutingNumberValidator routingNumberValidator = new RoutingNumberValidator();
validRoutingNumbers.forEach(it-> assertThat(routingNumberValidator.isValid(it)).as("Invalid Routing Number should not be valid %s", it).isTrue());
invalidRoutingNumbers.forEach(it-> assertThat(routingNumberValidator.isValid(it)).as("Invalid Routing Number should not be valid %s", it).isFalse());
}
}
I know this question is old and is already answered many times, but this answer from BrainJar is quite concise and works perfectly. So I thought I'd share.
validateRoutingNumber(num: string) {
// Run through each digit and calculate the total.
let n = 0;
for (let i = 0; i < num.length; i += 3) {
n += parseInt(num.charAt(i), 10) * 3
+ parseInt(num.charAt(i + 1), 10) * 7
+ parseInt(num.charAt(i + 2), 10);
}
// If the resulting sum is an even multiple of ten (but not zero),
// the aba routing number is good.
if (n != 0 && n % 10 == 0) {
return true;
} else {
return false;
}
}
and here is for python:
def validate_routing_number(routing_number):
# quick easy validations
if routing_number is None or routing_number == '':
return False
invalid_routing_message = 'invalid routing number'
if not re.match(r'^[0-9]{9}$', routing_number):
return False
# here is the more complicated validation!
checksum = int(routing_number[-1]) # last digit
sum = 0 # http://en.wikipedia.org/wiki/Routing_transit_number
sum += 7 * (int(routing_number[0])+int(routing_number[3])+int(routing_number[6]))
sum += 3 * (int(routing_number[1])+int(routing_number[4])+int(routing_number[7]))
sum += 9 * (int(routing_number[2])+int(routing_number[5]))
mod = sum % 10
return checksum != mod
package RoutingNumberAlgo;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int checksum = 0, len = 0, sum = 0, mod = 0, rem = 0;
Scanner ss = new Scanner(System.in);
System.out.print("Enter the Routing Number: ");
String s = ss.nextLine();
len = s.length();
if (len != 9) {
System.out.print("Length not 9");
} else {
String newString = s.substring(s.length() - 1);
checksum = Integer.parseInt(newString);
sum = (3 * (Integer.parseInt("" + s.charAt(0)))) + (7 * (Integer.parseInt("" + s.charAt(1))))
+ (1 * (Integer.parseInt("" + s.charAt(2)))) + (3 * (Integer.parseInt("" + s.charAt(3))))
+ (7 * (Integer.parseInt("" + s.charAt(4)))) + (1 * (Integer.parseInt("" + s.charAt(5))))
+ (3 * (Integer.parseInt("" + s.charAt(6)))) + (7 * (Integer.parseInt("" + s.charAt(7))));
mod = 10 - (sum % 10);
if (mod == checksum)
System.out.print("True");
else
System.out.print("False");
;
}
}
}

Making change recursively: How do I modify my algorithm to print all combinations?

I have an algorithm that recursively makes change in the following manner:
public static int makeChange(int amount, int currentCoin) {
//if amount = zero, we are at the bottom of a successful recursion
if (amount == 0){
//return 1 to add this successful solution
return 1;
//check to see if we went too far
}else if(amount < 0){
//don't count this try if we went too far
return 0;
//if we have exhausted our list of coin values
}else if(currentCoin < 0){
return 0;
}else{
int firstWay = makeChange(amount, currentCoin-1);
int secondWay = makeChange(amount - availableCoins[currentCoin], currentCoin);
return firstWay + secondWay;
}
}
However, I'd like to add the capability to store or print each combination as they successfully return. I'm having a bit of a hard time wrapping my head around how to do this. The original algorithm was pretty easy, but now I am frustrated. Any suggestions?
CB
Without getting into the specifics of your code, one pattern is to carry a mutable container for your results in the arguments
public static int makeChange(int amount, int currentCoin, List<Integer>results) {
// ....
if (valid_result) {
results.add(result);
makeChange(...);
}
// ....
}
And call the function like this
List<Integer> results = new LinkedList<Integer>();
makeChange(amount, currentCoin, results);
// after makeChange has executed your results are saved in the variable "results"
I don't understand logic or purpose of above code but this is how you can have each combination stored and then printed.
public class MakeChange {
private static int[] availableCoins = {
1, 2, 5, 10, 20, 25, 50, 100 };
public static void main(String[] args) {
Collection<CombinationResult> results = makeChange(5, 7);
for (CombinationResult r : results) {
System.out.println(
"firstWay=" + r.getFirstWay() + " : secondWay="
+ r.getSecondWay() + " --- Sum=" + r.getSum());
}
}
public static class CombinationResult {
int firstWay;
int secondWay;
CombinationResult(int firstWay, int secondWay) {
this.firstWay = firstWay;
this.secondWay = secondWay;
}
public int getFirstWay() {
return this.firstWay;
}
public int getSecondWay() {
return this.secondWay;
}
public int getSum() {
return this.firstWay + this.secondWay;
}
public boolean equals(Object o) {
boolean flag = false;
if (o instanceof CombinationResult) {
CombinationResult r = (CombinationResult) o;
flag = this.firstWay == r.firstWay
&& this.secondWay == r.secondWay;
}
return flag;
}
public int hashCode() {
return this.firstWay + this.secondWay;
}
}
public static Collection<CombinationResult> makeChange(
int amount, int currentCoin) {
Collection<CombinationResult> results =
new ArrayList<CombinationResult>();
makeChange(amount, currentCoin, results);
return results;
}
public static int makeChange(int amount, int currentCoin,
Collection<CombinationResult> results) {
// if amount = zero, we are at the bottom of a successful recursion
if (amount == 0) {
// return 1 to add this successful solution
return 1;
// check to see if we went too far
} else if (amount < 0) {
// don't count this try if we went too far
return 0;
// if we have exhausted our list of coin values
} else if (currentCoin < 0) {
return 0;
} else {
int firstWay = makeChange(
amount, currentCoin - 1, results);
int secondWay = makeChange(
amount - availableCoins[currentCoin],
currentCoin, results);
CombinationResult resultEntry = new CombinationResult(
firstWay, secondWay);
results.add(resultEntry);
return firstWay + secondWay;
}
}
}
I used the following:
/**
* This is a recursive method that calculates and displays the combinations of the coins included in
* coinAmounts that sum to amountToBeChanged.
*
* #param coinsUsed is a list of each coin used so far in the total. If this branch is successful, we will add another coin on it.
* #param largestCoinUsed is used in the recursion to indicate at which coin we should start trying to add additional ones.
* #param amountSoFar is used in the recursion to indicate what sum we are currently at.
* #param amountToChange is the original amount that we are making change for.
* #return the number of successful attempts that this branch has calculated.
*/private static int change(List<Integer> coinsUsed, Integer currentCoin, Integer amountSoFar, Integer amountToChange)
{
//if last added coin took us to the correct sum, we have a winner!
if (amountSoFar == amountToChange)
{
//output
System.out.print("Change for "+amountToChange+" = ");
//run through the list of coins that we have and display each.
for(Integer count: coinsUsed){
System.out.print(count + " ");
}
System.out.println();
//pass this back to be tallied
return 1;
}
/*
* Check to see if we overshot the amountToBeChanged
*/
if (amountSoFar > amountToChange)
{
//this branch was unsuccessful
return 0;
}
//this holds the sum of the branches that we send below it
int successes=0;
// Pass through each coin to be used
for (Integer coin:coinAmounts)
{
//we only want to work on currentCoin and the coins after it
if (coin >= currentCoin)
{
//copy the list so we can branch from it
List<Integer> copyOfCoinsUsed = new ArrayList<Integer>(coinsUsed);
//add on one of our current coins
copyOfCoinsUsed.add(coin);
//branch and then collect successful attempts
successes += change(copyOfCoinsUsed, coin, amountSoFar + coin, amountToChange);
}
}
//pass back the current
return successes;
}

Categories

Resources