I am trying to solve a problem where every letter has a respective number such as a-1,b-2....z-26.
Now given a number, in how many ways can the number be decoded is the question. consider an example where 25114 can be decoded as 'BEAN',‘BEAAD’, ‘YAAD’, ‘YAN’, ‘YKD’ and ‘BEKD’. this could be decoded in 6 ways.
I have written code in c++ but I am getting the wrong answer. Please correct my code.
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end)
return;
int j =start;
if(factor==2&&j==end-1)//if j is the last element and factor is 2,accessing j+1 element is illegual
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
total++;
func(start+1,end,1);
func(start+1,end,2);
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
essentially what my code is doing is that it fixes one number from the given array(using one digit or two digits from the the given array) and recurses until all the combinations are covered. for example considering the above case, I first choose '2' as my first digit and decode it as 'B'(factor = 1) and then choose '25' and decode it as 'E'(factor = 2).
**following are the input and output from the following code
input : 25114
expected output : 6
my output : 15
input : 3333333333(10 digits)
expected output : 1
my output : 10
Based on the original program from the question I suggest to count the encodings when you reach the end only (if(start==end)).
As func will always be called twice with factor=1 and factor=2, I can freely choose either condition for counting.
Here is the modified code:
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end) {
if(factor == 1) total++; // count once when reaching the end
return;
}
int j =start;
if((factor==2) && (j==end-1))//if j is the last element and factor is 2,accessing j+1 element is illegal
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
//total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
//total++;
func(start+1,end,1);
func(start+1,end,2);
}
return;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
This calculates the expected results from the example input in the question.
$ echo 5 2 5 1 1 4|./program
6
$ echo 10 3 3 3 3 3 3 3 3 3 3|./program
1
There is room for improvement.
Instead of modifying a global variable I would return the number of combinations from func and add the values in the higher level.
I would also handle the distinction between 2-digit and 1-digit numbers in the called func instead of in the caller.
Something like this pseudo code:
int func(int start, int end)
{
if(remaining length is <2) {
// we reached the end, so this is one combination
return 1;
}
if(two-digit number is >26) {
// only a 1-digit number is possible, count remaining combinations
return func(start+1, end);
}
// both a 1-digit or 2-digit number is possible, add the remaining combinations for both cases
return func(start+1) + func(start+2);
}
Your question is tagged as "dynamic-programming", but it is anything but.
Instead, think about the state space and its boundary conditions:
The empty string has zero encodings;
A single digit has a single encoding;
An n-digit string has as many encodings as an (n-1)-digit substring plus as many encodings as an (n-2)-digit substring if the first two digits are <= 26.
Thus, we can walk the string from back to front and store the intermediate results for reuse:
uint64_t solve(std::vector<int>& digits) {
const int n = digits.size();
std::vector<int> encodings(n+1);
encodings[n] = 1;
for (int i = n-1; i >= 0; i--) {
bool two_digits_fit = (i < n - 1) && (digits[i] * 10 + digits[i+1]) <= 26; // What if digits[i] == 0?
encodings[i] = encodings[i+1] + (two_digits_fit ? encodings[i+2] : 0);
}
return encodings[0];
}
Related
I want to build the following program:
The user has to insert a number between 100 and 999 (like 100 < i < 999) and the numbers have to be multiplied among themselves.
Example:
A Valid Input: 178
Corresponding Result: 1*7*8 = 72
I tried to achieve the first part i.e. checking for the number given as input to be within 100 and 999 in the two ways below, but my approach isn't said to be elegant:
#include <stdio.h>
int main()
{
char n[4];
scanf("%s", n);
printf("%d\n", (n[0]-'0')*(n[1]-'0')*(n[2]-'0'));
return 0;
}
or
#include<stdio.h>
int main()
{
int array[3];
scanf("%1d%1d%1d", &array[0],&array[1],&array[2]);
for ( int i=0; i<3; i++) {
printf("%d\n", array[i]);
}
return 0;
}
Are they any better ways to achieve the same?
I'm looking for a C++ solution.
You can impose std::cin as a conditional in a while:
int x;
while (std::cin >> x && x>=100 && x <=999)
\\ Do what you want
For multiplying the digits, simply extract each digit by getting its remainder when divided by 10, multiply that with the current product (set a variable, with inital value 1) then divide by 10 subsequently in a loop till you get the product of all digits. For example, create a function which returns the product of digits of a number:
int digitproduct(int x)
{ int product = 1;
while (x != 0)
{
product *= (n % 10);
x /= 10;
}
return product;
}
Call that inside the while:
int x;
while (std::cin >> x && x>=100 && x <=999)
{ cout<< digitproduct(x);
break;
}
People may say, your solution isn't elegant, because it does not easily scales if you may want to add more digest or remove some.
The first one will also have a buffer overflow as soon the user enters more than 4 characters!
But out of my option I like the second one quite much, because it shows a much better understanding of C than just reading the number via int n; std::cin >> n;, validating it, and then calculating the result.
But there is a small flaw as well, you need to check the return value of scanf in order to detect if a number has been successfully parsed or not.
int res = scanf("%1d%1d%1d", &array[0],&array[1],&array[2]);
if(res != 3) {
printf("Invalid number format. Expected a three digit number, but got %d", res);
return 0;
}
More elegant solution will be to obtain the number as an integer and then decompose it to the single digits with division and modulo operations.
This greatly increases the ability to validate the input number and knowing how to decompose the integer may be useful if the number is not given as a string, but from other parts of the program as a number.
Sample code:
#include <stdio.h>
int main() {
int number;
scanf("%d", &number);
if(number > 999 || number < 100) {
printf("Number not in range\n");
return -1;
}
printf("%d\n",
(number / 100) * // hundreds digit
(number / 10 % 10) * // tens digit
(number % 10) // units digit
);
return 0;
}
I have an interval (m,n) and there I have to print out all the numbers which have different digits. I wrote this, but it only works for 2 digit numbers. I simply do not know how to make it work for anything but 2 digit numbers. I imagine that, if I added as much for loops as the digits of my number it would work, but the interval(m,n) isn't specified so it has to be something reliable. I've been trying to solve this problem on my own for 6 damn hours and I'm absolutely fed up.
Input 97,113;
Output 97,98,102,103,104,105,106,107,108,109
Numbers 99,100,101,110+ don't get printed, because they have 2 digits that are
the same.
#include<conio.h>
#include<math.h>
#include<stdio.h>
int main()
{
int m,n,test,checker=0;
scanf("%d%d",&m,&n);
if(m>n)
{
int holder=n;
n=m;
m=holder;
}
for(int start=m;start<=n;start++)
{
int itemCount=floor(log10(abs(start)))+1;
int nums[itemCount];
int index=0;
test=start;
do
{
int nextVal = test % 10;
nums[index++]=nextVal;
test = test / 10;
}while(test>0);
for (int i = 0; i < itemCount - 1; i++)
{ // read comment by #nbro
for (int j = i + 1; j < itemCount; j++)
{
if (nums[i] == nums[j])
{
checker++;
}
}
if(checker==0)printf("%d ",start);
}
checker=0;
}
}
Since you tagged this as C++, here is a very simple solution using simple modulus and division in a loop. No conversion to string is done.
#include <iostream>
#include <bitset>
bool is_unique_digits(int num)
{
std::bitset<10> numset = 0;
while (num > 0)
{
// get last digit
int val = num % 10;
// if bit is on, then this digit is unique
if (numset[val])
return false;
// turn bit on and remove last digit from number
numset.set(val);
num /= 10;
}
return true;
}
int main()
{
for (int i = 97; i <= 113; ++i)
{
if (is_unique_digits(i))
std::cout << i << "\n";
}
}
The is_unique_digit function simply takes the number and repeatedly extracts the digits from it by taking the last digit in the number. Then this digit is tested to see if the same digit appears in the bitset. If the number already exists, false is immediately returned.
If the number is not in the bitset, then the bit that corresponds to that digit is turned "on" and the number is divided by 10 (effectively removing the last digit from the number). If the loop completes, then true is returned.
Live Example
As an idea for a design:
print the number to a string, if it isn't a string already;
declare an array of int d[10]; and set it to all zeroes
for each ascii digit c of the string,
if (d[c-'0']==1) return 0; // this digit exists already in the number
else d[c-'0']= 1;
just put if(checker==0)printf("%d ",start); outside of second loop the loop
like this
for (int i = 0; i < itemCount - 1; i++)
{
for (int j = i + 1; j < itemCount; j++)
{
if (nums[i] == nums[j])
{
checker++;
break;
}
}
}
if(checker==0)
printf("%d ",start);
checker=0;
However instead of using two nested for loop you can use count array which is more efficient
to check 1 number, you can do
X=10; //number to analyze
char counts[10]; for int i=0;i<10;i++) counts[i]=0;
char number[10];
sprintf(&number,"%s",X); bool bad=false;
for(int i=0;i<strlen(number);i++)
{
if(++counts[number[i]-'0']>1) {bad=true;break;}
}`
Recently I have been trying to do a problem that requires me to find all the different combinations with selecting only 1 element from each row. For example, I'm inputting n rows with 2 strings per row. However, I only want to find all the different combinations where I choose 1 string from each row.
Example:
Input:
3
alex bob
straw mat
eat drink
Example combination:
alex straw drink
This results in 2^n combinations, which in this case would be 2^3 = 8 combinations. However, if I was to use n for loops to find the combinations
e.g.
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int n;
int main(int argc, char ** argv) {
cin >> n; //rows of words
string words[n][2]; //the words with 2 words per row
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
cin >> words[i][j]; //input of words
}
}
//finding all possible combinations
for (int i =0; i<n; i++){
for (int j=0; j<2; j++){
for (int x=0; x<2; x++){
//and so on per n
}
}
}
return 0;
}
this would take n for loops to find out all the combinations of the array with only taking one item from each row. What would be the best and simplest approach to finding all different combinations with size n as I would take 1 string out of the two in each row? Thanks.
You can do recursion.
Assuming C++11, something like this maybe (didn't try to compile this though):
// finding all possible combinations
std::vector<std::vector<std::string>> combinations;
const auto processLine = [&](const std::vector<std::string>& currentCombination, int line) {
std::vector<std::string> combination0 = currentCombination;
std::vector<std::string> combination1 = currentCombination;
combination0.push_back(words[line][0]);
combination1.push_back(words[line][1]);
if (line + 1 < n) {
// process next line
processLine(combination0, line + 1);
processLine(combination1, line + 1);
}
else {
// last line - keep the result
combinations.push_back(combination0);
combinations.push_back(combination1);
}
};
std::vector<std::string> empty;
processLine(empty, 0);
// print results
for (const auto& combination : combinations) {
for (const auto& word : combination) {
std::cout << word << " ";
}
std::cout << std::endl;
}
A very simple solution for a setting where you have always 2 elements per row would be to use datatype integer and interpret each bit as a decision for the first or the second column in the respective row; then simply count from 0 to 2^n - 1 in order to get all combinations.
Applied to your example this would look as follows:
int bits meaning
0 000 alex,straw,eat
1 001 alex,straw,drink
2 010 alex,mat,eat
3 011 alex,mat,dring
4 100 bob,straw,eat
5 101 bob,straw,drink
6 110 bob,mat,eat
7 111 bob,mat,drink
For any of the given integer values 0..7, use bit shift operators or &-bitmask to map each bit to a column index:
void getCombinationRepresentedByIntValue(vector<string>& combination, int value) {
int mask = 1;
for (int i=n-1; i>=0; i--) {
if (value & mask)
combination.push_back(words[i][1]);
else
combination.push_back(words[i][0]);
mask = mask << 1;
}
}
That seems to answer your question :
int ct[n]; // count of the number of pass
int current = 0; // index of the current word (n)
/* while not all combinaison have been exploited */
while (current >= 0)
{
cout << words[current][ct[current]]; /* <<<<< can be used another way*/
/* down to the next word */
current ++; // to get the next word
if (current >=n) { // at the end of the list
cout << " ";
current--; // restore last
ct[current]++; // increment number of time we passed
/* find the previous not completely exploited */
while (current >= 0 && ct[current]> 1) /* <<< change 1 to any number of words per line */
{
ct[current] = 0;
current--;
if (current >= 0) ct[current]++;
}
if (current > 0 ) current = 0;
}
}
With your example :
Input :
3
alex bob
straw mat
eat drink
output :
alexstraweat
alexstrawdrink
alexmateat
alexmatdrink
bobstraweat
bobstrawdrink
bobmateat
bobmatdrink
hope it helps !
I have to find the the length of largest increasing sub-sequence of an array such that difference between any two consecutive elements of sub-sequence is 1
For example: {5,4,2,1,6,2,3,4,5}
length of largest consecutive increasing sub-sequence : 5 {1,2,3,4,5}
SO far I have tried this:
#include <iostream>
using namespace std;
int a[1000001];
int m[1000001]={0};
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
m[a[i]]=i;
}
int maxm=0;
for(int i=1;i<=n;i++)
{
if(m[a[i]-1]==0 || m[a[i]]<=m[a[i]-1])
{
int k=a[i];
int prev = m[k];
k++;
int c=1;
while(m[k]>prev)
{
c++;
prev=m[k];
k++;
}
maxm=max(maxm,c);
}
}
cout<<maxm;
return 0;
}
But this is giving wrong answer for cases like{2,2,1,2,3,1,2,3,4,3,5}
Any help would be appreciated.
Let's discuss the algorithm here rather than jumping to the answer/code.
Associate a value with each element. The value with any element X will be how many elements from X-1 till 1 have I seen before I encountered X and add 1 to the value because now we have encountered X also.
So since an element of an array is strictly between 1 <= A[i] <= 106 we are in luck.
We make an array for each of the elements, whether they appear in the array or not. This kind of approach is similar to Hash Table
but since all our elements are integers, we are using an array as a simple hash table where key is the index of the array and value is the hash_table[index] i.e.. the value stores in the index.
Now lets dry run our approach for one of our sample inputs :
5 1 5 6 2 3 8 7 4
Initiall the hash-table looks like this :
hash_table = {0,0,0,0,0,0,0,0,0}; // Not showing indices > 8 because they won't be affected.
Now we encounter 5 :
We look up the value of hash_table[4] and add 1 and put it as the value of 5 i.e. hash_table[5] = hash_table[4] + 1
So hash table looks like this now :
hash_table = {0,0,0,0,0,1,0,0,0};
Then we encounter 1 : we do the same thing :
hash_table = {0,1,0,0,0,1,0,0,0};
Like that after taking in all the numbers hash_table looks like this :
hash_table = {0,1,2,3,4,1,2,3,1}
Our answer is the maximum value of the hash_table, which is 4.
Talk is cheap show me the code :
#include <stdio.h>
#define MAX (int)1e6
int h[MAX];
int main ()
{
int N,i,max=0,temp;
scanf ("%d",&N);
for (i=0;i<N;i++)
{
scanf ("%d",&temp);
h[temp] = h[temp - 1] + 1;
if (h[temp] > max)
max = h[temp];
}
printf ("%d\n",max);
return 0;
}
So what if you can't upvote. You can still accept this answer if you found it useful !
You are thinking a bit too complicated. You just have to iterate through the array once and count the lenght of sequences and remeber the longest one :
int main() {
int size;
int input[100000];
/* ... get your input with size elements ... */
int current = 1;
int biggest = 1;
for (int i=1;i<size;i++) {
if (input[i] == input[i-1] + 1) { current++; }
else {
if (current > biggest) { biggest = current; }
current = 1;
}
}
}
I'm making a program to sum a digits, Have a look into this program:
#include<iostream>
using namespace std;
int main(){
int i, j;
int sum=1;
cout<<"Enter your sum: "<<endl;
cin>>i;
while(i>0){
j=i%10;
sum=sum+j;
i=i/10;
}
cout<<"Sum: "<<sum;
cout<<endl;
}
So, as I type into output as 25 it'll give me as an output 7.
But I want to make it in a single digit of every sum, let's say as I type 147. It gives me an output 10 but I want 1 as an output.
I know it could be done as:
while(i>0){
j=i%10;
sum=sum+j;
i=i/10;
}
cout<<"Sum: "<<sum/10;
and surely it'll give me an output as 1.
But as I type a number 185 it gives me an output 1.. But I want the whole sum of digit.
I want that program into which if i type 185
Output must suppose to be as
1+8+5=14
1+4=5
And output must be 5.. So please help me to resolve this kind of issue.
What you describe is called a digital root. Interestingly enough, it can be computed by simply determining the remainder when dividing by 9 - whereas 0 is substituted by 9.
unsigned digitalRoot(unsigned i)
{
return 1 + (i-1)%9; // if i%9==0, (i-1)%9==8 and adding 1 yields 9
}
digitalRoot(185) is 5 since 185 = 9*20 + 5.
as I type into output as 25 it'll give me as an output 7.
No, it is actually 8 (demo). The problem is that you initialize sum to 1 instead of 0.
As far as making the sum a single digit goes, add another loop to your program:
for (;;) { // Loop until the break is reached
while(i>0){
j=i%10;
sum=sum+j;
i=i/10;
}
if (sum < 10) break; // It's single digit
i = sum;
sum = 0;
}
You can try this:
while(i>0){
j=i%10;
sum=sum+j;
i=i/10;
if (i == 0 && sum >= 10) // if all the digits of previous number is processed and sum is not a single digit
{
i = sum;
sum = 0;
}
}
Note that there is no nested loop!
Do not forget to initialize sum to 0 instead of 1.
import java.util.*;
public class SingleDigit
{
public static void main(String[] args)
{
int number = 0, temp = 0, result = 0;
Scanner inp = new Scanner(System.in);
System.out.print("Enter the Number :");
number = inp.nextInt();
temp = number;
while(temp>0)
{
result = result + (temp%10);
temp = temp/10;
if(result > 9)
result = (result % 10)+(result / 10);
}
System.out.println("Single Digit Number for the Number "+number+" is :" result);
System.out.println("Thank You KING....");
}
}