string-comparison algorithm for user defined dictionary - java

In my project the user input is translated to a string in the form of [x,x,x,x,x,x,x,x,x,x] where x is a number between 1 and 8 and stored to a library of this type of strings. Later I have to compare the user new input with every string in that library.
So I'm trying to find the similarity between two strings of the mention format. I tried the Levenhstein distance algorithm but it does not suit my needs. For the strings [1,8,7,6,5,4,3,2,0,0] and [1,7,6,5,4,3,2,0,0,0], Levenhstein finds distance of 7 while in my prospective the distance is only one. Levenhstein only edits each character but does not shift the characters.
Can someone suggest another spell-check or string-compare algorithm with the criteria I mentioned before?
Levenshtein algorithm I used:
public static int getLevenshteinDistance(String s, String t)
{
if (s == null || t == null)
{
throw new IllegalArgumentException("Strings must not be null");
}
int d[][]; // matrix
int n; // length of s
int m; // length of t
int i; // iterates through s
int j; // iterates through t
char s_i; // ith character of s
char t_j; // jth character of t
int cost; // cost
// Step 1
n = s.length();
m = t.length();
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
d = new int[n + 1][m + 1];
// Step 2
for (i = 0; i <= n; i++)
{
d[i][0] = i;
}
for (j = 0; j <= m; j++)
{
d[0][j] = j;
}
// Step 3
for (i = 1; i <= n; i++)
{
s_i = s.charAt(i - 1);
// Step 4
for (j = 1; j <= m; j++)
{
t_j = t.charAt(j - 1);
// Step 5
if (s_i == t_j)
{
cost = 0;
}
else
{
cost = 1;
}
// Step 6
d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
}
}
// Step 7
return d[n][m];
}

Related

What exactly is special on this case that my median algorithm doesn't work anymore?

I wrote a code in java for school to compute the median of an array.
We have some test cases for this. The first column is the input, the second the expected and the third the actual output. Is anything special on the case that does not work? I've worked so long on this code now and slowly but surely i am getting frustrated. I really don't know where or why my code does not work in this specific scenario. the code is the following:
/**
* This class calculates the median of a list to use it in quicksort for a runtime of O(log(n));
* #author Niklas
*
*/
public class Median {
/**
* The position i.
*/
private static int positionI = -1;
/**
* a help array for the quicksort algorithm.
*/
private static int[] quicksortArray;
/**
* Computes and retrieves the lower median of the given array of numbers using
* the Median algorithm presented in the lecture.
*
* #param input numbers.
* #return the lower median.
* #throw IllegalArgumentException if the array is {#code null} or empty.
*/
public static int lowerMedian(int[] numbers) {
if (numbers.length == 0 || numbers == null) {
throw new IllegalArgumentException("Array must contain values");
}
// avoiding that positionI is part of the recursion
if (positionI == -1) {
positionI = (int) Math.floor((double) ((numbers.length + 1) / 2));
}
// Step 1: dividing the list into groups.
int[] medians = new int[(int) Math.ceil((float) numbers.length / 5)];
int[] subArray = new int[5];
int positionForMedianArray = 0;
// the end case that the array is < 5.
if (numbers.length <= 5) {
sortArray(numbers);
if (positionI <= numbers.length) {
return numbers[positionI - 1];
}
return numbers.length % 2 == 0 ? numbers[(numbers.length / 2) - 1] : numbers[numbers.length / 2];
}
for (int i = 0; i < numbers.length; i += 5) {
if (numbers.length < i + 5) {
subArray = Arrays.copyOfRange(numbers, i, numbers.length);
} else {
subArray = Arrays.copyOfRange(numbers, i, i + 5);
}
// Step 2: calculate the median of each subArray.
sortArray(subArray);
medians[positionForMedianArray] = subArray.length % 2 == 0 ? subArray[subArray.length / 2 - 1]
: subArray[subArray.length / 2];
positionForMedianArray += 1;
}
// Step 3: calculate x recursively
int x = lowerMedian(medians);
// Step 4: partioniate the lists.
// computing how big the arrays have to be because arraylists doesnt work as
// good in this code.
int countS = 0;
int countG = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] < x) {
countS += 1;
} else if (numbers[i] > x) {
countG += 1;
}
}
// creating the arrays with the right size.
int[] smaller = new int[countS];
int[] greater = new int[countG];
countS = 0;
countG = 0;
// filling the Arrays (L1 and L2).
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] < x) {
smaller[countS] = numbers[i];
countS += 1;
} else if (numbers[i] > x) {
greater[countG] = numbers[i];
countG += 1;
}
}
int k = smaller.length + 1;
// for testing
// System.out.println("\nnumbers: " + Arrays.toString(numbers));
// System.out.println("position i: " + positionI);
// System.out.println("SubArray " + (positionForMedianArray) + ": " + Arrays.toString(subArray));
// System.out.println("Median Array im Durchlauf " + (positionForMedianArray) + ": " + Arrays.toString(medians));
// System.out.println("x: " + x);
// System.out.println("L1: " + Arrays.toString(smaller));
// System.out.println("L2: " + Arrays.toString(greater));
// System.out.println("Position k: " + k);
if (positionI < k) {
return lowerMedian(smaller);
} else if (positionI > k) {
positionI -= k;
return lowerMedian(greater);
}
return x;
}
/**
* Sorts the given array in an inefficent way.
*
* #param numbers the array to sort.
*/
private static void sortArray(int[] numbers) {
for (int i = 0; i < numbers.length; i++) {
for (int j = 0; j < numbers.length; j++) {
if (numbers[i] < numbers[j]) {
int tempVar = numbers[j];
numbers[j] = numbers[i];
numbers[i] = tempVar;
}
}
}
}
I would appreciate any kind of help!
I'm not sure why your approach for calculating low median is so complicated. All you need to do is sort the list of number and if the list has odd number of values then just return value at <array length> / 2 and if the list has even number of values then return value at (<array_length> / 2) - 1. Regarding the sorting the input list, you can either implement your own quicksort algorithm or use Arrays.sort. Below is a potential approach to calculate lower median using Java built-in sort method.
public static int lowerMedian(int[] numbers) {
Arrays.sort(numbers, 0, numbers.length);
int length = numbers.length;
if (length == 0) {
return 0;
} else if (length % 2 == 0) {
return numbers[(length / 2) - 1];
} else {
return numbers[length / 2];
}
}

Is there a recursion that checks whether the matrix diagonally has a sequence of alphabetic letters

I got a homework assignment, I have to find a recursive function that gets a 2D matrix and the number of rows in a matrix and returns true / false If the diagonal of the matrix has a sequence of letters a b c,
Can not think of a solution
public static void main(String[] args) {
char[][] mat = new char[5][5];
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[i].length; j++)
mat[i][j] = (char) (int) ((Math.random() * 26) + 'a');
}
for (int i=0 ; i <mat.length ; i++)
mat[i][i] = (char)('a' + i);
//mat[2][2] = 'b';
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[i].length; j++)
System.out.print(mat[i][j] + " ");
System.out.println();
}
System.out.println(isDiagonalLettersSequence(mat, mat.length));
}[Here are two examples that I hope will help me explain myself][1]
https://i.stack.imgur.com/Z6qmn.png
This is pretty simple. Just check on each iteration if the current value is equals to previous +1:
public static boolean isDiagonalHasSequence(char[][] matrix) {
return isDiagonalHasSequence(matrix, 0);
}
private static boolean isDiagonalHasSequence(char[][] matrix, int row) {
if (row > 0 && row < matrix.length) {
// check diagonal \
if (matrix[row][row] != matrix[row - 1][row - 1] + 1)
return false;
// check diagonal /
if (matrix[row][matrix.length - row - 1] != matrix[row - 1][matrix.length - row - 2] + 1)
return false;
}
return row == matrix.length || isDiagonalHasSequence(matrix, row + 1);
}
In the main function:
String[][] arr = { {"a","e","d"},
{"h","b","c"},
{"f","f","c"}};
if(diagonal(arr, 0).equals("abc"))
System.out.print("true");
And the global recursive function should be:
public static String diagonal(String[][] arr, int i) {
if(i == arr.length - 1)
return arr[i][i];
return arr[i][i] + diagonal(arr, i + 1);
}

Edit Distance between the words comparing between two Strings

I have seen many resources from the internet but couldn't found the exact help. i am trying to figure out the edit distance between the two strings example:
String a = "put return between paragraph gioo";
String b = "put hello between line phone gio";
here I am always comparing with String a with the other string so here the edit distance should be 4.
I have done some code execution its comparing me with the each character in the string.
int len1 = row10.length();
int len2 = row01.length();
int[][] dp = new int[len1 + 1][len2 + 1];
for (int i = 0; i <= len1; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= len2; j++) {
dp[0][j] = j;
}
for (int i = 0; i < len1; i++) {
char c1 = row10.charAt(i);
for (int j = 0; j < len2; j++) {
char c2 = row01.charAt(j);
if (c1 == c2) {
dp[i + 1][j + 1] = dp[i][j];
} else {
int replace = dp[i][j] + 1;
int insert = dp[i][j + 1] + 1;
int delete = dp[i + 1][j] + 1;
int min = replace > insert ? insert : replace;
min = delete > min ? min : delete;
dp[i + 1][j + 1] = min;
}
}
}
System.out.println(dp[len1][len2]);
Made a sample function. It doesn't really take into the consideration of corner cases but it works. Also, do think about the case sensitivity of the words.
package test;
public class CalcWordDiff {
public static void main(String[] args) {
// TODO Auto-generated method stub
String a = "My name is ABC.";
String b = "My name xyz.";
System.out.println("Edit distance will be : "+calcDistanceBetweenWords(a,b));
}
public static int calcDistanceBetweenWords(String first, String second)
{
int res = 0;
String[] words_string_first = first.trim().split(" "); // By trim, I removed the Whitespaces if they exist
String[] words_string_second = second.trim().split(" ");
//Check the length of both the arrays
System.out.println("Size of arrays first is : "+words_string_first.length);
System.out.println("Size of arrays second is : "+words_string_second.length);
int lowerWordSentSize = 0;
if(words_string_first.length<=words_string_second.length)
{
lowerWordSentSize = words_string_first.length;
}
else
{
lowerWordSentSize = words_string_second.length;
}
//Now iterate through the array of lower size
for(int i = 0; i< lowerWordSentSize; i++)
{
if(words_string_first[i].equals(words_string_second[i]))
{
//Do nothing, it means both the words are same
}
else
{
System.out.println("Words mismatched at "+(i+1)+" th Position.");
res = i;
}
}
return res;
}
}

Count the minimum number of jumps required for a frog to get to the other side of a river

I work with a Codility problem provided below,
The Fibonacci sequence is defined using the following recursive formula:
F(0) = 0
F(1) = 1
F(M) = F(M - 1) + F(M - 2) if M >= 2
A small frog wants to get to the other side of a river. The frog is initially located at one bank of the river (position −1) and wants to get to the other bank (position N). The frog can jump over any distance F(K), where F(K) is the K-th Fibonacci number. Luckily, there are many leaves on the river, and the frog can jump between the leaves, but only in the direction of the bank at position N.
The leaves on the river are represented in an array A consisting of N integers. Consecutive elements of array A represent consecutive positions from 0 to N − 1 on the river. Array A contains only 0s and/or 1s:
0 represents a position without a leaf;
1 represents a position containing a leaf.
The goal is to count the minimum number of jumps in which the frog can get to the other side of the river (from position −1 to position N). The frog can jump between positions −1 and N (the banks of the river) and every position containing a leaf.
For example, consider array A such that:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
The frog can make three jumps of length F(5) = 5, F(3) = 2 and F(5) = 5.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A consisting of N integers, returns the minimum number of jumps by which the frog can get to the other side of the river. If the frog cannot reach the other side of the river, the function should return −1.
For example, given:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
the function should return 3, as explained above.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer that can have one of the following values: 0, 1.
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I wrote the following solution,
class Solution {
private class Jump {
int position;
int number;
public int getPosition() {
return position;
}
public int getNumber() {
return number;
}
public Jump(int pos, int number) {
this.position = pos;
this.number = number;
}
}
public int solution(int[] A) {
int N = A.length;
List<Integer> fibs = getFibonacciNumbers(N + 1);
Stack<Jump> jumps = new Stack<>();
jumps.push(new Jump(-1, 0));
boolean[] visited = new boolean[N];
while (!jumps.isEmpty()) {
Jump jump = jumps.pop();
int position = jump.getPosition();
int number = jump.getNumber();
for (int fib : fibs) {
if (position + fib > N) {
break;
} else if (position + fib == N) {
return number + 1;
} else if (!visited[position + fib] && A[position + fib] == 1) {
visited[position + fib] = true;
jumps.add(new Jump(position + fib, number + 1));
}
}
}
return -1;
}
private List<Integer> getFibonacciNumbers(int N) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
list.add(i);
}
int i = 2;
while (list.get(list.size() - 1) <= N) {
list.add(i, (list.get(i - 1) + list.get(i - 2)));
i++;
}
for (i = 0; i < 2; i++) {
list.remove(i);
}
return list;
}
public static void main(String[] args) {
int[] A = new int[11];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 1;
A[4] = 1;
A[5] = 0;
A[6] = 1;
A[7] = 0;
A[8] = 0;
A[9] = 0;
A[10] = 0;
System.out.println(solution(A));
}
}
However, while the correctness seems good, the performance is not high enough. Is there a bug in the code and how do I improve the performance?
Got 100% with simple BFS:
public class Jump {
int pos;
int move;
public Jump(int pos, int move) {
this.pos = pos;
this.move = move;
}
}
public int solution(int[] A) {
int n = A.length;
List < Integer > fibs = fibArray(n + 1);
Queue < Jump > positions = new LinkedList < Jump > ();
boolean[] visited = new boolean[n + 1];
if (A.length <= 2)
return 1;
for (int i = 0; i < fibs.size(); i++) {
int initPos = fibs.get(i) - 1;
if (A[initPos] == 0)
continue;
positions.add(new Jump(initPos, 1));
visited[initPos] = true;
}
while (!positions.isEmpty()) {
Jump jump = positions.remove();
for (int j = fibs.size() - 1; j >= 0; j--) {
int nextPos = jump.pos + fibs.get(j);
if (nextPos == n)
return jump.move + 1;
else if (nextPos < n && A[nextPos] == 1 && !visited[nextPos]) {
positions.add(new Jump(nextPos, jump.move + 1));
visited[nextPos] = true;
}
}
}
return -1;
}
private List < Integer > fibArray(int n) {
List < Integer > fibs = new ArrayList < > ();
fibs.add(1);
fibs.add(2);
while (fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2) <= n) {
fibs.add(fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2));
}
return fibs;
}
You can apply knapsack algorithms to solve this problem.
In my solution I precomputed fibonacci numbers. And applied knapsack algorithm to solve it. It contains duplicate code, did not have much time to refactor it. Online ide with the same code is in repl
import java.util.*;
class Main {
public static int solution(int[] A) {
int N = A.length;
int inf=1000000;
int[] fibs={1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025};
int[] moves = new int[N+1];
for(int i=0; i<=N; i++){
moves[i]=inf;
}
for(int i=0; i<fibs.length; i++){
if(fibs[i]-1<N && A[fibs[i]-1]==1){
moves[ fibs[i]-1 ] = 1;
}
if(fibs[i]-1==N){
moves[N] = 1;
}
}
for(int i=0; i<N; i++){
if(A[i]==1)
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
for(int i=N; i<=N; i++){
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
if(moves[N]==inf) return -1;
return moves[N];
}
public static void main(String[] args) {
int[] A = new int[4];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 0;
System.out.println(solution(A));
}
}
Javascript 100%
function solution(A) {
function fibonacciUntilNumber(n) {
const fib = [0,1];
while (true) {
let newFib = fib[fib.length - 1] + fib[fib.length - 2];
if (newFib > n) {
break;
}
fib.push(newFib);
}
return fib.slice(2);
}
A.push(1);
const fibSet = fibonacciUntilNumber(A.length);
if (fibSet.includes(A.length)) return 1;
const reachable = Array.from({length: A.length}, () => -1);
fibSet.forEach(jump => {
if (A[jump - 1] === 1) {
reachable[jump - 1] = 1;
}
})
for (let index = 0; index < A.length; index++) {
if (A[index] === 0 || reachable[index] > 0) {
continue;
}
let minValue = 100005;
for (let jump of fibSet) {
let previousIndex = index - jump;
if (previousIndex < 0) {
break;
}
if (reachable[previousIndex] > 0 && minValue > reachable[previousIndex]) {
minValue = reachable[previousIndex];
}
}
if (minValue !== 100005) {
reachable[index] = minValue + 1;
}
}
return reachable[A.length - 1];
}
Python 100% answer.
For me the easiest solution was to locate all leaves within one fib jump of -1. Then consider each of these leaves to be index[0] and find all jumps from there.
Each generation or jump is recorded in a set until a generation contains len(A) or no more jumps can be found.
def gen_fib(n):
fn = [0,1]
i = 2
s = 2
while s < n:
s = fn[i-2] + fn[i-1]
fn.append(s)
i+=1
return fn
def new_paths(A, n, last_pos, fn):
"""
Given an array A of len n.
From index last_pos which numbers in fn jump to a leaf?
returns list: set of indexes with leaves.
"""
paths = []
for f in fn:
new_pos = last_pos + f
if new_pos == n or (new_pos < n and A[new_pos]):
paths.append(new_pos)
return path
def solution(A):
n = len(A)
if n < 3:
return 1
# A.append(1) # mark final jump
fn = sorted(gen_fib(100000)[2:]) # Fib numbers with 0, 1, 1, 2.. clipped to just 1, 2..
# print(fn)
paths = set([-1]) # locate all the leaves that are one fib jump from the start position.
jump = 1
while True:
# Considering each of the previous jump positions - How many leaves from there are one fib jump away
paths = set([idx for pos in paths for idx in new_paths(A, n, pos, fn)])
# no new jumps means game over!
if not paths:
break
# If there was a result in the new jumps record that
if n in paths:
return jump
jump += 1
return -1
https://app.codility.com/demo/results/training4GQV8Y-9ES/
https://github.com/niall-oc/things/blob/master/codility/fib_frog.py
Got 100%- solution in C.
typedef struct state {
int pos;
int step;
}state;
int solution(int A[], int N) {
int f1 = 0;
int f2 = 1;
int count = 2;
// precalculating count of maximum possible fibonacci numbers to allocate array in next loop. since this is C language we do not have flexible dynamic structure as in C++
while(1)
{
int f3 = f2 + f1;
if(f3 > N)
break;
f1 = f2;
f2 = f3;
++count;
}
int fib[count+1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
// calculating fibonacci numbers in array
while(1)
{
fib[i] = fib[i-1] + fib[i-2];
if(fib[i] > N)
break;
++i;
}
// reversing the fibonacci numbers because we need to create minumum jump counts with bigger jumps
for(int j = 0, k = count; j < count/2; j++,k--)
{
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
state q[N];
int front = 0 ;
int rear = 0;
q[0].pos = -1;
q[0].step = 0;
int que_s = 1;
while(que_s > 0)
{
state s = q[front];
front++;
que_s--;
for(int i = 0; i <= count; i++)
{
int nextpo = s.pos + fib[i];
if(nextpo == N)
{
return s.step+1;
}
else if(nextpo > N || nextpo < 0 || A[nextpo] == 0){
continue;
}
else
{
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
//100% on codility Dynamic Programming Solution. https://app.codility.com/demo/results/training7WSQJW-WTX/
class Solution {
public int solution(int[] A) {
int n = A.length + 1;
int dp[] = new int[n];
for(int i=0;i<n;i++) {
dp[i] = -1;
}
int f[] = new int[100005];
f[0] = 1;
f[1] = 1;
for(int i=2;i<100005;i++) {
f[i] = f[i - 1] + f[i - 2];
}
for(int i=-1;i<n;i++) {
if(i == -1 || dp[i] > 0) {
for(int j=0;i+f[j] <n;j++) {
if(i + f[j] == n -1 || A[i+f[j]] == 1) {
if(i == -1) {
dp[i + f[j]] = 1;
} else if(dp[i + f[j]] == -1) {
dp[i + f[j]] = dp[i] + 1;
} else {
dp[i + f[j]] = Math.min(dp[i + f[j]], dp[i] + 1);
}
}
}
}
}
return dp[n - 1];
}
}
Ruby 100% solution
def solution(a)
f = 2.step.inject([1,2]) {|acc,e| acc[e] = acc[e-1] + acc[e-2]; break(acc) if acc[e] > a.size + 1;acc }.reverse
mins = []
(a.size + 1).times do |i|
next mins[i] = -1 if i < a.size && a[i] == 0
mins[i] = f.inject(nil) do |min, j|
k = i - j
next min if k < -1
break 1 if k == -1
next min if mins[k] < 0
[mins[k] + 1, min || Float::INFINITY].min
end || -1
end
mins[a.size]
end
I have translated the previous C solution to Java and find the performance is improved.
import java.util.*;
class Solution {
private static class State {
int pos;
int step;
public State(int pos, int step) {
this.pos = pos;
this.step = step;
}
}
public static int solution(int A[]) {
int N = A.length;
int f1 = 0;
int f2 = 1;
int count = 2;
while (true) {
int f3 = f2 + f1;
if (f3 > N) {
break;
}
f1 = f2;
f2 = f3;
++count;
}
int[] fib = new int[count + 1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
while (true) {
fib[i] = fib[i - 1] + fib[i - 2];
if (fib[i] > N) {
break;
}
++i;
}
for (int j = 0, k = count; j < count / 2; j++, k--) {
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
State[] q = new State[N];
for (int j = 0; j < N; j++) {
q[j] = new State(-1,0);
}
int front = 0;
int rear = 0;
// q[0].pos = -1;
// q[0].step = 0;
int que_s = 1;
while (que_s > 0) {
State s = q[front];
front++;
que_s--;
for (i = 0; i <= count; i++) {
int nextpo = s.pos + fib[i];
if (nextpo == N) {
return s.step + 1;
}
//
else if (nextpo > N || nextpo < 0 || A[nextpo] == 0) {
continue;
}
//
else {
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
}
JavaScript with 100%.
Inspired from here.
function solution(A) {
const createFibs = n => {
const fibs = Array(n + 2).fill(null)
fibs[1] = 1
for (let i = 2; i < n + 1; i++) {
fibs[i] = fibs[i - 1] + fibs[i - 2]
}
return fibs
}
const createJumps = (A, fibs) => {
const jumps = Array(A.length + 1).fill(null)
let prev = null
for (i = 2; i < fibs.length; i++) {
const j = -1 + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
jumps[j] = 1
if (prev === null) prev = j
}
}
if (prev === null) {
jumps[A.length] = -1
return jumps
}
while (prev < A.length) {
for (let i = 2; i < fibs.length; i++) {
const j = prev + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
const x = jumps[prev] + 1
const y = jumps[j]
jumps[j] = y === null ? x : Math.min(y, x)
}
}
prev++
while (prev < A.length) {
if (jumps[prev] !== null) break
prev++
}
}
if (jumps[A.length] === null) jumps[A.length] = -1
return jumps
}
const fibs = createFibs(26)
const jumps = createJumps(A, fibs)
return jumps[A.length]
}
const A = [0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0]
console.log(A)
const s = solution(A)
console.log(s)
You should use a QUEUE AND NOT A STACK. This is a form of breadth-first search and your code needs to visit nodes that were added first to the queue to get the minimum distance.
A stack uses the last-in, first-out mechanism to remove items while a queue uses the first-in, first-out mechanism.
I copied and pasted your exact code but used a queue instead of a stack and I got 100% on codility.
100% C++ solution
More answers in my github
Inspired from here
Solution1 : Bottom-Top, using Dynamic programming algorithm (storing calculated values in an array)
vector<int> getFibonacciArrayMax(int MaxNum) {
if (MaxNum == 0)
return vector<int>(1, 0);
vector<int> fib(2, 0);
fib[1] = 1;
for (int i = 2; fib[fib.size()-1] + fib[fib.size() - 2] <= MaxNum; i++)
fib.push_back(fib[i - 1] + fib[i - 2]);
return fib;
}
int solution(vector<int>& A) {
int N = A.size();
A.push_back(1);
N++;
vector<int> f = getFibonacciArrayMax(N);
const int oo = 1'000'000;
vector<int> moves(N, oo);
for (auto i : f)
if (i - 1 >= 0 && A[i-1])
moves[i-1] = 1;
for (int pos = 0; pos < N; pos++) {
if (A[pos] == 0)
continue;
for (int i = f.size()-1; i >= 0; i--) {
if (pos + f[i] < N && A[pos + f[i]]) {
moves[pos + f[i]] = min(moves[pos]+1, moves[pos + f[i]]);
}
}
}
if (moves[N - 1] != oo) {
return moves[N - 1];
}
return -1;
}
Solution2: Top-Bottom using set container:
#include <set>
int solution2(vector<int>& A) {
int N = A.size();
vector<int> fib = getFibonacciArrayMax(N);
set<int> positions;
positions.insert(N);
for (int jumps = 1; ; jumps++)
{
set<int> new_positions;
for (int pos : positions)
{
for (int f : fib)
{
// return jumps if we reach to the start point
if (pos - (f - 1) == 0)
return jumps;
int prev_pos = pos - f;
// we do not need to calculate bigger jumps.
if (prev_pos < 0)
break;
if (prev_pos < A.size() && A[prev_pos])
new_positions.insert(prev_pos);
}
}
if (new_positions.size() == 0)
return -1;
positions = new_positions;
}
return -1;
}

Recursive method for Amicable numbers between 1 - 10000 Java

I have a problem with creating a recursive method for finding Amicable numbers between 1 - 10000. I created a method to find out if two numbers are Amicable, but I don't know how to run it against every possible number combination. Here are both methods which I wrote.
public void amicable(int n, int m) {
int sumM = 0;
int sumN = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumN += i;
}
}
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumM += j;
}
}
if (sumN == m && sumM == n) {
System.out.println(n + " and " + m + " are amicable numbers");
}
}
public static void amicableBetween(int n, int m) {
int sumaM = 0;
int sumaN = 0;
if (m >= 1) {
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumaM += j;
}
}
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumaN += i;
}
}
if (sumaN == m && sumaM == n) {
System.out.println(n + " and " + m + " are amicable numbers");
amicableBetween(n + 1, m - 1);
} else {
System.out.println(n + " i " + m + " aren't amicable numbers");
amicableBetween(n + 1, m - 1);
}
}
}
}
Minor disclaimer, this method might take forever and you might run out of stack space so I'm not 100% sure that calculating all the amicable numbers from 1-10000 recursively is the way to go. If this is just for fun or practice then I guess is ok.
One approach will be to sweep n until we reach m - 1 and call amicable(n,m) in each step. Once n has reached m - 1, we can decrease m by 1 and repeat the process until n is equal to m - 1 then we have checked all possible combinations. To do this, you can break your two methods into three methods.
The first method is the amicable method you already have, just changed the return type so that we can reuse it while we are going down the recursion chain:
public static boolean amicable(int n, int m) {
int sumM = 0;
int sumN = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumN += i;
}
}
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumM += j;
}
}
return sumN == m && sumM == n;
}
The second will be the public method amicableBetween(int n, int m)
public static void amicableBetween(int n, int m) {
amicableBetween(n, m, true);
}
Which will call a third private helper method amicableBetween(int n, int m, boolean start) that has a third parameter start that it can use to identify if n has reached m. Then we need to decrease m by 1 and repeat the process:
private static void amicableBetween(int n, int m, boolean start) {
if(n == m) {
return;
}
if (m >= 1) {
if (amicable(n, m)) {
System.out.println(n + " and " + m + " are amicable numbers");
} else {
System.out.println(n + " and " + m + " aren't amicable numbers");
}
amicableBetween(n + 1, m, false);
}
if(start) {
amicableBetween(n, m - 1, true);
}
}
I wonder why do you want a recursive algorithm. Don't you warry about StackOvervlowException?! It is pretty easy to find with simple Map within O(n) time:
public static void amicable(int lo, int hi) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = lo; i <= hi; i++) {
int j = map.computeIfAbsent(i, DIV_SUM);
if (j > i && j <= hi && map.computeIfAbsent(j, DIV_SUM) == i)
System.out.format("[%d : %d]\n", i, j);
}
}
private static final Function<Integer, Integer> DIV_SUM = val -> {
int sum = 0;
for (int i = 1, max = val / 2; i <= max; i++)
if (val % i == 0)
sum += i;
return sum;
};
Demo: time ~150ms
amicable(1, 10000);
[220 : 284]
[1184 : 1210]
[2620 : 2924]
[5020 : 5564]
[6232 : 6368]
So, you wrote a method that can tell if two numbers are amicable. That's the hard part out of the way. All you have to do is call that from inside two loops, one for the upper bound, one for the lower bound.
for(lowerNumber = 1; lowerNumber < 10000; lowerNumber++){
for(upperNumber = lowerNumber + 1; upperNumber <= 10000; upperNumber++){
amicable(lowerNumber, upperNumber);
}
}
I'm not sure why you need two parameters in the amicable function. An amicable number has a repeating aliquot sequence of period 2, which means
s(s(n)) == n
We can find the number's complement by retrieving the sum of its proper divisors and checking the assertion above.
This means to find the amicable numbers for n between 1 and 10,000 we only need n, and would also make trivial the part of the process you seem to want as a recursion.
JavaScript code:
function s(n){
let s = n > 1 ? 1 : 0;
let sqrt_n = Math.sqrt(n);
let d1=Math.floor(n/2);
for (; d1>=sqrt_n; d1--){
let d2 = n / d1;
if (d2 == Math.floor(d2))
s += d1 + d2;
}
if (d1 == sqrt_n)
s += d1;
return s;
}
let n = 220;
let s_n = s(n);
if (s(s_n) == n)
console.log('Amicable!', n, s_n);

Categories

Resources