All possible combinations of N objects in K buckets - algorithm

Suppose I have 3 boxes labeled A, B, C and I have 2 balls, B1 and B2. I want to get all possible combinations of these balls in the boxes. Please note, it is important to know which ball is in each box, meaning B1 and B2 are not the same.
A B C
B1, B2
B1 B2
B1 B2
B2 B1
B2 B1
B1, B2
B1 B2
B2 B1
B1, B2
Edit
If there is a known algorithm for this problem, please tell me its name.

Let N be number of buckets (3 in the example), M number of balls (2). Now, let's have a look at numbers in a range [0..N**M) - [0..9) in the example; these numbers we represent with radix = N. For the example in the question we have trinary numbers
Now we can easily interprete these numbers: first digit shows 1st ball location, second - 2nd ball position.
|--- Second Ball position [0..2]
||-- First Ball position [0..2]
||
0 = 00 - both balls are in the bucket #0 (`A`)
1 = 01 - first ball is in the bucket #1 ('B'), second is in the bucket #0 (`A`)
2 = 02 - first ball is in the bucket #2 ('C'), second is in the bucket #0 (`A`)
3 = 10 - first ball is in the bucket #0 ('A'), second is in the bucket #1 (`B`)
4 = 11 - both balls are in the bucket #1 (`B`)
5 = 12 ...
6 = 20
7 = 21 ...
8 = 22 - both balls are in the bucket #2 (`C`)
the general algorithm is:
For each number in 0 .. N**M range
ith ball (i = 0..M-1) will be in the bucket # (number / N**i) % N (here / stands for integer division, % for remainder)
If you want just total count, the answer is simple N ** M, in the example above 3 ** 2 == 9
C# Code The algorithm itself is easy to implement:
static IEnumerable<int[]> BallsLocations(int boxCount, int ballCount) {
BigInteger count = BigInteger.Pow(boxCount, ballCount);
for (BigInteger i = 0; i < count; ++i) {
int[] balls = new int[ballCount];
int index = 0;
for (BigInteger value = i; value > 0; value /= boxCount)
balls[index++] = (int)(value % boxCount);
yield return balls;
}
}
It's answer representation which can be entangled:
static IEnumerable<string> BallsSolutions(int boxCount, int ballCount) {
foreach (int[] balls in BallsLocations(boxCount, ballCount)) {
List<int>[] boxes = Enumerable
.Range(0, boxCount)
.Select(_ => new List<int>())
.ToArray();
for (int j = 0; j < balls.Length; ++j)
boxes[balls[j]].Add(j + 1);
yield return string.Join(Environment.NewLine, boxes
.Select((item, index) => $"Box {index + 1} : {string.Join(", ", item.Select(b => $"B{b}"))}"));
}
}
Demo:
int balls = 3;
int boxes = 2;
string report = string.Join(
Environment.NewLine + "------------------" + Environment.NewLine,
BallsSolutions(boxes, balls));
Console.Write(report);
Outcome:
Box 1 : B1, B2, B3
Box 2 :
------------------
Box 1 : B2, B3
Box 2 : B1
------------------
Box 1 : B1, B3
Box 2 : B2
------------------
Box 1 : B3
Box 2 : B1, B2
------------------
Box 1 : B1, B2
Box 2 : B3
------------------
Box 1 : B2
Box 2 : B1, B3
------------------
Box 1 : B1
Box 2 : B2, B3
------------------
Box 1 :
Box 2 : B1, B2, B3
Fiddle

There's a very simple recursive implementation that at each level adds the current ball to each box. The recursion ends when all balls have been processed.
Here's some Java code to illustrate. We use a Stack to represent each box so we can simply pop the last-added ball after each level of recursion.
void boxBalls(List<Stack<String>> boxes, String[] balls, int i)
{
if(i == balls.length)
{
System.out.println(boxes);
return;
}
for(Stack<String> box : boxes)
{
box.push(balls[i]);
boxBalls(boxes, balls, i+1);
box.pop();
}
}
Test:
String[] balls = {"B1", "B2"};
List<Stack<String>> boxes = new ArrayList<>();
for(int i=0; i<3; i++) boxes.add(new Stack<>());
boxBalls(boxes, balls, 0);
Output:
[[B1, B2], [], []]
[[B1], [B2], []]
[[B1], [], [B2]]
[[B2], [B1], []]
[[], [B1, B2], []]
[[], [B1], [B2]]
[[B2], [], [B1]]
[[], [B2], [B1]]
[[], [], [B1, B2]]

Related

How to get the permutations without repetition of all the combinations of a set of letters? [duplicate]

This question already has answers here:
Algorithm to return all combinations of k elements from n
(77 answers)
Closed 3 years ago.
I'm trying to create an algorithm that after giving it a number of random letters, for example: abcd, it shows you all the possible permutations, in this case, the answer would be:
abcd abc abd acd ab ac ad a bcd bc bd b cd c d
As you can see, the different permutations must have different letters, I have spent hours trying to do it without success, this is what I did so far:
vector<char> letters;
letters.push_back('a');
letters.push_back('b');
letters.push_back('c');
letters.push_back('d');
int number_of_letters = 4;
int number_of_repetitions;
vector<char> combination;
vector<char> comb_copy;
for(int i = 0; i < number_of_letters; i++){
number_of_repetitions = 1;
changing_letters = number_of_letters - (i + 1);
for(int j = i+1; j < number_of_letters; j++){
combination.push_back(letters[j]);
}
comb_copy = combination;
for(int i = 0; i < comb_copy.size(); i++){
cout << comb_copy[i];
}
while(number_of_repetitions <= changing_letters){
comb_copy = combinations(comb_copy, number_of_repetitions);
for(int i = 0; i < comb_copy.size(); i++){
cout << comb_copy[i];
}
comb_copy = combination;
number_of_repetitions++;
}
}
vector<char> combinations(vector<char> combi, int reps){
combi.erase(combi.end() - reps);
return (reps > 1?combinations(combi, reps-1):combi);
}
And this is what I'm getting:
abcd abc abd acd bc bd c
I would need to get:
abcd abc abd acd ab ac ad a bcd bc bd b cd c d
Can someone help me? :)
Thanks!!
You want to get all subsets of n items except for empty one. There are 2^n-1 such subsets. A pair of methods to generate them:
1) Make loop for value R in range 1..2^n-1. At every step represent R in binary. Every non-zero bit of R corresponds to index of initial array used in result. For example R=5=0101b denotes "ac" (0-th and 2-nd elements)
2) Use recursive procedure, at every level make two recursive calls - adding elelent with current index and omitting it. At the deepest level output result (if not empty)
Python examples:
s = "abcd"
n = len(s)
for r in range(1, 1<<n):
result = ""
for i in range(n):
if r & (1 << i):
result += s[i]
print(result, end = " ")
a b ab c ac bc abc d ad bd abd cd acd bcd abcd
def subs(s, result, idx):
if idx == len(s):
if len(result) > 0:
print(result, end = " ")
else:
subs(s, result + s[idx], idx + 1)
subs(s, result, idx + 1)
subs("abcd", "", 0)
abcd abc abd ab acd ac ad a bcd bc bd b cd c d

Algorithm to find all line segment intersections given n lines

I'm looking for a algorithm to find all the intersection points given n line segments.
Below is the pseudo code from http://jeffe.cs.illinois.edu/teaching/373/notes/x06-sweepline.pdf
The input S[1 .. n] is an array of line
segments.
label[i] is the label of the ith leftmost endpoint.
sort the endpoints of S from left to right
create an empty label sequence
for i ← 1 to 2n
line ← label[i]
if isLeftEndPoint[i]
Insert(line)
if Intersect(S[line], S[Successor(line)])
return TRUE
if Intersect(S[line], S[Predecessor(line)])
return TRUE
else
if Intersect(S[Successor(line)], S[Predecessor(line)])
return TRUE
Delete(label[i])
return FALSE
Apply the algorithm to the line set below, only one intersection point is checked. What should I do to know the existence of the other 2 intersection points?
line[1] enters
line[2] enters, intersection between line[1] and line[2] is checked.
line[3] enters, intersection between line[2] and line[3] is checked.
line[4] enters, intersection between line[4] and line[1] is checked. Intersection A is found.
line[4] leaves, nothing is checked.
line[1] leaves, nothing is checked.
line[2] leaves, nothing is checked.
line[3] leaves, nothing is checked.
Standard line equation
Ax+By=C
The slope(m) of a line defined by the standard line of equation is
m = -(A/B)
Point-slope line equation
y-y1=m(x-x1)
Substituting m = (-A/B) in the point-slope line equation
y2-y1 = (A/-B)*(x2-x1)
(y2-y1)/(x2-x1) = A/-B
thus:
A = y2-y1
B = x1-x2
C = Ax+By
x = (C-By)/A
y = (C-Ax)/B
Given two lines with equation
A1x1+B1y1=C1 and A2x2+B2y2=C2.
Then the point of intersection between the lines is specified
by the points that make A1x+B1y-C1 = A2x+B2y-C2
A1x+B1y=C1
A2x+B2y=C2
A1B2x+B1B2y=B2C1 (multiply the first equation by B2)
A1B2x+B1B2y-B2C1=0
A2B1x+B1B2y=B1C2 (multiply the second equation by B1)
A2B1x+B1B2y-B1C2=0
Equating the two equations
A1B2x+B1B2y-B2C1=A2B1x+B1B2y-B1C2
A1B2x+B1B2y-B2C1-A2B1x-B1B2y+B1C2=0
A1B2x-B2C1-A2B1x+B1C2=0
A1B2x-A2B1x=B2C1-B1C2
x(A1B2-A2B1)=B2C1-B1C2
x = (B2C1-B1C2)/A1B2-A2B1
A1x+B1y=C1
A2x+B2y=C2
A1A2x+A2B1y=A2C1 (multiply the first equation by A2)
A1A2x+A2B1y-A2C1=0
A1A2x+A1B2y=A1C2 (multiply the second equation by A1)
A1A2x+A1B2y-A1C2=0
Equating the two equations
A1A2x+A2B1y-A2C1=A1A2x+A1B2y-A1C2
A1A2x+A2B1y-A2C1-A1A2x-A1B2y+A1C2=0
A1C2-A2C2=A1B2y-A2B1y
A1B2y-A2B1y=A1C2-A2C2
y(A1B2-A2B1)=A1C2-A2C1
y(A1B2-A2B1)=A1C2-A2C1
y = (A1C2-A2C1)/(A1B1-A2B1)
the denominator in y and in x are the same so
denominator = A1B1-A2B1
thus:
x = (B2C1-B1C2)/denominator
y = (A1C2-A2C1)/denominator
These are the x and y coordinates of the intersection of two lines with points (x1, y1), (x2, y2) and (x3, y3), (x4, y4)
Now for a line segment it's the same but we need to check that the x or y coordinate is in both segments. That means between the x coordinate of both segments with lesser value and the x coordinate of both segments with greater value
This is a C++ program that returns true if the segments intersect and returns false if they don't. If the segments intersect it stores the point of intersection in a variable i.
struct Point
{
float x, y;
};
//p1 and p2 are the points of the first segment
//p3 and p4 are the points of the second segment
bool intersection(Point p1, Point p2, Point p3, Point p4, Point &i)
{
float max1; //x-coordinate with greater value in segment 1
float min1; //x-coordinate with lesse value in segment 1
float max2; //x-coordinate with greater value in segment 2
float min2; //x-coordinate with lesser value in segment 2
float A1 = p2.y - p1.y;
float B1 = p1.x - p2.x;
float C1 = A1 * p1.x + B1 * p1.y;
float A2 = p4.y - p3.y;
float B2 = p3.x - p4.x;
float C2 = A2 * p3.x + B2 * p3.y;
float denom = A1 * B2 - A2 * B1;
if (denom == 0.0) //When denom == 0, is because the lines are parallel
return false; //Parallel lines do not intersect
i.x = (C1 * B2 - C2 * B1) / denom;
i.y = (A1 * C2 - A2 * C1) / denom;
if (p1.x > p2.x)
{
max1 = p1.x;
min1 = p2.x;
}
else
{
max1 = p2.x;
min1 = p1.x;
}
if (p3.x > p4.x)
{
max2 = p3.x;
min2 = p4.x;
}
else
{
max2 = p4.x;
min2 = p3.x;
}
//check if x coordinate is in both segments
if (i.x >= min1 && i.x <= max1 &&
i.x >= min2 && i.x <= max2)
return true;
return false; //Do no intersect, intersection of the lines is not between the segments
}
Now you just need to compare on a loop all the segments and store the intersection point on array.

Logic: Applying gravity to a vector

There is a method called gravity(Vector[] vector) The vector contains sequence of numbers. The gravity function should return a new vector after applying gravity which is explained below.
Assume 0's are air and 1's are brick. When gravity is applied the bricks should fall down to the lowest level.
Let vector = [3, 7, 8]
Converting this to binary we get:
0 0 1 1 for 3
0 1 1 1 for 7
1 0 0 0 for 8
Applying gravity:
0 0 0 0 which is 0
0 0 1 1 which is 3
1 1 1 1 which is 15
So the gravity function should return [0, 3, 15].
Hope you people understood the explanation. I tried a lot but I couldn't figure out the logic for this. One thing I observed was the sum of the numbers in the vector before and after applying gravity remains same.
That is,
3 + 7 + 8 = 18 = 0 + 3 + 15 for the above case.
I think it is as simple as counting the total '1' bit of each position...
Let N be the input vector size, b be the longest binary length of the input elements
Pre-compute the total # of '1' bit of each position, stored in count[], O(N*b)
Run Gravity Function, that is, to regenerate N numbers from the count[], O(N*b)
Total run time is O(N*b)
Below is the sample code in C++
#include<bits/stdc++.h>
using namespace std;
int v[5] = {3,9,7,8,5};
int cnt[5] = {0};
vector<int> ans;
vector<int> gravity(){
vector<int> ret;
for(int i=0; i<5;i++){
int s = 0;
for(int j=0; j<5;j++)
if(cnt[j]){
s += (1<<j); cnt[j]--;
}
ret.push_back(s);
}
return ret;
}
int main(){
// precompute sum of 1 of each bit
for(int i=0, j=0, tmp=v[i]; i<5; i++, j=0, tmp=v[i]){
while(tmp){
if(tmp&1) cnt[j]++;
tmp >>= 1; j++;
}
}
ans = gravity();
for(int i=ans.size()-1; i>=0; i--) printf("%d ", ans[i]);
return 0;
}
The output is as follows:
Success time: 0 memory: 3272 signal:0
0 1 1 15 15
Start at the bottom. Any bricks in the row on top of that one will fall down except where there is already a brick on the bottom. So, the new bottom row is:
bottom_new = bottom_old OR top_old
The new top is:
top_new = bottom_old AND top_old
That is, there will be a brick in the new bottom row if there was a brick in either row, but there's only going to be a brick in the new top row if there was a brick in both rows.
Then you just work your way up the stack, with the new top row becoming the old bottom row for the next step.
The only solution I can think of so far uses nested for loops:
v is the input vector of N integers
D is the number of digits in each integer
c keeps track of the bottom-most free space where a brick can fall
The algorithm checks if the ith bit in the number n is set using (n & (1<<i)), which works in most C-like languages.
The algorithm in C:
for (int j=0; j<D; ++j)
int bit = 1<<j;
int c = N-1;
for (int i=N-1; i>=0; --i)
if (v[i] & bit) { // if bit j of number v[i] is set...
v[i] ^= bit; // set bit j in the number i to 0 using XOR
v[c] ^= bit; // set bottom-most bit in the number i to 1 using XOR
c -= 1; //increment by bottom row 1
}
If N is small and known it advance, you could work out the truth tables for the values of each digit and get the correct result using only bitwise operations and no loops.
Solution:
So I found a solution which needs recursion I guess. Though I don't know the condition to stop the recursion.
The vector v = [3, 7, 8] is very simple that its not possible to explain why recursion is required so am considering a new vector v = [3, 9, 7, 8, 5]
In binary form :
0 0 1 1 - a4
1 0 0 1 - a3
0 1 1 1 - a2
1 0 0 0 - a1
0 1 0 1 - a0
Iteration 1 :
0 0 0 0 - b7 (b7 = a4 AND b5)
0 0 1 1 - b6 (b6 = a4 OR b5)
0 0 0 0 - b5 (b5 = a3 AND b3) ignore this
1 0 0 1 - b4 (b4 = a3 OR b3)
0 0 0 0 - b3 (b3 = a2 AND b1) ignore this
0 1 1 1 - b2 (b2 = a2 OR b1)
0 0 0 0 - b1 (b1 = a0 AND a1) ignore this
1 1 0 1 - b0 (b0 = a0 OR a1)
Intermediate vector = [b7, b6, b4, b2, b0] = [0, 3, 9, 7, 13]
Iteration 2 :
0 0 0 0 - c7 (c7 = b4 AND c5)
0 0 0 1 - c6 (c6 = b4 OR c5)
0 0 0 1 - c5 (c5 = b3 AND c3) ignore this
0 0 1 1 - c4 (c4 = b3 OR c3)
0 0 0 1 - c3 (c3 = b2 AND c1) ignore this
1 1 0 1 - c2 (c2 = b2 OR c1)
0 1 0 1 - c1 (c1 = b0 AND b1) ignore this
1 1 1 1 - c0 (c0 = b0 OR b1)
Intermediate vector = [c7, c6, c4, c2, c0] = [0, 1, 3, 13, 15]
Iteration 3 :
0 0 0 0 - d7 (d7 = c4 AND d5)
0 0 0 1 - d6 (d6 = c4 OR d5)
0 0 0 1 - d5 (d5 = c3 AND d3) ignore this
0 0 0 1 - d4 (d4 = c3 OR d3)
0 0 0 1 - d3 (d3 = c2 AND d1) ignore this
1 1 1 1 - d2 (d2 = c2 OR d1)
1 1 0 1 - d1 (d1 = c0 AND c1) ignore this
1 1 1 1 - d0 (d0 = c0 OR c1)
Resultant vector = [d7, d6, d4, d2, d0] = [0, 1, 1, 15, 15]
I got this solution by going backwards through the vector.
Another solution:
Construct a multidimensional array with all the bits of all the elements in the vector (i.e) if v = [3,7,8] then construct a 3x4 array and store all the bits.
Count the number of 1's in each column and store the count.
Fill each column with count number of 1's starting from the bottom bit.
This approach is simple but requires construction of large matrices.

Rounding of double to nearest member of an arithmetical progression?

I have a formula of a sequence of double numbers k = a + d * n, where a and d are constant double values, n is an integer number, k >= 0, a >= 0. For example:
..., 300, 301.6, 303.2, 304.8, 306.4, ...
I want to round a given number c to a nearest value from this sequence which is lower than c.
Currently I use something like this:
double someFunc(double c) {
static double a = 1;
static double d = 2;
int n = 0;
double a1 = a;
if (c >= a) {
while (a1 < c) {
a1 += d;
}
a1 -= d;
} else {
while (a1 > c) {
a1 -= d;
}
}
return a1;
}
Is it possible to do the same without these awful cycles? I ask because the following situation may appear:
abs(a - c) >> abs(d) (the first number is much more then the second one and so a lot of iterations possible)
My question is similar to the following one. But in my case I also have a a variable which has influence on the final result. It means that a sequence may haven't number 0.
Suppose c is a number in your sequence. Then you have n = (c - a) / d.
Since you want an integer <= c, then take n = floor((c - a) / d).
Then you can round c to: a + d * floor((c - a) / d)
Suppose k = 3 + 5 * n and you round c=21.
And 3 + 5 * floor((21 - 3) / 5) = 3 + 5 * 3 = 18

Find all possible combinations of a String representation of a number

Given a mapping:
A: 1
B: 2
C: 3
...
...
...
Z: 26
Find all possible ways a number can be represented. E.g. For an input: "121", we can represent it as:
ABA [using: 1 2 1]
LA [using: 12 1]
AU [using: 1 21]
I tried thinking about using some sort of a dynamic programming approach, but I am not sure how to proceed. I was asked this question in a technical interview.
Here is a solution I could think of, please let me know if this looks good:
A[i]: Total number of ways to represent the sub-array number[0..i-1] using the integer to alphabet mapping.
Solution [am I missing something?]:
A[0] = 1 // there is only 1 way to represent the subarray consisting of only 1 number
for(i = 1:A.size):
A[i] = A[i-1]
if(input[i-1]*10 + input[i] < 26):
A[i] += 1
end
end
print A[A.size-1]
To just get the count, the dynamic programming approach is pretty straight-forward:
A[0] = 1
for i = 1:n
A[i] = 0
if input[i-1] > 0 // avoid 0
A[i] += A[i-1];
if i > 1 && // avoid index-out-of-bounds on i = 1
10 <= (10*input[i-2] + input[i-1]) <= 26 // check that number is 10-26
A[i] += A[i-2];
If you instead want to list all representations, dynamic programming isn't particularly well-suited for this, you're better off with a simple recursive algorithm.
First off, we need to find an intuitive way to enumerate all the possibilities. My simple construction, is given below.
let us assume a simple way to represent your integer in string format.
a1 a2 a3 a4 ....an, for instance in 121 a1 -> 1 a2 -> 2, a3 -> 1
Now,
We need to find out number of possibilities of placing a + sign in between two characters. + is to mean characters concatenation here.
a1 - a2 - a3 - .... - an, - shows the places where '+' can be placed. So, number of positions is n - 1, where n is the string length.
Assume a position may or may not have a + symbol shall be represented as a bit.
So, this boils down to how many different bit strings are possible with the length of n-1, which is clearly 2^(n-1). Now in order to enumerate the possibilities go through every bit string and place right + signs in respective positions to get every representations,
For your example, 121
Four bit strings are possible 00 01 10 11
1 2 1
1 2 + 1
1 + 2 1
1 + 2 + 1
And if you see a character followed by a +, just add the next char with the current one and do it sequentially to get the representation,
x + y z a + b + c d
would be (x+y) z (a+b+c) d
Hope it helps.
And you will have to take care of edge cases where the size of some integer > 26, of course.
I think, recursive traverse through all possible combinations would do just fine:
mapping = {"1":"A", "2":"B", "3":"C", "4":"D", "5":"E", "6":"F", "7":"G",
"8":"H", "9":"I", "10":"J",
"11":"K", "12":"L", "13":"M", "14":"N", "15":"O", "16":"P",
"17":"Q", "18":"R", "19":"S", "20":"T", "21":"U", "22":"V", "23":"W",
"24":"A", "25":"Y", "26":"Z"}
def represent(A, B):
if A == B == '':
return [""]
ret = []
if A in mapping:
ret += [mapping[A] + r for r in represent(B, '')]
if len(A) > 1:
ret += represent(A[:-1], A[-1]+B)
return ret
print represent("121", "")
Assuming you only need to count the number of combinations.
Assuming 0 followed by an integer in [1,9] is not a valid concatenation, then a brute-force strategy would be:
Count(s,n)
x=0
if (s[n-1] is valid)
x=Count(s,n-1)
y=0
if (s[n-2] concat s[n-1] is valid)
y=Count(s,n-2)
return x+y
A better strategy would be to use divide-and-conquer:
Count(s,start,n)
if (len is even)
{
//split s into equal left and right part, total count is left count multiply right count
x=Count(s,start,n/2) + Count(s,start+n/2,n/2);
y=0;
if (s[start+len/2-1] concat s[start+len/2] is valid)
{
//if middle two charaters concatenation is valid
//count left of the middle two characters
//count right of the middle two characters
//multiply the two counts and add to existing count
y=Count(s,start,len/2-1)*Count(s,start+len/2+1,len/2-1);
}
return x+y;
}
else
{
//there are three cases here:
//case 1: if middle character is valid,
//then count everything to the left of the middle character,
//count everything to the right of the middle character,
//multiply the two, assign to x
x=...
//case 2: if middle character concatenates the one to the left is valid,
//then count everything to the left of these two characters
//count everything to the right of these two characters
//multiply the two, assign to y
y=...
//case 3: if middle character concatenates the one to the right is valid,
//then count everything to the left of these two characters
//count everything to the right of these two characters
//multiply the two, assign to z
z=...
return x+y+z;
}
The brute-force solution has time complexity of T(n)=T(n-1)+T(n-2)+O(1) which is exponential.
The divide-and-conquer solution has time complexity of T(n)=3T(n/2)+O(1) which is O(n**lg3).
Hope this is correct.
Something like this?
Haskell code:
import qualified Data.Map as M
import Data.Maybe (fromJust)
combs str = f str [] where
charMap = M.fromList $ zip (map show [1..]) ['A'..'Z']
f [] result = [reverse result]
f (x:xs) result
| null xs =
case M.lookup [x] charMap of
Nothing -> ["The character " ++ [x] ++ " is not in the map."]
Just a -> [reverse $ a:result]
| otherwise =
case M.lookup [x,head xs] charMap of
Just a -> f (tail xs) (a:result)
++ (f xs ((fromJust $ M.lookup [x] charMap):result))
Nothing -> case M.lookup [x] charMap of
Nothing -> ["The character " ++ [x]
++ " is not in the map."]
Just a -> f xs (a:result)
Output:
*Main> combs "121"
["LA","AU","ABA"]
Here is the solution based on my discussion here:
private static int decoder2(int[] input) {
int[] A = new int[input.length + 1];
A[0] = 1;
for(int i=1; i<input.length+1; i++) {
A[i] = 0;
if(input[i-1] > 0) {
A[i] += A[i-1];
}
if (i > 1 && (10*input[i-2] + input[i-1]) <= 26) {
A[i] += A[i-2];
}
System.out.println(A[i]);
}
return A[input.length];
}
Just us breadth-first search.
for instance 121
Start from the first integer,
consider 1 integer character first, map 1 to a, leave 21
then 2 integer character map 12 to L leave 1.
This problem can be done in o(fib(n+2)) time with a standard DP algorithm.
We have exactly n sub problems and button up we can solve each problem with size i in o(fib(i)) time.
Summing the series gives fib (n+2).
If you consider the question carefully you see that it is a Fibonacci series.
I took a standard Fibonacci code and just changed it to fit our conditions.
The space is obviously bound to the size of all solutions o(fib(n)).
Consider this pseudo code:
Map<Integer, String> mapping = new HashMap<Integer, String>();
List<String > iterative_fib_sequence(string input) {
int length = input.length;
if (length <= 1)
{
if (length==0)
{
return "";
}
else//input is a-j
{
return mapping.get(input);
}
}
List<String> b = new List<String>();
List<String> a = new List<String>(mapping.get(input.substring(0,0));
List<String> c = new List<String>();
for (int i = 1; i < length; ++i)
{
int dig2Prefix = input.substring(i-1, i); //Get a letter with 2 digit (k-z)
if (mapping.contains(dig2Prefix))
{
String word2Prefix = mapping.get(dig2Prefix);
foreach (String s in b)
{
c.Add(s.append(word2Prefix));
}
}
int dig1Prefix = input.substring(i, i); //Get a letter with 1 digit (a-j)
String word1Prefix = mapping.get(dig1Prefix);
foreach (String s in a)
{
c.Add(s.append(word1Prefix));
}
b = a;
a = c;
c = new List<String>();
}
return a;
}
old question but adding an answer so that one can find help
It took me some time to understand the solution to this problem – I refer accepted answer and #Karthikeyan's answer and the solution from geeksforgeeks and written my own code as below:
To understand my code first understand below examples:
we know, decodings([1, 2]) are "AB" or "L" and so decoding_counts([1, 2]) == 2
And, decodings([1, 2, 1]) are "ABA", "AU", "LA" and so decoding_counts([1, 2, 1]) == 3
using the above two examples let's evaluate decodings([1, 2, 1, 4]):
case:- "taking next digit as single digit"
taking 4 as single digit to decode to letter 'D', we get decodings([1, 2, 1, 4]) == decoding_counts([1, 2, 1]) because [1, 2, 1, 4] will be decode as "ABAD", "AUD", "LAD"
case:- "combining next digit with the previous digit"
combining 4 with previous 1 as 14 as a single to decode to letter N, we get decodings([1, 2, 1, 4]) == decoding_counts([1, 2]) because [1, 2, 1, 4] will be decode as "ABN" or "LN"
Below is my Python code, read comments
def decoding_counts(digits):
# defininig count as, counts[i] -> decoding_counts(digits[: i+1])
counts = [0] * len(digits)
counts[0] = 1
for i in xrange(1, len(digits)):
# case:- "taking next digit as single digit"
if digits[i] != 0: # `0` do not have mapping to any letter
counts[i] = counts[i -1]
# case:- "combining next digit with the previous digit"
combine = 10 * digits[i - 1] + digits[i]
if 10 <= combine <= 26: # two digits mappings
counts[i] += (1 if i < 2 else counts[i-2])
return counts[-1]
for digits in "13", "121", "1214", "1234121":
print digits, "-->", decoding_counts(map(int, digits))
outputs:
13 --> 2
121 --> 3
1214 --> 5
1234121 --> 9
note: I assumed that input digits do not start with 0 and only consists of 0-9 and have a sufficent length
For Swift, this is what I came up with. Basically, I converted the string into an array and goes through it, adding a space into different positions of this array, then appending them to another array for the second part, which should be easy after this is done.
//test case
let input = [1,2,2,1]
func combination(_ input: String) {
var arr = Array(input)
var possible = [String]()
//... means inclusive range
for i in 2...arr.count {
var temp = arr
//basically goes through it backwards so
// adding the space doesn't mess up the index
for j in (1..<i).reversed() {
temp.insert(" ", at: j)
possible.append(String(temp))
}
}
print(possible)
}
combination(input)
//prints:
//["1 221", "12 21", "1 2 21", "122 1", "12 2 1", "1 2 2 1"]
def stringCombinations(digits, i=0, s=''):
if i == len(digits):
print(s)
return
alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
total = 0
for j in range(i, min(i + 1, len(digits) - 1) + 1):
total = (total * 10) + digits[j]
if 0 < total <= 26:
stringCombinations(digits, j + 1, s + alphabet[total - 1])
if __name__ == '__main__':
digits = list()
n = input()
n.split()
d = list(n)
for i in d:
i = int(i)
digits.append(i)
print(digits)
stringCombinations(digits)

Resources