An interview puzzle: A Broken Calculator - algorithm

Time limit : 2sec / Stack limit : 256MB / Memory limit : 256MB
Problem
Dave's calculator is broken. It halts when presented with more than K different digits.
Dave wants to input an integer A, but if he inputs this number correctly the calculator might halt. Instead, he inputs the closest integer that won't halt the calculator.
Output the difference between Dave's input and the integer A.
Input
The input will be given in the following format from the Standard Input.
A K
On the first line, you will be given the integer A(1≦A≦10^15), the integer Dave wants to input, followed by a space and K(1≦K≦10), the number of different digits his calculator can recognize.
Output
Output the minimum difference between Dave's input and the integer A in one line. Make sure to insert a line break at the end of the output.
Input Example 1
1234 2
Output Example 1
12
In this case Dave can only use up to 2 different digits. He will input the closest integer 1222, so the difference is 12.
Input Example 2
7328495 10
Output Example 2
0
In this case Dave's calculator is not broken at all. He can input the given integer A as is.
Input Example 3
800000 1
Output Example 3
22223
Dave can use only one digit, so 777777 is the closest integer.
Input Example 4
262004 2
Output Example 4
218
The closest integer is 262222.
I have solved the problem by a brute force solution...
I try all possible situation where i in 1<= i < A or A < i <= 10^15.
I'll get two solutions composed from K different digits, and find the min difference between A and solutions.
It's a straightforward solution.
When A is larger, the execution will exceed the threshold of 2 sec.
Is there a smart and efficient way to solve it?

The first part is: Choose which k digits (out of the 10 possible) are used in the result
With a bit math (binomial coefficient) it´s easy to calculate the number
of different digit combinations possible for a given k.
There are up to 252 possibilities to choose (252 if k=5, else not so many).
If it is not clear what I´m saying: For k=2, there are 01,02,03,...09,12,13,...,19,23,24,...,89
No eg. 11 because it´s only 1 but k=2 allows two different digits.
And no eg. 90 because it´s the same as 09, 91=19 etc.
The count of these possible combinations is 252 for k=5, and it won´t get larger.
Finding all of the (up to) 252 possibilities for the current k
and iterating over them in a loop shouldn´t be too hard.
For each of the possibilities do the following:
{
Within the loop, we have the A, K, and the current choosen valid digits
for the solution (latter differs in each iteration of the loop, of course)
Lets take A=12899, K=3, digits 123 as example.
Now search the first digit of a (from left to right) which is not allowed.
In the example, this would be 12899, because 1 and 2 left of it are allowed.
Replace this (8) with the next-lower allowed digit (2) if there is one
and replace everything right of it with the highest possible digit (3 too).
12899=>12399=>12333
Save the result 12333 somewhere in an array etc.
If there was no next-lower possible digit, do nothing (nothing goes to the array)
(A proper addition with carry would introduce a new digit left of the changed one,
ie. invalid. A solution with this new digit will be found
when the loop comes to that digit)
Then the same thing again in the other direction:
Replace the found digit with the next-higher possible one
and everything right with the lowest. This goes in the array too,
of course only if there was a next-higher possible digit.
In case of 12899, the only higher replacement for 8 would be 9,
but 9 is not possible (only 123).
}
After the whole loop has finished (and every iteration has produced
up to two new array entries), you have up to 502 possible solutions for the problem.
The only thing left to do is to check which soltion is the best (ie. calculate the difference
to A for every entry and take the solution which minimal difference)

At each step you can use the digit you need, that digit + 1 (mod 10), that digit -1 (mod 10), or any digit you have used before. Once you run out of digits you can only use digits you have used before.
This creates a tree. At each step take the current states and calculate all possible new states in the next level down.
You can prune the tree as you go along by removing any next steps that have a delta that's more than a certain distance from the smallest delta of any of the next steps.
This is essentially a linear programming problem.
Below is the complete algorithm! Maybe someone can fine tune the decision as to which branches to prune to make it even faster.
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
public static class Converter
{
public static int ToInt(this IEnumerable<int> values)
{
return values.Aggregate(0, (total, v) => total * 10 + v);
}
public static IEnumerable<int> ToList (this int value)
{
if (value == 0) return Enumerable.Empty<int>();
else return value.ToString().Select(x => (int)x - '0').ToList();
}
}
class Program
{
static void Main(string[] args)
{
//int desired = 262004;
//int digits = 2;
int desired = 800000;
int digits = 1;
IEnumerable<State> currentStates = new[] { new State(0, 0, desired, digits) };
foreach (var digit in desired.ToList())
{
var nextStates = currentStates.SelectMany(x => x.NextPossibleStates());
foreach (var state in nextStates.OrderBy(s => s.Delta()).Take(10))
{
Console.WriteLine(state.ToString());
}
currentStates = nextStates;
Console.WriteLine("------------");
}
Console.ReadKey();
}
public class State
{
int index;
int current;
int desired;
int digitsRemaining;
private int desiredToNow()
{
return desired.ToList().Take(index).ToInt();
}
public int Delta()
{
return Math.Abs(desiredToNow() - current);
}
public State(int index, int current, int desired, int digitsRemaining)
{
this.index = index;
this.current = current;
this.desired = desired;
this.digitsRemaining = digitsRemaining;
}
private State Next (int nextDigit, int digitsRemaining)
{
return new State(this.index + 1, this.current * 10 + nextDigit, this.desired, digitsRemaining);
}
private IEnumerable<int> NextPossibleDigitsWithDuplicates()
{
if (this.digitsRemaining > 0)
{
int nextDesiredDigit = desired.ToList().Skip(index).First();
yield return nextDesiredDigit;
yield return (nextDesiredDigit + 9) % 10;
yield return (nextDesiredDigit + 1) % 10;
}
// Any previously used digit is OK
foreach (int i in this.current.ToList())
yield return i;
}
public IEnumerable<State> NextPossibleStates()
{
var possibles = this.NextPossibleDigitsWithDuplicates().Distinct();
var possiblesUsingExistingDigits = possibles.Where(p => this.current.ToList().Contains(p));
var possiblesUsingNewDigits = possibles.Where(p => !this.current.ToList().Contains(p));
var states = possiblesUsingExistingDigits.Select(p => Next(p, this.digitsRemaining))
.Concat(possiblesUsingNewDigits.Select(p => Next(p, this.digitsRemaining - 1)))
.ToList();
var bestDelta = states.Min(s => s.Delta());
// Now reject any that can never be better
// Guessing on the '2' here ...
var validStates = states.Where(s => s.Delta() < bestDelta + 2);
return validStates;
}
public override string ToString()
{
return this.current + " d=" + this.Delta() + " remaining " + this.digitsRemaining;
}
}
}

After thinking a bit about the problem I guess an A* algorithm that assigns digits from left to right is best. For that we need an estimation of the lower bound for the error of a partial solution. A simple possibility is:
if the already set digits are exactly the same as in the problem the bound is 0
if the already set digits are lower as in the problem replace the missing digits by 9 to get the lower bound
if the already set digits are higher as in the problem replace the missing digits by 0 to get the lower bound
Taking the example problem 12899 3 the algorithm would work like this:
Start node
node best error
xxxxx 12899 0
expansion of the most promising partial solution xxxxx
node best error
0xxxx 09999 2900
1xxxx 12899 0
2xxxx 20000 7101
3xxxx 30000 17101
4xxxx 40000 27101
5xxxx 50000 37101
6xxxx 60000 47101
7xxxx 70000 57101
8xxxx 80000 67101
9xxxx 90000 77101
Expansion of the most promising partial solution 1xxxx
node best error
0xxxx 09999 2900
10xxx 10999 1900
11xxx 11999 900
12xxx 12899 0
13xxx 13000 101
14xxx 14000 1101
15xxx 15000 2101
16xxx 16000 3101
17xxx 17000 4101
18xxx 18000 5101
19xxx 19000 6101
2xxxx 20000 7101
3xxxx 30000 17101
4xxxx 40000 27101
5xxxx 50000 37101
6xxxx 60000 47101
7xxxx 70000 57101
8xxxx 80000 67101
9xxxx 90000 77101
Expansion of the most promising partial solution 12xxx
node best error
0xxxx 09999 2900
10xxx 10999 1900
11xxx 11999 900
120xx 12099 800
121xx 12199 700
122xx 12299 600
123xx 12399 500
124xx 12499 400
125xx 12599 300
126xx 12699 200
127xx 12799 100
128xx 12899 0
129xx 12900 1
13xxx 13000 101
14xxx 14000 1101
15xxx 15000 2101
16xxx 16000 3101
17xxx 17000 4101
18xxx 18000 5101
19xxx 19000 6101
2xxxx 20000 7101
3xxxx 30000 17101
4xxxx 40000 27101
5xxxx 50000 37101
6xxxx 60000 47101
7xxxx 70000 57101
8xxxx 80000 67101
9xxxx 90000 77101
Expansion of the most promising partial solution 128xx (only the digits 1, 2 and 8 are allowed now)
node best error
0xxxx 09999 2900
10xxx 10999 1900
11xxx 11999 900
120xx 12099 800
121xx 12199 700
122xx 12299 600
123xx 12399 500
124xx 12499 400
125xx 12599 300
126xx 12699 200
127xx 12799 100
1281x 12819 80
1282x 12829 70
1288x 12889 10
129xx 12900 1
13xxx 13000 101
14xxx 14000 1101
15xxx 15000 2101
16xxx 16000 3101
17xxx 17000 4101
18xxx 18000 5101
19xxx 19000 6101
2xxxx 20000 7101
3xxxx 30000 17101
4xxxx 40000 27101
5xxxx 50000 37101
6xxxx 60000 47101
7xxxx 70000 57101
8xxxx 80000 67101
9xxxx 90000 77101
Expansion of the most promising partial solution 129xx (only the digits 1, 2 and 9 are allowed now)
node best error
0xxxx 09999 2900
10xxx 10999 1900
11xxx 11999 900
120xx 12099 800
121xx 12199 700
122xx 12299 600
123xx 12399 500
124xx 12499 400
125xx 12599 300
126xx 12699 200
127xx 12799 100
1281x 12819 80
1282x 12829 70
1288x 12889 10
1291x 12910 11
1292x 12920 21
1299x 12990 91
13xxx 13000 101
14xxx 14000 1101
15xxx 15000 2101
16xxx 16000 3101
17xxx 17000 4101
18xxx 18000 5101
19xxx 19000 6101
2xxxx 20000 7101
3xxxx 30000 17101
4xxxx 40000 27101
5xxxx 50000 37101
6xxxx 60000 47101
7xxxx 70000 57101
8xxxx 80000 67101
9xxxx 90000 77101
Expansion of the most promising partial solution 1288x (only the digits 1, 2 and 8 are allowed now)
node best error
0xxxx 09999 2900
10xxx 10999 1900
11xxx 11999 900
120xx 12099 800
121xx 12199 700
122xx 12299 600
123xx 12399 500
124xx 12499 400
125xx 12599 300
126xx 12699 200
127xx 12799 100
1281x 12819 80
1282x 12829 70
12881 12881 18
12882 12882 17
12888 12888 11 <-- optimal solution found
1291x 12910 11
1292x 12920 21
1299x 12990 91
13xxx 13000 101
14xxx 14000 1101
15xxx 15000 2101
16xxx 16000 3101
17xxx 17000 4101
18xxx 18000 5101
19xxx 19000 6101
2xxxx 20000 7101
3xxxx 30000 17101
4xxxx 40000 27101
5xxxx 50000 37101
6xxxx 60000 47101
7xxxx 70000 57101
8xxxx 80000 67101
9xxxx 90000 77101
This does still not cover the case that the optimal solution may have more digits than the original number (not sure if this is even possible), but you get the idea ...

For K=10 , the solution is trivial. Difference equals to 0.
If the original number use less than or equals to K distinct digit. Difference equals to 0. For example, 987777 5 use 3 distinct digit which is less than K (= 5).
For K=1 ,
A number with length n will be bound by 999...999 (n-digit) and 999...999((n-1)-digit). Which mean 587 is bound by 999 and 99. Hence, the solution must either be a n-digit length number or 999...999((n-1)-digit).
Let leading digit of the number be a (5 in 587), denote b=a+1 and c=a-1. Compare the number with aaa...aaa, bbb...bbb, ccc...ccc (all n-digit length). Notice that this just check at most 2 of them.
If original number = aaa...aaa, difference equals to 0.
If original number > aaa...aaa, continue to compare with bbb...bbb.
If original number < aaa...aaa, continue to compare with ccc...ccc.
Regulation for K=1, if b=10, ignore bbb...bbb since aaa...aaa = 999...999 which is upper bound. if c=0, change ccc...ccc to 999...999((n-1)-digit) for lower bound checking like 10000 1 -> 9999
For K in range [2,9], observe that first K-1 distinct digit from left to right must be used. For example, 9988898988981234 3, 2 digit 9 and 8 must be used in this case.
Proof:
Fact :
Number of distinct digit in original number > K
K-1 != 0
We can always form two value z000...000 and z999...999 using K distinct digit where z is form by K-1 distinct digit (z = 998889898898 in above example) and assign K th digit as 0 or 9 (ignore the fact that 0 or 9 may be used in K-1 as not important)
With z000...000 and z999...999 (9988898988980000 and 9988898988989999), the optimal solution is bound by the two value. If z change to z+1 or z-1, the difference will increase which makes no sense. Thus, z part will always be used and first K-1 distinct digit from left to right must be used holds.
End of Proof
At the first encounter K th distinct digit (leading digit right after z part, denote as t), there are three possible cases to consider: t, t+1 and t-1.
Let's start with t first. Using t will use up all K digit, so no more digit can be assigned. Keep on to check digit on the right part until we encounter a digit that is not in those K distinct digit. This time, we have at most two choose. The closest digit in K that is larger than the encounter digit and the closest digit in K that is smaller than the encounter digit. Using larger closest digit in K will result in a number larger than original number, so the remaining digit should be minimized by choosing smallest digit in K. Similarly, the remaining digit for smaller closest digit in K case will be largest digit in K.
For case t+1, this only need to be checked when there is no larger closest digit in K for case t. Using t+1 will always larger than original number, we need to minimized the remaining digit. Notice that t+1 may be one of the digit in K-1 , we have a free digit and so include 0 (if 0 is not in K-1). Then, we can choose the smallest digit in K (or K-1 if t+1 and 0 are in K-1) for remaining digit.
For case t-1, this only need to be checked when there is no smaller closest digit in K for case t. Using t-1 will always smaller than original number, we need to maximized the remaining digit. Notice that t-1 may be one of the digit in K-1 , we have a free digit and so include 9 (if 9 is not in K-1). Then, we can choose the largest digit in K (or K-1 if t-1 and 9 are in K-1) for remaining digit.

The solution time is O(len(A)).
To find the min|A - B|, with differnt K digits number.
First , to remove the abs, we should find B1 with the condition( min(Bi| Bi>=A, with different digits number),
Let A=a1a2...an, B1 = b1b2…bn,find the longest sequence which ai=bi until the different number exceed the K. Suppose we have a1->aj = b1->bj
If j == n, then B1 = A
From the set of {a1, a2,…,aj}, find the minimal number which is bigger than b[j+1]
If find ak(1<=k<=j), then let b[j+1]= ak, and the rest of b[j+1]->bn is filled with min{a1, a2,…,aj}
If not find, we change bj from aj to a[j]+1. For the rest of b[j+1]->bn,
If a[j]+1 is in the set of {a1, a2,…,aj-1}, it means we still can have one digit to press, we choose the 0 as the padding. b[j+1]->bn is all filled with 0.
If a[j]+1 is not in the set of {a1, a2,…,aj-1}, we choose the min{a1, a2,…,aj-1, a[j]+1} as the value which is filled with b[j+1]->bn
Similarity, we can find the closest number B2 which is smaller than A,
After that ,we just compare the B1-A with A-B2, choose the minimal.
Following the C++ Code:
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <sstream>
using namespace std;
string target_num;
string up_num;
string down_num;
int K;
bool hash_key[10];
bool hash_copy[10];
int find_closet_k(int c, bool up) {
int i = c;
while(true) {
if (hash_key[i]) {
return i;
}
if(up) {
++i;
if (10 <= i) {
break;
}
} else {
--i;
if (i < 0) {
break;
}
}
}
return -1;
}
char min_k() {
for (int i = 0; i < 10; ++i) {
if (hash_key[i]) {
return '0' + i;
}
}
}
char max_k() {
for (int i = 9; 0 <= i; --i) {
if (hash_key[i]) {
return '0' + i;
}
}
}
bool is_head_zero(int v, string num,int end_pos) {
if (0 == v) {
for (int i = 0; i < end_pos; ++i) {
if (num[i] != '0') {
return false;
}
}
return true;
}
return false;
}
int string2int(string s) {
std::stringstream ss;
ss << s;
int is;
ss >> is;
return is;
}
void find_closest() {
int k = 0;
int i = 0;
for (i = 0; i < target_num.size(); ++i) {
int c = target_num[i] - '0';
if (!hash_key[c]) {
if (k == K) {
break;
}
hash_key[c] = true;
++k;
}
up_num.push_back(target_num[i]);
down_num.push_back(target_num[i]);
}
if (i == target_num.size()) {
printf("0\n");
return;
}
copy(hash_key, hash_key + 10, hash_copy);
int j = i - 1;
up_num.resize(target_num.size());
int c = target_num[j + 1] - '0';
int v = find_closet_k(c, true);
if (v == -1) {
int aj = target_num[j] - '0';
up_num[j] = aj + 1 + '0';
if (hash_key[aj + 1]) {
//only used K - 1, use 0 as min_k();
fill(up_num.begin() + j + 1, up_num.end(), '0');
} else {
hash_key[aj] = false;
hash_key[aj + 1] = true;
fill(up_num.begin() + j + 1, up_num.end(), min_k());
}
} else {
up_num[j + 1] = v + '0';
fill(up_num.begin() + j + 1, up_num.end(), min_k());
}
copy(hash_copy, hash_copy + 10, hash_key);
j = i - 1;
down_num.resize(target_num.size());
v = find_closet_k(c, false);
if (v == -1) {
int aj = target_num[j] - '0';
down_num[j] = aj - 1 + '0';
if (hash_key[aj - 1] || is_head_zero(aj - 1,down_num, j)) {
fill(down_num.begin() + j + 1, down_num.end(), '9');
} else {
hash_key[aj] = false;
hash_key[aj -1] = true;
fill(down_num.begin() + j + 1, down_num.end(), max_k());
}
} else {
down_num[j + 1] = v + '0';
fill(down_num.begin() + j + 1, down_num.end(), max_k());
}
unsigned __int64 upi;
unsigned __int64 targeti;
unsigned __int64 downi;
sscanf(up_num.c_str(), "%lld", &upi);
sscanf(target_num.c_str(),"%lld",&targeti);
sscanf(down_num.c_str(),"%lld",&downi);
unsigned __int64 delta = min(upi - targeti, targeti - downi);
printf("%lld\n", delta);
}
int main(){
while (true) {
cin>>target_num>>K;
fill(hash_key, hash_key + 10, false);
find_closest();
up_num.clear();
down_num.clear();
target_num.clear();
}
}

Edit N2
on every step check if:
a) putting closeset possible digit less then current, and then maximizing remaining digits is better then current answer
b) putting closest possible digit greater then current, and then minimizing remaining digits is better then current answer
then if possible put same digit and then proceed to next digit

Related

How do I make this program work for input >10 for the USACO Training Pages Square Palindromes?

Problem Statement -
Given a number base B (2 <= B <= 20 base 10), print all the integers N (1 <= N <= 300 base 10) such that the square of N is palindromic when expressed in base B; also print the value of that palindromic square. Use the letters 'A', 'B', and so on to represent the digits 10, 11, and so on.
Print both the number and its square in base B.
INPUT FORMAT
A single line with B, the base (specified in base 10).
SAMPLE INPUT
10
OUTPUT FORMAT
Lines with two integers represented in base B. The first integer is the number whose square is palindromic; the second integer is the square itself. NOTE WELL THAT BOTH INTEGERS ARE IN BASE B!
SAMPLE OUTPUT
1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
264 69696
My code works for all inputs <=10, however, gives me some weird output for inputs >10.
My Code-
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int baseToBase(int num, int base) //accepts a number in base 10 and the base to be converted into as arguments
{
int result=0, temp=0, i=1;
while(num>0)
{
result = result + (num%base)*pow(10, i);
i++;
num = num/base;
}
result/=10;
return result;
}
long long int isPalin(int n, int base) //checks the palindrome
{
long long int result=0, temp, num=n*n, x=n*n;
num = baseToBase(num, base);
x = baseToBase(x, base);
while(num)
{
temp=num%10;
result = result*10 + temp;
num/=10;
}
if(x==result)
return x;
else
return 0;
}
int main()
{
int base, i, temp;
long long int sq;
cin >> base;
for(i=1; i<=300; i++)
{
temp=baseToBase(i, base);
sq=isPalin(i, base);
if(sq!=0)
cout << temp << " " << sq << endl;
}
return 0;
}
For input = 11, the answer should be
1 1
2 4
3 9
6 33
11 121
22 484
24 565
66 3993
77 5335
101 10201
111 12321
121 14641
202 40804
212 44944
234 53535
While my answer is
1 1
2 4
3 9
6 33
11 121
22 484
24 565
66 3993
77 5335
110 10901
101 10201
111 12321
121 14641
209 40304
202 40804
212 44944
227 50205
234 53535
There is a difference in my output and the required one as 202 shows under 209 and 110 shows up before 101.
Help appreciated, thanks!
a simple example for B = 11 to show error in your base conversion is for i = 10 temp should be A but your code calculates temp = 10. Cause in we have only 10 symbols 0-9 to perfectly show every number in base 10 or lower but for bases greater than that you have to use other symbols to represent a different digit like 'A', 'B' and so on. problem description clearly states that. Hope You will be able to fix your code now by modifying your int baseToBase(int num, int base)function.

Generating number within range with equal probability with dice

I've been thinking about this but can't seem to figure it out. I need to pick a random integer between 1 to 50 (inclusive) in such a way that each of the integer in it would be equally likely. I will have to do this using a 8 sided dice and a 15 sided dice.
I've read somewhat similar questions related to random number generators with dices but I am still confused. I think it is somewhere along the line of partitioning the numbers into sets. Then, I would roll a die, and then, depending on the outcome, decide which die to roll again.
Can someone help me with this?
As a simple - not necessarily "optimal" solution, roll the 8 sided die, then the 15 sided:
8 sided 15 sided 1..50 result
1 or 2 1..15 1..15
3 or 4 1..15 16..30 (add 15 to 15-sided roll)
5 or 6 1..15 31..45 (add 30 to 15-sided roll)
7 or 8 1..5 46..50 (add 45 to 15-sided roll)
7 or 8 6..15 start again / reroll both dice
lets say you have two functions: d8(), which returns a number from 0 to 7, and d15(), which returns a number from 0 to 14. You want to write a d50() that returns a number from 0 to 49.
Of all the simple ways, this one is probably the most efficient in terms of how many dice you have to roll, and something like this will work for all combinations of dice you have and dice you want:
int d50()
{
int result;
do
{
result = d8()*8+d8(); //random from 0 to 63
} while(result >=50);
return result;
}
If you want really constant time, you can do this:
int d50()
{
int result = d15();
int result = result*15+d15(); //0 to 225
int result = result*8+d8(); //0 to 1799
return result/36; //integer division rounds down
}
This way combines dice until the number of possibilities (1800) is evenly divisible by 50, so the same number of possibilities correspond to each result. This works OK in this case, but doesn't work if the prime factors of the dice you have (2, 3, and 5 in this case), don't cover the factors of the dice you want (2, 5)
I think that you can consider each dice result as a subdivision of a bigger interval. So throwing one 8 sided dice you choose one out the 8 major interval that divide your range of value. Throwing a 15 sided dice means selecting one out the 15 sub-interval and so on.
Considering that 15 = 3*5, 8 = 2*2*2 and 50 = 2*5*5 you can choose 36 = 3*3*2*2 as an handy multiple of 50 so that:
15*15*8 = 50*36 = 1800
You can even think of expressing the numbers from 0 to 1799 in base 15 and choose ramdomly the three digits:
choice = [0-7]*15^2 + [0-14]*15^1 + [0-14]*15^0
So my proposal, with a test of the distribution, is (in the c++ language):
#include <iostream>
#include <random>
#include <map>
int main() {
std::map<int, int> hist;
int result;
std::random_device rd;
std::mt19937 gen(rd()); // initialiaze the random generator
std::uniform_int_distribution<> d8(0, 7); // istantiate the dices
std::uniform_int_distribution<> d15(0, 14);
for (int i = 0; i < 20000; ++i) { // make a lot of throws...
result = d8(gen) * 225;
result += d15(gen) * 15; // add to result
result += d15(gen);
++hist[ result / 36 + 1]; // count each result
}
for (auto p : hist) { // show the occurences of each result
std::cout << p.first << " : " << p.second << '\n';
}
return 0;
}
The output should be something like this:
1 : 387
2 : 360
3 : 377
4 : 393
5 : 402
...
48 : 379
49 : 378
50 : 420

Display all the possible numbers having its digits in ascending order

Write a program that can display all the possible numbers in between given two numbers, having its digits in ascending order.
For Example:-
Input: 5000 to 6000
Output: 5678 5679 5689 5789
Input: 90 to 124
Output: 123 124
Brute force approach can make it count to all numbers and check of digits for each one of them. But I want approaches that can skip some numbers and can bring complexity lesser than O(n). Do any such solution(s) exists that can give better approach for this problem?
I offer a solution in Python. It is efficient as it considers only the relevant numbers. The basic idea is to count upwards, but handle overflow somewhat differently. While we normally set overflowing digits to 0, here we set them to the previous digit +1. Please check the inline comments for further details. You can play with it here: http://ideone.com/ePvVsQ
def ascending( na, nb ):
assert nb>=na
# split each number into a list of digits
a = list( int(x) for x in str(na))
b = list( int(x) for x in str(nb))
d = len(b) - len(a)
# if both numbers have different length add leading zeros
if d>0:
a = [0]*d + a # add leading zeros
assert len(a) == len(b)
n = len(a)
# check if the initial value has increasing digits as required,
# and fix if necessary
for x in range(d+1, n):
if a[x] <= a[x-1]:
for y in range(x, n):
a[y] = a[y-1] + 1
break
res = [] # result set
while a<=b:
# if we found a value and add it to the result list
# turn the list of digits back into an integer
if max(a) < 10:
res.append( int( ''.join( str(k) for k in a ) ) )
# in order to increase the number we look for the
# least significant digit that can be increased
for x in range( n-1, -1, -1): # count down from n-1 to 0
if a[x] < 10+x-n:
break
# digit x is to be increased
a[x] += 1
# all subsequent digits must be increased accordingly
for y in range( x+1, n ):
a[y] = a[y-1] + 1
return res
print( ascending( 5000, 9000 ) )
Sounds like task from Project Euler. Here is the solution in C++. It is not short, but it is straightforward and effective. Oh, and hey, it uses backtracking.
// Higher order digits at the back
typedef std::vector<int> Digits;
// Extract decimal digits of a number
Digits ExtractDigits(int n)
{
Digits digits;
while (n > 0)
{
digits.push_back(n % 10);
n /= 10;
}
if (digits.empty())
{
digits.push_back(0);
}
return digits;
}
// Main function
void PrintNumsRec(
const Digits& minDigits, // digits of the min value
const Digits& maxDigits, // digits of the max value
Digits& digits, // digits of current value
int pos, // current digits with index greater than pos are already filled
bool minEq, // currently filled digits are the same as of min value
bool maxEq) // currently filled digits are the same as of max value
{
if (pos < 0)
{
// Print current value. Handle leading zeros by yourself, if need
for (auto pDigit = digits.rbegin(); pDigit != digits.rend(); ++pDigit)
{
if (*pDigit >= 0)
{
std::cout << *pDigit;
}
}
std::cout << std::endl;
return;
}
// Compute iteration boundaries for current position
int first = minEq ? minDigits[pos] : 0;
int last = maxEq ? maxDigits[pos] : 9;
// The last filled digit
int prev = digits[pos + 1];
// Make sure generated number has increasing digits
int firstInc = std::max(first, prev + 1);
// Iterate through possible cases for current digit
for (int d = firstInc; d <= last; ++d)
{
digits[pos] = d;
if (d == 0 && prev == -1)
{
// Mark leading zeros with -1
digits[pos] = -1;
}
PrintNumsRec(minDigits, maxDigits, digits, pos - 1, minEq && (d == first), maxEq && (d == last));
}
}
// High-level function
void PrintNums(int min, int max)
{
auto minDigits = ExtractDigits(min);
auto maxDigits = ExtractDigits(max);
// Make digits array of the same size
while (minDigits.size() < maxDigits.size())
{
minDigits.push_back(0);
}
Digits digits(minDigits.size());
int pos = digits.size() - 1;
// Placeholder for leading zero
digits.push_back(-1);
PrintNumsRec(minDigits, maxDigits, digits, pos, true, true);
}
void main()
{
PrintNums(53, 297);
}
It uses recursion to handle arbitrary amount of digits, but it is essentially the same as the nested loops approach. Here is the output for (53, 297):
056
057
058
059
067
068
069
078
079
089
123
124
125
126
127
128
129
134
135
136
137
138
139
145
146
147
148
149
156
157
158
159
167
168
169
178
179
189
234
235
236
237
238
239
245
246
247
248
249
256
257
258
259
267
268
269
278
279
289
Much more interesting problem would be to count all these numbers without explicitly computing it. One would use dynamic programming for that.
There is only a very limited number of numbers which can match your definition (with 9 digits max) and these can be generated very fast. But if you really need speed, just cache the tree or the generated list and do a lookup when you need your result.
using System;
using System.Collections.Generic;
namespace so_ascending_digits
{
class Program
{
class Node
{
int digit;
int value;
List<Node> children;
public Node(int val = 0, int dig = 0)
{
digit = dig;
value = (val * 10) + digit;
children = new List<Node>();
for (int i = digit + 1; i < 10; i++)
{
children.Add(new Node(value, i));
}
}
public void Collect(ref List<int> collection, int min = 0, int max = Int16.MaxValue)
{
if ((value >= min) && (value <= max)) collection.Add(value);
foreach (Node n in children) if (value * 10 < max) n.Collect(ref collection, min, max);
}
}
static void Main(string[] args)
{
Node root = new Node();
List<int> numbers = new List<int>();
root.Collect(ref numbers, 5000, 6000);
numbers.Sort();
Console.WriteLine(String.Join("\n", numbers));
}
}
}
Why the brute force algorithm may be very inefficient.
One efficient way of encoding the input is to provide two numbers: the lower end of the range, a, and the number of values in the range, b-a-1. This can be encoded in O(lg a + lg (b - a)) bits, since the number of bits needed to represent a number in base-2 is roughly equal to the base-2 logarithm of the number. We can simplify this to O(lg b), because intuitively if b - a is small, then a = O(b), and if b - a is large, then b - a = O(b). Either way, the total input size is O(2 lg b) = O(lg b).
Now the brute force algorithm just checks each number from a to b, and outputs the numbers whose digits in base 10 are in increasing order. There are b - a + 1 possible numbers in that range. However, when you represent this in terms of the input size, you find that b - a + 1 = 2lg (b - a + 1) = 2O(lg b) for a large enough interval.
This means that for an input size n = O(lg b), you may need to check in the worst case O(2 n) values.
A better algorithm
Instead of checking every possible number in the interval, you can simply generate the valid numbers directly. Here's a rough overview of how. A number n can be thought of as a sequence of digits n1 ... nk, where k is again roughly log10 n.
For a and a four-digit number b, the iteration would look something like
for w in a1 .. 9:
for x in w+1 .. 9:
for y in x+1 .. 9:
for x in y+1 .. 9:
m = 1000 * w + 100 * x + 10 * y + w
if m < a:
next
if m > b:
exit
output w ++ x ++ y ++ z (++ is just string concatenation)
where a1 can be considered 0 if a has fewer digits than b.
For larger numbers, you can imagine just adding more nested for loops. In general, if b has d digits, you need d = O(lg b) loops, each of which iterates at most 10 times. The running time is thus O(10 lg b) = O(lg b) , which is a far better than the O(2lg b) running time you get by checking if every number is sorted or not.
One other detail that I have glossed over, which actually does affect the running time. As written, the algorithm needs to consider the time it takes to generate m. Without going into the details, you could assume that this adds at worst a factor of O(lg b) to the running time, resulting in an O(lg2 b) algorithm. However, using a little extra space at the top of each for loop to store partial products would save lots of redundant multiplication, allowing us to preserve the originally stated O(lg b) running time.
One way (pseudo-code):
for (digit3 = '5'; digit3 <= '6'; digit3++)
for (digit2 = digit3+1; digit2 <= '9'; digit2++)
for (digit1 = digit2+1; digit1 <= '9'; digit1++)
for (digit0 = digit1+1; digit0 <= '9'; digit0++)
output = digit3 + digit2 + digit1 + digit0; // concatenation

How can I fairly choose an item from a list?

Let's say that I have a list of prizes:
PrizeA
PrizeB
PrizeC
And, for each of them, I want to draw a winner from a list of my attendees.
Give that my attendee list is as follows:
user1, user2, user3, user4, user5
What is an unbiased way to choose a user from that list?
Clearly, I will be using a cryptographically secure pseudo-random number generator, but how do I avoid a bias towards the front of the list? I assume I will not be using modulus?
EDIT
So, here is what I came up with:
class SecureRandom
{
private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
private ulong NextUlong()
{
byte[] data = new byte[8];
rng.GetBytes(data);
return BitConverter.ToUInt64(data, 0);
}
public int Next()
{
return (int)(NextUlong() % (ulong)int.MaxValue);
}
public int Next(int maxValue)
{
if (maxValue < 0)
{
throw new ArgumentOutOfRangeException("maxValue");
}
if (maxValue == 0)
{
return 0;
}
ulong chop = ulong.MaxValue - (ulong.MaxValue % (ulong)maxValue);
ulong rand;
do
{
rand = NextUlong();
} while (rand >= chop);
return (int)(rand % (ulong)maxValue);
}
}
BEWARE:
Next() Returns an int in the range [0, int.MaxValue]
Next(int.MaxValue) Returns an int in the range [0, int.MaxValue)
Pseudocode for special random number generator:
rng is random number generator produces uniform integers from [0, max)
compute m = max modulo length of attendee list
do {
draw a random number r from rng
} while(r >= max - m)
return r modulo length of attendee list
This eliminates the bias to the front part of the list. Then
put the attendees in some data structure indexable by integers
for every prize in the prize list
draw a random number r using above
compute index = r modulo length of attendee list
return the attendee at index
In C#:
public NextUnbiased(Random rg, int max) {
do {
int r = rg.Next();
} while(r >= Int32.MaxValue - (Int32.MaxValue % max));
return r % max;
}
public Attendee SelectWinner(IList<Attendee> attendees, Random rg) {
int winningAttendeeIndex = NextUnbiased(rg, attendees.Length)
return attendees[winningAttendeeIndex];
}
Then:
// attendees is list of attendees
// rg is Random
foreach(Prize prize in prizes) {
Attendee winner = SelectWinner(attendees, rg);
Console.WriteLine("Prize {0} won by {1}", prize.ToString(), winner.ToString());
}
Assuming a fairly distributed random number generator...
do {
i = rand();
} while (i >= RAND_MAX / 5 * 5);
i /= 5;
This gives each of 5 slots
[ 0 .. RAND_MAX / 5 )
[ RAND_MAX / 5 .. RAND_MAX / 5 * 2 )
[ RAND_MAX / 5 * 2 .. RAND_MAX / 5 * 3 )
[ RAND_MAX / 5 * 3 .. RAND_MAX / 5 * 4 )
[ RAND_MAX / 5 * 4 .. RAND_MAX / 5 * 5 )
and discards a roll which falls out of range.
You have already seem several perfectly good answers that depend on knowing the length of the list in advance.
To fairly select a single item from a list without needing to know the length of the list in the first place do this:
if (list.empty()) error_out_somehow
r=list.first() // r is a reference or pointer
s=list.first() // so is s
i = 2
while (r.next() is not NULL)
r=r.next()
if (random(i)==0) s=r // random() returns a uniformly
// drawn integer between 0 and i
i++
return s
(Useful if you list is stored as a linked list)
To distribute prizes in this scenario, just walk down the list of prizes selecting a random winner for each one. (If you want to prevent double winning you then remove the winner from the participant list.)
Why does it work?
You start with the first item at 1/1
On the next pass, you select the second item half the time (1/2), which means that the first item has probability 1 * (2-1)/2 = 1/2
on further iteration, you select the nth item with probability 1/n, and the chance for each previous item is reduced by a factor of (n-1)/n
which means that when you come to the end, the chance of having the mth item in the list (of n items) is
1/m * m/(m+1) * (m+1)/(m+2) * ... * (n-2)/(n-1) * (n-1)/n = 1/n
and is the same for every item.
If you are paying attention, you'll note that this means walking the whole list every time you want to select an item from the list, so this is not maximally efficient for (say) reordering the whole list (though it does that fairly).
I suppose one answer would be to assign each item a random value, and take the largest or smallest, drilling down as necessary.
I'm not sure if this is the most efficient, tho...
If you're using a good number generator, even with a modulus your bias will be miniscule. If, for instance, you're using a random number generator with 64 bits of entropy and five users, your bias toward the front of the array should be on the order of 3x10^-19 (my numbers may be off, by I don't think by much). That's an extra 3-in-10-quintillion likelihood of the first user winning compared to the later users. That should be good enough to be fair in anyone's book.
You can buy truly random bits from a provider, or use a mechanical device.
Here you will find Oleg Kiselyov's discussion of purely functional random shuffling.
A description of the linked content (quoted from the beginning of that article):
This article will give two pure functional programs that perfectly,
randomly and uniformly shuffle a sequence of arbitrary elements. We
prove that the algorithms are correct. The algorithms are implemented
in Haskell and can trivially be re-written into other (functional)
languages. We also discuss why a commonly used sort-based shuffle
algorithm falls short of perfect shuffling.
You could use that to shuffle your list and then pick the first item of the shuffled result (or maybe you'd prefer not to give two prizes two the same person -- then use n initial positions of the result, for n = number of prizes); or you could simplify the algorithm to just produce the first item; or you could take a look around that site, because I could have sworn there's an article on picking one random element from an arbitrary tree-like structure with uniform distribution, in a purely functional way, proof of correctness provided, but my search-fu is failing me and I can't seem to find it.
Without truly random bits, you will always have some bias. The number of ways to assign prizes to guests is much larger than any common PRNG's period for even a fairly low number of guests and prizes. As suggested by lpthnc, buy some truly random bits, or buy some random-bit-generating hardware.
As for the algorithm, just do a random shuffle of the guest list. Be careful, as naive shuffling algorithms do have a bias: http://en.wikipedia.org/wiki/Shuffling#Shuffling_algorithms
You can 100% reliably pick a random item from any arbitrary list with a single pass and without knowing how many items are in the list ahead of time.
Psuedo Code:
count = 0.0;
item_selected = none;
foreach item in list
count = count + 1.0;
chance = 1.0 / count;
if ( random( 1.0 ) <= chance ) then item_selected = item;
Test program comparing results of a single rand() % N vs iterating as above:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
static inline float frand01()
{
return (float)rand() / (float)RAND_MAX;
}
int _tmain(int argc, _TCHAR* argv[])
{
static const int NUM_ITEMS = 50;
int resultRand[NUM_ITEMS];
int resultIterate[NUM_ITEMS];
memset( resultRand, 0, NUM_ITEMS * sizeof(int) );
memset( resultIterate, 0, NUM_ITEMS * sizeof(int) );
for ( int i = 0; i < 100000; i++ )
{
int choiceRand = rand() % NUM_ITEMS;
int choiceIterate = 0;
float count = 0.0;
for ( int item = 0; item < NUM_ITEMS; item++ )
{
count = count + 1.0f;
float chance = 1.0f / count;
if ( frand01() <= chance )
{
choiceIterate = item;
}
}
resultRand[choiceRand]++;
resultIterate[choiceIterate]++;
}
printf("Results:\n");
for ( int i = 0; i < NUM_ITEMS; i++ )
{
printf( "%02d - %5d %5d\n", i, resultRand[i], resultIterate[i] );
}
return 0;
}
Output:
Results:
00 - 2037 2050
01 - 2038 2009
02 - 2094 1986
03 - 2007 1953
04 - 1990 2142
05 - 1867 1962
06 - 1941 1997
07 - 2023 1967
08 - 1998 2070
09 - 1930 1953
10 - 1972 1900
11 - 2013 1985
12 - 1982 2001
13 - 1955 2063
14 - 1952 2022
15 - 1955 1976
16 - 2000 2044
17 - 1976 1997
18 - 2117 1887
19 - 1978 2020
20 - 1886 1934
21 - 1982 2065
22 - 1978 1948
23 - 2039 1894
24 - 1946 2010
25 - 1983 1927
26 - 1965 1927
27 - 2052 1964
28 - 2026 2021
29 - 2090 1993
30 - 2039 2016
31 - 2030 2009
32 - 1970 2094
33 - 2036 2048
34 - 2020 2046
35 - 2010 1998
36 - 2104 2041
37 - 2115 2019
38 - 1959 1986
39 - 1998 2031
40 - 2041 1977
41 - 1937 2060
42 - 1946 2048
43 - 2014 1986
44 - 1979 2072
45 - 2060 2002
46 - 2046 1913
47 - 1995 1970
48 - 1959 2020
49 - 1970 1997

algorithm to sum up a list of numbers for all combinations

I have a list of numbers and I want to add up all the different combinations.
For example:
number as 1,4,7 and 13
the output would be:
1+4=5
1+7=8
1+13=14
4+7=11
4+13=17
7+13=20
1+4+7=12
1+4+13=18
1+7+13=21
4+7+13=24
1+4+7+13=25
Is there a formula to calculate this with different numbers?
A simple way to do this is to create a bit set with as much bits as there are numbers.
In your example 4.
Then count from 0001 to 1111 and sum each number that has a 1 on the set:
Numbers 1,4,7,13:
0001 = 13=13
0010 = 7=7
0011 = 7+13 = 20
1111 = 1+4+7+13 = 25
Here's how a simple recursive solution would look like, in Java:
public static void main(String[] args)
{
f(new int[] {1,4,7,13}, 0, 0, "{");
}
static void f(int[] numbers, int index, int sum, String output)
{
if (index == numbers.length)
{
System.out.println(output + " } = " + sum);
return;
}
// include numbers[index]
f(numbers, index + 1, sum + numbers[index], output + " " + numbers[index]);
// exclude numbers[index]
f(numbers, index + 1, sum, output);
}
Output:
{ 1 4 7 13 } = 25
{ 1 4 7 } = 12
{ 1 4 13 } = 18
{ 1 4 } = 5
{ 1 7 13 } = 21
{ 1 7 } = 8
{ 1 13 } = 14
{ 1 } = 1
{ 4 7 13 } = 24
{ 4 7 } = 11
{ 4 13 } = 17
{ 4 } = 4
{ 7 13 } = 20
{ 7 } = 7
{ 13 } = 13
{ } = 0
The best-known algorithm requires exponential time. If there were a polynomial-time algorithm, then you would solve the subset sum problem, and thus the P=NP problem.
The algorithm here is to create bitvector of length that is equal to the cardinality of your set of numbers. Fix an enumeration (n_i) of your set of numbers. Then, enumerate over all possible values of the bitvector. For each enumeration (e_i) of the bitvector, compute the sum of e_i * n_i.
The intuition here is that you are representing the subsets of your set of numbers by a bitvector and generating all possible subsets of the set of numbers. When bit e_i is equal to one, n_i is in the subset, otherwise it is not.
The fourth volume of Knuth's TAOCP provides algorithms for generating all possible values of the bitvector.
C#:
I was trying to find something more elegant - but this should do the trick for now...
//Set up our array of integers
int[] items = { 1, 3, 5, 7 };
//Figure out how many bitmasks we need...
//4 bits have a maximum value of 15, so we need 15 masks.
//Calculated as:
// (2 ^ ItemCount) - 1
int len = items.Length;
int calcs = (int)Math.Pow(2, len) - 1;
//Create our array of bitmasks... each item in the array
//represents a unique combination from our items array
string[] masks = Enumerable.Range(1, calcs).Select(i => Convert.ToString(i, 2).PadLeft(len, '0')).ToArray();
//Spit out the corresponding calculation for each bitmask
foreach (string m in masks)
{
//Get the items from our array that correspond to
//the on bits in our mask
int[] incl = items.Where((c, i) => m[i] == '1').ToArray();
//Write out our mask, calculation and resulting sum
Console.WriteLine(
"[{0}] {1}={2}",
m,
String.Join("+", incl.Select(c => c.ToString()).ToArray()),
incl.Sum()
);
}
Outputs as:
[0001] 7=7
[0010] 5=5
[0011] 5+7=12
[0100] 3=3
[0101] 3+7=10
[0110] 3+5=8
[0111] 3+5+7=15
[1000] 1=1
[1001] 1+7=8
[1010] 1+5=6
[1011] 1+5+7=13
[1100] 1+3=4
[1101] 1+3+7=11
[1110] 1+3+5=9
[1111] 1+3+5+7=16
Here is a simple recursive Ruby implementation:
a = [1, 4, 7, 13]
def add(current, ary, idx, sum)
(idx...ary.length).each do |i|
add(current + [ary[i]], ary, i+1, sum + ary[i])
end
puts "#{current.join('+')} = #{sum}" if current.size > 1
end
add([], a, 0, 0)
Which prints
1+4+7+13 = 25
1+4+7 = 12
1+4+13 = 18
1+4 = 5
1+7+13 = 21
1+7 = 8
1+13 = 14
4+7+13 = 24
4+7 = 11
4+13 = 17
7+13 = 20
If you do not need to print the array at each step, the code can be made even simpler and much faster because no additional arrays are created:
def add(ary, idx, sum)
(idx...ary.length).each do |i|
add(ary, i+1, sum + ary[i])
end
puts sum
end
add(a, 0, 0)
I dont think you can have it much simpler than that.
Mathematica solution:
{#, Total##}& /# Subsets[{1, 4, 7, 13}] //MatrixForm
Output:
{} 0
{1} 1
{4} 4
{7} 7
{13} 13
{1,4} 5
{1,7} 8
{1,13} 14
{4,7} 11
{4,13} 17
{7,13} 20
{1,4,7} 12
{1,4,13} 18
{1,7,13} 21
{4,7,13} 24
{1,4,7,13} 25
This Perl program seems to do what you want. It goes through the different ways to choose n items from k items. It's easy to calculate how many combinations there are, but getting the sums of each combination means you have to add them eventually. I had a similar question on Perlmonks when I was asking How can I calculate the right combination of postage stamps?.
The Math::Combinatorics module can also handle many other cases. Even if you don't want to use it, the documentation has a lot of pointers to other information about the problem. Other people might be able to suggest the appropriate library for the language you'd like to you.
#!/usr/bin/perl
use List::Util qw(sum);
use Math::Combinatorics;
my #n = qw(1 4 7 13);
foreach my $count ( 2 .. #n ) {
my $c = Math::Combinatorics->new(
count => $count, # number to choose
data => [#n],
);
print "combinations of $count from: [" . join(" ",#n) . "]\n";
while( my #combo = $c->next_combination ){
print join( ' ', #combo ), " = ", sum( #combo ) , "\n";
}
}
You can enumerate all subsets using a bitvector.
In a for loop, go from 0 to 2 to the Nth power minus 1 (or start with 1 if you don't care about the empty set).
On each iteration, determine which bits are set. The Nth bit represents the Nth element of the set. For each set bit, dereference the appropriate element of the set and add to an accumulated value.
ETA: Because the nature of this problem involves exponential complexity, there's a practical limit to size of the set you can enumerate on. If it turns out you don't need all subsets, you can look up "n choose k" for ways of enumerating subsets of k elements.
PHP: Here's a non-recursive implementation. I'm not saying this is the most efficient way to do it (this is indeed exponential 2^N - see JasonTrue's response and comments), but it works for a small set of elements. I just wanted to write something quick to obtain results. I based the algorithm off Toon's answer.
$set = array(3, 5, 8, 13, 19);
$additions = array();
for($i = 0; $i < pow(2, count($set)); $i++){
$sum = 0;
$addends = array();
for($j = count($set)-1; $j >= 0; $j--) {
if(pow(2, $j) & $i) {
$sum += $set[$j];
$addends[] = $set[$j];
}
}
$additions[] = array($sum, $addends);
}
sort($additions);
foreach($additions as $addition){
printf("%d\t%s\n", $addition[0], implode('+', $addition[1]));
}
Which will output:
0
3 3
5 5
8 8
8 5+3
11 8+3
13 13
13 8+5
16 13+3
16 8+5+3
18 13+5
19 19
21 13+8
21 13+5+3
22 19+3
24 19+5
24 13+8+3
26 13+8+5
27 19+8
27 19+5+3
29 13+8+5+3
30 19+8+3
32 19+13
32 19+8+5
35 19+13+3
35 19+8+5+3
37 19+13+5
40 19+13+8
40 19+13+5+3
43 19+13+8+3
45 19+13+8+5
48 19+13+8+5+3
For example, a case for this could be a set of resistance bands for working out. Say you get 5 bands each having different resistances represented in pounds and you can combine bands to sum up the total resistance. The bands resistances are 3, 5, 8, 13 and 19 pounds. This set gives you 32 (2^5) possible configurations, minus the zero. In this example, the algorithm returns the data sorted by ascending total resistance favoring efficient band configurations first, and for each configuration the bands are sorted by descending resistance.
This is not the code to generate the sums, but it generates the permutations. In your case:
1; 1,4; 1,7; 4,7; 1,4,7; ...
If I have a moment over the weekend, and if it's interesting, I can modify this to come up with the sums.
It's just a fun chunk of LINQ code from Igor Ostrovsky's blog titled "7 tricks to simplify your programs with LINQ" (http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/).
T[] arr = …;
var subsets = from m in Enumerable.Range(0, 1 << arr.Length)
select
from i in Enumerable.Range(0, arr.Length)
where (m & (1 << i)) != 0
select arr[i];
You might be interested in checking out the GNU Scientific Library if you want to avoid maintenance costs. The actual process of summing longer sequences will become very expensive (more-so than generating a single permutation on a step basis), most architectures have SIMD/vector instructions that can provide rather impressive speed-up (I would provide examples of such implementations but I cannot post URLs yet).
Thanks Zach,
I am creating a Bank Reconciliation solution. I dropped your code into jsbin.com to do some quick testing and produced this in Javascript:
function f(numbers,ids, index, sum, output, outputid, find )
{
if (index == numbers.length){
var x ="";
if (find == sum) {
y= output + " } = " + sum + " " + outputid + " }<br/>" ;
}
return;
}
f(numbers,ids, index + 1, sum + numbers[index], output + " " + numbers[index], outputid + " " + ids[index], find);
f(numbers,ids, index + 1, sum, output, outputid,find);
}
var y;
f( [1.2,4,7,13,45,325,23,245,78,432,1,2,6],[1,2,3,4,5,6,7,8,9,10,11,12,13], 0, 0, '{','{', 24.2);
if (document.getElementById('hello')) {
document.getElementById('hello').innerHTML = y;
}
I need it to produce a list of ID's to exclude from the next matching number.
I will post back my final solution using vb.net
v=[1,2,3,4]#variables to sum
i=0
clis=[]#check list for solution excluding the variables itself
def iterate(lis,a,b):
global i
global clis
while len(b)!=0 and i<len(lis):
a=lis[i]
b=lis[i+1:]
if len(b)>1:
t=a+sum(b)
clis.append(t)
for j in b:
clis.append(a+j)
i+=1
iterate(lis,a,b)
iterate(v,0,v)
its written in python. the idea is to break the list in a single integer and a list for eg. [1,2,3,4] into 1,[2,3,4]. we append the total sum now by adding the integer and sum of remaining list.also we take each individual sum i.e 1,2;1,3;1,4. checklist shall now be [1+2+3+4,1+2,1+3,1+4] then we call the new list recursively i.e now int=2,list=[3,4]. checklist will now append [2+3+4,2+3,2+4] accordingly we append the checklist till list is empty.
set is the set of sums and list is the list of the original numbers.
Its Java.
public void subSums() {
Set<Long> resultSet = new HashSet<Long>();
for(long l: list) {
for(long s: set) {
resultSet.add(s);
resultSet.add(l + s);
}
resultSet.add(l);
set.addAll(resultSet);
resultSet.clear();
}
}
public static void main(String[] args) {
// this is an example number
long number = 245L;
int sum = 0;
if (number > 0) {
do {
int last = (int) (number % 10);
sum = (sum + last) % 9;
} while ((number /= 10) > 0);
System.err.println("s = " + (sum==0 ? 9:sum);
} else {
System.err.println("0");
}
}

Resources