Optimal way to group time intervals based on projected points - algorithm

Imagine we have sorted list of time intervals (sorted by time of beginning).
I'm looking for optimal solution to 'project' these intervals to axis, having as a result an array of objects, describing: projected interval start&end time and arrays of source intervals that fall into projected intevals.
Let me explain on example: imagine we have 4 intervals as input (sorted by start time, then by end time):
[---R1---)
[-----R2-----)
[---------R3-------)
[----R4----)
--|-----|--|----|----|-----|---> t (time axis)
1 3 2 3 2
In that case I'm expecting to get array of 5 elements, each element is an object describing interval start/end and a list of source intervals. Numbers under axis on chart shows number of items in that list.
Please, help me to find fastest way to solve this task

Something like this?
def groupIntervals(intervals):
events = {}
for start, stop, name in intervals:
if start not in events: events[start] = []
events[start].append(('start', name))
if stop not in events: events[stop] = []
events[stop].append(('stop', name))
last = None
output = []
active = set()
for time in sorted(events.keys()):
if active and last is not None:
output.append((last, time, active.copy()))
last = time
for action, name in events[time]:
if action == 'start': active.add(name)
elif action == 'stop': active.remove(name)
else: assert False
return output
Example usage:
>>> groupIntervals([(1, 3, 'R1'), (2, 5, 'R2'), (2, 6, 'R3'),
... (4, 6, 'R4')])
[(1, 2, set(['R1'])),
(2, 3, set(['R1', 'R2', 'R3'])),
(3, 4, set(['R2', 'R3'])),
(4, 5, set(['R4', 'R2', 'R3'])),
(5, 6, set(['R4', 'R3']))]
C++ version with cleverer data structure usage.
#include <cstdio>
#include <limits>
#include <list>
#include <queue>
#include <string>
#include <vector>
struct Interval {
Interval(std::string name, int start, int stop);
std::string name;
int start;
int stop;
};
Interval::Interval(std::string name, int start, int stop)
: name(name), start(start), stop(stop) {
}
typedef std::list<std::vector<Interval>::const_iterator> ActiveList;
struct StopEvent {
StopEvent(int stop, ActiveList::iterator j);
int stop;
ActiveList::iterator j;
};
StopEvent::StopEvent(int stop, ActiveList::iterator j)
: stop(stop), j(j) {
}
struct StopEventGreater {
bool operator()(StopEvent const& a,
StopEvent const& b) const;
};
bool StopEventGreater::operator()(StopEvent const& a,
StopEvent const& b) const {
return a.stop > b.stop;
}
void Sweep(std::vector<Interval> const& intervals) {
std::vector<Interval>::const_iterator i(intervals.begin());
std::priority_queue<StopEvent,
std::vector<StopEvent>,
StopEventGreater> active_queue;
ActiveList active_list;
int last_time(std::numeric_limits<int>::min());
while (i != intervals.end() || !active_queue.empty()) {
bool start(i != intervals.end() &&
(active_queue.empty() || i->start < active_queue.top().stop));
int time(start ? i->start : active_queue.top().stop);
if (time != last_time && !active_list.empty()) {
std::printf("[%d, %d):", last_time, time);
for (ActiveList::const_iterator j(active_list.begin());
j != active_list.end();
++j) {
std::printf(" %s", (*j)->name.c_str());
}
std::putchar('\n');
}
last_time = time;
if (start) {
active_queue.push(StopEvent(i->stop,
active_list.insert(active_list.end(), i)));
++i;
} else {
active_list.erase(active_queue.top().j);
active_queue.pop();
}
}
}
int main(void) {
std::vector<Interval> intervals;
intervals.push_back(Interval("R1", 0, 4));
intervals.push_back(Interval("R2", 1, 9));
intervals.push_back(Interval("R3", 1, 11));
intervals.push_back(Interval("R4", 6, 11));
Sweep(intervals);
}

Finally I've found the most effective way. It uses one sorting operation and O(N*2) iterations to build result.
public IEnumerable<DateProjectedItems<T>> Project(IList<T> items)
{
if (items.Count <= 1)
{
if (items.Count == 0)
{
yield break;
}
yield return new DateProjectedItems<T>
{
DateRange = items[0].DateRange,
Items = items
};
}
else
{
var endOrdered = items.OrderBy(i => i.DateRange.DateTimeTo).ToList();
var active = new List<T>();
DateTime? last = null;
foreach (var pair in TwoArrayIterator(items, endOrdered))
{
DateTime current = pair.Key == 1 ? pair.Value.DateRange.DateTimeFrom : pair.Value.DateRange.DateTimeTo;
if (last != null && current != last)
{
yield return new DateProjectedItems<T>
{
DateRange = new DateRange(last.Value, current),
Items = active.ToList()
};
}
if (pair.Key == 1)
{
active.Add(pair.Value);
}
else
{
active.Remove(pair.Value);
}
last = current;
}
}
}
public IEnumerable<KeyValuePair<int, T>> TwoArrayIterator(IList<T> arr1, IList<T> arr2)
{
var index1 = 0;
var index2 = 0;
while (index1 < arr1.Count || index2 < arr2.Count)
{
if (index1 >= arr1.Count)
yield return new KeyValuePair<int, T>(2, arr2[index2++]);
else if (index2 >= arr2.Count)
yield return new KeyValuePair<int, T>(1, arr1[index1++]);
else
{
var elt1 = arr1[index1];
var elt2 = arr2[index2];
if (elt1.DateRange.DateTimeFrom < elt2.DateRange.DateTimeTo)
{
index1++;
yield return new KeyValuePair<int, T>(1, elt1);
}
else
{
index2++;
yield return new KeyValuePair<int, T>(2, elt2);
}
}
}
}

Related

Puzzle: Find the order of n persons standing in a line (based on their heights)

Saw this question on Careercup.com:
Given heights of n persons standing in a line and a list of numbers corresponding to each person (p) that gives the number of persons who are taller than p and standing in front of p. For example,
Heights: 5 3 2 6 1 4
InFronts:0 1 2 0 3 2
Means that the actual actual order is: 5 3 2 1 6 4
The question gets the two lists of Heights and InFronts, and should generate the order standing in line.
My solution:
It could be solved by first sorting the list in descending order. Obviously, to sort, we need to define an object Person (with two attributes of Height and InFront) and then sort Persons based on their height. Then, I would use two stacks, a main stack and a temp one, to build up the order.
Starting from the tallest, put it in the main stack. If the next person had an InFront value of greater than the person on top of the stack, that means the new person should be added before the person on top. Therefore, we need to pop persons from the main stack, insert the new person, and then return the persons popped out in the first step (back to the main stack from temp one). I would use a temp stack to keep the order of the popped out persons. But how many should be popped out? Since the list is sorted, we need to pop exactly the number of persons in front of the new person, i.e. corresponding InFront.
I think this solution works. But the worst case order would be O(n^2) -- when putting a person in place needs popping out all previous ones.
Is there any other solutions? possibly in O(n)?
The O(nlogn) algoritm is possible.
First assume that all heights are different.
Sort people by heights. Then iterate from shortest to tallest. In each step you need an efficient way to put the next person to the correct position. Notice that people we've already placed are not taller that the current person. And the people we place after are taller than the current. So we have to find a place such that the number of empty positions in the front is equal to the inFronts value of this person. This task can be done using a data structure called interval tree in O(logn) time. So the total time of an algorithm is O(nlogn).
This algorithm works well in case where there's no ties. As it may be safely assumed that empty places up to front will be filled by taller people.
In case when ties are possible, we need to assure that people of the same height are placed in increasing order of their positions. It can be achieved if we will process people by non-decreasing inFronts value. So, in case of possible ties we should also consider inFronts values when sorting people.
And if at some step we can't find a position for next person then the answer it "it's impossible to satisfy problem constraints".
There exists an algorithm with O(nlogn) average complexity, however worst case complexity is still O(n²).
To achieve this you can use a variation of a binary tree. The idea is, in this tree, each node corresponds to a person and each node keeps track of how many people are in front of him (which is the size of the left subtree) as nodes are inserted.
Start iterating the persons array in decreasing height order and insert each person into the tree starting from the root. Insertion is as follows:
Compare the frontCount of the person with the current node's (root at the beginning) value.
If it is smaller than it insert the node to the left with value 1. Increase the current node's value by 1.
Else, descend to the right by decreasing the person's frontCount by current node's value. This enables the node to be placed in the correct location.
After all nodes finished, an inorder traversal gives the correct order of people.
Let the code speak for itself:
public static void arrange(int[] heights, int[] frontCounts) {
Person[] persons = new Person[heights.length];
for (int i = 0; i < persons.length; i++)
persons[i] = new Person(heights[i], frontCounts[i]);
Arrays.sort(persons, (p1, p2) -> {
return Integer.compare(p2.height, p1.height);
});
Node root = new Node(persons[0]);
for (int i = 1; i < persons.length; i++) {
insert(root, persons[i]);
}
inOrderPrint(root);
}
private static void insert(Node root, Person p) {
insert(root, p, p.frontCount);
}
private static void insert(Node root, Person p, int value) {
if (value < root.value) { // should insert to the left
if (root.left == null) {
root.left = new Node(p);
} else {
insert(root.left, p, value);
}
root.value++; // Increase the current node value while descending left!
} else { // insert to the right
if (root.right == null) {
root.right = new Node(p);
} else {
insert(root.right, p, value - root.value);
}
}
}
private static void inOrderPrint(Node root) {
if (root == null)
return;
inOrderPrint(root.left);
System.out.print(root.person.height);
inOrderPrint(root.right);
}
private static class Node {
Node left, right;
int value;
public final Person person;
public Node(Person person) {
this.value = 1;
this.person = person;
}
}
private static class Person {
public final int height;
public final int frontCount;
Person(int height, int frontCount) {
this.height = height;
this.frontCount = frontCount;
}
}
public static void main(String[] args) {
int[] heights = {5, 3, 2, 6, 1, 4};
int[] frontCounts = {0, 1, 2, 0, 3, 2};
arrange(heights, frontCounts);
}
I think one approach can be the following. Although it again seems to be O(n^2) at present.
Sort the Height array and corresponding 'p' array in ascending order of heights (in O(nlogn)). Pick the first element in the list. Put that element in the final array in the position given by the p index.
For example after sorting,
H - 1, 2, 3, 4, 5, 6
p - 3, 2, 1, 2, 0, 0.
1st element should go in position 3. Hence final array becomes:
---1--
2nd element shall go in position 2. Hence final array becomes:
--21--
3rd element should go in position 1. Hence final array becomes:
-321--
4th element shall go in position 2. This is the position among the empty ones. Hence final array becomes:
-321-4
5th element shall go in position 0. Hence final array becomes:
5321-4
6th element should go in position 0. Hence final array becomes:
532164
I think the approach indicated above is correct. However a critical piece missing in the solutions above are.
Infronts is the number of taller candidate before the current person. So after sorting the persons based on height(Ascending), when placing person 3 with infront=2, if person 1 and 2 was in front placed at 0, 1 position respectively, you need to discount their position and place 3 at position 4, I.E 2 taller candidates will take position 2,3.
As some indicated interval tree is the right structure. However a dynamic sized container, with available position will do the job.(code below)
struct Person{
int h, ct;
Person(int ht, int c){
h = ht;
ct = c;
}
};
struct comp{
bool operator()(const Person& lhs, const Person& rhs){
return (lhs.h < rhs.h);
}
};
vector<int> heightOrder(vector<int> &heights, vector<int> &infronts) {
if(heights.size() != infronts.size()){
return {};
}
vector<int> result(infronts.size(), -1);
vector<Person> persons;
vector<int> countSet;
for(int i= 0; i< heights.size(); i++){
persons.emplace_back(Person(heights[i], infronts[i]));
countSet.emplace_back(i);
}
sort(persons.begin(), persons.end(), comp());
for(size_t i=0; i<persons.size(); i++){
Person p = persons[i];
if(countSet.size() > p.ct){
int curr = countSet[p.ct];
//cout << "the index to place height=" << p.h << " , is at pos=" << curr << endl;
result[curr] = p.h;
countSet.erase(countSet.begin() + p.ct);
}
}
return result;
}
I'm using LinkedList for the this. Sort the tallCount[] in ascending order and accordingly re-position the items in heights[]. This is capable of handling the duplicate elements also.
public class FindHeightOrder {
public int[] findOrder(final int[] heights, final int[] tallCount) {
if (heights == null || heights.length == 0 || tallCount == null
|| tallCount.length == 0 || tallCount.length != heights.length) {
return null;
}
LinkedList list = new LinkedList();
list.insertAtStart(heights[0]);
for (int i = 1; i < heights.length; i++) {
if (tallCount[i] == 0) {
Link temp = list.getHead();
while (temp != null && temp.getData() <= heights[i]) {
temp = temp.getLink();
}
if (temp != null) {
if (temp.getData() <= heights[i]) {
list.insertAfterElement(temp.getData(), heights[i]);
} else {
list.insertAtStart(heights[i]);
}
} else {
list.insertAtEnd(heights[i]);
}
} else {
Link temp = list.getHead();
int pos = tallCount[i];
while (temp != null
&& (temp.getData() <= heights[i] || pos-- > 0)) {
temp = temp.getLink();
}
if (temp != null) {
if (temp.getData() <= heights[i]) {
list.insertAfterElement(temp.getData(), heights[i]);
} else {
list.insertBeforeElement(temp.getData(), heights[i]);
}
} else {
list.insertAtEnd(heights[i]);
}
}
}
Link fin = list.getHead();
int i = 0;
while (fin != null) {
heights[i++] = fin.getData();
fin = fin.getLink();
}
return heights;
}
public class Link {
private int data;
private Link link;
public Link(int data) {
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Link getLink() {
return link;
}
public void setLink(Link link) {
this.link = link;
}
#Override
public String toString() {
return this.data + " -> "
+ (this.link != null ? this.link : "null");
}
}
public class LinkedList {
private Link head;
public Link getHead() {
return head;
}
public void insertAtStart(int data) {
if (head == null) {
head = new Link(data);
head.setLink(null);
} else {
Link link = new Link(data);
link.setLink(head);
head = link;
}
}
public void insertAtEnd(int data) {
if (head != null) {
Link temp = head;
while (temp != null && temp.getLink() != null) {
temp = temp.getLink();
}
temp.setLink(new Link(data));
} else {
head = new Link(data);
}
}
public void insertAfterElement(int after, int data) {
if (head != null) {
Link temp = head;
while (temp != null) {
if (temp.getData() == after) {
Link link = new Link(data);
link.setLink(temp.getLink());
temp.setLink(link);
break;
} else {
temp = temp.getLink();
}
}
}
}
public void insertBeforeElement(int before, int data) {
if (head != null) {
Link current = head;
Link previous = null;
Link ins = new Link(data);
while (current != null) {
if (current.getData() == before) {
ins.setLink(current);
break;
} else {
previous = current;
current = current.getLink();
if (current != null && current.getData() == before) {
previous.setLink(ins);
ins.setLink(current);
break;
}
}
}
}
}
#Override
public String toString() {
return "LinkedList [head=" + this.head + "]";
}
}
}
As people already corrected for original input:
Heights : A[] = { 5 3 2 6 1 4 }
InFronts: B[] = { 0 1 2 0 3 2 }
Output should look like: X[] = { 5 3 1 6 2 4 }
Here is the O(N*logN) way to approach solution (with assumption that there are no ties).
Iterate over array B and build chain of inequalities (by placing items into a right spot on each iteration, here we can use hashtable for O(1) lookups):
b0 > b1
b0 > b1 > b2
b3 > b0 > b1 > b2
b3 > b0 > b1 > b4 > b2
b3 > b0 > b5 > b1 > b4 > b2
Sort array A and reverse it
Initialize output array X, iterate over chain from #1 and fill array X by placing items from A into a position defined in a chain
Steps #1 and #3 are O(N), step #2 is the most expensive O(N*logN).
And obviously reversing sorted array A (in step #2) is not required.
This is the implementation for the idea provided by user1990169. Complexity being O(N^2).
public class Solution {
class Person implements Comparator<Person>{
int height;
int infront;
public Person(){
}
public Person(int height, int infront){
this.height = height;
this.infront = infront;
}
public int compare(Person p1, Person p2){
return p1.height - p2.height;
}
}
public ArrayList<Integer> order(ArrayList<Integer> heights, ArrayList<Integer> infronts) {
int n = heights.size();
Person[] people = new Person[n];
for(int i = 0; i < n; i++){
people[i] = new Person(heights.get(i), infronts.get(i));
}
Arrays.sort(people, new Person());
Person[] rst = new Person[n];
for(Person p : people){
int count = 0;
for(int i = 0; i < n ; i++){
if(count == p.infront){
while(rst[i] != null && i < n - 1){
i++;
}
rst[i] = p;
break;
}
if(rst[i] == null) count++;
}
}
ArrayList<Integer> heightrst = new ArrayList<Integer>();
for(int i = 0; i < n; i++){
heightrst.add(rst[i].height);
}
return heightrst;
}
}
Was solving this problem today, here is what I came up with:
The idea is to sort the heights array in descending order. Once, we have this sorted array - pick up an element from this element and place it in the resultant array at the corresponding index (I am using an ArrayList for the same, it would be nice to use LinkedList) :
public class Solution {
public ArrayList<Integer> order(ArrayList<Integer> heights, ArrayList<Integer> infronts) {
Person[] persons = new Person[heights.size()];
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < persons.length; i++) {
persons[i] = new Person(heights.get(i), infronts.get(i));
}
Arrays.sort(persons, (p1, p2) -> {
return Integer.compare(p2.height, p1.height);
});
for (int i = 0; i < persons.length; i++) {
//System.out.println("adding "+persons[i].height+" "+persons[i].count);
res.add(persons[i].count, persons[i].height);
}
return res;
}
private static class Person {
public final int height;
public final int count;
public Person(int h, int c) {
height = h;
count = c;
}
}
}
I found this kind of problem on SPOJ. I created a binary tree with little variation. When a new height is inserted, if the front is smaller than the root's front then it goes to the left otherwise right.
Here is the C++ implementation:
#include<bits/stdc++.h>
using namespace std;
struct TreeNode1
{
int val;
int _front;
TreeNode1* left;
TreeNode1*right;
};
TreeNode1* Add(int x, int v)
{
TreeNode1* p= (TreeNode1*) malloc(sizeof(TreeNode1));
p->left=NULL;
p->right=NULL;
p->val=x;
p->_front=v;
return p;
}
TreeNode1* _insert(TreeNode1* root, int x, int _front)
{
if(root==NULL) return Add(x,_front);
if(root->_front >=_front)
{
root->left=_insert(root->left,x,_front);
root->_front+=1;
}
else
{
root->right=_insert(root->right,x,_front-root->_front);
}
return root;
}
bool comp(pair<int,int> a, pair<int,int> b)
{
return a.first>b.first;
}
void in_order(TreeNode1 * root, vector<int>&v)
{
if(root==NULL) return ;
in_order(root->left,v);
v.push_back(root->val);
in_order(root->right,v);
}
vector<int>soln(vector<int>h, vector<int>in )
{
vector<pair<int , int> >vc;
for(int i=0;i<h.size();i++) vc.push_back( make_pair( h[i],in[i] ) );
sort(vc.begin(),vc.end(),comp);
TreeNode1* root=NULL;
for(int i=0;i<vc.size();i++)
root=_insert(root,vc[i].first,vc[i].second);
vector<int>v;
in_order(root,v);
return v;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
vector<int>h;
vector<int>in;
for(int i=0;i<n;i++) {int x;
cin>>x;
h.push_back(x);}
for(int i=0;i<n;i++) {int x; cin>>x;
in.push_back(x);}
vector<int>v=soln(h,in);
for(int i=0;i<n-1;i++) cout<<v[i]<<" ";
cout<<v[n-1]<<endl;
h.clear();
in.clear();
}
}
Here is a Python solution that uses only elementary list functions and takes care of ties.
def solution(heights, infronts):
person = list(zip(heights, infronts))
person.sort(key=lambda x: (x[0] == 0, x[1], -x[0]))
output = []
for p in person:
extended_output = output + [p]
extended_output.sort(key=lambda x: (x[0], -x[1]))
output_position = [p for p in extended_output].index(p) + p[1]
output.insert(output_position, p)
for c, p in enumerate(output):
taller_infronts = [infront for infront in output[0:c] if infront[0] >= p[0]]
assert len(taller_infronts) == p[1]
return output
Simple O(n^2) solution for this in Java:
Algorith:
If the position of the shortest person is i, i-1 taller people will be in front of him.
We fix the position of shortest person and then move to second shortest person.
Sort people by heights. Then iterate from shortest to tallest. In each step you need an efficient way to put the next person to the correct position.
We can optimise this solution even more by using segment tree. See this link.
class Person implements Comparable<Person>{
int height;
int pos;
Person(int height, int pos) {
this.height = height;
this.pos = pos;
}
#Override
public int compareTo(Person person) {
return this.height - person.height;
}
}
public class Solution {
public int[] order(int[] heights, int[] positions) {
int n = heights.length;
int[] ans = new int[n];
PriorityQueue<Person> pq = new PriorityQueue<Person>();
for( int i=0; i<n; i++) {
pq.offer(new Person(heights[i], positions[i]) );
}
for(int i=0; i<n; i++) {
Person person = pq.poll();
int vacantTillNow = 0;
int index = 0;
while(index < n) {
if( ans[index] == 0) vacantTillNow++;
if( vacantTillNow > person.pos) break;
index++;
}
ans[index] = person.height;
}
return ans;
}
}
Segment tree can be used to solve this in O(nlog n) if there are no ties in heights.
Please look for approach 3 in this link for a clear explanation of this method.
https://www.codingninjas.com/codestudio/problem-details/order-of-people-heights_1170764
Below is my code for the same approach in python
def findEmptySlot(tree, root, left, right, K, result):
tree[root]-=1
if left==right:
return left
if tree[2*root+1] >= K:
return findEmptySlot(tree, 2*root+1, left, (left+right)//2, K, result)
else:
return findEmptySlot(tree, 2*root+2, (left+right)//2+1, right, K-tree[2*root+1], result)
def buildsegtree(tree, pos, start, end):
if start==end:
tree[pos]=1
return tree[pos]
mid=(start+end)//2
left = buildsegtree(tree, 2*pos+1,start, mid)
right = buildsegtree(tree,2*pos+2,mid+1, end)
tree[pos]=left+right
return tree[pos]
class Solution:
# #param A : list of integers
# #param B : list of integers
# #return a list of integers
def order(self, A, B):
n=len(A)
people=[(A[i],B[i]) for i in range(len(A))]
people.sort(key=lambda x: (x[0], x[1]))
result=[0]*n
tree=[0]*(4*n)
buildsegtree(tree,0, 0, n-1)
for i in range(n):
idx=findEmptySlot(tree, 0, 0, n-1, people[i][1]+1, result)
result[idx]=people[i][0]
return result

Interview - Oracle

In a game the only scores which can be made are 2,3,4,5,6,7,8 and they can be made any number of times
What are the total number of combinations in which the team can play and the score of 50 can be achieved by the team.
example 8,8,8,8,8,8,2 is valid 8,8,8,8,8,4,4,2 is also valid. etc...
The problem can be solved with dynamic programming, with 2 parameters:
i - the index up to which we have considered
s - the total score.
f(i, s) will contain the total number of ways to achieve score s.
Let score[] be the list of unique positive scores that can be made.
The formulation for the DP solution:
f(0, s) = 1, for all s divisible to score[0]
f(0, s) = 0, otherwise
f(i + 1, s) = Sum [for k = 0 .. floor(s/score[i + 1])] f(i, s - score[i + 1] * k)
This looks like a coin change problem. I wrote some Python code for it a while back.
Edited Solution:
from collections import defaultdict
my_dicto = defaultdict(dict)
def row_analysis(v, my_dicto, coins):
temp = 0
for coin in coins:
if v >= coin:
if v - coin == 0: # changed from if v - coin in (0, 1):
temp += 1
my_dicto[coin][v] = temp
else:
temp += my_dicto[coin][v - coin]
my_dicto[coin][v] = temp
else:
my_dicto[coin][v] = temp
return my_dicto
def get_combs(coins, value):
'''
Returns answer for coin change type problems.
Coins are assumed to be sorted.
Example:
>>> get_combs([1,2,3,5,10,15,20], 50)
2955
'''
dicto = defaultdict(dict)
for v in xrange(value + 1):
dicto = row_analysis(v, dicto, coins)
return dicto[coins[-1]][value]
In your case:
>>> get_combs([2,3,4,5,6,7,8], 50)
3095
It is like visit a 7-branches decision tree.
The code is:
class WinScore{
static final int totalScore=50;
static final int[] list={2,3,4,5,6,7,8};
public static int methodNum=0;
static void visitTree( int achieved , int index){
if (achieved >= totalScore ){
return;
}
for ( int i=index; i< list.length; i++ ){
if ( achieved + list[i] == totalScore ) {
methodNum++;
}else if ( achieved + list[i] < totalScore ){
visitTree( achieved + list[i], i );
}
}
}
public static void main( String[] args ){
visitTree(0, 0);
System.out.println("number of methods are:" + methodNum );
}
}
output:
number of methods are:3095
Just stumbled on this question - here's a c# variation which allows you to explore the different combinations:
static class SlotIterator
{
public static IEnumerable<string> Discover(this int[] set, int maxScore)
{
var st = new Stack<Slot>();
var combinations = 0;
set = set.OrderBy(c => c).ToArray();
st.Push(new Slot(0, 0, set.Length));
while (st.Count > 0)
{
var m = st.Pop();
for (var i = m.Index; i < set.Length; i++)
{
if (m.Counter + set[i] < maxScore)
{
st.Push(m.Clone(m.Counter + set[i], i));
}
else if (m.Counter + set[i] == maxScore)
{
m.SetSlot(i);
yield return m.Slots.PrintSlots(set, ++combinations, maxScore);
}
}
}
}
public static string PrintSlots(this int[] slots, int[] set, int numVariation, int maxScore)
{
var sb = new StringBuilder();
var accumulate = 0;
for (var j = 0; j < slots.Length; j++)
{
if (slots[j] <= 0)
{
continue;
}
var plus = "+";
for (var k = 0; k < slots[j]; k++)
{
accumulate += set[j];
if (accumulate == maxScore) plus = "";
sb.AppendFormat("{0}{1}", set[j], plus);
}
}
sb.AppendFormat("={0} - Variation nr. {1}", accumulate, numVariation);
return sb.ToString();
}
}
public class Slot
{
public Slot(int counter, int index, int countSlots)
{
this.Slots = new int[countSlots];
this.Counter = counter;
this.Index = index;
}
public void SetSlot(int index)
{
this.Slots[index]++;
}
public Slot Clone(int newval, int index)
{
var s = new Slot(newval, index, this.Slots.Length);
this.Slots.CopyTo(s.Slots, 0);
s.SetSlot(index);
return s;
}
public int[] Slots { get; private set; }
public int Counter { get; set; }
public int Index { get; set; }
}
Example:
static void Main(string[] args)
{
using (var sw = new StreamWriter(#"c:\test\comb50.txt"))
{
foreach (var s in new[] { 2, 3, 4, 5, 6, 7, 8 }.Discover(50))
{
sw.WriteLine(s);
}
}
}
Yields 3095 combinations.

Dyanmic Task Scheduling Interview Street

The task scheduling problem for n tasks is solved by greedy algorithm. I have encountered this particular sort of problem in various coding challenges which asks to find out minimum of maximum overshoot dynamically. One of them is stated below:
Interview Street Problem:
You have a long list of tasks that you need to do today. Task i is specified by the deadline by which you have to complete it (Di) and the number of minutes it will take you to complete the task (Mi). You need not complete a task at a stretch. You can complete a part of it, switch to another task and then switch back.
You've realized that it might not actually be possible complete all the tasks by their deadline, so you have decided to complete them so that the maximum amount by which a task's completion time overshoots its deadline is minimized.
My Approach
Now consider an intermediate stage where we have found the solution for i-1 tasks and have arranged them in sorted order. We have also stored the index of the task which had the maximum overshoot with i-1 tasks say maxLate. After the arrival of the *i*th task we check if D[i] < D[maxlate] then the new maxLate will be either old maxLate of the ith task.
I am confused for the case when D[i] > D[maxlate]. Is a linear scan necessary for this case?
Also suggest a good data structure for updating the new list and keeping them in sorted order.
Thanks for your help.
First of all, you need to prove that given a set of task (m_i, d_i), the best schedule is finish the jobs according to their deadlines, i.e. emergent jobs first.
And the problem is equivalent to:
for each job in original order:
dynamically insert this job (m_i, d_i) into a sorted job_list
query max{ (sum(m_k for all k <= n) - d_n) for all n in job_list }
This algorithm run in O(N^2) where N is the number of jobs, which is too slow for getting accepted in interview street. However, we can use some advanced data structure, to speed up the insert and query operation.
I use a segment tree with lazy update to solve this problem in O(NlgN) time, and here's my code
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
class SegTree
{
public:
SegTree(int left, int right, const vector<int>& original_data)
{
this->left = left;
this->right = right;
this->lazy_flag = 0;
left_tree = right_tree = NULL;
if (left == right)
{
this->value = this->max_value = original_data[left];
}
else
{
mid = (left + right) / 2;
left_tree = new SegTree(left, mid, original_data);
right_tree = new SegTree(mid + 1, right, original_data);
push_up();
}
}
void modify(int left, int right, int m_value)
{
if (this->left == left && this->right == right)
{
leaf_modify(m_value);
}
else
{
push_down();
if (left <= mid)
{
if (right >= mid + 1)
{
left_tree->modify(left, mid, m_value);
right_tree->modify(mid + 1, right, m_value);
}
else
{
left_tree->modify(left, right, m_value);
}
}
else
{
right_tree->modify(left, right, m_value);
}
push_up();
}
}
int query(int left, int right)
{
if (this->left == left && this->right == right)
{
return this->max_value;
}
else
{
push_down();
if (left <= mid)
{
if (right >= mid + 1)
{
int max_value_l = left_tree->query(left, mid);
int max_value_r = right_tree->query(mid + 1, right);
return max(max_value_l, max_value_r);
}
else
{
return left_tree->query(left, right);
}
}
else
{
return right_tree->query(left, right);
}
}
}
private:
int left, right, mid;
SegTree *left_tree, *right_tree;
int value, lazy_flag, max_value;
void push_up()
{
this->max_value = max(this->left_tree->max_value, this->right_tree->max_value);
}
void push_down()
{
if (this->lazy_flag > 0)
{
left_tree->leaf_modify(this->lazy_flag);
right_tree->leaf_modify(this->lazy_flag);
this->lazy_flag = 0;
}
}
void leaf_modify(int m_value)
{
this->lazy_flag += m_value;
this->max_value += m_value;
}
};
vector<int> vec_d, vec_m, vec_idx, vec_rank, vec_d_reorder;
int cmp(int idx_x, int idx_y)
{
return vec_d[idx_x] < vec_d[idx_y];
}
int main()
{
int T;
scanf("%d", &T);
for (int i = 0; i < T; i++)
{
int d, m;
scanf("%d%d", &d, &m);
vec_d.push_back(d);
vec_m.push_back(m);
vec_idx.push_back(i);
}
sort(vec_idx.begin(), vec_idx.end(), cmp);
vec_rank.assign(T, 0);
vec_d_reorder.assign(T, 0);
for (int i = 0; i < T; i++)
{
vec_rank[ vec_idx[i] ] = i;
}
for (int i = 0; i < T; i++)
{
vec_d_reorder[i] = -vec_d[ vec_idx[i] ];
}
// for (int i = 0; i < T; i++)
// {
// printf("m:%d\td:%d\tidx:%d\trank:%d\t-d:%d\n", vec_m[i], vec_d[i], vec_idx[i], vec_rank[i], vec_d_reorder[i]);
// }
SegTree tree(0, T-1, vec_d_reorder);
for (int i = 0; i < T; i++)
{
tree.modify(vec_rank[i], T-1, vec_m[i]);
int ans = tree.query(0, T-1);
printf("%d\n", max(0,ans));
}
}
class Schedule {
int deadLine = 0;
int taskCompletionTime = 0;
int done = 0;
Schedule(int deadline, int taskCompletionTime) {
this.deadLine = deadline;
this.taskCompletionTime = taskCompletionTime;
}
}
class TaskScheduler {
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int max = 0;
ArrayList<Schedule> sch = new ArrayList<Schedule>();
for(int i = 0; i < n; i++) {
int deadLine = in.nextInt();
int taskCompletionTime = in.nextInt();
Schedule s = new Schedule(deadLine, taskCompletionTime);
int j = i-1;
while(j >= 0 && sch.get(j).deadLine > s.deadLine) {
Schedule s1 = sch.get(j);
if(s1.deadLine <= s.deadLine) break;
s1.done += s.taskCompletionTime;
max = Math.max(max, s1.done - s1.deadLine);
j--;
}
sch.add(j+1, s);
if(j < 0)
s.done = s.taskCompletionTime;
else
s.done = sch.get(j).done + s.taskCompletionTime;
max = Math.max(max, s.done - s.deadLine);
System.out.println(max);
}
}
}

Add two big numbers represented as linked lists without reversing the linked lists

Suppose you have 2 big numbers represented as linked lists, how do you add them and store the result in a separate linked list.
eg
a = 2 -> 1 -> 7
b = 3 -> 4
result = 2 -> 5 -> 1
Can you add them without reversing the linked lists
Pseudocode:
Step 1. Traverse the linked lists and push the elements in two different stacks
Step 2. Pop the top elements from both the stacks
Step 3. Add the elements (+ any carry from previous additions) and store the carry in a temp variable
Step 4. Create a node with the sum and insert it into beginning of the result list
I think this's something beyond context but can be very performance incentive for the person who originally posted this question.
So here's a recommendation:
instead of using every node as a single digit of the number, use each node to store a large number(close to the size of integer) and if the highest possible number you chose to store in each node be x(your case 9) then you can view your number as a representation in base x+1.
where each digit is a number between 0 and x.
This would give you significant performance gain as the algorithm would run in O(log n) time and require the same number of nodes as against O(n) in your case , n being the number of decimal digits of the larger of two addends.
Typically for the ease of your algorithm, you can choose a power of 10 as the base which fits in the range of your integer.
For example if your number be 1234567890987654321 and you want to store it in linked list choosing the base to be 10^8 then your representation should look like:
87654321-> 4567890 -> 123(little endian)
Here's my hacky attempt in Java that runs in about O(max(len(a),len(b))). I've provided a complete sample with a very simple singly linked list implementation. It's quite late here so the code is not as nice as I'd like - sorry!
This code assumes:
That the length of the lists is known
Singly linked list
Dealing with integer data
It uses recursion to propagate the sums and carry for each digit, and sums left to right. The lists are never reversed - sums are performed left to right, and carry propagates up the recursive stack. It could be unrolled in an iterative solution, but I won't worry about that.
public class LinkedListSum {
static class LLNode {
int value;
LLNode next;
public LLNode(int value){
this.value = value;
}
public int length(){
LLNode node = this;
int count = 0;
do {
count++;
} while((node = node.next) != null);
return count;
}
public List<Integer> toList(){
List<Integer> res = new ArrayList<Integer>();
LLNode node = this;
while(node != null){
res.add(node.value);
node = node.next;
}
return res;
}
}
public static void main(String[] argc){
LLNode list_a = fromArray(new int[]{4,7,4,7});
LLNode list_b = fromArray(new int[]{5,3,7,4,7,4});
System.out.println("Sum: " + sum(list_a, list_b).toList());
}
private static LLNode fromArray(int[] arr){
LLNode res = new LLNode(0);
LLNode current = res;
for(int i = 0; i < arr.length; i++){
LLNode node = new LLNode(arr[i]);
current.next = node;
current = node;
}
return res.next;
}
private static LLNode sum(LLNode list_1, LLNode list_2){
LLNode longer;
LLNode shorter;
if(list_1.length() >= list_2.length()){
longer = list_1;
shorter = list_2;
} else {
longer = list_2;
shorter = list_1;
}
// Pad short to same length as long
int diff = longer.length() - shorter.length();
for(int i = 0; i < diff; i++){
LLNode temp = new LLNode(0);
temp.next = shorter;
shorter = temp;
}
System.out.println("Longer: " + longer.toList());
System.out.println("Shorter: " + shorter.toList());
return sum_same_length(new LLNode(0), null, longer, shorter);
}
private static LLNode sum_same_length(LLNode current, LLNode previous, LLNode longerList, LLNode shorterList){
LLNode result = current;
if(longerList == null){
previous.next = null;
return result;
}
int sum = longerList.value + shorterList.value;
int first_value = sum % 10;
int first_carry = sum / 10;
current.value = first_value;
// Propagate the carry backwards - increase next multiple of 10 if necessary
LLNode root = propagateCarry(current,previous,first_carry);
current.next = new LLNode(0);
sum_same_length(current.next, current, longerList.next, shorterList.next);
// Propagate the carry backwards - increase next multiple of 10 if necessary:
// The current value could have been increased during the recursive call
int second_value = current.value % 10;
int second_carry = current.value / 10;
current.value = second_value;
root = propagateCarry(current,previous,second_carry);
if(root != null) result = root;
return result;
}
// Returns the new root of the linked list if one had to be added (due to carry)
private static LLNode propagateCarry(LLNode current, LLNode previous, int carry){
LLNode result = null;
if(carry != 0){
if(previous != null){
previous.value += carry;
} else {
LLNode first = new LLNode(carry);
first.next = current;
result = first;
}
}
return result;
}
}
Here is a pseudo code.
list *add (list *l1, list *l2)
{
node *l3, l3_old;
while (l1 != NULL)
{
stack1.push (l1);
l1 = l1->next;
}
while (l2 != NULL)
{
stack2.push (l2);
l2 = l2->next;
}
l3_old = NULL;
while (!stack1.isempty () && !stack2.isempty ()) // at least one stack is not empty
{
l3 = get_new_node ();
l1 = stack1.pop ();
l2 = stack2.pop ();
l3->val = l1->val + l2->val;
if (l3_old != NULL)
{
l3->val = l3->val + (int)l3_old/10;
l3_old->val %= 10;
}
l3->next = l3_old;
l3_old = l3;
}
while (!stack1.isempty ())
{
l1 = stack1.pop ();
l3 = get_new_node ();
l3->val = l1->val + (int)l3_old->val/10;
l3_old->val %= 10;
l3->next = l3_old;
l3_old = l3;
}
while (!stack2.isempty ())
{
l2 = stack2.pop ();
l3 = get_new_node ();
l3->val = l2->val + (int)l3_old->val/10;
l3_old->val %= 10;
l3->next = l3_old;
l3_old = l3;
}
return l3;
}
Here is my attempt, using the two linked lists and returning the sum as a new list using recursion.
public class SumList {
int[] a1= {7,3,2,8};
int[] a2= {4,6,8,4};
LinkedList l1= new LinkedList(a1);
LinkedList l2= new LinkedList(a2);
Node num1= l1.createList();
Node num2= l2.createList();
Node result;
public static void main(String[] args) {
SumList sl= new SumList();
int c= sl.sum(sl.num1, sl.num2);
if(c>0) {
Node temp= new Node(c);
temp.next= sl.result;
sl.result= temp;
}
while(sl.result != null){
System.out.print(sl.result.data);
sl.result= sl.result.next;
}
}
int sum(Node n1, Node n2) {
if(n1==null || n2==null)
return 0;
int a1= this.getSize(n1);
int a2= this.getSize(n2);
int carry, s= 0;
if(a1>a2) {
carry= sum(n1.next, n2);
s= n1.data+carry;
}
else if(a2>a1) {
carry= sum(n1, n2.next);
s= n2.data+carry;
}
else {
carry= sum(n1.next, n2.next);
s= n1.data+n2.data+carry;
}
carry= s/10;
s=s%10;
Node temp= new Node(s);
temp.next= result;
result= temp;
return carry;
}
int getSize(Node n) {
int count =0;
while(n!=null) {
n=n.next;
count++;
}
return count;
}
}
// A recursive program to add two linked lists
#include <stdio.h>
#include <stdlib.h>
// A linked List Node
struct node
{
int data;
struct node* next;
};
typedef struct node node;
/* A utility function to insert a node at the beginning of linked list */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node = (struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* A utility function to print linked list */
void printList(struct node *node)
{
while (node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
printf("\n");
}
// A utility function to swap two pointers
void swapPointer( node** a, node** b )
{
node* t = *a;
*a = *b;
*b = t;
}
/* A utility function to get size of linked list */
int getSize(struct node *node)
{
int size = 0;
while (node != NULL)
{
node = node->next;
size++;
}
return size;
}
// Adds two linked lists of same size represented by head1 and head2 and returns
// head of the resultant linked list. Carry is propagated while returning from
// the recursion
node* addSameSize(node* head1, node* head2, int* carry)
{
// Since the function assumes linked lists are of same size,
// check any of the two head pointers
if (head1 == NULL)
return NULL;
int sum;
// Allocate memory for sum node of current two nodes
node* result = (node *)malloc(sizeof(node));
// Recursively add remaining nodes and get the carry
result->next = addSameSize(head1->next, head2->next, carry);
// add digits of current nodes and propagated carry
sum = head1->data + head2->data + *carry;
*carry = sum / 10;
sum = sum % 10;
// Assigne the sum to current node of resultant list
result->data = sum;
return result;
}
// This function is called after the smaller list is added to the bigger
// lists's sublist of same size. Once the right sublist is added, the carry
// must be added toe left side of larger list to get the final result.
void addCarryToRemaining(node* head1, node* cur, int* carry, node** result)
{
int sum;
// If diff. number of nodes are not traversed, add carry
if (head1 != cur)
{
addCarryToRemaining(head1->next, cur, carry, result);
sum = head1->data + *carry;
*carry = sum/10;
sum %= 10;
// add this node to the front of the result
push(result, sum);
}
}
// The main function that adds two linked lists represented by head1 and head2.
// The sum of two lists is stored in a list referred by result
void addList(node* head1, node* head2, node** result)
{
node *cur;
// first list is empty
if (head1 == NULL)
{
*result = head2;
return;
}
// second list is empty
else if (head2 == NULL)
{
*result = head1;
return;
}
int size1 = getSize(head1);
int size2 = getSize(head2) ;
int carry = 0;
// Add same size lists
if (size1 == size2)
*result = addSameSize(head1, head2, &carry);
else
{
int diff = abs(size1 - size2);
// First list should always be larger than second list.
// If not, swap pointers
if (size1 < size2)
swapPointer(&head1, &head2);
// move diff. number of nodes in first list
for (cur = head1; diff--; cur = cur->next);
// get addition of same size lists
*result = addSameSize(cur, head2, &carry);
// get addition of remaining first list and carry
addCarryToRemaining(head1, cur, &carry, result);
}
// if some carry is still there, add a new node to the fron of
// the result list. e.g. 999 and 87
if (carry)
push(result, carry);
}
// Driver program to test above functions
int main()
{
node *head1 = NULL, *head2 = NULL, *result = NULL;
int arr1[] = {9, 9, 9};
int arr2[] = {1, 8};
int size1 = sizeof(arr1) / sizeof(arr1[0]);
int size2 = sizeof(arr2) / sizeof(arr2[0]);
// Create first list as 9->9->9
int i;
for (i = size1-1; i >= 0; --i)
push(&head1, arr1[i]);
// Create second list as 1->8
for (i = size2-1; i >= 0; --i)
push(&head2, arr2[i]);
addList(head1, head2, &result);
printList(result);
return 0;
}
1.First traverse the two lists and find the lengths of the two lists(Let m,n be the lengths).
2.Traverse n-m nodes in the longer list and set 'prt1' to the current node and 'ptr2' to beginning of the other list.
3.Now call the following recursive function with flag set to zero:
void add(node* ptr1,node* ptr2){
if(ptr1==NULL)
return;
add(ptr1->next,ptr2->next);
insertAtBegin(ptr1->data+ptr2->data+flag);
flag=(ptr1->data+ptr2->data)%10;
}
4.Now you need to add the remaining n-m nodes at the beginning of your target list, you can do it directly using a loop. Please note that for the last element in the loop you need to add the flag returned by the add() function as there might be a carry.
If your question is without using recursion:
1.Repeat the first two steps, then create your target list initalising every elements with '0'(make sure that the length of the list is accurate).
2.Traverse the two lists along with your target list(a step behind).If you find sum of two nodes greater than 10, make the value in the target list as '1'.
3.With the above step you took care of the carry. Now in one more pass just add the two nodes modulo 10 and add this value in the corresponding node of the target list.
without using stack .....
simply store the content of link list in array and perform addition and and then again put addition into link list
code :
#include<stdio.h>
#include<malloc.h>
typedef struct node
{
int value;
struct node *next;
}node;
int main()
{
printf("\nEnter the number 1 : ");
int ch;
node *p=NULL;
node *k=NULL;
printf("\nEnter the number of digit : ");
scanf("%d",&ch);
int i=0;
while(ch!=i)
{
i++;
node *q=NULL;
int a=0;
q=(node *)malloc(sizeof(node));
printf("\nEnter value : ");
scanf("%d",&a);
q->value=a;
if(p==NULL)
{
q->next=NULL;
p=q;
k=p;
}
else
{
q->next=NULL;
p->next=q;
p=q;
}
}
printf("\nEnter the number 2 : ");
int ch1;
node *p1=NULL;
node *k1=NULL;
int i1=0;
printf("\nEnter the number of digit : ");
scanf("%d",&ch1);
while(ch1!=i1)
{
i1++;
node *q1=NULL;
int a1=0;
q1=(node *)malloc(sizeof(node));
printf("\nEnter value : ");
scanf("%d",&a1);
q1->value=a1;
if(p1==NULL)
{
q1->next=NULL;
p1=q1;
k1=p1;
}
else
{
q1->next=NULL;
p1->next=q1;
p1=q1;
}
}
printf("\n\t");
int arr1[100];
int arr1_ptr=0;
while(k != NULL )
{
printf("%d\t",k->value);
arr1[arr1_ptr++]=k->value;
k=k->next;
}
printf("\n\t");
int arr2[100];
int arr2_ptr=0;
while(k1 != NULL )
{
printf("%d\t",k1->value);
arr2[arr2_ptr++]=k1->value;
k1=k1->next;
}
//addition logic ...
int result[100]={0};
int result_ptr=0;
int loop_ptr=0;
int carry=0;
arr1_ptr--;
arr2_ptr--;
if(arr1_ptr>arr2_ptr)
loop_ptr=arr1_ptr+1;
else
loop_ptr=arr2_ptr+1;
for(int i = loop_ptr ; i >= 0;i--)
{
if(arr1_ptr >= 0 && arr2_ptr >= 0)
{
if( (arr1[arr1_ptr] + arr2[arr2_ptr] + carry ) > 9 )
{
result[i]=((arr1[arr1_ptr] + arr2[arr2_ptr]+carry) % 10 );
carry = ((arr1[arr1_ptr--] + arr2[arr2_ptr--]+carry ) / 10 ) ;
}
else
{
result[i]=(arr1[arr1_ptr--] + arr2[arr2_ptr--] + carry );
carry = 0 ;
}
}
else if( !(arr1_ptr < 0 ) || !( arr2_ptr < 0 ) )
{
if( arr1_ptr < 0)
result[i]=arr2[arr2_ptr--]+carry;
else
result[i]=arr1[arr1_ptr--]+carry;
}
else
result[i]=carry;
}
/*printf("\n");
for(int i=0;i<loop_ptr+1;i++)
printf("%d\t",result[i]);
*/
node *k2=NULL,*p2=NULL;
for(int i=0;i<loop_ptr+1;i++)
{
node *q2=NULL;
q2=(node *)malloc(sizeof(node));
q2->value=result[i];
if(p2==NULL)
{
q2->next=NULL;
p2=q2;
k2=p2;
}
else
{
q2->next=NULL;
p2->next=q2;
p2=q2;
}
}
printf("\n");
while(k2 != NULL )
{
printf("%d\t",k2->value);
k2=k2->next;
}
return 0;
}
We can add them by using recursion. Assume the question is defined as follows: we have lists l1 and l2 and we want to add them by storing the result in l1. For simplicity assume that both lists have the same length (the code can be easily modified to work for different lengths). Here is my working Java solution:
private static ListNode add(ListNode l1, ListNode l2){
if(l1 == null)
return l2;
if(l2 == null)
return l1;
int[] carry = new int[1];
add(l1, l2, carry);
if(carry[0] != 0){
ListNode newHead = new ListNode(carry[0]);
newHead.next = l1;
return newHead;
}
return l1;
}
private static void add(ListNode l1, ListNode l2, int[] carry) {
if(l1.next == null && l2.next == null){
carry[0] = l1.val + l2.val;
l1.val = carry[0]%10;
carry[0] /= 10;
return;
}
add(l1.next, l2.next, carry);
carry[0] += l1.val + l2.val;
l1.val = carry[0]%10;
carry[0] /= 10;
}
Input : List a , List b
Output : List c
Most approaches here require extra space for List a and List b. This can be removed.
Reverse List a and List b so that they are represented in the reverse order (i.e., tail as head and all the links reversed) with constant space of O(1).
Then add the lists efficiently by traversing through both of them simultaneously and maintaining a carry.
Reverse List a and List b if required
Try this
/* No Recursion, No Reversal - Java */
import java.util.*;
class LinkedListAddMSB
{
static LinkedList<Integer> addList(LinkedList<Integer> num1, LinkedList<Integer> num2)
{
LinkedList<Integer> res = new LinkedList<Integer>();
LinkedList<Integer> shorter = new LinkedList<Integer>();
LinkedList<Integer> longer = new LinkedList<Integer>();
int carry = 0;
int maxlen,minlen;
if(num1.size() >= num2.size())
{
maxlen = num1.size();
minlen = num2.size();
shorter = num2;
longer = num1;
}
else
{
maxlen = num2.size();
minlen = num1.size();
shorter = num1;
longer = num2;
}
//Pad shorter list to same length by adding preceeding 0
int diff = maxlen - minlen;
for(int i=0; i<diff; i++)
{
shorter.addFirst(0);
}
for(int i=maxlen-1; i>=0; i--)
{
int temp1 = longer.get(i);
int temp2 = shorter.get(i);
int temp3 = temp1 + temp2 + carry;
carry = 0;
if(temp3 >= 10)
{
carry = (temp3/10)%10;
temp3 = temp3%10;
}
res.addFirst(temp3);
}
if(carry > 0)
res.addFirst(carry);
return res;
}
public static void main(String args[])
{
LinkedList<Integer> num1 = new LinkedList<Integer>();
LinkedList<Integer> num2 = new LinkedList<Integer>();
LinkedList<Integer> res = new LinkedList<Integer>();
//64957
num1.add(6);
num1.add(4);
num1.add(9);
num1.add(5);
num1.add(7);
System.out.println("First Number: " + num1);
//48
num2.add(4);
num2.add(8);
System.out.println("First Number: " + num2);
res = addList(num1,num2);
System.out.println("Result: " + res);
}
}
/* this baby does not reverse the list
** , it does use recursion, and it uses a scratch array */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list {
struct list *next;
unsigned value;
};
unsigned recurse( char target[], struct list *lp);
struct list * grab ( char buff[], size_t len);
unsigned recurse( char target[], struct list *lp)
{
unsigned pos;
if (!lp) return 0;
pos = recurse (target, lp->next);
/* We should do a bounds check target[] here */
target[pos] += lp->value;
if (target[pos] >= 10) {
target[pos+1] += target[pos] / 10;
target[pos] %= 10;
}
return 1+pos;
}
struct list * grab ( char *buff, size_t len)
{
size_t idx;
struct list *ret, **hnd;
/* Skip prefix of all zeros. */
for (idx=len; idx--; ) {
if (buff [idx] ) break;
}
if (idx >= len) return NULL;
/* Build the result chain. Buffer has it's LSB at index=0,
** but we just found the MSB at index=idx.
*/
ret = NULL; hnd = &ret;
do {
*hnd = malloc (sizeof **hnd);
(*hnd)->value = buff[idx];
(*hnd)->next = NULL;
hnd = &(*hnd)->next;
} while (idx--);
return ret;
}
int main (void)
{
char array[10];
struct list a[] = { {NULL, 2} , {NULL, 1} , {NULL, 7} };
struct list b[] = { {NULL, 3} , {NULL, 4} };
struct list *result;
a[0].next = &a[1]; a[1].next = &a[2];
b[0].next = &b[1];
memset(array, 0 , sizeof array );
(void) recurse ( array, a);
(void) recurse ( array, b);
result = grab ( array, sizeof array );
for ( ; result; result = result->next ) {
printf( "-> %u" , result->value );
}
printf( "\n" );
return 0;
}
Final version (no list reversal, no recursion):
#include <stdio.h>
#include <stdlib.h>
struct list {
struct list *nxt;
unsigned val;
};
struct list *sumlist(struct list *l, struct list *r);
int difflen(struct list *l, struct list *r);
struct list *sumlist(struct list *l, struct list *r)
{
int carry,diff;
struct list *result= NULL, **pp = &result;
/* If the lists have different lengths,
** the sum will start with the prefix of the longest list
*/
for (diff = difflen(l, r); diff; diff += (diff > 0) ? -1 : 1) {
*pp = malloc (sizeof **pp) ;
(*pp)->nxt = NULL;
if (diff > 0) { (*pp)->val = l->val; l= l->nxt; }
else { (*pp)->val = r->val; r= r->nxt; }
pp = &(*pp)->nxt ;
}
/* Do the summing.
** whenever the sum is ten or larger we increment a carry counter
*/
for (carry=0; l && r; l=l->nxt, r=r->nxt) {
*pp = malloc (sizeof **pp) ;
(*pp)->nxt = NULL;
(*pp)->val = l->val + r->val;
if ((*pp)->val > 9) carry++;
pp = &(*pp)->nxt ;
}
/* While there are any carries, we will need to propagate them.
** Because we cannot reverse the list (or walk it backward),
** this has to be done iteratively.
** Special case: if the first digit needs a carry,
** we have to insert a node in front of it
*/
for (diff =0 ;carry; carry = diff) {
struct list *tmp;
if (result && result->val > 9) {
tmp = malloc(sizeof *tmp);
tmp->nxt = result;
tmp->val = 0;
result = tmp;
}
diff=0;
for (tmp=result; tmp ; tmp= tmp->nxt) {
if (tmp->nxt && tmp->nxt->val > 9) {
tmp->val += tmp->nxt->val/10;
tmp->nxt->val %= 10; }
if (tmp->val > 9) diff++;
}
}
return result;
}
int difflen(struct list *l, struct list *r)
{
int diff;
for (diff=0; l || r; l = (l)?l->nxt:l, r = (r)?r->nxt:r ) {
if (l && r) continue;
if (l) diff++; else diff--;
}
return diff;
}
int main (void)
{
struct list one[] = { {one+1, 2} , {one+2, 6} , {NULL, 7} };
struct list two[] = { {two+1, 7} , {two+2, 3} , {NULL, 4} };
struct list *result;
result = sumlist(one, two);
for ( ; result; result = result->nxt ) {
printf( "-> %u" , result->val );
}
printf( ";\n" );
return 0;
}
In java i will do it this way
public class LLSum {
public static void main(String[] args) {
LinkedList<Integer> ll1 = new LinkedList<Integer>();
LinkedList<Integer> ll2 = new LinkedList<Integer>();
ll1.add(7);
ll1.add(5);
ll1.add(9);
ll1.add(4);
ll1.add(6);
ll2.add(8);
ll2.add(4);
System.out.println(addLists(ll1,ll2));
}
public static LinkedList<Integer> addLists(LinkedList<Integer> ll1, LinkedList<Integer> ll2){
LinkedList<Integer> finalList = null;
int num1 = makeNum(ll1);
int num2 = makeNum(ll2);
finalList = makeList(num1+num2);
return finalList;
}
private static LinkedList<Integer> makeList(int num) {
LinkedList<Integer> newList = new LinkedList<Integer>();
int temp=1;
while(num!=0){
temp = num%10;
newList.add(temp);
num = num/10;
}
return newList;
}
private static int makeNum(LinkedList<Integer> ll) {
int finalNum = 0;
for(int i=0;i<ll.size();i++){
finalNum += ll.get(i) * Math.pow(10,i);
}
return finalNum;
}
}
Here is my first try:
public class addTwo {
public static void main(String args[]){
LinkedListNode m =new LinkedListNode(3);
LinkedListNode n = new LinkedListNode(5);
m.appendNew(1);
m.appendNew(5);
m.appendNew(5);
n.appendNew(9);
n.appendNew(2);
n.appendNew(5);
n.appendNew(9);
n.appendNew(9 );
m.print();
n.print();
LinkedListNode add=addTwo(m,n);
add.print();
}
static LinkedListNode addTwo(LinkedListNode m,LinkedListNode n){
LinkedListNode result;
boolean flag =false;
int num;
num=m.data+n.data+(flag?1:0);
flag=false;
if(num>9){
flag=true;
}
result = new LinkedListNode(num%10);
while(m.link!=null && n.link!=null){
m=m.link;
n=n.link;
num=m.data+n.data+(flag?1:0);
flag=false;
if(num>9){
flag=true;
}
result.appendNew(num%10);
}
if(m.link==null && n.link==null){
if(flag)
result.appendNew(1);
flag=false;
}else if(m.link!=null){
while(m.link !=null){
m=m.link;
num=m.data;
num=m.data+(flag?1:0);
flag=false;
if(num>9){
flag=true;
}
result.appendNew(num%10);
}
}else{
while(n.link !=null){
n=n.link;
num=n.data;
num=n.data+(flag?1:0);
flag=false;
if(num>9){
flag=true;
}
result.appendNew(num%10);
}
}
if(flag){
result.appendNew(1);
}
return result;
}
class LinkedListNode {
public int data;
public LinkedListNode link;
public LinkedListNode(){System.out.println(this+":"+this.link+":"+this.data);}
public LinkedListNode(int data){
this.data=data;
}
void appendNew(int data){
if(this==null){
System.out.println("this is null");
LinkedListNode newNode = new LinkedListNode(data);
}
LinkedListNode newNode = new LinkedListNode(data);
LinkedListNode prev =this;
while(prev.link!=null){
prev = prev.link;
}
prev.link=newNode;
}
void print(){
LinkedListNode n=this;
while(n.link!=null){
System.out.print(n.data +"->");
n = n.link;
}
System.out.println(n.data);
}
}
result is:
3->1->5->5
5->9->2->5->9->9
8->0->8->0->0->0->1
My recursive Java implementation:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return addTwoNumbers(l1, l2, 0);
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2, int carryOver) {
int result;
ListNode next = null;
if (l1 == null && l2 == null) {
if (carryOver > 0) {
return new ListNode(carryOver);
} else {
return null;
}
} else if (l1 == null && l2 != null) {
result = l2.val + carryOver;
next = addTwoNumbers(null, l2.next, result / 10);
} else if (l1 != null && l2 == null){
result = l1.val + carryOver;
next = addTwoNumbers(l1.next, null, result / 10);
} else {
result = l1.val + l2.val + carryOver;
next = addTwoNumbers(l1.next, l2.next, result / 10);
}
ListNode node = new ListNode(result % 10);
node.next = next;
return node;
}
}
Hope that helps.
/* spoiler: just plain recursion will do */
#include <stdio.h>
struct list {
struct list *next;
unsigned value;
};
struct list a[] = { {NULL, 2} , {NULL, 1} , {NULL, 7} };
struct list b[] = { {NULL, 3} , {NULL, 4} };
unsigned recurse( unsigned * target, struct list *lp);
unsigned recurse( unsigned * target, struct list *lp)
{
unsigned fact;
if (!lp) return 1;
fact = recurse (target, lp->next);
*target += fact * lp->value;
return 10*fact;
}
int main (void)
{
unsigned result=0;
/* set up the links */
a[0].next = &a[1];
a[1].next = &a[2];
b[0].next = &b[1];
(void) recurse ( &result, a);
(void) recurse ( &result, b);
printf( "Result = %u\n" , result );
return 0;
}

How can I print out all possible letter combinations a given phone number can represent?

I just tried for my first programming interview and one of the questions was to write a program that given a 7 digit telephone number, could print all possible combinations of letters that each number could represent.
A second part of the question was like what about if this would have been a 12 digit international number? How would that effect your design.
I don't have the code that I wrote in the interview, but I got the impression he wasn't happy with it.
What is the best way to do this?
In Python, iterative:
digit_map = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz',
}
def word_numbers(input):
input = str(input)
ret = ['']
for char in input:
letters = digit_map.get(char, '')
ret = [prefix+letter for prefix in ret for letter in letters]
return ret
ret is a list of results so far; initially it is populated with one item, the empty string. Then, for each character in the input string, it looks up the list of letters that match it from the dict defined at the top. It then replaces the list ret with the every combination of existing prefix and possible letter.
It is similar to a question called letter combinations of a phone number,
here is my solution.
It works for an arbitrary number of digits, so long as the result doesn't exceed the memory limit.
import java.util.HashMap;
public class Solution {
public ArrayList<String> letterCombinations(String digits) {
ArrayList<String> res = new ArrayList<String>();
ArrayList<String> preres = new ArrayList<String>();
res.add("");
for(int i = 0; i < digits.length(); i++) {
String letters = map.get(digits.charAt(i));
if (letters.length() == 0)
continue;
for(String str : res) {
for(int j = 0; j < letters.length(); j++)
preres.add(str + letters.charAt(j));
}
res = preres;
preres = new ArrayList<String>();
}
return res;
}
static final HashMap<Character,String> map = new HashMap<Character,String>(){{
put('1', "");
put('2',"abc");
put('3',"def");
put('4',"ghi");
put('5',"jkl");
put('6',"mno");
put('7',"pqrs");
put('8',"tuv");
put('9',"wxyz");
put('0', "");
}} ;
}
I'm not sure how 12-digit international numbers affect the design.
Edit: International numbers will also be handled
In Java using recursion:
import java.util.LinkedList;
import java.util.List;
public class Main {
// Number-to-letter mappings in order from zero to nine
public static String mappings[][] = {
{"0"}, {"1"}, {"A", "B", "C"}, {"D", "E", "F"}, {"G", "H", "I"},
{"J", "K", "L"}, {"M", "N", "O"}, {"P", "Q", "R", "S"},
{"T", "U", "V"}, {"W", "X", "Y", "Z"}
};
public static void generateCombosHelper(List<String> combos,
String prefix, String remaining) {
// The current digit we are working with
int digit = Integer.parseInt(remaining.substring(0, 1));
if (remaining.length() == 1) {
// We have reached the last digit in the phone number, so add
// all possible prefix-digit combinations to the list
for (int i = 0; i < mappings[digit].length; i++) {
combos.add(prefix + mappings[digit][i]);
}
} else {
// Recursively call this method with each possible new
// prefix and the remaining part of the phone number.
for (int i = 0; i < mappings[digit].length; i++) {
generateCombosHelper(combos, prefix + mappings[digit][i],
remaining.substring(1));
}
}
}
public static List<String> generateCombos(String phoneNumber) {
// This will hold the final list of combinations
List<String> combos = new LinkedList<String>();
// Call the helper method with an empty prefix and the entire
// phone number as the remaining part.
generateCombosHelper(combos, "", phoneNumber);
return combos;
}
public static void main(String[] args) {
String phone = "3456789";
List<String> combos = generateCombos(phone);
for (String s : combos) {
System.out.println(s);
}
}
}
The obvious solution is a function to map a digit to a list of keys, and then a function that would generate the possible combinations:
The first is obvious, the second is more problematic because you have around 3^number of digits combinations, which can be a very large number.
One way to do it is to look at each possibility for digit matching as a digit in a number (on base 4) and implement something close to a counter (jumping over some instances, since there are usually less than 4 letters mappable to a digit).
The more obvious solutions would be nested loops or recursion, which are both less elegant, but in my opinion valid.
Another thing for which care must be taken is to avoid scalability issues (e.g. keeping the possibilities in memory, etc.) since we are talking about a lot of combinations.
P.S. Another interesting extension of the question would be localization.
In C++(recursive):
string pattern[] = {"0",".,!","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"};
ofstream keyout("keypad.txt");
void print_keypad(char* str, int k, vector<char> patt, int i){
if(str[k] != '\0')
{
int x = str[k] - '0';
for(int l = 0; l < pattern[x].length(); l++)
{
patt[i] = pattern[x][l];
print_keypad(str, k+1, patt, i+1);
}
keyout << endl;
}
else if(i == k)
{
string st(patt.data());
keyout << st << endl;
return;
}
}
This function can be called with 'k' and 'i' equal to zero.
Anyone, who requires more illustration to understand the logic, can combine recursion technique with following output:
ADG
ADH
ADI
AEG
AEH
AEI
AFG
AFH
AFI
BDG
BDH
BDI
BEG
BEH
BEI
BFG
BFH
...
In numeric keyboards, texts and numbers are placed on the same key. For example 2 has “ABC” if we wanted to write anything starting with ‘A’ we need to type key 2 once. If we wanted to type ‘B’, press key 2 twice and thrice for typing ‘C’. below is picture of such keypad.
keypad http://d2o58evtke57tz.cloudfront.net/wp-content/uploads/phoneKeyboard.png
Given a keypad as shown in diagram, and a n digit number, list all words which are possible by pressing these numbers.
For example if input number is 234, possible words which can be formed are (Alphabetical order):
adg adh adi aeg aeh aei afg afh afi bdg bdh bdi beg beh bei bfg bfh bfi cdg cdh cdi ceg ceh cei cfg cfh cfi
Let’s do some calculations first. How many words are possible with seven digits with each digit representing n letters? For first digit we have at most four choices, and for each choice for first letter, we have at most four choices for second digit and so on. So it’s simple maths it will be O(4^n). Since keys 0 and 1 don’t have any corresponding alphabet and many characters have 3 characters, 4^n would be the upper bound of number of words and not the minimum words.
Now let’s do some examples.
For number above 234. Do you see any pattern? Yes, we notice that the last character always either G,H or I and whenever it resets its value from I to G, the digit at the left of it gets changed.
Similarly whenever the second last alphabet resets its value, the third last alphabet gets changes and so on. First character resets only once when we have generated all words. This can be looked from other end also. That is to say whenever character at position i changes, character at position i+1 goes through all possible characters and it creates ripple effect till we reach at end.
Since 0 and 1 don’t have any characters associated with them. we should break as there will no iteration for these digits.
Let’s take the second approach as it will be easy to implement it using recursion. We go till the end and come back one by one. Perfect condition for recursion. let’s search for base case.
When we reach at the last character, we print the word with all possible characters for last digit and return. Simple base case.When we reach at the last character, we print the word with all possible characters for last digit and return. Simple base case.
Following is C implementation of recursive approach to print all possible word corresponding to a n digit input number. Note that input number is represented as an array to simplify the code.
#include <stdio.h>
#include <string.h>
// hashTable[i] stores all characters that correspond to digit i in phone
const char hashTable[10][5] = {"", "", "abc", "def", "ghi", "jkl",
"mno", "pqrs", "tuv", "wxyz"};
// A recursive function to print all possible words that can be obtained
// by input number[] of size n. The output words are one by one stored
// in output[]
void printWordsUtil(int number[], int curr_digit, char output[], int n)
{
// Base case, if current output word is prepared
int i;
if (curr_digit == n)
{
printf("%s ", output);
return ;
}
// Try all 3 possible characters for current digir in number[]
// and recur for remaining digits
for (i=0; i<strlen(hashTable[number[curr_digit]]); i++)
{
output[curr_digit] = hashTable[number[curr_digit]][i];
printWordsUtil(number, curr_digit+1, output, n);
if (number[curr_digit] == 0 || number[curr_digit] == 1)
return;
}
}
// A wrapper over printWordsUtil(). It creates an output array and
// calls printWordsUtil()
void printWords(int number[], int n)
{
char result[n+1];
result[n] ='\0';
printWordsUtil(number, 0, result, n);
}
//Driver program
int main(void)
{
int number[] = {2, 3, 4};
int n = sizeof(number)/sizeof(number[0]);
printWords(number, n);
return 0;
}
Output:
adg adh adi aeg aeh aei afg afh afi bdg bdh bdi beg beh bei bfg bfh bfi cdg cdh cdi ceg ceh cei cfg cfh cfi
Time Complexity:
Time complexity of above code is O(4^n) where n is number of digits in input number.
References:
http://www.flipkart.com/programming-interviews-exposed-secrets-landing-your-next-job-3rd/p/itmdxghumef3sdjn?pid=9788126539116&affid=sandeepgfg
In JavaScript. A CustomCounter class takes care of incrementing indexes. Then just output the different possible combinations.
var CustomCounter = function(min, max) {
this.min = min.slice(0)
this.max = max.slice(0)
this.curr = this.min.slice(0)
this.length = this.min.length
}
CustomCounter.prototype.increment = function() {
for (var i = this.length - 1, ii = 0; i >= ii; i--) {
this.curr[i] += 1
if (this.curr[i] > this.max[i]) {
this.curr[i] = 0
} else {
break
}
}
}
CustomCounter.prototype.is_max = function() {
for (var i = 0, ii = this.length; i < ii; ++i) {
if (this.curr[i] !== this.max[i]) {
return false
}
}
return true
}
var PhoneNumber = function(phone_number) {
this.phone_number = phone_number
this.combinations = []
}
PhoneNumber.number_to_combinations = {
1: ['1']
, 2: ['2', 'a', 'b', 'c']
, 3: ['3', 'd', 'e', 'f']
, 4: ['4', 'g', 'h', 'i']
, 5: ['5', 'j', 'k', 'l']
, 6: ['6', 'm', 'n', 'o']
, 7: ['7', 'p', 'q', 'r', 's']
, 8: ['8', 't', 'u', 'v']
, 9: ['9', 'w', 'x', 'y', 'z']
, 0: ['0', '+']
}
PhoneNumber.prototype.get_combination_by_digit = function(digit) {
return PhoneNumber.number_to_combinations[digit]
}
PhoneNumber.prototype.add_combination_by_indexes = function(indexes) {
var combination = ''
for (var i = 0, ii = indexes.length; i < ii; ++i) {
var phone_number_digit = this.phone_number[i]
combination += this.get_combination_by_digit(phone_number_digit)[indexes[i]]
}
this.combinations.push(combination)
}
PhoneNumber.prototype.update_combinations = function() {
var min_indexes = []
, max_indexes = []
for (var i = 0, ii = this.phone_number.length; i < ii; ++i) {
var digit = this.phone_number[i]
min_indexes.push(0)
max_indexes.push(this.get_combination_by_digit(digit).length - 1)
}
var c = new CustomCounter(min_indexes, max_indexes)
while(true) {
this.add_combination_by_indexes(c.curr)
c.increment()
if (c.is_max()) {
this.add_combination_by_indexes(c.curr)
break
}
}
}
var phone_number = new PhoneNumber('120')
phone_number.update_combinations()
console.log(phone_number.combinations)
This problem is similar to this leetcode problem. Here is the answer I submitted for this problem to leetcode (check github and video for explanation).
So the very first thing we need is some way to hold the mappings of a digit and we can use a map for this:
private Map<Integer, String> getDigitMap() {
return Stream.of(
new AbstractMap.SimpleEntry<>(2, "abc"),
new AbstractMap.SimpleEntry<>(3, "def"),
new AbstractMap.SimpleEntry<>(4, "ghi"),
new AbstractMap.SimpleEntry<>(5, "jkl"),
new AbstractMap.SimpleEntry<>(6, "mno"),
new AbstractMap.SimpleEntry<>(7, "pqrs"),
new AbstractMap.SimpleEntry<>(8, "tuv"),
new AbstractMap.SimpleEntry<>(9, "wxyz"))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue));
}
The above method is preparing the map and next method I would use is to provide the mapping for provided digit:
private String getDigitMappings(String strDigit, Map<Integer,String> digitMap) {
int digit = Integer.valueOf(strDigit);
return digitMap.containsKey(digit) ? digitMap.get(digit) : "";
}
This problem can be solved using backtracking and a backtracking solution generally has a structure where the method signature will contain: result container, temp results, original source with index etc. So the method structure would be of the form:
private void compute(List<String> result, StringBuilder temp, String digits, int start, Map<Integer, String> digitMap) {
// Condition to populate temp value to result
// explore other arrangements based on the next input digit
// Loop around the mappings of a digit and then to explore invoke the same method recursively
// Also need to remove the digit which was in temp at last so as to get proper value in temp for next cycle in loop
}
And now the method body can be filled as (result will be kept in a list, temp in string builder etc.)
private void compute(List<String> result, StringBuilder temp, String digits, int start, Map<Integer, String> digitMap) {
if(start >= digits.length()) { // condition
result.add(temp.toString());
return;
}
String letters = getDigitMappings(digits.substring(start, start + 1), digitMap); // mappings of a digit to loop around
for (int i = 0; i < letters.length(); i++) {
temp.append(letters.charAt(i));
compute(result, temp, digits, start+1, digitMap); //explore for remaining digits
temp.deleteCharAt(temp.length() - 1); // remove last in temp
}
}
And finally the method can be invoked as:
public List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<>();
if(digits == null || digits.length() == 0) return result;
compute(result, new StringBuilder(), digits, 0, getDigitMap());
return result;
}
Now the max mapped chars for a digit can be 4 (e.g. 9 has wxyz) and backtracking involves exhaustive search to explore all possible arrangements (state space tree) so for a digit of size n we are going to have 4x4x4....n times i.e. complexity would be O(4^n).
namespace WordsFromPhoneNumber
{
/// <summary>
/// Summary description for WordsFromPhoneNumber
/// </summary>
[TestClass]
public class WordsFromPhoneNumber
{
private static string[] Chars = { "0", "1", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ" };
public WordsFromPhoneNumber()
{
//
// TODO: Add constructor logic here
//
}
#region overhead
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[TestMethod]
public void TestMethod1()
{
IList<string> words = Words(new int[] { 2 });
Assert.IsNotNull(words, "null");
Assert.IsTrue(words.Count == 3, "count");
Assert.IsTrue(words[0] == "A", "a");
Assert.IsTrue(words[1] == "B", "b");
Assert.IsTrue(words[2] == "C", "c");
}
[TestMethod]
public void TestMethod23()
{
IList<string> words = Words(new int[] { 2 , 3});
Assert.IsNotNull(words, "null");
Assert.AreEqual(words.Count , 9, "count");
Assert.AreEqual(words[0] , "AD", "AD");
Assert.AreEqual(words[1] , "AE", "AE");
Assert.AreEqual(words[2] , "AF", "AF");
Assert.AreEqual(words[3] , "BD", "BD");
Assert.AreEqual(words[4] , "BE", "BE");
Assert.AreEqual(words[5] , "BF", "BF");
Assert.AreEqual(words[6] , "CD", "CD");
Assert.AreEqual(words[7] , "CE", "CE");
Assert.AreEqual(words[8] , "CF", "CF");
}
[TestMethod]
public void TestAll()
{
int[] number = new int [4];
Generate(number, 0);
}
private void Generate(int[] number, int index)
{
for (int x = 0; x <= 9; x += 3)
{
number[index] = x;
if (index == number.Length - 1)
{
var w = Words(number);
Assert.IsNotNull(w);
foreach (var xx in number)
{
Console.Write(xx.ToString());
}
Console.WriteLine(" possible words:\n");
foreach (var ww in w)
{
Console.Write("{0} ", ww);
}
Console.WriteLine("\n\n\n");
}
else
{
Generate(number, index + 1);
}
}
}
#endregion
private IList<string> Words(int[] number)
{
List<string> words = new List<string>(100);
Assert.IsNotNull(number, "null");
Assert.IsTrue(number.Length > 0, "length");
StringBuilder word = new StringBuilder(number.Length);
AddWords(number, 0, word, words);
return words;
}
private void AddWords(int[] number, int index, StringBuilder word, List<string> words)
{
Assert.IsTrue(index < number.Length, "index < length");
Assert.IsTrue(number[index] >= 0, "number >= 0");
Assert.IsTrue(number[index] <= 9, "number <= 9");
foreach (var c in Chars[number[index]].ToCharArray())
{
word.Append(c);
if (index < number.Length - 1)
{
AddWords(number, index + 1, word, words);
}
else
{
words.Add(word.ToString());
}
word.Length = word.Length - 1;
}
}
}
}
Use a list L where L[i] = the symbols that digit i can represent.
L[1] = #,.,! (for example)
L[2] = a,b,c
Etc.
Then you can do something like this (pseudo-C):
void f(int k, int st[])
{
if ( k > numberOfDigits )
{
print contents of st[];
return;
}
for each character c in L[Digit At Position k]
{
st[k] = c;
f(k + 1, st);
}
}
Assuming each list contains 3 characters, we have 3^7 possibilities for 7 digits and 3^12 for 12, which isn't that many. If you need all combinations, I don't see a much better way. You can avoid recursion and whatnot, but you're not going to get something a lot faster than this no matter what.
public class Permutation {
//display all combination attached to a 3 digit number
public static void main(String ar[]){
char data[][]= new char[][]{{'a','k','u'},
{'b','l','v'},
{'c','m','w'},
{'d','n','x'},
{'e','o','y'},
{'f','p','z'},
{'g','q','0'},
{'h','r','0'},
{'i','s','0'},
{'j','t','0'}};
int num1, num2, num3=0;
char tempdata[][]= new char[3][3];
StringBuilder number = new StringBuilder("324"); // a 3 digit number
//copy data to a tempdata array-------------------
num1= Integer.parseInt(number.substring(0,1));
tempdata[0] = data[num1];
num2= Integer.parseInt(number.substring(1,2));
tempdata[1] = data[num2];
num3= Integer.parseInt(number.substring(2,3));
tempdata[2] = data[num3];
//display all combinations--------------------
char temp2[][]=tempdata;
char tempd, tempd2;
int i,i2, i3=0;
for(i=0;i<3;i++){
tempd = temp2[0][i];
for (i2=0;i2<3;i2++){
tempd2 = temp2[1][i2];
for(i3=0;i3<3;i3++){
System.out.print(tempd);
System.out.print(tempd2);
System.out.print(temp2[2][i3]);
System.out.println();
}//for i3
}//for i2
}
}
}//end of class
#include <sstream>
#include <map>
#include <vector>
map< int, string> keyMap;
void MakeCombinations( string first, string joinThis , vector<string>& eachResult )
{
if( !first.size() )
return;
int length = joinThis.length();
vector<string> result;
while( length )
{
string each;
char firstCharacter = first.at(0);
each = firstCharacter;
each += joinThis[length -1];
length--;
result.push_back(each);
}
first = first.substr(1);
vector<string>::iterator begin = result.begin();
vector<string>::iterator end = result.end();
while( begin != end)
{
eachResult.push_back( *begin);
begin++;
}
return MakeCombinations( first, joinThis, eachResult);
}
void ProduceCombinations( int inNumber, vector<string>& result)
{
vector<string> inputUnits;
int number = inNumber;
while( number )
{
int lastdigit ;
lastdigit = number % 10;
number = number/10;
inputUnits.push_back( keyMap[lastdigit]);
}
if( inputUnits.size() == 2)
{
MakeCombinations(inputUnits[0], inputUnits[1], result);
}
else if ( inputUnits.size() > 2 )
{
MakeCombinations( inputUnits[0] , inputUnits[1], result);
vector<string>::iterator begin = inputUnits.begin();
vector<string>::iterator end = inputUnits.end();
begin += 2;
while( begin != end )
{
vector<string> intermediate = result;
vector<string>::iterator ibegin = intermediate.begin();
vector<string>::iterator iend = intermediate.end();
while( ibegin != iend)
{
MakeCombinations( *ibegin , *begin, result);
//resultbegin =
ibegin++;
}
begin++;
}
}
else
{
}
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
keyMap[1] = "";
keyMap[2] = "abc";
keyMap[3] = "def";
keyMap[4] = "ghi";
keyMap[5] = "jkl";
keyMap[6] = "mno";
keyMap[7] = "pqrs";
keyMap[8] = "tuv";
keyMap[9] = "wxyz";
keyMap[0] = "";
string inputStr;
getline(cin, inputStr);
int number = 0;
int length = inputStr.length();
int tens = 1;
while( length )
{
number += tens*(inputStr[length -1] - '0');
length--;
tens *= 10;
}
vector<string> r;
ProduceCombinations(number, r);
cout << "[" ;
vector<string>::iterator begin = r.begin();
vector<string>::iterator end = r.end();
while ( begin != end)
{
cout << *begin << "," ;
begin++;
}
cout << "]" ;
return 0;
}
A Python solution is quite economical, and because it uses generators is efficient in terms of memory use.
import itertools
keys = dict(enumerate('::ABC:DEF:GHI:JKL:MNO:PQRS:TUV:WXYZ'.split(':')))
def words(number):
digits = map(int, str(number))
for ls in itertools.product(*map(keys.get, digits)):
yield ''.join(ls)
for w in words(258):
print w
Obviously itertools.product is solving most of the problem for you. But writing it oneself is not difficult. Here's a solution in go, which is careful to re-use the array result to generate all solutions in, and a closure f to capture the generated words. Combined, these give O(log n) memory use inside product.
package main
import (
"bytes"
"fmt"
"strconv"
)
func product(choices [][]byte, result []byte, i int, f func([]byte)) {
if i == len(result) {
f(result)
return
}
for _, c := range choices[i] {
result[i] = c
product(choices, result, i+1, f)
}
}
var keys = bytes.Split([]byte("::ABC:DEF:GHI:JKL:MNO:PQRS:TUV:WXYZ"), []byte(":"))
func words(num int, f func([]byte)) {
ch := [][]byte{}
for _, b := range strconv.Itoa(num) {
ch = append(ch, keys[b-'0'])
}
product(ch, make([]byte, len(ch)), 0, f)
}
func main() {
words(256, func(b []byte) { fmt.Println(string(b)) })
}
This is the C# port of this answer.
Code
public class LetterCombinations
{
private static readonly Dictionary<string, string> Representations = new Dictionary<string, string>
{
{"2", "abc" },
{"3", "def" },
{"4", "ghi" },
{"5", "jkl" },
{"6", "mno" },
{"7", "pqrs" },
{"8", "tuv" },
{"9", "wxyz" },
};
public static List<string> FromPhoneNumber(string phoneNumber)
{
var result = new List<string> { string.Empty };
// go through each number in the phone
for (int i = 0; i < phoneNumber.Length; i++)
{
var pre = new List<string>();
foreach (var str in result)
{
var letters = Representations[phoneNumber[i].ToString()];
// go through each representation of the number
for (int j = 0; j < letters.Length; j++)
{
pre.Add(str + letters[j]);
}
}
result = pre;
}
return result;
}
}
Unit Tests
public class UnitTest
{
[TestMethod]
public void One_Digit_Yields_Three_Representations()
{
var sut = "2";
var expected = new List<string>{ "a", "b", "c" };
var actualResults = LetterCombinations.FromPhoneNumber(sut);
CollectionAssert.AreEqual(expected, actualResults);
}
[TestMethod]
public void Two_Digits_Yield_Nine_Representations()
{
var sut = "22";
var expected = new List<string> { "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc" };
var actualResults = LetterCombinations.FromPhoneNumber(sut);
CollectionAssert.AreEqual(expected, actualResults);
}
[TestMethod]
public void Three_Digits_Yield_ThirtyNine_Representations()
{
var sut = "222";
var actualResults = LetterCombinations.FromPhoneNumber(sut);
var possibleCombinations = Math.Pow(3,3); //27
Assert.AreEqual(possibleCombinations, actualResults.Count);
}
}
Python solution with
def keypad_words(number):
num_pad_dict = {
'2': ['a', 'b', 'c'],
'3': ['d', 'e', 'f'],
'4': ['g', 'h', 'i'],
'5': ['j', 'k', 'l'],
'6': ['m', 'n', 'o'],
'7': ['p', 'q', 'r', 's'],
'8': ['t', 'u', 'v'],
'9': ['w', 'x', 'y', 'z'],
}
result = num_pad_dict.get(number[0], '')
for i in range(1,len(number)):
letters = num_pad_dict.get(number[i], '')
new_result = []
for prefix in result:
for letter in letters:
new_result.append(prefix+letter)
result = new_result
return result
return []
This version in C# is reasonably efficient, and it works for non-western digits (like "۱۲۳۴۵۶۷" for example).
static void Main(string[] args)
{
string phoneNumber = null;
if (1 <= args.Length)
phoneNumber = args[0];
if (string.IsNullOrEmpty(phoneNumber))
{
Console.WriteLine("No phone number supplied.");
return;
}
else
{
Console.WriteLine("Alphabetic phone numbers for \"{0}\":", phoneNumber);
foreach (string phoneNumberText in GetPhoneNumberCombos(phoneNumber))
Console.Write("{0}\t", phoneNumberText);
}
}
public static IEnumerable<string> GetPhoneNumberCombos(string phoneNumber)
{
phoneNumber = RemoveNondigits(phoneNumber);
if (string.IsNullOrEmpty(phoneNumber))
return new List<string>();
char[] combo = new char[phoneNumber.Length];
return GetRemainingPhoneNumberCombos(phoneNumber, combo, 0);
}
private static string RemoveNondigits(string phoneNumber)
{
if (phoneNumber == null)
return null;
StringBuilder sb = new StringBuilder();
foreach (char nextChar in phoneNumber)
if (char.IsDigit(nextChar))
sb.Append(nextChar);
return sb.ToString();
}
private static IEnumerable<string> GetRemainingPhoneNumberCombos(string phoneNumber, char[] combo, int nextDigitIndex)
{
if (combo.Length - 1 == nextDigitIndex)
{
foreach (char nextLetter in phoneNumberAlphaMapping[(int)char.GetNumericValue(phoneNumber[nextDigitIndex])])
{
combo[nextDigitIndex] = nextLetter;
yield return new string(combo);
}
}
else
{
foreach (char nextLetter in phoneNumberAlphaMapping[(int)char.GetNumericValue(phoneNumber[nextDigitIndex])])
{
combo[nextDigitIndex] = nextLetter;
foreach (string result in GetRemainingPhoneNumberCombos(phoneNumber, combo, nextDigitIndex + 1))
yield return result;
}
}
}
private static char[][] phoneNumberAlphaMapping = new char[][]
{
new char[] { '0' },
new char[] { '1' },
new char[] { 'a', 'b', 'c' },
new char[] { 'd', 'e', 'f' },
new char[] { 'g', 'h', 'i' },
new char[] { 'j', 'k', 'l' },
new char[] { 'm', 'n', 'o' },
new char[] { 'p', 'q', 'r', 's' },
new char[] { 't', 'u', 'v' },
new char[] { 'w', 'x', 'y', 'z' }
};
Oracle SQL: Usable with any phone number length and can easily support localization.
CREATE TABLE digit_character_map (digit number(1), character varchar2(1));
SELECT replace(permutations,' ','') AS permutations
FROM (SELECT sys_connect_by_path(map.CHARACTER,' ') AS permutations, LEVEL AS lvl
FROM digit_character_map map
START WITH map.digit = substr('12345',1,1)
CONNECT BY digit = substr('12345',LEVEL,1))
WHERE lvl = length('12345');
Here is one for pain C. This one is likley not efficet (in fact I don't think it is at all). But there are some intresting aspects to it.
It take a number and converts it into a string
It just raises the seed number once each time to create the next sequential string
Whats nice about this is that there is no real limit to the size of the string (no character limit) This allows you to generate longer and longer strings if need be just by waiting.
#include <stdlib.h>
#include <stdio.h>
#define CHARACTER_RANGE 95 // The range of valid password characters
#define CHARACTER_OFFSET 32 // The offset of the first valid character
void main(int argc, char *argv[], char *env[])
{
int i;
long int string;
long int worker;
char *guess; // Current Generation
guess = (char*)malloc(1); // Allocate it so free doesn't fail
int cur;
for ( string = 0; ; string++ )
{
worker = string;
free(guess);
guess = (char*)malloc((string/CHARACTER_RANGE+1)*sizeof(char)); // Alocate for the number of characters we will need
for ( i = 0; worker > 0 && i < string/CHARACTER_RANGE + 1; i++ ) // Work out the string
{
cur = worker % CHARACTER_RANGE; // Take off the last digit
worker = (worker - cur) / CHARACTER_RANGE; // Advance the digits
cur += CHARACTER_OFFSET;
guess[i] = cur;
}
guess[i+1] = '\0'; // NULL terminate our string
printf("%s\t%d\n", guess, string);
}
}
static final String[] keypad = {"", "", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"};
String[] printAlphabet(int num){
if (num >= 0 && num < 10){
String[] retStr;
if (num == 0 || num ==1){
retStr = new String[]{""};
} else {
retStr = new String[keypad[num].length()];
for (int i = 0 ; i < keypad[num].length(); i++){
retStr[i] = String.valueOf(keypad[num].charAt(i));
}
}
return retStr;
}
String[] nxtStr = printAlphabet(num/10);
int digit = num % 10;
String[] curStr = null;
if(digit == 0 || digit == 1){
curStr = new String[]{""};
} else {
curStr = new String[keypad[digit].length()];
for (int i = 0; i < keypad[digit].length(); i++){
curStr[i] = String.valueOf(keypad[digit].charAt(i));
}
}
String[] result = new String[curStr.length * nxtStr.length];
int k=0;
for (String cStr : curStr){
for (String nStr : nxtStr){
result[k++] = nStr + cStr;
}
}
return result;
}
/**
* Simple Java implementation without any input/error checking
* (expects all digits as input)
**/
public class PhoneSpeller
{
private static final char[][] _letters = new char[][]{
{'0'},
{'1'},
{'A', 'B', 'C'},
{'D', 'E', 'F'},
{'G', 'H', 'I'},
{'J', 'K', 'L'},
{'M', 'N', 'O'},
{'P', 'Q', 'R', 'S'},
{'T', 'U', 'V'},
{'W', 'X', 'Y', 'Z'}
};
public static void main(String[] args)
{
if (args.length != 1)
{
System.out.println("Please run again with your phone number (no dashes)");
System.exit(0);
}
recursive_phoneSpell(args[0], 0, new ArrayList<String>());
}
private static void recursive_phoneSpell(String arg, int index, List<String> results)
{
if (index == arg.length())
{
printResults(results);
return;
}
int num = Integer.parseInt(arg.charAt(index)+"");
if (index==0)
{
for (int j = 0; j<_letters[num].length; j++)
{
results.add(_letters[num][j]+"");
}
recursive_phoneSpell(arg, index+1, results);
}
else
{
List<String> combos = new ArrayList<String>();
for (int j = 0; j<_letters[num].length; j++)
{
for (String result : results)
{
combos.add(result+_letters[num][j]);
}
}
recursive_phoneSpell(arg, index+1, combos);
}
}
private static void printResults(List<String> results)
{
for (String result : results)
{
System.out.println(result);
}
}
}
I am rather a newbie so please correct me wherever I am wrong.
First thing is looking into space & time complexity. Which is really bad since it's factorial
so for factorial(7) = 5040 any recursive algorithm would do. But for factorial(12) ~= 4 * 10^8 which can cause stack overflow in recursive solution.
So I would not attempt a recursive algorithm. Looping solution is very straight forward using "Next Permutation".
So I would create and array {0, 1, 2, 3, 4, 5} and generate all permutation and while printing replace them with respective characters eg. 0=A, 5=F
Next Perm algorithm works as follows. eg Given 1,3,5,4 next permutation is 1,4,3,5
Steps for finding next perm.
From right to left, find first decreasing number. eg 3
From left to right, find lowest number bigger than 3 eg. 4
Swap these numbers as reverse the subset. 1,4,5,3 reverse subset 1,4,3,5
Using Next permutation ( or rotation) you generate specific subset of permutations, say you want to show 1000 permutations starting from a particular phone number. This can save you from having all numbers in memory. If I store numbers as 4 byte integers, 10^9 bytes = 1 GB !.
Here is the working code for the same..
its a recursion on each step checking possibility of each combinations on occurrence of same digit in a series....I am not sure if there is any better solution then this from complexity point of view.....
Please let me know for any issues....
import java.util.ArrayList;
public class phonenumbers {
/**
* #param args
*/
public static String mappings[][] = {
{"0"}, {"1"}, {"A", "B", "C"}, {"D", "E", "F"}, {"G", "H", "I"},
{"J", "K", "L"}, {"M", "N", "O"}, {"P", "Q", "R", "S"},
{"T", "U", "V"}, {"W", "X", "Y", "Z"}
};
public static void main(String[] args) {
// TODO Auto-generated method stub
String phone = "3333456789";
ArrayList<String> list= generateAllnums(phone,"",0);
}
private static ArrayList<String> generateAllnums(String phone,String sofar,int j) {
// TODO Auto-generated method stub
//System.out.println(phone);
if(phone.isEmpty()){
System.out.println(sofar);
for(int k1=0;k1<sofar.length();k1++){
int m=sofar.toLowerCase().charAt(k1)-48;
if(m==-16)
continue;
int i=k1;
while(true && i<sofar.length()-2){
if(sofar.charAt(i+1)==' ')
break;
else if(sofar.charAt(i+1)==sofar.charAt(k1)){
i++;
}else{
break;
}
}
i=i-k1;
//System.out.print(" " + m +", " + i + " ");
System.out.print(mappings[m][i%3]);
k1=k1+i;
}
System.out.println();
return null;
}
int num= phone.charAt(j);
int k=0;
for(int i=j+1;i<phone.length();i++){
if(phone.charAt(i)==num){
k++;
}
}
if(k!=0){
int p=0;
ArrayList<String> list2= generateAllnums(phone.substring(p+1), sofar+phone.charAt(p)+ " ", 0);
ArrayList<String> list3= generateAllnums(phone.substring(p+1), sofar+phone.charAt(p), 0);
}
else{
ArrayList<String> list1= generateAllnums(phone.substring(1), sofar+phone.charAt(0), 0);
}
return null;
}
}
You find source (Scala) here and an working applet here.
Since 0 and 1 aren't matched to characters, they build natural breakpoints in numbers. But they don't occur in every number (except 0 at the beginning). Longer numbers like +49567892345 from 9 digits starting, can lead to OutOfMemoryErrors. So it would be better to split a number into groups like
01723 5864
0172 35864
to see, if you can make sense from the shorter parts. I wrote such a program, and tested some numbers from my friends, but found rarely combinations of shorter words, which could be checked in a dictionary for matching, not to mention single, long words.
So my decision was to only support searching, no full automation, by displaying possible combinations, encouraging splitting the number by hand, maybe multiple time.
So I found +-RAD JUNG (+-bycicle boy).
If you accept misspellings, abbreviations, foreign words, numbers as words, numbers in words, and names, your chance to find a solution is much better, than without fiddling around.
246848 => 2hot4u (too hot for you)
466368 => goodn8 (good night)
1325 => 1FCK (Football club)
53517 => JDK17 (Java Developer Kit)
are things a human might observe - to make an algorithm find such things is rather hard.
This is a recursive algorithm in C++11.
#include <iostream>
#include <array>
#include <list>
std::array<std::string, 10> pm = {
"0", "1", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"
};
void generate_mnemonic(const std::string& numbers, size_t i, std::string& m,
std::list<std::string>& mnemonics)
{
// Base case
if (numbers.size() == i) {
mnemonics.push_back(m);
return;
}
for (char c : pm[numbers[i] - '0']) {
m[i] = c;
generate_mnemonic(numbers, i + 1, m, mnemonics);
}
}
std::list<std::string> phone_number_mnemonics(const std::string& numbers)
{
std::list<std::string> mnemonics;
std::string m(numbers.size(), 0);
generate_mnemonic(numbers, 0, m, mnemonics);
return mnemonics;
}
int main() {
std::list<std::string> result = phone_number_mnemonics("2276696");
for (const std::string& s : result) {
std::cout << s << std::endl;
}
return 0;
}
I rewrote the latest answer to this (referred above) , from C to Java. I also included the support for 0 and 1 (as 0 and 1) because numbers such as 555-5055 weren't working at all with the above code.
Here it is. Some comments are preserved.
public static void printPhoneWords(int[] number) {
char[] output = new char[number.length];
printWordsUtil(number,0,output);
}
static String[] phoneKeys= new String[]{"0", "1", "ABC", "DEF", "GHI", "JKL",
"MNO", "PQRS", "TUV", "WXYZ"};
private static void printWordsUtil(int[] number, int curDigIndex, char[] output) {
// Base case, if current output word is done
if (curDigIndex == output.length) {
System.out.print(String.valueOf(output) + " ");
return;
}
// Try all 3-4 possible characters for the current digit in number[]
// and recurse for the remaining digits
char curPhoneKey[] = phoneKeys[number[curDigIndex]].toCharArray();
for (int i = 0; i< curPhoneKey.length ; i++) {
output[curDigIndex] = curPhoneKey[i];
printWordsUtil(number, curDigIndex+1, output);
if (number[curDigIndex] <= 1) // for 0 or 1
return;
}
}
public static void main(String[] args) {
int number[] = {2, 3, 4};
printPhoneWords(number);
System.out.println();
}
private List<string> strs = new List<string>();
char[] numbersArray;
private int End = 0;
private int numberOfStrings;
private void PrintLetters(string numbers)
{
this.End = numbers.Length;
this.numbersArray = numbers.ToCharArray();
this.PrintAllCombinations(this.GetCharacters(this.numbersArray[0]), string.Empty, 0);
}
private void PrintAllCombinations(char[] letters, string output, int depth)
{
depth++;
for (int i = 0; i < letters.Length; i++)
{
if (depth != this.End)
{
output += letters[i];
this.PrintAllCombinations(this.GetCharacters(Convert.ToChar(this.numbersArray[depth])), output, depth);
output = output.Substring(0, output.Length - 1);
}
else
{
Console.WriteLine(output + letters[i] + (++numberOfStrings));
}
}
}
private char[] GetCharacters(char x)
{
char[] arr;
switch (x)
{
case '0': arr = new char[1] { '.' };
return arr;
case '1': arr = new char[1] { '.' };
return arr;
case '2': arr = new char[3] { 'a', 'b', 'c' };
return arr;
case '3': arr = new char[3] { 'd', 'e', 'f' };
return arr;
case '4': arr = new char[3] { 'g', 'h', 'i' };
return arr;
case '5': arr = new char[3] { 'j', 'k', 'l' };
return arr;
case '6': arr = new char[3] { 'm', 'n', 'o' };
return arr;
case '7': arr = new char[4] { 'p', 'q', 'r', 's' };
return arr;
case '8': arr = new char[3] { 't', 'u', 'v' };
return arr;
case '9': arr = new char[4] { 'w', 'x', 'y', 'z' };
return arr;
default: return null;
}
}
One option in Objective-C:
- (NSArray *)lettersForNumber:(NSNumber *)number {
switch ([number intValue]) {
case 2:
return #[#"A",#"B",#"C"];
case 3:
return #[#"D",#"E",#"F"];
case 4:
return #[#"G",#"H",#"I"];
case 5:
return #[#"J",#"K",#"L"];
case 6:
return #[#"M",#"N",#"O"];
case 7:
return #[#"P",#"Q",#"R",#"S"];
case 8:
return #[#"T",#"U",#"V"];
case 9:
return #[#"W",#"X",#"Y",#"Z"];
default:
return nil;
}
}
- (NSArray *)letterCombinationsForNumbers:(NSArray *)numbers {
NSMutableArray *combinations = [[NSMutableArray alloc] initWithObjects:#"", nil];
for (NSNumber *number in numbers) {
NSArray *lettersNumber = [self lettersForNumber:number];
//Ignore numbers that don't have associated letters
if (lettersNumber.count == 0) {
continue;
}
NSMutableArray *currentCombinations = [combinations mutableCopy];
combinations = [[NSMutableArray alloc] init];
for (NSString *letter in lettersNumber) {
for (NSString *letterInResult in currentCombinations) {
NSString *newString = [NSString stringWithFormat:#"%#%#", letterInResult, letter];
[combinations addObject:newString];
}
}
}
return combinations;
}
I tried it in ruby, and came up with a different way of doing, it's probably not efficient, like time and space O(?) at this point, but I like it because it uses Ruby's builtin Array.product method. What do you think?
EDIT: I see a very similar solution in Python above, but I hadn't seen it when I added my answer
def phone_to_abc(phone)
phone_abc = [
'0', '1', 'abc', 'def', 'ghi',
'jkl', 'mno', 'pqrs', 'tuv', 'wxyz'
]
phone_map = phone.chars.map { |x| phone_abc[x.to_i].chars }
result = phone_map[0]
for i in 1..phone_map.size-1
result = result.product(phone_map[i])
end
result.each { |x|
puts "#{x.join}"
}
end
phone_to_abc('86352')
An R solution using nested loops:
# Create phone pad
two <- c("A", "B", "C")
three <- c("D", "E", "F")
four <- c("G", "H", "I")
five <- c("J", "K", "L")
six <- c("M", "N", "O", "P")
seven <- c("Q", "R", "S")
eight <- c("T", "U", "V")
nine <- c("W", "X", "Y", "Z")
# Choose three numbers
number_1 <- two
number_2 <- three
number_3 <- six
# create an object to save the combinations to
combinations <- NULL
# Loop through the letters in number_1
for(i in number_1){
# Loop through the letters in number_2
for(j in number_2){
# Loop through the letters in number_3
for(k in number_3){
# Add each of the letters to the combinations object
combinations <- c(combinations, paste0(i, j, k))
}
}
}
# Print all of the possible combinations
combinations
I posted another, more bizarre R solution using more loops and sampling on my blog.
This approach uses R and is based on first converting the dictionary to its corresponding digit representation, then using this as a look-up.
The conversion only takes 1 second on my machine (converting from the native Unix dictionary of about 100,000 words), and typical look-ups of up to 100 different digit inputs take a total of .1 seconds:
library(data.table)
#example dictionary
dict.orig = tolower(readLines("/usr/share/dict/american-english"))
#split each word into its constituent letters
#words shorter than the longest padded with "" for simpler retrieval
dictDT = setDT(tstrsplit(dict.orig, split = "", fill = ""))
#lookup table for conversion
#NB: the following are found in the dictionary and would need
# to be handled separately -- ignoring here
# (accents should just be appended to
# matches for unaccented version):
# c("", "'", "á", "â", "å", "ä",
# "ç", "é", "è", "ê", "í", "ñ",
# "ó", "ô", "ö", "û", "ü")
lookup = data.table(num = c(rep('2', 3), rep('3', 3), rep('4', 3),
rep('5', 3), rep('6', 3), rep('7', 4),
rep('8', 3), rep('9', 4)),
let = letters)
#using the lookup table, convert to numeric
for (col in names(dictDT)) {
dictDT[lookup, (col) := i.num, on = setNames("let", col)]
}
#back to character vector
dict.num = do.call(paste0, dictDT)
#sort both for faster vector search
idx = order(dict.num)
dict.num = dict.num[idx]
dict.orig = dict.orig[idx]
possibilities = function(input) dict.orig[dict.num == input]
#sample output:
possibilities('269')
# [1] "amy" "bmw" "cox" "coy" "any" "bow" "box" "boy" "cow" "cox" "coy"
possibilities('22737')
# [1] "acres" "bards" "barer" "bares" "barfs" "baser" "bases" "caper"
# [9] "capes" "cards" "cares" "cases"

Resources