find the number of times a character occurs between two indexes - c++

I was given an input string, which is formed of N number of repetitions of a base string.
I need to find the occurrence of 'b' between two index points.
string mystr="ababba"
number of repetitions = 1000 ,
find occurrence of 'b' between two indexes, say 120 and 250.
I cannot use brute force where I increment my way upto 120 and then count the number of 'b' till the end index, this times out for large input string.
I have calculated and stored the occurrence of b in the the string of 6 character "ababba" as 3.
how do I proceed?
for( auto& each : mystr)
{
if (each == 'b')
cntb++;
}

try this:
#include <iostream>
#include <cstring>
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
int main()
{
char inputString[11];
int b_in_string, b_occurrence, repetitions, startIndex, endIndex, actual_needed_count;
cout<<"Input string: ";
cin>>inputString;
cout<<"Repetitions: ";
cin>>repetitions;
cout<<"Start index: ";
cin>>startIndex;
cout<<"End index: ";
cin>>endIndex;
if(endIndex < startIndex)
{
cout<<"End index must be larger than start index. Program terminated.";
return 1;
}
b_in_string = 0;
b_occurrence = 0;
for(int i = 0; i < sizeof(inputString); i++)
{
if(inputString[i] == 'b')
{
b_in_string++;
}
}
actual_needed_count = endIndex - startIndex + 1; //start and end indexes inclusive
b_occurrence = b_in_string * actual_needed_count;
cout<<"Number of times 'b' occurs: ";
cout<<b_occurrence;
return 0;
}
It works on https://www.onlinegdb.com/online_c++_compiler. Hope it helps.

Related

Finding the largest three-digits number "within" a number

For this question, I need to find the largest three-digit number within a larger number.
Sample Test Case 1: 534535 Output: 535
Sample Test Case 2 : 23457888976 Output : 976
I've tried the following code:
#include <iostream>
using namespace std;
int main() {
int num;
cin>>num;
int len= to_string(num).length();
int arr[10],lnum=0,max=0;
for (int i =len-1;i>=0;i--)
{
arr[i] = num%10;
num =num/10; //to convert int into array
}
for (int i=0;i<len-2;i++)
{
if (arr[i] >arr[i+1])
lnum = arr[i]*100+arr[i+1]*10+arr[i];
if (lnum>max)
max= lnum;
}
cout<<max;
return 0;
}
Although this code seems to work for Test Case 1, it doesn't work for most of the inputs.
(Please do help with this too. )
1. This is for numbers with 10-digits only (that too, most of it have wrong output). What to do in case of bigger numbers?
2. Is there any better way to convert the integer into an array? Or will a string array work in similar way?
3. It's really slow, can anyone help me figure out how to speed this up?
Thanks for any help !!
#include <iostream>
#include <string>
using namespace std;
int main() {
int i, n;
string s;
cin >> s;
n = (int)s.size();
if(n<3){
/* there are less than 3 digits in the input number
Here, you can print the number itself as it will be largest number or
print -1 which can state that no 3 digit number exists.
*/
cout<<-1;
return 0;
}
int maxans = (s[0]-'0')*100 + (s[1]-'0')*10 + (s[2]-'0');
// storing the first 3 digits as the maximum answer till now.
int prev = maxans;
for(i = 3;i<n;i++){
int cur = (prev%100)*10 + (s[i]-'0'); // using %100 to extract the last two digits and then multiplying by 10 and adding the ith digit to make the next 3 digit number.
maxans = max(maxans, cur);
prev = cur;
}
cout<<maxans;
return 0;
}
This code is of time complexity O(n) where n is the length of input string and space complexity O(1)
This approach will work with any big number you can store in variable. The approach is as follows,
First convert number into string and then create an array of all possible numbers of 3 digits as showed below,
Number = 534535
All possible 3 digits number array = ["534", "345", "453", "535"]
Then sort this array, after sorting last element will be max number of three digit, as highlighted below,
Sorted array = ["345", "453", "534", "535"]
Another example,
Number = 23457888976
All possible 3 digits number array = ["234", "345", "457", "578", "788", "888", "889", "897", "976"]
After sorting, last element is max number as highlighted below
Sorted array = ["234", "345", "457", "578", "788", "888", "889", "897", "976"]
Note: Radix sort will perform better then std::sort(), std::sort() offers Quick sort. Radix sort is ideal for string sorting and specially in this case because max bucket size is only 10 (possible range 0-9), but you have to implement radix sort your self.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cout;
std::vector<std::string> allThreeDigitNumbers(const std::string& numStr){
std::vector<std::string> allNumStr(numStr.size() - 2, std::string("000"));
std::vector<std::string>::iterator aIt = allNumStr.begin();
for(std::string::const_iterator it = numStr.cbegin(), lastIt = it + (numStr.size() - 2); lastIt != it; ++it, ++aIt){
std::copy(it, it + 3, aIt->begin());
}
return allNumStr;
}
unsigned maxThreeDigitNumberInNumber(unsigned long long num){
std::string numStr = std::to_string(num);
if(numStr.size() < 3){
return 0;
}
std::vector<std::string> allNumStr = allThreeDigitNumbers(numStr);
std::sort(allNumStr.begin(), allNumStr.end());
return std::stoul(allNumStr.back());
}
int main(){
cout<< "Max 3 digits number of 534535 => "<< maxThreeDigitNumberInNumber(534535)<< '\n';
cout<< "max 3 digits number of 23457888976 => "<< maxThreeDigitNumberInNumber(23457888976)<< '\n';
}
Output
Max 3 digits number of 534535 => 535
max 3 digits number of 23457888976 => 976
Read the comments to understand the code below:
#include <assert.h>
#include <iostream>
#include <boost/hana/functional/partial.hpp>
#include <functional>
#include <range/v3/to_container.hpp>
#include <range/v3/view/all.hpp>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/algorithm/all_of.hpp>
#include <string>
using namespace boost::hana;
using namespace ranges;
using namespace ranges::views;
auto constexpr is9 = partial(std::equal_to<>{}, 9);
template<typename Range>
Range fun(Range const& r) {
if (r.size() == 3) { // 3 digits only?
return r; // this is the result
} else if (all_of(r | take(3), is9)) { // 999?
return r | take(3); // nothing better than this!
} else { // otherwise?
auto tail = r | drop(1); // drop the first to get the tail
if (r.front() < tail.front()) { // if the first is less the the tip of the tail
return fun(tail); // then let the first go and recurse on the tail
} else { // otherwise
auto result = std::max( // get the maximum between
r | take(3) | to<std::string>, // the current first three
fun(tail) | to<std::string> // and the result of recursing on the tail
);
return result; // and that's the result
}
}
return r;
}
int main() {
std::string s1 = "534535";
std::string s2 = "23457888976";
assert((fun(subrange(s1)) | to<std::string>) == std::string{"535"});
assert((fun(subrange(s2)) | to<std::string>) == std::string{"976"});
}
The number is treated as a string, and since we need to compare (sub-)strings of length 3, the lexicographic operator< for std::strings gives us the same result as the arithmetic operator< would give for the two corresponding numbers.
The logic is:
we start from left and recurse to the right if needed
in the case of only 3 digits left, r.size() == 3, we return all of them, return r;
in the case of three leading nines, all_of(r | take(3), is9), we trivially return those three, return r | take(3);;
otherwise, we take the std::max between the leading 3-digit string, r | take(3) | to<std::string>, and the std::string we obtain by recursing on the rest of the sequence without the first digit, fun(tail) | to<std::string>.
Solution in Python3
#!/usr/bin/env python
num = input("Enter the number : ")
if len(num) == 3:
print(f"Largest digit is : {num}")
exit(0)
elif len(num) < 3:
print(-1)
exit(0)
maxans = int((num[0].replace("0", "")))*100 + int((num[1].replace("0", "")))*10 + int((num[2].replace("0", "")))
prev = maxans
for i in range(3, 6):
cur = (prev%100)*10 + int((num[i].replace("0", "")))
maxans = max(maxans, cur)
prev = cur
print(f"The Largest num = : {maxans}")

Count the number of occurrences of all the digits in the string S.?

output format: string = 7714
0 0
1 1
2 0
3 0 .....
7 2 and so on till digit 9. Note: there will be new line after each digit occurence value. Alongside each digits same occurence is showing up which is 15 or 20 or 25.
#include <iostream>
using namespace std;
int main()
{
string s;
cin>>s;
int i,j;
int c=0;
int a;
int l=s.length();
for(i=0;i<l;i++)
{
cin>>s[i];
}
for(i=0;i<l;i++)
{
for(j=0;j<=9;j++)
{
if(s[j]==1 || s[j]==2 || s[j]==3 || s[j]==4 || s[j]==5 || s[j]==6 || s[j]==7 || s[j]==8 || s[j]==9 || s[j]==0)
{
c++;
}
}
}
for(i=0;i<=9;i++)
{
cout<<i<<" "<<c<<endl;
}
}
Since after one day all the comments and answers so far obviously could not help you, see the following simple solution.
The exercise targets people starting with C++, so I suppose it is better to use basic constructs like arrays and loops.
The array counts holds the counts of the digits, one for each possible digit; so the size of the array is 10. Note that the characters in the string are not integral digits from 0..9, but characters in (very likely) ASCII code from 48..57. The ASCII-code of character '0' is integral value 48, not integral value 0. So to get a range from 0..9, one has to substract 48 (or '0', which is the same as integral 48) from the respective character.
Hope it helps.
#include <iostream>
#include <string>
int main() {
std::string s = "7714";
int counts[10] = { 0 }; // init all the counters with 0
for (int i=0; i<s.length();i++) { // iterate over the characters in s
char c = s[i];
if (isdigit(c)) {
int index = c - '0'; // c is from '0' to '9' (i.e. ASCII codes 48..57); need it from 0..9; char('0') stands for int(49).
counts[index]++; // increment the counter representing the respective digit
} else {
std::cout << "invalid character (not a digit) in s" << std::endl;
}
}
for (int i=0; i<9; i++) {
std::cout << i << ": " << counts[i] << std::endl;
}
}
Output:
0: 0
1: 1
2: 0
3: 0
4: 1
5: 0
6: 0
7: 2
8: 0
The power of algorithms . . .
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
// Get String from user
std::string s; std::cin >> s;
// This is what we want to search
std::string digits("0123456789");
// Do all the work in a one liner
std::for_each(digits.begin(), digits.end(), [&s](const char c) { std::cout << c << ' ' << std::count(s.begin(), s.end(), c) << '\n'; });
return 0;
}
Create an array of counters.
int counters[10]; //will store the counts of each instance.
//counters[0] will count the number of 0s, etc.
Convert each input character to integer.
look up how to do this on the internet.
Increment that index of counters array.
counters[the_converted_character_to_integer]++;

Is this a good way to break out of the while loop if there is not substring?

I'm working on this small code. It is giving the right output but I think the loop that I have on it could be improved.
Question 1: Given a string A consisting of n characters, and a string B consisting of m characters, write a function that will return the number of times A must be stated such that B is a substring of the repeated A. If B can never be a substring, return -1.
Example:
A = "abcd"
B = "cdabcdab"
The function should return 3 because after stating A 3 times, getting "abcdabcdabcd", B is now a substring of A.
You can assume that n and m are integers in the range [1, 1000].
This is my code:
#include "pch.h"
#include <iostream>
#include <string>
#include <fstream>
#include <istream>
using namespace std;
int findthestring(string A, string B)
{
string original = B;
int times = 1 ;
if (B.find(A) != string::npos)
{
cout << "String Found\n";
times =1;
}
for (unsigned int i = 0; i < (10 * A.length());i++)
{
cout << "String not Found\n";
B = B + original;
times = times + 1;
if (times>10)
{
return -1;
break;
}
}
return times;
}
int main()
{
int times = findthestring("cdabcdab","abcd");
cout << "Number of Times: " << times;
return 0;
}
On this code, I have the loop run for 10 times, if there is no sub string, then the loop breaks out and returns 1.
Is there a better way to do that?
You could use recursively the method string::find(const std::string& str, size_t pos = 0) while its returned value would be equal to std::string::npos:
#include <iostream>
#include <string>
int findthestring(const std::string& substr, const std::string& str)
{
size_t times = 1;
std::string temp(substr);
while (temp.find(str) == std::string::npos) { // while not found
times++;
if (times > 10) {
return -1;
}
temp += substr; // concatenate string
}
return times;
}
int main()
{
int times = findthestring("abcd", "cdabc");
std::cout << "Number of Times: " << times;
return 0;
}

How to generate nine digits numbers in which each digit differ from the others

I am making a program and I need to generate all 9 digits numbers which have each digit different to the other digits, the 0 is not a valid digit in this case so I am only considering digits from 1 to 9.
So far I have this solution using random number generation, but I am facing performance issues
using namespace std;
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <string>
#include <map>
int main()
{
srand (time(NULL));
int secret;
string number = "";
map <string, bool> m;
int count = 0;
int nine_permutation = 362880;
vector <int> v{0,1,2,3,4,5,6,7,8,9};
int x = 9;
while(count < nine_permutation)
{
for(int i = 0; i < 9; i++)
{
secret = rand() % x +1;
number += to_string(v[secret]);
v.erase(v.begin() + secret);
x--;
}
x = 9;
v = {0,1,2,3,4,5,6,7,8,9};
if(m.count(number) == 0)
{
m[number] = true;
count ++;
}
cout << count << endl;
}
cout << number;
}
So you have 10 digits 0,1,2,3,4,5,6,7,8,9 and number you want to get numbers with nine digits.
I think you can start with 123456789, generate all permutations and then replace each character with '0' which would give set:
{023456789, 103456789, 120456789, 123056789, 123406789, 123450789, 123456089, 123456709, 123456780}. And for each element from this set also generate all permutations.
Something like this:
void allNumbersWithDistinctDigits() {
int idxForZero = 0;
std::string initial("123456789");
std::string local(initial);
do {
while (std::next_permutation(local.begin(), local.end())) {
if (local[0] != '0') {
std::cout << local << std::endl;
}
}
local = initial;
local[idxForZero] = '0';
} while(++idxForZero <= initial.size());
}
Condition if (local[0] != '0') is optional and it gets rid of numbers starting with 0, like: 012345678 which is in fact 8 digits 12345678 or octal number.

How to apply multiple formatting methods at the same time, e.g."1,234,567,890" and "12-3456-7890" to "1,2-34,56-7,890"

for example, if I want to convert "1234567890" to "1,234,567,890", I can use:
#include <string>
#include <stdio.h>
using namespace std;
int main(){
string st="1234567890";
for(int i=st.length()-3;i>0;st.insert(i,","),i-=3);
printf("%s\n",st.c_str());
return 0;
}
and if I want to convert "1234567890" to "12-3456-7890", just replace the for loop as :
for(int i=st.length()-4;i>0;st.insert(i,"-"),i-=4);
but the problem is, it can apply 1 format method only,and this formatting method is sequential, if I apply 2 for loops together, e.g.:
for(int i=st.length()-3;i>0;st.insert(i,","),i-=3);
for(int i=st.length()-4;i>0;st.insert(i,"-"),i-=4);
the output is 1-,234-,567-,890 but not "1,2-34,56-7,890", what is the generic way to do this?
Or in simpler words, I want a program that can:
1. insert "," for every 3 characters
2. insert "-" for every 4 characters
3. insert ":" for every 7 characters
.
.
.
which can add insert conditions in generic way, what is the simplest way to do this?
Instead of using several loops, you can just use one loop, decremental by 1, with conditional insert. For example:
string st="1234567890";
int originalLength = st.length();
for(int i=originalLength-1;i>0;i--)
{
int positionFromEnd = originalLength - i;
if (positionFromEnd % 3 == 0)
st.insert(i,",");
if (positionFromEnd % 4 == 0)
st.insert(i,"-");
if (positionFromEnd % 5 == 0)
st.insert(i,":");
// add more condition here as need be
}
printf("%s\n", st.c_str());
If it's ok for you, ignore anything that is not a number, in each pass:
#include <string>
#include <stdio.h>
using namespace std;
void insert_delimeter(string& st, string delimeter, int interval) {
for (int i = st.length() - 1, counter = 0; i > 0; i--) {
if (st[i] >= '0' && st[i] <= '9')
++counter;
if (counter == interval) {
st.insert(i,delimeter);
counter = 0;
}
}
}
int main(){
string st = "1234567890";
insert_delimeter(st, ",", 3);
insert_delimeter(st, "-", 4);
printf("%s\n", st.c_str());
return 0;
}
The outcome is
1,2-34,56-7,890
add one more counter to the first for loop
int num=0;
for(int i=st.length()-3;i>0;st.insert(i,","),i-=3)
num++;
for(int i=st.length()-4 + num ;i>0;st.insert(i,"-"),i-=4)
num++;
what happens here is num gets incremented everytime an insert takes place thus it helps to get correct string length in the next string update. which you can use to insert more symbols.