Minimum number of distinct characters to result in a given suffix array - java

Given a suffix array, a TopCoder task from SRM 630 asks to find the minium number of distinct characters in the string that could form a string with the given suffix array. The full problem statement can be found on the TopCoder website.
The best solution I found is right here: https://github.com/ftiasch/acm-icpc/blob/6db1ed02a727611830b974a1d4de38bab8f390f9/topcoder/single-round-match/single-round-match-630/SuffixArrayDiv1.java
Here is the algorithm written by ftiasch:
public int minimalCharacters(int[] array) {
int n = array.length;
int[] position = new int[n + 1];
for (int i = 0; i < n; ++i) {
position[array[i]] = i;
}
position[n] = -1;
int[] minimum = new int[n + 1];
for (int i = n - 1; i >= 0; --i) {
minimum[i] = Integer.MAX_VALUE;
for (int j = i + 1; j <= n; ++j) {
boolean valid = true;
for (int x = i; x < j; ++x) {
for (int y = x + 1; y < j; ++y) {
valid &= position[array[x] + 1] < position[array[y] + 1];
}
}
if (valid && minimum[j] < Integer.MAX_VALUE) {
minimum[i] = Math.min(minimum[i], minimum[j] + 1);
}
}
}
return minimum[0];
}
I understand that this is a dynamic programming algorithm but how does it work? I really need a hand understanding it.
EDIT
Here is what ftiasch wrote me back:
hi Ariel,
First of all, thanks to your compliment. Frankly speaking, my solution
is not the best solution to the problem. The optimal one runs in O(n)
time but mine takes O(n^4). I just picked this idea during the contest
because n is relatively small.
Keep in mind that same characters become continuous in the SA. Since
the problem asked for the least number of characters, so I decided to
use dynamic programming to partition the SA into consecutive segments
so that each segments start with the same character.
Which condition is necessary for S[SA[i]] == S[SA[j]] assumed that i <
j? The lexicographic comparison suggests that suffix(SA[i] + 1) should
be smaller than suffix(SA[j] + 1). We can easily find that the
condition is also sufficient.
Write to me if you have any other question. :)
EDIT1
We finally managed to make it work, thanks to David. Here is the linear time algorithm in java from David's Python version:
public int minimalCharacters(int[] array) {
int n = array.length, i;
if (n == 0)
return 0;
int[] array1 = new int[n + 1];
for (i = 0; i < n; i++)
array1[1 + i] = array[i];
int[] position = new int[n + 1];
for (i = 0; i < n + 1; i++)
position[array1[i]] = i;
int k = 1;
for (i = n; i > 1; i--) {
if (position[array1[i] + 1] <= position[array1[i - 1] + 1])
k++;
}
return k;
}

Here’s a quadratic-time algorithm. The suffix array specifies for each
pair of suffixes how they compare lexicographically (and the empty
suffix always is less than all of them). Let s be the unknown string
and suppose that we’re comparing suffix s[i...] with suffix s[j...].
If s[i] != s[j], then the comparison of s[i] and s[j] settles it.
Otherwise, the result is the same as if we compare s[i+1...] and
s[j+1...].
Suppose that we wish to ensure that s[i...] < s[j...]. Clearly we need
s[i] <= s[j]. In fact, unless s[i+1...] < s[j+1...], we need the
strict inequality s[i] < s[j], as otherwise the tiebreaker will go the
wrong way. Otherwise, s[i] == s[j] will suffice regardless of the rest
of the string. Gather up all of the inequalities as arcs in a directed
graph with vertices corresponding to positions in s. This graph is
necessarily acyclic by the total order on suffixes. Make each arc length
1 if the inequality is strict and length 0 otherwise. Output the length
of the longest path, plus one (or zero if the graph is empty).
At least this many distinct letters are needed, by the corresponding
chain of inequalities. What’s perhaps less clear is that this many
distinct letters suffices, but if we determine the label of each
vertex/position in s by the length of the longest path starting there,
then the head and tail of each arc are labeled appropriately.
To get down to linear time, we can exploit the structure of the
graph. It’s straightforward (though not trivial; the graph is metric
after all) to show that the path visiting all vertices of the graph is
the longest, so we merely have to compute its length.
Below are a transliterated version of the sample code (minChars1), an
implementation straight from the description above (minChars2, now
stripped of all comprehension usage), a brute force solution
(minChars3), and the linear-time solution (minChars4).
import itertools
def minChars1(array):
n = len(array)
position = [-1] * (n + 1)
for i in range(n):
position[array[i]] = i
infinity = n + 1
minimum = [infinity] * (n + 1)
minimum[n] = 0
for i in range(n - 1, -1, -1):
for j in range(i + 1, n + 1):
valid = True
for x in range(i, j):
for y in range(x + 1, j):
valid = valid and position[array[x] + 1] < position[array[y] + 1]
if valid and minimum[j] < infinity:
minimum[i] = min(minimum[i], minimum[j] + 1)
return minimum[0]
def lengthOfLongestPath(graph, memo, i):
if i not in memo:
result = 0
for w, j in graph[i]:
result = max(result, w + lengthOfLongestPath(graph, memo, j))
memo[i] = result
return memo[i]
def minChars2(array):
n = len(array)
position = [-1] * (n + 1)
for i in range(n):
position[array[i]] = i
graph = {}
for i in range(n):
graph[i] = []
for j in range(n):
if position[i] > position[j]:
w = 0 if position[i + 1] > position[j + 1] else 1
graph[i].append((w, j))
memo = {None: -1}
for i in range(n):
lengthOfLongestPath(graph, memo, i)
return max(memo.values()) + 1
def minChars3(array):
n = len(array)
position = [None] * n
for i in range(n):
position[array[i]] = i
for k in range(n):
for s in itertools.product(range(k), repeat=n):
valid = True
for i in range(n):
for j in range(n):
valid = valid and (s[i:] < s[j:]) == (position[i] < position[j])
if valid:
return k
return n
def minChars4(array):
n = len(array)
if n == 0:
return 0
array1 = [n] * (n + 1)
for i in range(n):
array1[1 + i] = array[i]
position = [None] * (n + 1)
for i in range(n + 1):
position[array1[i]] = i
k = 1
for i in range(n, 1, -1):
if position[array1[i] + 1] <= position[array1[i - 1] + 1]:
k += 1
return k
def test():
for n in range(7):
for array in itertools.permutations(range(n)):
assert minChars1(array) == minChars2(array) == minChars3(array) == minChars4(array)
test()

Related

Find the maximal sum of any double slice

I'm trying to solve a problem from the Codility that I already have a solution. The problem description is provided below,
A non-empty array A consisting of N integers is given.
A triplet (X, Y, Z), such that 0 ≤ X < Y < Z < N, is called a double slice.
The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2] + ... + A[Y − 1] + A[Y + 1] + A[Y + 2] + ... + A[Z − 1].
For example, array A such that:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
contains the following example double slices:
double slice (0, 3, 6), sum is 2 + 6 + 4 + 5 = 17,
double slice (0, 3, 7), sum is 2 + 6 + 4 + 5 − 1 = 16,
double slice (3, 4, 5), sum is 0.
The goal is to find the maximal sum of any double slice.
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty array A consisting of N integers, returns the maximal sum of any double slice.
For example, given:
A[0] = 3
A[1] = 2
A[2] = 6
A[3] = -1
A[4] = 4
A[5] = 5
A[6] = -1
A[7] = 2
the function should return 17, because no double slice of array A has a sum of greater than 17.
Assume that:
N is an integer within the range [3..100,000];
each element of array A is an integer within the range [−10,000..10,000].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N) (not counting the storage required for input arguments)
The solution is provided below,
public static int solution(int[] A) {
int max = 0;
int N = A.length;
int[] A1 = new int[N];
int[] A2 = new int[N];
for (int i = 1; i < N - 1; i++) {
A1[i] = Math.max(A1[i - 1] + A[i], 0);
}
for (int i = N - 2; i >= 1; i--) {
A2[i] = Math.max(A2[i + 1] + A[i], 0);
}
for (int i = 1; i < N - 1; i++) {
max = Math.max(max, A1[i - 1] + A2[i + 1]);
}
return max;
}
I understand what was done in the initial 2 loops, however, the intention was not clear. My thoughts get disjointed at the time I approached the last for loop. Anyone kindly please explain the solution to me briefly?
I will base my explanation on the code from here, as it uses clearer variable names. Other than that, it's basically the same code as in your question:
class Solution {
public int solution(int[] A) {
int[] maxStartingHere = new int[A.length];
int[] maxEndingHere = new int[A.length];
int maxSum = 0, len = A.length;
for(int i = len - 2; i > 0; --i ) {
maxSum = Math.max(0, A[i] + maxSum);
maxStartingHere[i] = maxSum;
}
maxSum = 0;
for(int i = 1; i < len - 1; ++i ) {
maxSum = Math.max(0, A[i] + maxSum);
maxEndingHere[i] = maxSum;
}
int maxDoubleSlice = 0;
for(int i = 0; i < len - 2; ++i) {
maxDoubleSlice = Math.max(maxDoubleSlice, maxEndingHere[i] + maxStartingHere[i+2]);
}
return maxDoubleSlice;
}
}
The key here is that the code does not look for the maximum slice, only for its sum. The array maxStartingHere records at index i what maximum sum you'd reach if you combine contiguous items starting at i+1; maxEndingHere does the same in reverse. Let's look at an example for that:
i: 0 1 2 3 4
A: 1 -3 2 -1 ...
maxEndingHere: 0 1 0 2 1
Note that:
i=0: there are no elements left of i, so the sum is 0.
i=2: Taking A[0..1] is suboptimal, so the maximum of 0 is achieved by not summing anything at all.
i=4: Another negative element, but 2 + -1 is still better than 0. We're not considering 1 + -3 + 2 + -1 because we already know that the maximum we can reach left of the 2 is negative.
I hope you see that this array shows what can be achieved by choosing different X, but the concrete choice of X is not recorded - just its consequence. Every i corresponds to a Y, and maxEndingHere[i-1] corresponds to the consequence of choosing X optimally for a particular Y.
So we know what sums choosing X and Z optimally, for a particular Y, result in. That means it only remains to choose the best Y (or more precisely: the sum resulting from the best Y). And that is what happens in the third loop.
To reiterate:
What is the maximum you can get, ending anywhere, when starting from a particular item? That's maxStartingHere.
What is the maximum you can get, starting anywhere, when ending at a particular item? That's maxEndingHere.
What is the maximum you can get when ending/starting at a particular item? That's maxDoubleSlice.

Minimum number of substitutions to reach string: 01010101 ... 01 or 10101010 ... 10

Given a binary string, that is it contains only 0s and 1s (number of zeros equals the number of ones) We need to make this string a sequence of alternate characters by swapping some of the bits, our goal is to minimize the number swaps.
For example, for the string "00011011" the minimum number of swaps is 2, one way to do it is:
1) swap the bits : 00011011 --->> 00010111
2) swap the bits(after the first swap) : 00010111 --->> 01010101
Note that if we are given the string "00101011" we can turn it into an alternate string starting with 0 (that requires 3 swaps) and also into alternate string starting with 1 ( that requires one swap - the first and the last bits ).
So the minimum in this case is one swap.
The end goal is to return the minimum number of swaps for a given string of ones and zeros. What is the most efficient way to solve it?
What you are looking for is called the Levenshtein distance. It is a bit more complex since it works on all type of String not just bitstrings but based on the implementation you should be able to develop your own fitting solution. Here is an java implementation I found on Wikibooks:
public static int computeLevenshteinDistance(CharSequence lhs, CharSequence rhs) {
int[][] distance = new int[lhs.length() + 1][rhs.length() + 1];
for (int i = 0; i <= lhs.length(); i++)
distance[i][0] = i;
for (int j = 1; j <= rhs.length(); j++)
distance[0][j] = j;
for (int i = 1; i <= lhs.length(); i++)
for (int j = 1; j <= rhs.length(); j++)
distance[i][j] = minimum(
distance[i - 1][j] + 1,
distance[i][j - 1] + 1,
distance[i - 1][j - 1] + ((lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1));
return distance[lhs.length()][rhs.length()];
}

Dynamic Programming, sum of all 3 subarrays after bitwise xor them

I recently ran to a dynamic programming problem and I needed to solve it, so i couldn't figure it out myself so I started looking for solutions. The problem is:
There are N students in your class. The strength of each student is a small nonnegative integer.
You are
given these strengths in the int[] strength with N elements.
You are going to divide all students into three teams for the boat race "TrySail". Each student must be
assigned to exactly one of the three teams. Teams cannot be empty.
Strangely enough, in this race the strength of a team is the bitwise xor of the strengths of its members.
You want to maximize the sum of strengths of the three teams. Compute and return the largest possible
sum of the teams' strengths.
Constraints:
1) N will be between 3 and 50, inclusive.
2) strength will contain exactly N elements.
3)Each element of strength will be between 0 and 255, inclusive.
I found some solutions and specific this one. But i still don't know what happens here even when i debug it line per line. So if someone knows this problem or understands this and where and why he uses the variable sum and bitwise xor them (^) it would be really nice for some comments.
Here is the code:
public class TrySail
{
public int get(int[] strength)
{
var dp = new bool[256, 256];
dp[0, 0] = true;
var sum = 0;
foreach (var x in strength)
{
var next = new bool[256, 256];
for (int i = 0; i < 256; i++)
for (int j = 0; j < 256; j++)
{
if (!dp[i, j]) continue;
var rem = sum ^ i ^ j;
next[i ^ x, j] |= dp[i, j];
next[i, j ^ x] |= dp[i, j];
next[i, j] |= dp[i, j];
}
dp = next;
sum ^= x;
}
var max = 0;
for (int i = 0; i < 256; i++)
for (int j = 0; j < 256; j++)
{
if (!dp[i, j]) continue;
var rem = sum ^ i ^ j;
max = Math.Max(max, i + j + rem);
}
return max;
}
}
An example:
{7,3,5,2}
Returns: 17
There are 6 ways to make 3 teams:
· {0},{1},{2,3}: sum of strengths is 7+3+(5 xor 2) = 17
· {0},{2},{1,3}: sum of strengths is 7+5+(3 xor 2) = 13
· {0},{3},{1,2}: sum of strengths is 7+2+(3 xor 5) = 15
· {1},{2},{0,3}: sum of strengths is 3+5+(7 xor 2) = 13
· {1},{3},{0,2}: sum of strengths is 3+2+(7 xor 5) = 7
· {2},{3},{0,1}: sum of strengths is 5+2+(7 xor 3) = 11
Therefore, the answer is 17.
The code is written in C#

Given a number N, find the smallest even number E such that E > N

Given a number N, find the smallest even number E such that E > N and digits in N and E are same.
Print NONE otherwise.
Sample:
Case1
Input
N = 34722641
Output
E = 34724126
Case2
Input
N = 8234961
Output
E = 8236194 (instead of 8236149)
My second case passed first case i am getting wrong output
public static int nextDigit(int number) {
String num = String.valueOf(number);
int stop = 0;
char[] orig_chars = null;
char[] part1 = null;
char[] part2 = null;
orig_chars = num.toCharArray();
for (int i = orig_chars.length - 1; i > 0; i--) {
String previous = orig_chars[i - 1] + "";
String next = orig_chars[i] + "";
if (Integer.parseInt(previous) < Integer.parseInt(next))
{
if (Integer.parseInt(previous) % 2 == 0) {
String partString1 = "";
String partString2 = "";
for (int j = 0; j <= i - 1; j++) {
partString1 = partString1.concat(orig_chars[j] + "");
}
part1 = partString1.toCharArray();
for (int k = i; k < orig_chars.length; k++) {
partString2 = partString2.concat(orig_chars[k] + "");
}
part2 = partString2.toCharArray();
Arrays.sort(part2);
for (int l = 0; l < part2.length; l++) {
char temp = '0';
if (part2[l] > part1[i - 1]) {
temp = part1[i - 1];
part1[i - 1] = part2[l];
part2[l] = temp;
break;
}
}
for (int m = 0; m < part2.length; m++) {
char replace = '0';
if (part2[m] % 2 == 0) {
replace = part2[m];
for (int n = m; n < part2.length - 1; n++) {
part2[n] = part2[n + 1];
}
part2[part2.length - 1] = replace;
break;
}
}
System.out.print(part1);
System.out.println(part2);
System.exit(0);
}
}
}
System.out.println("NONE");
return 0;
}
First idea was to generate the next permutation until an even one is found. This works well for small inputs or when an even permutation is nearby, but badly for large inputs such as 2135791357913579 where many permutations have to happen "to the right" before the sole even digit is moved into place.
גלעד ברקן suggested a patch which with minor adjustment provides a superior algorithm.
As with the next permutation algorithm, we find indices i and j with i < j where the ith digit is less than the jth digit. When we swap those digits, this makes a larger number then N.
Apply the additional constraint that there is an even number to the right of i after the swap.
Take the largest such even number to the right of the index (might not be the one you just swapped), move it to the end. This guarantees evenness.
Then sort the remaining digits in between in ascending order. This provides the smallest permutation available.
The algorithm in Clojure could be written as follows. I tried to stick to a fairly imperative style. See if you can translate.
(defn num->digits [n] (mapv #(Character/getNumericValue %) (str n)))
(defn digits->num [v] (when (seq v) (read-string (apply str v))))
(defn swap
"Swap elements at index i and j in vector v"
[v i j]
(assoc (assoc v i (v j)) j (v i)))
(defn find-max-where
"Find index i in vector v such that (v i) is the largest satisfying pred"
[pred v]
(first
(reduce-kv
(fn [[k m] i x]
(if (and m (> m x))
[k m]
(if (pred x) [i x] [k m])))
[nil nil]
v)))
(defn next-even-perm [v]
(->>
(for [j (range (count v))
i (range j)
:when (< (v i) (v j))
:let [v (swap v i j)
k (find-max-where even? (vec (subvec v (inc i))))]
:when k
:let [v (swap v (+ (inc i) k) (dec (count v)))]]
(concat (subvec v 0 (inc i))
(sort (subvec v (inc i) (dec (count v))))
[(peek v)]))
(map vec) sort first))
(defn next-even-num [n] (-> n num->digits next-even-perm digits->num))
Provided examples:
(next-even-num 34722641)
;=> 34724126
(next-even-num 8234961)
;=> 8236194
(next-even-num 4321)
;=> nil (no solution)
Hard cases for previous algorithm
(time (next-even-num 2135791357913579))
; "Elapsed time: 1.598446 msecs"
;=> 3111335557779992
(time (next-even-num 13244351359135913))
; "Elapsed time: 1.713501 msecs"
;=> 13245111333355994
(time (next-even-num 249999977777555553333311111N))
; "Elapsed time: 1.874579 msecs"
;=> 251111133333555577777999994N
Latest edit fixes problem where we were always wanting to swap with an even number moving right instead of just having any even number to the right whether or not it was involved in the swap. For example, the following failed in the previous edit, now fixed.
(next-even-num 1358)
;=> 1538
Many has suggested permutation, but for this problem, dynamic programming with bit-mask will be another solution.
For dynamic programming, the number of digit can be up to 20 digits, while with normal permutation, it can only be used if N has less than 12 digits. (With time constraint is 1 second , typically for competitive programming)
So the idea is, starting from the most significant digit to the least significant digit, at each step, we try to find the smallest value starting from this digit to the end, at each digit, we have two cases:
If the number being created is already larger than N for example N is 12345 and currently, we are 23xxx. (We need to find the smallest xxx in this case).
If the number is not yet larger than N , example N is 12345 and we have 12xxx.
Moreover, at the last digit, we need to determine if the created number is even or odd.
So, we have our simple recursive code:
public int cal(boolean[] selected, int[] num, int digit, boolean larger) {
//Arrays selected will tell which digit in N has already selected,
//int digit will tell currently, which digit we are checking
//boolean larger tells is the number already larger than N
if (digit + 1 == selected.length) {//Last digit
for (int i = 0; i < selected.length; i++) {
if (!selected[i]) {
if (num[i] % 2 != 0) {
return -1; // -1 means this is an invalid value
} else {
if (larger) {
return num[i];
} else {
return -1;
}
}
}
}
}
int result = -1;
for (int i = 0; i < selected.length; i++) {
if (!selected[i]) {
if (larger) {
selected[i] = true;
int val = (int) (num[i] * Math.pow(10, digit) + cal(selected, num, digit + 1, larger));
if (val != -1 && (result == -1 || result > val)) {
result = val;
}
} else if (num[i] >= num[digit]) {
int val = (int) (num[i] * Math.pow(10, digit) + cal(selected, num, digit + 1, num[i] > num[digit]));
if (val != -1 && (result == -1 || result > val)) {
result = val;
}
}
}
}
return result;
}
From this state, we notice that actually, the boolean [] selected can be replaced by a bit-mask value (Read about bitmask here Link) , So we can easily represent the state of this recursive by this array int [mask][larger] dp
Notice that the parameter digit is not necessary as we can easily determine the digit we are checking by counting the number of digit left to be selected.
Finally, we have our solution:
import java.util.Arrays;
/**
*
* #author Trung Pham
*/
public class Test {
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.largest(2135791357913579L));
}
long[][] dp;
public long largest(long N) {
String val = "" + N;
int[] num = new int[val.length()];
for (int i = 0; i < num.length; i++) {
num[i] = val.charAt(i) - '0';
// System.out.println(num[i] + " " + i);
}
dp = new long[1 << num.length][2];
for (long[] a : dp) {
Arrays.fill(a, -2);
}
return cal(0, num, 0);
}
public long cal(int mask, int[] num, int larger) {
//Arrays selected will tell which digit in N has already selected,
//int digit will tell currently, which digit we are checking
//int larger tells is the number already larger than N, if it is 1, it is larger, 0 is not.
int digit = 0;
for (int i = 0; i < num.length; i++) {
if (((1 << i) & mask) != 0) {
digit++;
}
}
if (dp[mask][larger] != -2) {
return dp[mask][larger];
}
if (digit + 1 == num.length) {//Last digit
//System.out.println(mask + " " + digit);
for (int i = 0; i < num.length; i++) {
if (((1 << i) & mask) == 0) {
if (num[i] % 2 != 0) {
return -1; // -1 means this is an invalid value
} else {
if (larger == 1) {
// System.out.println(num[i] + " " + i);
return num[i];
} else {
return -1;
}
}
}
}
return -1;
}
long result = -1;
int l = num.length;
for (int i = 0; i < num.length; i++) {
if (((1 << i) & mask) == 0) {
if (larger == 1) {
//System.out.println(num[i]* Math.pow(10,l - digit) + " " + digit);
long val = (long) (cal(mask | (1 << i), num, larger));
if (val != -1) {
val += num[i] * Math.pow(10, l - digit - 1);
if (result == -1 || result > val) {
result = val;
}
}
} else if (num[i] >= num[digit]) {
long val = (long) (cal(mask | (1 << i), num, num[i] > num[digit] ? 1 : 0));
if (val != -1) {
val += num[i] * Math.pow(10, l - digit - 1);
if (result == -1 || result > val) {
result = val;
}
}
}
}
}
return dp[mask][larger] = result;
}
}
Notice that this solution can still be improved if you notice that at each digit, we only selected value from 0 to 9 once, and the start digit cannot start with 0.
An attempt at a Haskell version of the newer algorithm in A. Webb's answer:
import qualified Data.Map as M
import Data.Ord (comparing)
import Data.List (sort,maximumBy)
import Data.Maybe (fromJust)
digs :: Integral x => x -> [x]
digs 0 = []
digs x = digs (x `div` 10) ++ [x `mod` 10]
nextE n
| e == -1 = "NONE"
| otherwise = concatMap show $ take (ie' + 1) (M.elems s)
++ sort (drop (ie' + 1) (M.elems s')) ++ [r]
where ds = M.fromList (zip [0..] (digs n))
rightMost (-1) _ = [(-1,0),(-1,0)]
rightMost ix xs
| even (x) && not (null $ filter (>x) xs) = [(x,ix),(y,iy)]
| otherwise = rightMost (ix - 1) (x:xs)
where x = fromJust (M.lookup ix ds)
(y,iy) = minimum . filter ((>= x) . fst)
$ zip xs [ix + 1..M.size ds - 1]
[(e,ie),(l,il)] = rightMost (M.size ds - 1) []
s = M.insert il e . M.insert ie l $ ds
(ir,r) = maximumBy (comparing snd) . M.toList
. M.filter even . snd $ M.split ie s
s' = M.delete ir s
ie' = fromIntegral ie
main = print (map (\x -> (x,nextE x)) [34722641,8234961,13244351359135913,3579])
Output:
*Main> main
[(34722641,"34724126"),(8234961,"8236194")
,(13244351359135913,"13245111333355994"),(3579,"NONE")]
(0.02 secs, 563244 bytes)
Cases where result will be "NONE":
Find the minimum even digit(0, 2, 4, 6, 8) from the given number. Let the digit is x.
Take the other digits, sort them in decreasing order. Let's assume this substring is S.
E = S + x (Here + means concatenation)
If no even digit is found in step 1, There is no such number.
If E, after step 2 is <= N, then there is no such number.
As there are only 5 possible digits those can be placed as the last digit of E, first we consider each of them. Let the current even digit be e. We'll scan N to find if e occurs in N.
If e doesn't occur in N, skip. Otherwise, we remove 1 occurrence of e from N and add it to the end of E. Let's assume the rest digits concatenate to E1.
If e > N % 10, then we need to find the permutation of E1 such that E1 >= N/10 and E1 is minimum. If e <= N %10 then we need a permutation of E1 such that E1 > N/10 and E1 is minimum of every such permutation. So the problem reduces to find a permutation of a number E1, that is greater than or equal to E1 (based on the value of e) and minimum.
You can take it from here and solve this problem as it only needs some careful coding from here to solve the next part of the problem.

Calculate element in matrix incrementally, using neighbors

I have this Java problem, which I suspect it relates to a higher-level algorithm, but my searches haven't been able to come up with anything practical.
You construct an array as follows:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
Basically, Ai,j = Ai-1,j-1+Ai-1,j. It's supposed to return the element at index (l, c): for (4, 1) it should return 4, (5, 2) returns 10, etc. My solution is straightforward, but it is not enough:
static long get(int l, int c){
long[][] matrix = new long[l+1][l+1];
matrix[0][0]=1;
matrix[1][0]=1;
matrix[1][1]=1;
for(int i=2;i<=l;i++){
matrix[i][0]=1;
for(int j=1;j<=i;j++){
matrix[i][j] = matrix[i-1][j-1]+matrix[i-1][j];
}
}
return matrix[l][c];
}
It doesn't work for large values of l and c. Using BigInteger doesn't work. My searches have led me to loop skewing and scalarization, but I don't know where to start. Any steer in the right direction is really appreciated.
PS: Sorry for the newbie-vibe, this is my first question!
You are describing Pascal's triangle, for which a closed formula exists:
matrix[n][k] = n!/(k! * (n-k)!)
P.S. If these numbers seem familiar, it is because they are also from the binomial theorem, where the common examples are:
(x+y)^2 = 1* x^2 + 2xy + 1*y^2
(x+y)^3 = 1*x^3 + 3*xy^2 + 3yx^2 + 1*y^3
You don't need to use a loop, this is simply pascal's triangle, the formula:
(n, k) = n! / ( k! * (n-k)!)
Will generate your answer for the position (n, k).
Try this:
static long get(int l, int c) throws Exception {
if (l != c)
throw new Exception("l != c");
long[][] matrix = new long[l+1][l+1];
matrix[0][0]=1;
for (int i = 1; i <= l; ++i) {
for (int j = 0; j <= i; ++j) {
if (j - 1 >= 0) {
matrix[i][j] = matrix[i - 1][j] + matrix[i - 1][j - 1];
} else {
matrix[i][j] = matrix[i - 1][j];
}
}
}
return matrix[l][c];
}

Categories