This is my code for the problem
Assume that the value of a = 1, b = 2, c = 3, ... , z = 26. You are
given a numeric string S. Write a program to return the list of all
possible codes that can be generated from the given string.
import java.util.*;
public class solution {
// Return a string array that contains all possible codes
public static String[] getCode(String input){
// Write your code here
List<String> arrStr = new ArrayList<>();
printAllPossibleCodes(input, "", arrStr);
// for(String name: arrStr) {
// System.out.println(name);
// }
String[] arr = new String[arrStr.size()];
for(int j =0; j < arrStr.size(); j++){
arr[j] = arrStr.get(j);
}
return arr;
}
public static char getChar(int n){
return (char) (n+96);
}
public static void printAllPossibleCodes(String input, String ans, List<String> arrStr){
if(input.length() == 0){
//System.out.println(ans);
arrStr.add(ans);
return;
}
int firstDigit = input.charAt(0) - '0';
printAllPossibleCodes(input.substring(1), ans + getChar(firstDigit), arrStr);
if(input.length() > 1){
int firstTwoDigits = (input.charAt(0) - '0') * 10 + (input.charAt(1) - '0');
if(firstTwoDigits >= 10 && firstTwoDigits <= 20){
printAllPossibleCodes(input.substring(2), ans + getChar(firstTwoDigits), arrStr);
}
}
}
}
I'm failing test cases for inputs "123" and "1123" while I'm passing the test for "35411". Where is my code going wrong?
You are requiring 10 <= firstTwoDigits <= 20 in order to call printAllPossibleCodes recursively in the two-digit case. However, as there are 26 letters in the English alphabet, the requirement should be 10 <= firstTwoDigits <= 26. Your first two test cases fail because they contain "23" as a substring, which is not between 10 and 20. However, the third test case contains no two-digit substring larger than 20 but less than 27 and thus does not have this issue.
Related
I am looking to create an algorithm preferably in Java. I would like to go through following char array and create every possible permutations and lengths out of it.
For example, loop and print the following:
a
aa
aaaa
aaaaa
.... keep going ....
aaaaaaaaaaaaaaaaa ....
ab
aba
abaa .............
Till I hit all possible lengths and permutations from my array.
private void method(){
char[] data = "abcdefghiABCDEFGHI0123456789".toCharArray();
// loop and print each time
}
I think it would be silly to come up with 10s of for loops for this. I am guessing some form of recursion would help here but can't get my head around to even start with. Could I get some help with this please? Even if pointing me to a start or a blog or something. Been Googling and looking around and many permutations examples exists but keeps to fixed max length. None seems to have examples on multiple length + permutations. Please advice. Thanks.
Another way to do it is this:
public class HelloWorld{
public static String[] method(char[] arr, int length) {
if(length == arr.length - 1) {
String[] strArr = new String[arr.length];
for(int i = 0; i < arr.length; i ++) {
strArr[i] = String.valueOf(arr[i]);
}
return strArr;
}
String[] before = method(arr, length + 1);
String[] newArr = new String[arr.length * before.length];
for(int i = 0; i < arr.length; i ++) {
for(int j = 0; j < before.length; j ++) {
if(i == 0)
System.out.println(before[j]);
newArr[i * before.length + j] = (arr[i] + before[j]);
}
}
return newArr;
}
public static void main(String []args){
String[] all = method("abcde".toCharArray(), 0);
for(int i = 0; i < all.length; i ++) {
System.out.println(all[i]);
}
}
}
However be careful you'll probably run out of memory or the program will take a looooong time to compile/run if it does at all. You are trying to print 3.437313508041091e+40 strings, that's 3 followed by 40 zeroes.
Here's the solution also in javascript because it starts running but it needs 4 seconds to get to 4 character permutations, for it to reach 5 character permutations it will need about 28 times that time, for 6 characters it's 4 * 28 * 28 and so on.
const method = (arr, length) => {
if(length === arr.length - 1)
return arr;
const hm = [];
const before = method(arr, length + 1);
for(let i = 0; i < arr.length; i ++) {
for(let j = 0; j < before.length; j ++) {
if(i === 0)
console.log(before[j]);
hm.push(arr[i] + before[j]);
}
}
return hm;
};
method('abcdefghiABCDEFGHI0123456789'.split(''), 0).forEach(a => console.log(a));
private void method(){
char[] data = "abcdefghiABCDEFGHI0123456789".toCharArray();
// loop and print each time
}
With your given input there are 3.43731350804×10E40 combinations. (Spelled result in words is eighteen quadrillion fourteen trillion three hundred ninety-eight billion five hundred nine million four hundred eighty-one thousand nine hundred eighty-four. ) If I remember it correctly the maths is some how
1 + x + x^2 + x^3 + x^4 + ... + x^n = (1 - x^n+1) / (1 - x)
in your case
28 + 28^2 + 28^3 + .... 28^28
cause you will have
28 combinations for strings with length one
28*28 combinations for strings with length two
28*28*28 combinations for strings with length three
...
28^28 combinations for strings with length 28
It will take a while to print them all.
One way I can think of is to use the Generex library, a Java library for generating String that match a given regular expression.
Generex github. Look at their page for more info.
Generex maven repo. Download the jar or add dependency.
Using generex is straight forward if you are somehow familiar with regex.
Example using only the first 5 chars which will have 3905 possible combinations
public static void main(String[] args) {
Generex generex = new Generex("[a-e]{1,5}");
System.out.println(generex.getAllMatchedStrings().size());
Iterator iterator = generex.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
Meaning of [a-e]{1,5} any combination of the chars a,b,c,d,e wit a min length of 1 and max length of 5
output
a
aa
aaa
aaaa
aaaaa
aaaab
aaaac
aaaad
aaaae
aaab
aaaba
aaabb
aaabc
aaabd
aaabe
aaac
....
eeee
eeeea
eeeeb
eeeec
eeeed
eeeee
You can have a for loop that starts from 1 and ends at array.length and in each iteration call a function that prints all the permutations for that length.
public void printPermutations(char[] array, int length) {
/*
* Create all permutations with length = length and print them
*/
}
public void method() {
char data = "abcdefghiABCDEFGHI0123456789".toCharArray();
for(int i = 1; i <= data.length; i ++) {
printPermutations(data, i);
}
}
I think the following recursion could solve your problem:
public static void main(String[] args) {
final String[] data = {"a", "b", "c"};
sampleWithReplacement(data, "", 1, 5);
}
private static void sampleWithReplacement(
final String[] letters,
final String prefix,
final int currentLength,
final int maxLength
) {
if (currentLength <= maxLength) {
for (String letter : letters) {
final String newPrefix = prefix + letter;
System.out.println(newPrefix);
sampleWithReplacement(letters, newPrefix, currentLength + 1, maxLength);
}
}
}
where data specifies your possible characters to sample from.
Is this what you're talking about?
public class PrintPermutations
{
public static String stream = "";
public static void printPermutations (char[] set, int count, int length)
{
if (count < length)
for (int i = 0; i < set.length; ++i)
{
stream += set[i];
System.out.println (stream);
printPermutations (set, count + 1, length);
stream = stream.substring (0, stream.length() - 1);
}
}
public static void main (String[] args)
{
char[] set = "abcdefghiABCDEFGHI0123456789".toCharArray();
printPermutations (set, 0, set.length);
}
}
Test it using a smaller string first.
On an input string 28 characters long this method is never going to end, but for smaller inputs it will generate all permutations up to length n, where n is the number of characters. It first prints all permutations of length 1, then all of length 2 etc, which is different from your example, but hopefully order doesn't matter.
static void permutations(char[] arr)
{
int[] idx = new int[arr.length];
char[] perm = new char[arr.length];
Arrays.fill(perm, arr[0]);
for (int i = 1; i < arr.length; i++)
{
while (true)
{
System.out.println(new String(perm, 0, i));
int k = i - 1;
for (; k >= 0; k--)
{
idx[k] += 1;
if (idx[k] < arr.length)
{
perm[k] = arr[idx[k]];
break;
}
idx[k] = 0;
perm[k] = arr[idx[k]];
}
if (k < 0)
break;
}
}
}
Test:
permutations("abc".toCharArray());
Output:
a
b
c
aa
ab
ac
ba
bb
bc
ca
cb
cc
I'm relatively new to java and am trying to break my code down as much as possible. This question is really on how to organize methods to work together
My credit card validator works if checkSum() code is written in the validateCreditCard() method. I think it's weird 'cause it works when called by the checkDigitControl() method
I used these sources for the program's logic:
To Check ~ https://www.creditcardvalidator.org/articles/luhn-algorithm
To Generate ~ https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm
Here's my code(I apologize in advance if it's rather clumsy)
public class CreditCards {
public static void main(String[] args) {
long num;
num = genCreditCard();
boolean bool = validateCreditCard(num);
}
// Validity Check
public static boolean validateCreditCard(long card) {
String number = card+"";
String string=null;
int i;
for(i=0; i<number.length()-1; i++) {//Populate new string, leaving out last digit.
string += number.charAt(i)+"";
}
String checkDigit = number.charAt(i)+"";// Stores check digit.
long sum = checkSum(string);// Program works if this line is swapped for the code below(from checkSum)
//**********************************************************************
// int[] digits = new int[number.length()];
// int lastIndex = digits.length-1;
// int position=2; int mod=10;
// int sum=0;
//
// for(int j=lastIndex; j>=0; j--) {// Populate array in REVERSE
// digits[j] = Integer.parseInt(number.charAt(j)+"");
// digits[j] *= ( (position%2 == 0) ? 2: 1 );// x2 every other digit FROM BEHIND
// position++;
//
// digits[j] = ( (digits[j] > 9) ? (digits[j] / mod)+(digits[j] % mod) : digits[j] );//Sums integers of double-digits
// sum += digits[j];
// }
//**********************************************************************
sum *= 9;
string = sum+"";
string = string.charAt(string.length()-1)+"";// Last digit of result.
return (string.equals(checkDigit));
}
public static long genCreditCard() {
String number = "34";// American Express(15 digits) starts with 34 or 37
for(int i=0; i<12; i++)
number += (int)(Math.random() * 10) + "";// Add 12 random digits 4 base.
number += checkDigitControl(number);// Concat the check digit.
System.out.println(number);
return Long.parseLong(number);
}
// Algorithm to calculate the last/checkSum digit.
public static int checkDigitControl(String number) {
int i;
for(i=0; i<5; i++)
++i;
int sum = checkSum(number);
return 10 - sum%10;// Returns number that makes checkSum a multiple of 10.
}
public static int checkSum(String number) {
int[] digits = new int[number.length()];
int lastIndex = digits.length-1;
int position=2; int mod=10;
int sum=0;
for(int j=lastIndex; j>=0; j--) {// Populate array in REVERSE
digits[j] = Integer.parseInt(number.charAt(j)+"");
digits[j] *= ( (position%2 == 0) ? 2: 1 );// x2 every other digit FROM BEHIND
position++;
digits[j] = ( (digits[j] > 9) ? (digits[j] / mod)+(digits[j] % mod) : digits[j] );//Sums integers of double-digits
sum += digits[j];
}
return sum;
}
}
Thx in advance, sorry if this isn't the right format; it's also my 1st Stackoverflow post ¯\_(ツ)_/¯
You are initializing the variable string with null value:
String string=null;
And in the following for you are adding every char of the card number to this string.
for(i=0; i<number.length()-1; i++) {
string += number.charAt(i)+"";
}
But this will result in the variable string to be null + cardnumbers, because you didn't initialize the String string, and the value null is converted to the string "null" (Concatenating null strings in Java)
This will fix you code:
String string = new String();
Note, this code:
for(i=0; i<number.length()-1; i++) {
string += number.charAt(i)+"";
}
can be easily replace by this line that does the same thing:
number = number.substring(0, number.length() -1);
If you switch to this code just pass number to checkSum method
I have a string format as '2112';
The possible combination should represent an Alphabet.
2,112 is not allowed as 112 is a three digit character and it cannot represent an alphabet, so basically 'a' represents 1 and 'z' represents 26.
like for this the possible combination is (2,1,1,2), (21,1,2),(2,11,2),(2,1,12),(21,21).
So here the characters are not reordered but have been split into combinations.
How do I approach it?
My tries:
public static void main(String[] args) {
System.out.println(permutationFinder("2112"));
}
private static Set<String> permutationFinder(String str) {
for (int i = 0; i < str.length(); i++) {
}
Set<String> stringSet = new HashSet<>();
if(str == null){
return null;
}
else if(str.length()==0){
stringSet.add("");
return stringSet;
}
char initial = str.charAt(0);
String rem = str.substring(1);
Set<String> words = permutationFinder(rem);
for(String word : words){
int length = word.length();
for(int i = 0; i <= length; i++){
stringSet.add(merge(word, initial, i));
}
}
return stringSet;
}
private static String merge(String word, char initial, int i) {
String begin = word.substring(0,i);
String end = word.substring(i);
return begin + initial + end;
}
But this gives combination.
I didn’t understand how your method was supposed to work, and then of course neither why it didn’t, sorry.
The standard solution for a combination problem like this one is recursion, the concept of a method calling it self to have a part of its task done. If you don’t know recursion, look it up and prepare for a learning curve. In this case I suggest that the method finds the possible first letters in the beginning of the string (in your example they would be 2 and 21), then calls itself recursively to find all possible combinations of the remainder of the string, finally puts the pieces together to form a full solution. Since we always call with ever shorter string arguments, we can be sure that the recursion will not continue infinitely. Sooner or later we will pass the empty string. So the first thing to consider is, what is the desired result for an empty string? It’s the empty list of letters. Now we can write the method:
private static List<List<String>> combinationFinder(String str) {
if (str.isEmpty()) {
return Collections.singletonList(Collections.emptyList());
}
List<List<String>> result = new ArrayList<>();
// can we split off 1 char from the start? requires just non-zero
if (str.charAt(0) != '0') {
String firstChar = str.substring(0, 1);
if (!Character.isDigit(firstChar.charAt(0))) {
throw new IllegalArgumentException("Not a digit: " + firstChar);
}
List<List<String>> combinationsOfRemainingStr
= combinationFinder(str.substring(1));
addAllCombos(result, firstChar, combinationsOfRemainingStr);
}
// can we split off 2 chars?
if (str.length() >= 2) {
String firstSubstring = str.substring(0, 2);
int firstNumber = Integer.parseInt(firstSubstring);
if (firstNumber >= 1 && firstNumber <= 26) { // OK
List<List<String>> combinationsOfRemainingStr
= combinationFinder(str.substring(2));
addAllCombos(result, firstSubstring, combinationsOfRemainingStr);
}
}
return result;
}
/** adds to result all lists made up of firstElement followed by a list from remainingElements */
private static void addAllCombos(List<List<String>> result,
String firstElement, List<List<String>> remainingElements) {
for (List<String> remCombo : remainingElements) {
List<String> totalCombo = new ArrayList<>(1 + remCombo.size());
totalCombo.add(firstElement);
totalCombo.addAll(remCombo);
result.add(totalCombo);
}
}
With your input example, 2112, this returns:
[[2, 1, 1, 2], [2, 1, 12], [2, 11, 2], [21, 1, 2], [21, 12]]
I believe this is exactly what you asked for.
The method is a little bit inconsistent as I wrote it: it will find 01 as a letter from the beginning of the string, but neither 001 nor 026. If this is an issue, I trust you to mend it.
Try the following code to
private static Set<String> findCharacterEquivalants(String str){
Set<String> charEqs = new HashSet<>();
int strLen = str.length();
for(int i = 0; i < strLen; i++){
if(str.charAt(i) == '0'){
//Skip it since 0 is not a match for any character
continue;
}
//single character which is not zero is always a match
charEqs.add("" + str.charAt(i));
switch(str.charAt(i)){
case '1' :
//Check to see whether combination of this char with the next char is a match
if((i + 1) < strLen){
charEqs.add("" + str.charAt(i) + str.charAt(i + 1));
}
break;
case '2' :
//Check to see whether combination of this char with the next char is a match.
if(((i + 1) < strLen)
&& (str.charAt(i + 1) == '0' || str.charAt(i + 1) == '1' || str.charAt(i + 1) == '2' || str.charAt(i + 1) == '3' || str.charAt(i + 1) == '4' || str.charAt(i + 1) == '5' || str.charAt(i + 1) == '6')){
charEqs.add("" + str.charAt(i) + str.charAt(i + 1));
}
}
}
return charEqs;
}
Note that this method takes the assumption that the permutations keep the order of characters in the string supplied. If you want to allow duplication of these substrings, use a List instead of Set.
I had a coding interview over the phone and was asked this question:
Given a String (for example):
"aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc"
and an expression (for example):
"a+b+c-"
where:
+: means the char before it is repeated 2 times
-: means the char before it is repeated 4 times
Find the number of times the given expression appears in the string with the operands occurring non continuously and continuously.
The above expression occurs 4 times:
1) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
2) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
3) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
4) aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc
^^ ^^ ^^^^
aa bb cccc
I had no idea how to do it. I started doing an iterative brute force method with lots of marking of indices but realized how messy and hard that would to code half way through:
import java.util.*;
public class Main {
public static int count(String expression, String input) {
int count = 0;
ArrayList<char[]> list = new ArrayList<char[]>();
// Create an ArrayList of chars to iterate through the expression and match to string
for(int i = 1; i<expression.length(); i=i+2) {
StringBuilder exp = new StringBuilder();
char curr = expression.charAt(i-1);
if(expression.charAt(i) == '+') {
exp.append(curr).append(curr);
list.add(exp.toString().toCharArray());
}
else { // character is '-'
exp.append(curr).append(curr).append(curr).append(curr);
list.add(exp.toString().toCharArray());
}
}
char[] inputArray = input.toCharArray();
int i = 0; // outside pointer
int j = 0; // inside pointer
while(i <= inputArray.length) {
while(j <= inputArray.length) {
for(int k = 0; k< list.size(); k++) {
/* loop through
* all possible combinations in array list
* with multiple loops
*/
}
j++;
}
i++;
j=i;
}
return count;
}
public static void main(String[] args) {
String expression = "a+b+c-";
String input = "aaksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc";
System.out.println("The expression occurs: "+count(expression, input)+" times");
}
}
After spending a lot of time doing it iteratively he mentioned recursion and I still couldn't see a clear way doing it recursively and I wasn't able to solve the question. I am trying to solve it now post-interview and am still not sure how to go about this question. How should I go about solving this problem? Is the solution obvious? I thought this was a really hard question for a coding phone interview.
Non-recursion algorithm that requires O(m) space and operates in O(n*m), where m is number of tokens in query:
#Test
public void subequences() {
String input = "aabbccaacccccbbd";
String query = "a+b+";
// here to store tokens of a query: e.g. {a, +}, {b, +}
char[][] q = new char[query.length() / 2][];
// here to store counts of subsequences ending by j-th token found so far
int[] c = new int[query.length() / 2]; // main
int[] cc = new int[query.length() / 2]; // aux
// tokenize
for (int i = 0; i < query.length(); i += 2)
q[i / 2] = new char[] {query.charAt(i), query.charAt(i + 1)};
// init
char[] sub2 = {0, 0}; // accumulator capturing last 2 chars
char[] sub4 = {0, 0, 0, 0}; // accumulator capturing last 4 chars
// main loop
for (int i = 0; i < input.length(); i++) {
shift(sub2, input.charAt(i));
shift(sub4, input.charAt(i));
boolean all2 = sub2[1] != 0 && sub2[0] == sub2[1]; // true if all sub2 chars are same
boolean all4 = sub4[3] != 0 && sub4[0] == sub4[1] // true if all sub4 chars are same
&& sub4[0] == sub4[2] && sub4[0] == sub4[3];
// iterate tokens
for (int j = 0; j < c.length; j++) {
if (all2 && q[j][1] == '+' && q[j][0] == sub2[0]) // found match for "+" token
cc[j] = j == 0 // filling up aux array
? c[j] + 1 // first token, increment counter by 1
: c[j] + c[j - 1]; // add value of preceding token counter
if (all4 && q[j][1] == '-' && q[j][0] == sub4[0]) // found match for "-" token
cc[j] = j == 0
? c[j] + 1
: c[j] + c[j - 1];
}
if (all2) sub2[1] = 0; // clear, to make "aa" occur in "aaaa" 2, not 3 times
if (all4) sub4[3] = 0;
copy(cc, c); // copy aux array to main
}
}
System.out.println(c[c.length - 1]);
}
// shifts array 1 char left and puts c at the end
void shift(char[] cc, char c) {
for (int i = 1; i < cc.length; i++)
cc[i - 1] = cc[i];
cc[cc.length - 1] = c;
}
// copies array contents
void copy(int[] from, int[] to) {
for (int i = 0; i < from.length; i++)
to[i] = from[i];
}
The main idea is to catch chars from the input one by one, holding them in 2- and 4-char accumulators and check if any of them match some tokens of the query, remembering how many matches have we got for sub-queries ending by these tokens so far.
Query (a+b+c-) is splitted into tokens (a+, b+, c-). Then we collect chars in accumulators and check if they match some tokens. If we find match for first token, we increment its counter by 1. If we find match for another j-th token, we can create as many additional subsequences matching subquery composed of tokens [0...j], as many of them now exist for subquery composed of tokens [0... j-1], because this match can be appended to every of them.
For example, we have:
a+ : 3 (3 matches for a+)
b+ : 2 (2 matches for a+b+)
c- : 1 (1 match for a+b+c-)
when cccc arrives. Then c- counter should be increased by b+ counter value, because so far we have 2 a+b+ subsequences and cccc can be appended to both of them.
Let's call the length of the string n, and the length of the query expression (in terms of the number of "units", like a+ or b-) m.
It's not clear exactly what you mean by "continuously" and "non-continuously", but if "continuously" means that there can't be any gaps between query string units, then you can just use the KMP algorithm to find all instances in O(m+n) time.
We can solve the "non-continuous" version in O(nm) time and space with dynamic programming. Basically, what we want to compute is a function:
f(i, j) = the number of occurrences of the subquery consisting of the first i units
of the query expression, in the first j characters of the string.
So with your example, f(2, 41) = 2, since there are 2 separate occurrences of the subpattern a+b+ in the first 41 characters of your example string.
The final answer will then be f(n, m).
We can compute this recursively as follows:
f(0, j) = 0
f(i, 0) = 0
f(i > 0, j > 0) = f(i, j-1) + isMatch(i, j) * f(i-1, j-len(i))
where len(i) is the length of the ith unit in the expression (always 2 or 4) and isMatch(i, j) is a function that returns 1 if the ith unit in the expression matches the text ending at position j, and 0 otherwise. For example, isMatch(15, 2) = 1 in your example, because s[14..15] = bb. This function takes just constant time to run, because it never needs to check more than 4 characters.
The above recursion will already work as-is, but we can save time by making sure that we only solve each subproblem once. Because the function f() depends only on its 2 parameters i and j, which range between 0 and m, and between 0 and n, respectively, we can just compute all n*m possible answers and store them in a table.
[EDIT: As Sasha Salauyou points out, the space requirement can in fact be reduced to O(m). We never need to access values of f(i, k) with k < j-1, so instead of storing m columns in the table we can just store 2, and alternate between them by always accessing column m % 2.]
Wanted to try it for myself and figured I could then share my solution as well. The parse method obviously has issues when there is indeed a char 0 in the expression (although that would probably be the bigger issue itself), the find method will fail for an empty needles array and I wasn't sure if ab+c- should be considered a valid pattern (I treat it as such). Note that this covers only the non-continous part so far.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Matcher {
public static void main(String[] args) {
String haystack = "aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc";
String[] needles = parse("a+b+c-");
System.out.println("Needles: " + Arrays.toString(needles));
System.out.println("Found: " + find(haystack, needles, 0));
needles = parse("ab+c-");
System.out.println("Needles: " + Arrays.toString(needles));
System.out.println("Found: " + find(haystack, needles, 0));
}
private static int find(String haystack, String[] needles, int i) {
String currentNeedle = needles[i];
int pos = haystack.indexOf(currentNeedle);
if (pos < 0) {
// Abort: Current needle not found
return 0;
}
// Current needle found (also means that pos + currentNeedle.length() will always
// be <= haystack.length()
String remainingHaystack = haystack.substring(pos + currentNeedle.length());
// Last needle?
if (i == needles.length - 1) {
// +1: We found one match for all needles
// Try to find more matches of current needle in remaining haystack
return 1 + find(remainingHaystack, needles, i);
}
// Try to find more matches of current needle in remaining haystack
// Try to find next needle in remaining haystack
return find(remainingHaystack, needles, i) + find(remainingHaystack, needles, i + 1);
}
private static String[] parse(String expression) {
List<String> searchTokens = new ArrayList<String>();
char lastChar = 0;
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
char[] chars;
switch (c) {
case '+':
// last char is repeated 2 times
chars = new char[2];
Arrays.fill(chars, lastChar);
searchTokens.add(String.valueOf(chars));
lastChar = 0;
break;
case '-':
// last char is repeated 4 times
chars = new char[4];
Arrays.fill(chars, lastChar);
searchTokens.add(String.valueOf(chars));
lastChar = 0;
break;
default:
if (lastChar != 0) {
searchTokens.add(String.valueOf(lastChar));
}
lastChar = c;
}
}
return searchTokens.toArray(new String[searchTokens.size()]);
}
}
Output:
Needles: [aa, bb, cccc]
Found: 4
Needles: [a, bb, cccc]
Found: 18
How about preprocessing aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc?
This become a1k1s1d1b1a2l1a1s1k1d1h1f1b2l1a1j1d1f1h1a1c4a1o1u1d1g1a1l1s1a2b2l1i1s1d1f1h1c4
Now find occurrences of a2, b2, c4.
Tried it code below but right now it gives only first possible match based of depth first.
Need to be changed to do all possible combination instead of just first
import java.util.ArrayList;
import java.util.List;
public class Parsing {
public static void main(String[] args) {
String input = "aksdbaalaskdhfbblajdfhacccc aoudgalsaa bblisdfhcccc";
System.out.println(input);
for (int i = 0; i < input.length(); i++) {
System.out.print(i/10);
}
System.out.println();
for (int i = 0; i < input.length(); i++) {
System.out.print(i%10);
}
System.out.println();
List<String> tokenisedSearch = parseExp("a+b+c-");
System.out.println(tokenisedSearch);
parse(input, 0, tokenisedSearch, 0);
}
public static boolean parse(String input, int searchFromIndex, List<String> tokensToSeach, int currentTokenIndex) {
if(currentTokenIndex >= tokensToSeach.size())
return true;
String token = tokensToSeach.get(currentTokenIndex);
int found = input.indexOf(token, searchFromIndex);
if(found >= 0) {
System.out.println("Found at Index "+found+ " Token " +token);
return parse(input, searchFromIndex+1, tokensToSeach, currentTokenIndex+1);
}
return false;
}
public static List<String> parseExp(String exp) {
List<String> list = new ArrayList<String>();
String runningToken = "";
for (int i = 0; i < exp.length(); i++) {
char at = exp.charAt(i);
switch (at) {
case '+' :
runningToken += runningToken;
list.add(runningToken);
runningToken = "";
break;
case '-' :
runningToken += runningToken;
runningToken += runningToken;
list.add(runningToken);
runningToken = "";
break;
default :
runningToken += at;
}
}
return list;
}
}
Recursion may be the following (pseudocode):
int search(String s, String expression) {
if expression consists of only one token t /* e. g. "a+" */ {
search for t in s
return number of occurrences
} else {
int result = 0
divide expression into first token t and rest expression
// e. g. "a+a+b-" -> t = "a+", rest = "a+b-"
search for t in s
for each occurrence {
s1 = substring of s from the position of occurrence to the end
result += search(s1, rest) // search for rest of expression in rest of string
}
return result
}
}
Applying this to entire string, you'll get number of non-continuous occurrences. To get continuous occurrences, you don't need recursion at all--just transform expression into string and search by iteration.
If you convert the search string first with a simple parser/compiler so a+ becomes aa etc. then you can simply take this string and run a regular expression match against your hay stack. (Sorry, I'm no Java coder so can't deliver any real code but it is not really difficult)
I didn't start too long ago with programming, and currently I need a method to produce an array, containing a character which is comes after the previous character. It should start with an 'A' at 0, then a B at '1' etc.. The hard part is making it so that after the 'Z' comes 'AA'.
What I came up with:
public static String[] charArray(int length)
{
String[] res = new String[length];
for(int i = 0; i < length; i++)
{
String name = "";
int colNumber = i;
while(colNumber > 0)
{
char c = (char) ('A' + (colNumber % 26));
name = c + name;
colNumber = colNumber / 26;
}
res[i] = name;
}
return res;
}
This works fine for the first 26 letters of the alphabet, but it produces "... Y, Z, BA, BB, BC..." instead of "... Y, Z, AA, AB, AC..."
What's wrong? Or are there any more efficient or easier ways to do this?
Thanks in advance!
You had a nice start. Instead of running through the while loop this example basically calculates the value of C based on the number % 26
Then the letter is added (concatenated) to the value within the array at the position: (index / 26) - 1 which ensures it's keeping up with the changes over time.
When iterating through on the first go, you'll have only one letter in each slot in the array A B C etc.
Once you've run through the alphabet, you'll then have an index that looks backwards and adds the current letter to that value.
You'll eventually get into AAA AAB AAC etc. or even more.
public static String[] colArray(int length) {
String[] result = new String[length];
String colName = "";
for(int i = 0; i < length; i++) {
char c = (char)('A' + (i % 26));
colName = c + "";
if(i > 25){
colName = result[(i / 26) - 1] + "" + c;
}
result[i] = colName;
}
return result;
}
Try like this:
public static String[] charArray(int length)
{
String[] res = new String[length];
int counter = 0;
for(int i = 0; counter < length; i++)
{
String name = "";
int colNumber = i;
while(colNumber > 0 && colNumber % 27 != 0)
{
char c = (char) ('A' + ((colNumber) % 27) - 1);
name = c + name;
colNumber = colNumber / 27;
}
res[counter] = name;
if (i % 27 != 0) {
counter++;
}
}
return res;
}
Basically your algorithm skipped all elements starting with an A (A, AA, AB, ...) (because an A is created when colNumber is 0, but this never happens because your while terminates in that case). Taking modulo of 27 and then actually subtracting 1 after from the char fixes this issue. Then we use counter as index as otherwise we would end up with some empty elements in the array (the ones where i would be i % 27 == 0).
This solution works for me. Having 26 vocabulary letters and knowing that 65 is the char 'A' in ASCII table, we can get the incrementing with this recursive method...
private fun indexLetters(index: Int, prefix: String = "") : String {
val indexSuffix:Int = index.rem(26)
val suffix = (65 + indexSuffix).toChar().toString().plus(".")
val newPrefix = suffix.plus(prefix)
val indexPrefix: Int = index / 26
return if (indexPrefix > 0) {
indexLetters(indexPrefix - 1, newPrefix)
} else {
newPrefix
}
}
You can call this kotlin method like
indexLetters(0) //To get an 'A'
indexLetters(25) //To get a 'Z'
indexLetters(26) //To get an 'A.A'
etcetera...
from an array iteration, depending of your requirements