Algorithm to iterate through sample space of numbers - algorithm

I hope this isn't a dupe, but it's hard to boil down the problem into keywords!
This is always something that I've wondered about. Let's say you have a black box that takes n integers as an input (where n > 1). Given that there is a bounds on the integer values, how would you go about writing an algorithm that will push the entire sample space through the black box? (bonus points if n can be specified at runtime)
My attempt when n = 2 is as follows:
int min = 0;
int max = 9;
int a = min;
int b = min;
while(a <= max && b <= max)
{
blackBox(a, b);
a++;
if(a > max)
{
a = min;
b++;
}
}
The above code is fine for two variables, but as you might guess, my algorithm gets really ugly when n approaches double-digits.
Is there a better way to do this other than nesting if statements like I have done?
I know a bad way to do it, which would be to randomly generate the values for each iteration and save the inputs of previous iterations so you don't poke the black box with the same variables twice. However, I was hoping for a more speedy method as collisions really hurt the execution time as the number of unique black box calls approaches (max - min + 1) ^ n

Why not used nested loops? Then you just add more nested loops as necessary.
Might not be overly efficent but you did indicate you need to cover the entire sample space, so you're going to have to run every possible combination of values of the input variables anway - so I doubt there's much you can do about efficency unless it's possible to only evaluate against a portion of the state space.
int min = 0;
int max = 9;
for( int a = min ; a <= max ; ++a )
for( int b = min ; b <= max ; ++b )
blackBox( a , b );
Also, I think you'll find the number of unique calls is (max - min + 1) ^ n, not the other way around.
Edit:
A different run-time version to that already suggested
Imre L seems to have hit the nail on the head for a real-time version using the same language type as your question (something C-like), but since you've tagged this as language agnostic I've decided to try something different (also, I'm learning Python at the moment so was looking for an excuse to practice).
Here's a Python real-time version, in each case x will be a n-tuple, such as [1,0,3,2]. Only thing I will say is this does not include max in the state-space (in the example below it will use 0 to 2 inclusive, not 3) so you'd have to increment max before use.
import itertools
min = 0
max = 3
n = 4
for x in itertools.product(range(min,max), repeat=n):
blackBox( x )

The numbers will be held in array a that will be set dynamically eg: int a[] = new int[n]
If the blackBox cannot be modified to take a sample as array then you can either write an ugly wrapper function for calling it with different count of parameters or you are pretty much out of luck for doing it dynamically.
(Procedural) Pseudo code:
int min = 0;
int max = 9;
int a[] = array();
int count = length(a);
setToMinValue(a);
while(a[count-1] <= max)
{
blackBox(a); // or bb(a[0],a[1],...)
a[0]++;
//while next number needs to be increased
for (int i = 0; a[i] > max && i < count-1; i++) {
a[i] = min;
a[i+1]++;
}
}

Here is a generic solution, in Java:
public class Counter implements Iterator<int[]> {
private int[] max;
private int[] vector;
public Counter(int[] maxValues) {
this.max = maxValues;
this.vector = new int[maxValues.length];
}
public int[] next() {
if (!hasNext())
throw new NoSuchElementException();
int[] res = vector.clone();
int i = 0;
while (i < vector.length && vector[i] == max[i]) {
vector[i] = 0;
i++;
}
if (i == vector.length)
vector = null;
else
vector[i]++;
return res;
}
#Override
public boolean hasNext() {
return (vector != null);
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
Counter c = new Counter(new int[]{3});
while (c.hasNext()) {
System.out.println(Arrays.toString(c.next()));
}
}
}
The constructor receives the maximum values for each position. The minimum is always 0 (therefore you can use it to simulate a counter in any radix, and in any "mixed radix"). I added a usage example at the bottom.

You may think of each input to the black box as an n-digit number in a max - min + 1 radix system. For example, if min = 3 and max = 12, then max - min + 1 == 10 and each input to the black box corresponds to an n-digit number in the decimal system. Simply iterate over all the numbers from 0 to (max - min + 1)^n, decode each number and feed the resulting vector to the black box.
Here's a Java implementation:
public static interface BlackBox {
void consume(int... vector);
}
public static void iterateSample(int min, int max, int n, BlackBox bb) {
int radix = max - min + 1;
long limit = (long) Math.pow(radix, n); /* Imprecise for larger numbers! */
for (int i = 0; i < limit; i++) {
int encoded = i;
int[] decoded = new int[n];
for (int j = 0; j < n; j++) {
decoded[j] = min + (encoded % radix);
encoded /= radix;
}
bb.consume(decoded);
}
}

Related

Best algorithm to pair items of two queues

I have to find the best algorithm to define pairing between the items from two lists as in the figure. The pair is valid only if the number of node in list A is lower than number of node in list B and there are no crosses between links. The quality of the matching algorithm is determined by the total number of links.
I firstly tried to use a very simple algorithm: take a node in the list A and then look for the first node in list B that is higher than the former. The second figure shows a test case where this algorithm is not the best one.
Simple back-tracking can work (it may not be optimal, but it will certainly work).
For each legal pairing A[i], B[j], there are two choices:
take it, and make it illegal to try to pair any A[x], B[y] with x>i and y<j
not take it, and look at other possible pairs
By incrementally adding legal pairs to a bunch of pairs, you will eventually exhaust all legal pairings down a path. The number of valid pairings in a path is what you seek to maximize, and this algorithm will look at all possible answers and is guaranteed to work.
Pseudocode:
function search(currentPairs):
bestPairing = currentPairs
for each currently legal pair:
nextPairing = search(copyOf(currentPairs) + this pair)
if length of nextPairing > length of bestPairing:
bestPairing = nextPairing
return bestPairing
Initially, you will pass an empty currentPairs. Searching for legal pairs is the tricky part. You can use 3 nested loops that look at all A[x], B[y], and finally, if A[x] < B[y], look against all currentPairs to see if the there is a crossing line (the cost of this is roughly O(n^3)); or you can use a boolean matrix of valid pairings, which you update at each level (less computation time, down to O(n^2) - but more expensive in terms of memory)
Here a Java implementation.
For convinience I first build a map with the valid choices for each entry of list(array) a to b.
Then I loop throuough the list, making no choice and the valid choices for a connection to b.
Since you cant go back without crossing the existing connections I keep track of the maximum assigned in b.
Works at least for the two examples...
public class ListMatcher {
private int[] a ;
private int[] b ;
private Map<Integer,List<Integer>> choicesMap;
public ListMatcher(int[] a, int[] b) {
this.a = a;
this.b = b;
choicesMap = makeMap(a,b);
}
public Map<Integer,Integer> solve() {
Map<Integer,Integer> solution = new HashMap<>();
return solve(solution, 0, -1);
}
private Map<Integer,Integer> solve(Map<Integer,Integer> soFar, int current, int max) {
// done
if (current >= a.length) {
return soFar;
}
// make no choice from this entry
Map<Integer, Integer> solution = solve(new HashMap<>(soFar),current+1, max);
for (Integer choice : choicesMap.get(current)) {
if (choice > max) // can't go back
{
Map<Integer,Integer> next = new HashMap<>(soFar);
next.put(current, choice);
next = solve(next, current+1, choice);
if (next.size() > solution.size()) {
solution = next;
}
}
}
return solution;
}
// init possible choices
private Map<Integer, List<Integer>> makeMap(int[] a, int[] b) {
Map<Integer,List<Integer>> possibleMap = new HashMap<>();
for(int i = 0; i < a.length; i++) {
List<Integer> possible = new ArrayList<>();
for(int j = 0; j < b.length; j++) {
if (a[i] < b[j]) {
possible.add(j);
}
}
possibleMap.put(i, possible);
}
return possibleMap;
}
public static void main(String[] args) {
ListMatcher matcher = new ListMatcher(new int[]{3,7,2,1,5,9,2,2},new int[]{4,5,10,1,12,3,6,7});
System.out.println(matcher.solve());
matcher = new ListMatcher(new int[]{10,1,1,1,1,1,1,1},new int[]{2,2,2,2,2,2,2,101});
System.out.println(matcher.solve());
}
}
Output
(format: zero-based index_in_a=index_in_b)
{2=0, 3=1, 4=2, 5=4, 6=5, 7=6}
{1=0, 2=1, 3=2, 4=3, 5=4, 6=5, 7=6}
Your solution isn't picked because the solutions making no choice are picked first.
You can change this by processing the loop first...
Thanks to David's suggestion, I finally found the algorithm. It is an LCS approach, replacing the '=' with an '>'.
Recursive approach
The recursive approach is very straightforward. G and V are the two vectors with size n and m (adding a 0 at the beginning of both). Starting from the end, if last from G is larger than last from V, then return 1 + the function evaluated without the last item, otherwise return max of the function removing last from G or last from V.
int evaluateMaxRecursive(vector<int> V, vector<int> G, int n, int m) {
if ((n == 0) || (m == 0)) {
return 0;
}
else {
if (V[n] < G[m]) {
return 1 + evaluateMaxRecursive(V, G, n - 1, m - 1);
} else {
return max(evaluateMaxRecursive(V, G, n - 1, m), evaluateMaxRecursive(V, G, n, m - 1));
}
}
};
The recursive approach is valid with small number of items, due to the re-evaluation of same lists that occur during the loop.
Non recursive approach
The non recursive approach goes in the opposite direction and works with a table that is filled in after having clared to 0 first row and first column. The max value is the value in the bottom left corner of the table
int evaluateMax(vector<int> V, vector<int> G, int n, int m) {
int** table = new int* [n + 1];
for (int i = 0; i < n + 1; ++i)
table[i] = new int[m + 1];
for (int i = 0; i < n + 1; i++)
for (int t = 0; t < m + 1; t++)
table[i][t] = 0;
for (int i = 1; i < m + 1; i++)
for (int t = 1; t < n + 1; t++) {
if (G[i - 1] > V[t - 1]) {
table[t] [i] = 1 + table[t - 1][i - 1];
}
else {
table[t][i] = max(table[t][i - 1], table[t - 1][i]);
}
}
return table[n][m];
}
You can find more details here LCS - Wikipedia

How do I compute the sum of differences in C++ given an array of N integers?

Problem Statement: https://www.codechef.com/ZCOPRAC/problems/ZCO13001
My code falls flat with a 2.01 second runtime on test cases 4 and 5. I cannot figure out the problem with my code:-
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int summation(long long int a[], int n, int count)
{
long long int sum=0;
int i;
if(count==n)
return 0;
else
{
for(i=count; i<n; i++)
sum+=a[i]-a[count];
}
return sum+summation(a, n, count+1);
}
int main()
{
int n, i;
long long int sum;
scanf("%d", &n);
long long int a[n];
for(i=0; i<n; i++)
scanf("%lld", &a[i]);
sort(a, a+n);
sum=summation(a, n, 0);
printf("%lld\n", sum);
return 0;
}
Thanks!
First of all you are on the correct track when you are sorting the numbers, but the complexity of your algorithm is O(n^2). What you want is an O(n) algorithm.
I'm only going to give you a hint, after that how you use it is up to you.
Let us take the example given on the site you specified itself i.e. 3,10,3,5. You sort these elements to get 3,3,5,10. Now what specifically are the elements of the sum of the differences in this? They are as follows -
3-3
5-3
10-3
5-3
10-3
10-5
Our result is supposed to be (3-3) + (5-3) + ... + (10-5). Let us approach this expression differently.
3 - 3
5 - 3
10 - 3
5 - 3
10 - 3
10 - 5
43 - 20
This we get by adding the elements on the left side and the right side of the - sign.
Now take a variable sum = 0.
You need to make the following observations -
As you can see in these individual differences how many times does the first 3 appear on the right side of the - sign ?
It appears 3 times so let us take sum = -3*3 = -9.
Now for the second 3 , it appears 2 times on the right side of the - sign and 1 time on the left side so we get (1-2)*3 = -3. Adding this to sum we get -12.
Similarly for 5 we have 2 times on the left side and 1 time on the right side. We get (2-1)*5 = 5. Adding this to sum we get -12+5 = -7.
Now for 10 we have it 3 times on the left side i.e. 3*10 so sum is = -7+30 = 23 which is your required answer. Now what you need to consider is how many times does a number appear on the left side and the right side of the - sign. This can be done in O(1) time and for n elements it takes O(n) time.
There you have your answer. Let me know if you don't understand any part of this answer.
Your code works, but there are two issues.
Using recursion will eventually run out of stack space. I ran your code for n=200000 (upper limit in Code Chef problem) and got stack overflow.
I converted the recursion to an equivalent loop. This hit the second issue - it takes a long time. It is doing 2*10^5 * (2*10^5 - 1) / 2 cycles which is 2*10^10 roughly. Assuming a processor can run 10^9 cycles a second, you're looking at 20 seconds.
To fix the time issue, look for duplicates in team strength value. Instead of adding the same strength value (val) each time it appears in the input, add it once and keep a count of how many times it was found (dup). Then, when calculating the contribution of the pair (i,j), multiply a[i].val - a[j].val by the number of times this combo appeared in raw input, which is the product of the two dup values a[i].dup * a[j].dup.
Here's the revised code, using Strength struct to hold the strength value & the number of times it occurred. I didn't have a handy input file, so used random number generator with range 1,100. By cycling through only the unique strength values, the total number of cycles is greatly reduced.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<random>
using namespace std;
int codechef_sum1(long long int a[], int n, int count)
{
long long int sum = 0;
int i;
if (count == n)
return 0;
else
{
for (i = count; i<n; i++)
sum += a[i] - a[count];
}
return sum + codechef_sum1(a, n, count + 1);
}
int codechef_sum2a(long long int a[], int n)
{
long long int sum = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
sum += (a[i] - a[j]);
return sum;
}
struct Strength
{
long long int val;
int dup;
//bool operator()(const Strength& lhs, const Strength & rhs) { return lhs.val < rhs.val; }
bool operator<(const Strength & rhs) { return this->val < rhs.val; }
};
int codechef_sum2b(Strength a[], int n)
{
long long int sum = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < i; j++)
sum += (a[i].val - a[j].val) * (a[i].dup * a[j].dup);
}
return sum;
}
int codechef_sum_test(int n)
{
std::default_random_engine generator;
std::uniform_int_distribution<int> distr(1, 100);
auto a1 = new long long int[n];
auto a2 = new Strength [n];
int dup = 0, num = 0;
for (int i = 0; i < n; i++)
{
int r = distr(generator);
a1[i] = r;
int dup_index = -1;
for (int ii = 0; ii < num; ii++)
{
if (a2[ii].val == r)
{
dup++;
dup_index = ii;
break;
}
}
if (dup_index == -1)
{
a2[num].val = r;
a2[num].dup = 1;
++num;
}
else
{
++a2[dup_index].dup;
}
}
sort(a1, a1 + n);
sort(a2, a2 + num);
auto sum11 = codechef_sum1(a1, n, 0);
auto sum12 = codechef_sum2a(a1, n);
auto sum2 = codechef_sum2b(a2, num);
printf("sum11=%lld, sum12=%lld\n", sum11, sum12);
printf("sum2=%lld, dup=%d, num=%d\n", sum2, dup, num);
delete[] a1;
delete[] a2;
return 0;
}
void main()
{
codechef_sum_test(50);
}
Here's my solution with a quicker algorithm.
Everything below is spoilers, in case you wanted to solve it yourself.
--
long long int summation_singlepass(long long int a[], int n)
{
long long int grand_total=0;
long long int iteration_sum, prev_iteration_sum=0;
int i;
for (i = 1; i < n; i++) {
iteration_sum = prev_iteration_sum + i * ( a[i] - a[i-1] );
grand_total += iteration_sum;
prev_iteration_sum = iteration_sum;
}
return grand_total;
}
--
To figure out an algorithm, take a few simple but meaningful cases. Then work through them step by step yourself. This usually gives good insights.
For example: 1,3,6,6,8 (after sorting)
Third element in series. Its sum of differences to previous elements is:
(6-1) + (6-3) = 8
Fourth element in series. No change! Sum of differences to previous elements is:
(6-1) + (6-3) + (6-6) = 8
Fifth element in series. Pattern emerges when compared to formula for third and fourth. Sum of differences to previous elements is:
(8-1) + (8-3) + (8-6) + (8-6) = 16
So it's an extra 2 for each prior element in the series. 2 is the difference between our current element (8) and the previous one (6).
To generalize this effect. Derive the current iteration sum as the previous iteration sum + (i - 1) * ( a[i] - a[i-1] ). Where i is our current (1-based) position in the series.
Note that the formula looks slightly different in code compared to how I wrote it above. This is because in C++ we're working with 0-based indices for arrays.
Also - if you wanted to continue tweaking the solution you posted in OP, change the function return of summation to long long int to handle larger sets without the running total getting chopped.

How to perform K-swap operations on an N-digit integer to get maximum possible number

I recently went through an interview and was asked this question. Let me explain the question properly:
Given a number M (N-digit integer) and K number of swap operations(a swap
operation can swap 2 digits), devise an algorithm to get the maximum
possible integer?
Examples:
M = 132 K = 1 output = 312
M = 132 K = 2 output = 321
M = 7899 k = 2 output = 9987
My solution ( algorithm in pseudo-code). I used a max-heap to get the maximum digit out of N-digits in each of the K-operations and then suitably swapping it.
for(int i = 0; i<K; i++)
{
int max_digit_currently = GetMaxFromHeap();
// The above function GetMaxFromHeap() pops out the maximum currently and deletes it from heap
int index_to_swap_with = GetRightMostOccurenceOfTheDigitObtainedAbove();
// This returns me the index of the digit obtained in the previous function
// .e.g If I have 436659 and K=2 given,
// then after K=1 I'll have 936654 and after K=2, I should have 966354 and not 963654.
// Now, the swap part comes. Here the gotcha is, say with the same above example, I have K=3.
// If I do GetMaxFromHeap() I'll get 6 when K=3, but I should not swap it,
// rather I should continue for next iteration and
// get GetMaxFromHeap() to give me 5 and then get 966534 from 966354.
if (Value_at_index_to_swap == max_digit_currently)
continue;
else
DoSwap();
}
Time complexity: O(K*( N + log_2(N) ))
// K-times [log_2(N) for popping out number from heap & N to get the rightmost index to swap with]
The above strategy fails in this example:
M = 8799 and K = 2
Following my strategy, I'll get M = 9798 after K=1 and M = 9978 after K=2. However, the maximum I can get is M = 9987 after K=2.
What did I miss?
Also suggest other ways to solve the problem & ways to optimize my solution.
I think the missing part is that, after you've performed the K swaps as in the algorithm described by the OP, you're left with some numbers that you can swap between themselves. For example, for the number 87949, after the initial algorithm we would get 99748. However, after that we can swap 7 and 8 "for free", i.e. not consuming any of the K swaps. This would mean "I'd rather not swap the 7 with the second 9 but with the first".
So, to get the max number, one would perform the algorithm described by the OP and remember the numbers which were moved to the right, and the positions to which they were moved. Then, sort these numbers in decreasing order and put them in the positions from left to right.
This is something like a separation of the algorithm in two phases - in the first one, you choose which numbers should go in the front to maximize the first K positions. Then you determine the order in which you would have swapped them with the numbers whose positions they took, so that the rest of the number is maximized as well.
Not all the details are clear, and I'm not 100% sure it handles all cases correctly, so if anyone can break it - go ahead.
This is a recursive function, which sorts the possible swap values for each (current-max) digit:
function swap2max(string, K) {
// the recursion end:
if (string.length==0 || K==0)
return string
m = getMaxDigit(string)
// an array of indices of the maxdigits to swap in the string
indices = []
// a counter for the length of that array, to determine how many chars
// from the front will be swapped
len = 0
// an array of digits to be swapped
front = []
// and the index of the last of those:
right = 0
// get those indices, in a loop with 2 conditions:
// * just run backwards through the string, until we meet the swapped range
// * no more swaps than left (K)
for (i=string.length; i-->right && len<K;)
if (m == string[i])
// omit digits that are already in the right place
while (right<=i && string[right] == m)
right++
// and when they need to be swapped
if (i>=right)
front.push(string[right++])
indices.push(i)
len++
// sort the digits to swap with
front.sort()
// and swap them
for (i=0; i<len; i++)
string.setCharAt(indices[i], front[i])
// the first len digits are the max ones
// the rest the result of calling the function on the rest of the string
return m.repeat(right) + swap2max(string.substr(right), K-len)
}
This is all pseudocode, but converts fairly easy to other languages. This solution is nonrecursive and operates in linear worst case and average case time.
You are provided with the following functions:
function k_swap(n, k1, k2):
temp = n[k1]
n[k1] = n[k2]
n[k2] = temp
int : operator[k]
// gets or sets the kth digit of an integer
property int : magnitude
// the number of digits in an integer
You could do something like the following:
int input = [some integer] // input value
int digitcounts[10] = {0, ...} // all zeroes
int digitpositions[10] = {0, ...) // all zeroes
bool filled[input.magnitude] = {false, ...) // all falses
for d = input[i = 0 => input.magnitude]:
digitcounts[d]++ // count number of occurrences of each digit
digitpositions[0] = 0;
for i = 1 => input.magnitude:
digitpositions[i] = digitpositions[i - 1] + digitcounts[i - 1] // output positions
for i = 0 => input.magnitude:
digit = input[i]
if filled[i] == true:
continue
k_swap(input, i, digitpositions[digit])
filled[digitpositions[digit]] = true
digitpositions[digit]++
I'll walk through it with the number input = 724886771
computed digitcounts:
{0, 1, 1, 0, 1, 0, 1, 3, 2, 0}
computed digitpositions:
{0, 0, 1, 2, 2, 3, 3, 4, 7, 9}
swap steps:
swap 0 with 0: 724886771, mark 0 visited
swap 1 with 4: 724876781, mark 4 visited
swap 2 with 5: 724778881, mark 5 visited
swap 3 with 3: 724778881, mark 3 visited
skip 4 (already visited)
skip 5 (already visited)
swap 6 with 2: 728776481, mark 2 visited
swap 7 with 1: 788776421, mark 1 visited
swap 8 with 6: 887776421, mark 6 visited
output number: 887776421
Edit:
This doesn't address the question correctly. If I have time later, I'll fix it but I don't right now.
How I would do it (in pseudo-c -- nothing fancy), assuming a fantasy integer array is passed where each element represents one decimal digit:
int[] sortToMaxInt(int[] M, int K) {
for (int i = 0; K > 0 && i < M.size() - 1; i++) {
if (swapDec(M, i)) K--;
}
return M;
}
bool swapDec(int[]& M, int i) {
/* no need to try and swap the value 9 as it is the
* highest possible value anyway. */
if (M[i] == 9) return false;
int max_dec = 0;
int max_idx = 0;
for (int j = i+1; j < M.size(); j++) {
if (M[j] >= max_dec) {
max_idx = j;
max_dec = M[j];
}
}
if (max_dec > M[i]) {
M.swapElements(i, max_idx);
return true;
}
return false;
}
From the top of my head so if anyone spots some fatal flaw please let me know.
Edit: based on the other answers posted here, I probably grossly misunderstood the problem. Anyone care to elaborate?
You start with max-number(M, N, 1, K).
max-number(M, N, pos, k)
{
if k == 0
return M
max-digit = 0
for i = pos to N
if M[i] > max-digit
max-digit = M[i]
if M[pos] == max-digit
return max-number(M, N, pos + 1, k)
for i = (pos + 1) to N
maxs.add(M)
if M[i] == max-digit
M2 = new M
swap(M2, i, pos)
maxs.add(max-number(M2, N, pos + 1, k - 1))
return maxs.max()
}
Here's my approach (It's not fool-proof, but covers the basic cases). First we'll need a function that extracts each DIGIT of an INT into a container:
std::shared_ptr<std::deque<int>> getDigitsOfInt(const int N)
{
int number(N);
std::shared_ptr<std::deque<int>> digitsQueue(new std::deque<int>());
while (number != 0)
{
digitsQueue->push_front(number % 10);
number /= 10;
}
return digitsQueue;
}
You obviously want to create the inverse of this, so convert such a container back to an INT:
const int getIntOfDigits(const std::shared_ptr<std::deque<int>>& digitsQueue)
{
int number(0);
for (std::deque<int>::size_type i = 0, iMAX = digitsQueue->size(); i < iMAX; ++i)
{
number = number * 10 + digitsQueue->at(i);
}
return number;
}
You also will need to find the MAX_DIGIT. It would be great to use std::max_element as it returns an iterator to the maximum element of a container, but if there are more you want the last of them. So let's implement our own max algorithm:
int getLastMaxDigitOfN(const std::shared_ptr<std::deque<int>>& digitsQueue, int startPosition)
{
assert(!digitsQueue->empty() && digitsQueue->size() > startPosition);
int maxDigitPosition(0);
int maxDigit(digitsQueue->at(startPosition));
for (std::deque<int>::size_type i = startPosition, iMAX = digitsQueue->size(); i < iMAX; ++i)
{
const int currentDigit(digitsQueue->at(i));
if (maxDigit <= currentDigit)
{
maxDigit = currentDigit;
maxDigitPosition = i;
}
}
return maxDigitPosition;
}
From here on its pretty straight what you have to do, put the right-most (last) MAX DIGITS to their places until you can swap:
const int solution(const int N, const int K)
{
std::shared_ptr<std::deque<int>> digitsOfN = getDigitsOfInt(N);
int pos(0);
int RemainingSwaps(K);
while (RemainingSwaps)
{
int lastHDPosition = getLastMaxDigitOfN(digitsOfN, pos);
if (lastHDPosition != pos)
{
std::swap<int>(digitsOfN->at(lastHDPosition), digitsOfN->at(pos));
++pos;
--RemainingSwaps;
}
}
return getIntOfDigits(digitsOfN);
}
There are unhandled corner-cases but I'll leave that up to you.
I assumed K = 2, but you can change the value!
Java code
public class Solution {
public static void main (String args[]) {
Solution d = new Solution();
System.out.println(d.solve(1234));
System.out.println(d.solve(9812));
System.out.println(d.solve(9876));
}
public int solve(int number) {
int[] array = intToArray(number);
int[] result = solve(array, array.length-1, 2);
return arrayToInt(result);
}
private int arrayToInt(int[] array) {
String s = "";
for (int i = array.length-1 ;i >= 0; i--) {
s = s + array[i]+"";
}
return Integer.parseInt(s);
}
private int[] intToArray(int number){
String s = number+"";
int[] result = new int[s.length()];
for(int i = 0 ;i < s.length() ;i++) {
result[s.length()-1-i] = Integer.parseInt(s.charAt(i)+"");
}
return result;
}
private int[] solve(int[] array, int endIndex, int num) {
if (endIndex == 0)
return array;
int size = num ;
int firstIndex = endIndex - size;
if (firstIndex < 0)
firstIndex = 0;
int biggest = findBiggestIndex(array, endIndex, firstIndex);
if (biggest!= endIndex) {
if (endIndex-biggest==num) {
while(num!=0) {
int temp = array[biggest];
array[biggest] = array[biggest+1];
array[biggest+1] = temp;
biggest++;
num--;
}
return array;
}else{
int n = endIndex-biggest;
for (int i = 0 ;i < n;i++) {
int temp = array[biggest];
array[biggest] = array[biggest+1];
array[biggest+1] = temp;
biggest++;
}
return solve(array, --biggest, firstIndex);
}
}else{
return solve(array, --endIndex, num);
}
}
private int findBiggestIndex(int[] array, int endIndex, int firstIndex) {
int result = firstIndex;
int max = array[firstIndex];
for (int i = firstIndex; i <= endIndex; i++){
if (array[i] > max){
max = array[i];
result = i;
}
}
return result;
}
}

Old Top Coder riddle: Making a number by inserting +

I am thinking about this topcoder problem.
Given a string of digits, find the minimum number of additions required for the string to equal some target number. Each addition is the equivalent of inserting a plus sign somewhere into the string of digits. After all plus signs are inserted, evaluate the sum as usual.
For example, consider "303" and a target sum of 6. The best strategy is "3+03".
I would solve it with brute force as follows:
for each i in 0 to 9 // i -- number of plus signs to insert
for each combination c of i from 10
for each pos in c // we can just split the string w/o inserting plus signs
insert plus sign in position pos
evaluate the expression
if the expression value == given sum
return i
Does it make sense? Is it optimal from the performance point of view?
...
Well, now I see that a dynamic programming solution will be more efficient. However it is interesting if the presented solution makes sense anyway.
It's certainly not optimal. If, for example, you are given the string "1234567890" and the target is a three-digit number, you know that you have to split the string into at least four parts, so you need not check 0, 1, or 2 inserts. Also, the target limits the range of admissible insertion positions. Both points have small impact for short strings, but can make a huge difference for longer ones. However, I suspect there's a vastly better method, smells a bit of DP.
I haven't given it much thought yet, but if you scroll down you can see a link to the contest it was from, and from there you can see the solvers' solutions. Here's one in C#.
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
public class QuickSums {
public int minSums(string numbers, int sum) {
int[] arr = new int[numbers.Length];
for (int i = 0 ; i < arr.Length; i++)
arr[i] = 0;
int min = 15;
while (arr[arr.Length - 1] != 2)
{
arr[0]++;
for (int i = 0; i < arr.Length - 1; i++)
if (arr[i] == 2)
{
arr[i] = 0;
arr[i + 1]++;
}
String newString = "";
for (int i = 0; i < numbers.Length; i++)
{
newString+=numbers[i];
if (arr[i] == 1)
newString+="+";
}
String[] nums = newString.Split('+');
int sum1 = 0;
for (int i = 0; i < nums.Length; i++)
try
{
sum1 += Int32.Parse(nums[i]);
}
catch
{
}
if (sum == sum1 && nums.Length - 1 < min)
min = nums.Length - 1;
}
if (min == 15)
return -1;
return min;
}
}
Because input length is small (10) all possible ways (which can be found by a simple binary counter of length 10) is small (2^10 = 1024), so your algorithm is fast enough and returns valid result, and IMO there is no need to improve it.
In all until your solution works fine in time and memory and other given constrains, there is no need to do micro optimization. e.g this case as akappa offered can be solved with DP like DP in two-Partition problem, but when your algorithm is fast there is no need to do this and may be adding some big constant or making code unreadable.
I just offer parse digits of string one time (in array of length 10) to prevent from too many string parsing, and just use a*10^k + ... (Also you can calculate 10^k for k=0..9 in startup and save its value).
I think the problem is similar to Matrix Chain Multiplication problem where we have to put braces for least multiplication. Here braces represent '+'. So I think it could be solved by similar dp approach.. Will try to implement it.
dynamic programming :
public class QuickSums {
public static int req(int n, int[] digits, int sum) {
if (n == 0) {
if (sum == 0)
return 0;
else
return -1;
} else if (n == 1) {
if (sum == digits[0]) {
return 0;
} else {
return -1;
}
}
int deg = 1;
int red = 0;
int opt = 100000;
int split = -1;
for (int i=0; i<n;i++) {
red += digits[n-i-1] * deg;
int t = req(n-i-1,digits,sum - red);
if (t != -1 && t <= opt) {
opt = t;
split = i;
}
deg = deg*10;
}
if (opt == 100000)
return -1;
if (split == n-1)
return opt;
else
return opt + 1;
}
public static int solve (String digits,int sum) {
int [] dig = new int[digits.length()];
for (int i=0;i<digits.length();i++) {
dig[i] = digits.charAt(i) - 48;
}
return req(digits.length(), dig, sum);
}
public static void doit() {
String digits = "9230560001";
int sum = 71;
int result = solve(digits, sum);
System.out.println(result);
}
Seems to be too late .. but just read some comments and answers here which say no to dp approach . But it is a very straightforward dp similar to rod-cutting problem:
To get the essence:
int val[N][N];
int dp[N][T];
val[i][j]: numerical value of s[i..j] including both i and j
val[i][j] can be easily computed using dynamic programming approach in O(N^2) time
dp[i][j] : Minimum no of '+' symbols to be inserted in s[0..i] to get the required sum j
dp[i][j] = min( 1+dp[k][j-val[k+1][j]] ) over all k such that 0<=k<=i and val[k][j]>0
In simple terms , to compute dp[i][j] you assume the position k of last '+' symbol and then recur for s[0..k]

Sum of factorials for large numbers

I want to calculate the sum of digits of N!.
I want to do this for really large values of N, say N(1500). I am not using .NET 4.0. I cannot use the BigInteger class to solve this.
Can this be solved by some other algorithm or procedure? Please help.
I want to do some thing like this Calculate the factorial of an arbitrarily large number, showing all the digits but in C#. However I am unable to solve.
There is no special magic that allows you to calculate the sum of the digits, as far as I am concerned.
It shouldn't be that hard to create your own BigInteger class anyway - you only need to implement the long multiplication algorithm from 3rd grade.
If your goal is to calculate the sum of the digits of N!, and if N is reasonably bounded, you can do the following without a BigInteger type:
Find a list of factorial values online (table lookup will be much more efficient than calculating from scratch, and does not require BigInteger)
Store as a string data type
Parse each character in the string as an integer
Add the resulting integers
There are two performance shortcuts that you can use for whatever implementation you choose.
Chop off any zeros from the numbers.
If the number is evenly divisible by 5^n, divide it by 10^n.
in this way,
16*15*14*13*12*11*10*9*8*7*6*5*4*3*2 = 20,922,789,888,000
//-->
16*1.5*14*13*12*11*1*9*8*7*6*0.5*4*3*2 = 20,922,789,888 //Sum of 63
Also, it feels like there should be some algorithm without reverting to calculating it all out. Going to 18!, the sums of the digits are:
2,6,6,3,9,9,9,27,27,36,27,27,45,45,63,63,63
//the sums of the resulting digits are:
2,6,6,3,9,9,9,9,9,9,9,9,9,9,9,9,9
and notably, the sum of the digits of 1500! is 16749 (the sum of whose digits are 27)
Here's some working code. Some components can be improved upon to increase efficiency. The idea is to use whatever multiplication algorithm I was told in school, and to store long integers as strings.
As an afterthought, I think it would be smarter to represent large numbers with List<int>() instead of string. But I'll leave that as an exercise to the reader.
Code Sample
static string Mult(string a, string b)
{
int shift = 0;
List<int> result = new List<int>();
foreach (int aDigit in a.Reverse().Select(c => int.Parse(c.ToString())))
{
List<int> subresult = new List<int>();
int store = 0;
foreach (int bDigit in b.Reverse().Select(c => int.Parse(c.ToString())))
{
int next = aDigit*bDigit + store;
subresult.Add(next%10);
store = next/10;
}
if (store != 0) subresult.Add(store);
subresult.Reverse();
for (int i = 0; i < shift; ++i) subresult.Add(0);
subresult.Reverse();
int newResult = new List<int>();
store = 0;
for (int i = 0; i < subresult.Count; ++i)
{
if (result.Count >= i + 1)
{
int next = subresult[i] + result[i] + store;
if (next >= 10)
newResult.Add(next % 10);
else newResult.Add(next);
store = next / 10;
}
else
{
int next = subresult[i] + store;
newResult.Add(next % 10);
store = next / 10;
}
}
if (store != 0) newResult.Add(store);
result = newResult;
++shift;
}
result.Reverse();
return string.Join("", result);
}
static int FactorialSum(int n)
{
string result = "1";
for (int i = 2; i <= n; i++)
result = Mult(i.ToString(), result);
return result.Sum(r => int.Parse(r.ToString()));
}
Code Testing
Assuming the code snippet above is in the same class as your Main method, call it thusly.
Input
static void Main(string[] args)
{
Console.WriteLine(FactorialSum(1500));
}
Output
16749
Here's a port of the C++ code you reference in one of your comments. One thing to realize when porting from C++ to C# is that integers that are zero evaluate to false and integers that are non-zero evaluate to true when used in a Boolean comparison.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ArbitraryFactorial
{
class Program
{
const int max = 5000;
static void display(int[] arr)
{
int ctr = 0;
for (int i = 0; i < max; i++)
{
if (ctr == 0 && arr[i] != 0) ctr = 1;
if (ctr != 0)
Console.Write(arr[i]);
}
}
static void factorial(int[] arr, int n)
{
if (n == 0) return;
int carry = 0;
for (int i = max - 1; i >= 0; --i)
{
arr[i] = (arr[i] * n) + carry;
carry = arr[i] / 10;
arr[i] %= 10;
}
factorial(arr, n - 1);
}
static void Main(string[] args)
{
int[] arr = new int[max];
arr[max - 1] = 1;
int num;
Console.Write("Enter the number: ");
num = int.Parse(Console.ReadLine());
Console.Write("Factorial of " + num + " is: ");
factorial(arr, num);
display(arr);
}
}
}
you can find the source code at : http://codingloverlavi.blogspot.in/2013/03/here-is-one-more-interesting-program.html
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<time.h>
#define max 5000
void multiply(long int *,long int);
void factorial(long int *,long int);
int main()
{
clrscr();
cout<<"PROGRAM TO CALCULATE FACTORIAL OF A NUMBER";
cout<<"\nENTER THE NUMBER\n";
long int num;
cin>>num;
long int a[max];
for(long int i=0;i<max;i++)
a[i]=0;
factorial(a,num);
clrscr();
//PRINTING THE FINAL ARRAY...:):):)
cout<<"THE FACTORIAL OF "<<num<<" is "<<endl<<endl;
long int flag=0;
int ans=0;
for(i=0;i<max;i++)
{
if(flag||a[i]!=0)
{
flag=1;
cout<<a[i];
ans=ans+a[i];
}
}
cout<<endl<<endl<<"the sum of all digits is: "<<ans;
getch();
return 1;
}
void factorial(long int *a,long int n)
{
long int lavish;
long int num=n;
lavish=n;
for(long int i=max-1;i>=0&&n;i--)
{
a[i]=n%10;
n=n/10;
}
for(i=2;i<(lavish);i++)
{
multiply(a,num-1);
num=num-1;
}
}
void multiply(long int *a,long int n)
{
for(long int i=0;i<max;i++)
a[i]=a[i]*n;
for(i=max-1;i>0;i--)
{
a[i-1]=a[i-1]+(a[i]/10);
a[i]=a[i]%10;
}
}
You can't use these numbers at all without a BigInteger type.
No algorithm or procedure can squeeze numbers larger than 264 into a long.
You need to find a BigInteger implementation for .Net 3.5.

Resources