Minimum Length Word in a string (C++) - c++

Given a string S (that can contain multiple words), you need to find the word which has minimum length.
Note : If multiple words are of same length, then answer will be first minimum length word in the string.
Words are separated by single space only.
Input Format :
String S
Output Format :
Minimum length word
Constraints :
1 <= Length of String S <= 10^5
Sample Input 1 :
this is test string
Sample Output 1 :
is
Sample Input 2 :
abc de ghihjk a uvw h j
Sample Output 2 :
a
Please check what is wrong. There is nothing coming in the output.
Here is the code:
/* input - Input String
* output - Save the result in the output array (passed as argument). You don’t have to
* print or return the result
*/
int length(char input[], int si, int ei){
int len = 0;
for(int i = si; i <= ei; i++){
len++;
}
return len;
}
char getString(char input[], int index){
return input[index];
}
void minLengthWord(char input[], char output[]){
int prev = -1;
int i = 0;
int minLength = 0, len = 0;
int si, ei;
for(; input[i] != '\0'; i++){
if(input[i] == ' '){
int len = length(input, prev + 1, i - 1);
if(len > minLength){
minLength = len;
si = prev + 1;
ei = i - 1;
}
prev = i;
}
}
length(input, prev + 1, i - 1);
if(len > minLength){
minLength = len;
si = prev + 1;
ei = i - 1;
}
for(int i = 0; i < minLength; i++){
output[i] = getString(input, si + i);
}
// Write your code here
}

In fact it is an assignment on testing the knowledge of standard C string functions.
The code shown in the question does not make sense.
For example within the function length
int length(char input[], int si, int ei){
int len = 0;
for(int i = si; i <= ei; i++){
len++;
}
return len;
}
the parameter input is not used. The loop within the function is redundant. The function could be defined simpler like
int length( int si, int ei )
{
return ei - si + 1;
}
Or in the function minLengthWord this if statement
if(len > minLength){
minLength = len;
determines the maximum length of the word instead of the minimum length.
The best approach to define the function is to define it such a way when it returns the position and the length of the minimum word in the given string. Having such an information you always can easily extract the minimum word if it will be required.
Here is a demonstrative program.
#include <iostream>
#include <utility>
#include <cstring>
std::pair<size_t, size_t> minimum_word( const char *s, const char *delim = " \t" )
{
std::pair<size_t, size_t> min = { 0, 0 };
size_t i = 0;
while ( *( s + i ) )
{
i += std::strspn( s + i, delim );
if ( *( s + i ) )
{
size_t n = std::strcspn( s + i, delim );
if ( min.second == 0 || n < min.second )
{
min.first = i;
min.second = n;
}
i += n;
}
}
if ( min.second == 0 ) min.first = i;
return min;
}
int main()
{
const char *s = "Hello John Bradely";
auto min = minimum_word( s );
std::cout << "The minimum word is ";
std::cout.write( s + min.first, min.second ) << '\n';
return 0;
}
The program output is
The minimum word is John
It is easy to change the shown function such a way that it will return a dynamically created array where the minimum word will be copied.
#include <iostream>
#include <utility>
#include <cstring>
char * minimum_word( const char *s, const char *delim = " \t" )
{
std::pair<size_t, size_t> min = { 0, 0 };
size_t i = 0;
while ( *( s + i ) )
{
i += std::strspn( s + i, delim );
if ( *( s + i ) )
{
size_t n = std::strcspn( s + i, delim );
if ( min.second == 0 || n < min.second )
{
min.first = i;
min.second = n;
}
i += n;
}
}
if ( min.second == 0 ) min.first = i;
char *word = new char[min.second + 1]();
std::memcpy( word, s + min.first, min.second );
return word;
}
int main()
{
const char *s = "Hello John Bradely";
char *word = minimum_word( s );
std::cout << "The minimum word is " << word << '\n';
delete [] word;
return 0;
}
The program output is
The minimum word is John

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
void minLengthWord(char input[], char output[]){
int n=strlen(input);
int mini=INT_MAX;
int start=-1;
int cnt=0;
for(int i=0;i<=n;i++){
if(input[i]!=' ' && i!=n){
cnt++;
}
else if(cnt<mini||(i==n &&cnt<mini)){
mini=cnt;
start=i-mini;
cnt=0;
}
else{
cnt=0;
}
}
for(int i=0;i<mini;i++){
output[i]=input[i+start];
}
}
int main(){
char ch[10000], output[10000];
cin.getline(ch, 10000);
minLengthWord(ch, output);
cout << output << endl;
}

Related

how to removing rubbish data(garbage data) from output in c++?

Well, I have to Create class to Insert String in another one at the specific position Without using class string(any pre-made classes except iostream.
When I ask for output it gets rubbish data..
#include "stdafx.h"
#include <iostream>
using namespace std;enter code here
//StrLen Calculates String Length
int StrLen(char *s) {
int len = 0;
while (s[len]!='\0'){
len++;
}
return len;
}
//The value of the string that is it's first argument is inserted into String that is it's second argument, pos is the beginning at position given by main.
char *InsertStr(char *s1, char *s2, int pos) {
int c = 0;
int len1 = StrLen(s1);
int len2 = StrLen(s2);
char s3[100];
int i = pos;
//This while move string from postion till the end of string to s3
while (s1[i] != '\0') {
s3[c] = s1[i];
c++;
i++;
}
c = 0;
i = pos;
//the string in s2[0 to the end of s2] moved to s1[from pos to len1]
while (s2[c] != '\0') {
s1[i] = s2[c];
c++;
i++;
}
int len3 = StrLen(s3);
len1 = StrLen(s1);
int x2 = len1 + len3;
c = 0;
len1 = StrLen(s1);
int x3 = pos + len2;
//this loop get the elements sent to s3 and get them back to
//s1[from pos + len2 till s3[i] reach the end]
for (int i = 0; i < len3; i++) {
s1[x3] = s3[i];
x3++;
}
return s1;
}
int main()
{
char s1[100];
char s2[100];
int pos=0;
cout << "Enter The First Argument String : \n";
cin.getline(s1, 100);
cout << "Enter The Second Argument String : \n";
cin.getline(s2, 100);
cout << "Enter The Position : \n";
cin >> pos;
cout << InsertStr(s1, s2, pos);
cout << "******************";
return 0;
}
I used In cin.getline(), to get all string till '\0'.
I traced the code all loops works fine except last one, Last one have garbage data.
I saw a video on youtube solved it like this but i couldn't trace it..
//This code is a working one, But i didn't use it since i couldn't trace it
#include "stdafx.h"
#include <iostream>
using namespace std;
int strlen(char *s)
{
int c = 0;
while (s[c] != '\0') c++;
return c;
}
char* my_strncat(char *s1, char *s2, int pos)
{
//k= pos
int len1, len2;
int i = 0, k = pos,l=0,j=0;
int x,x1, x2, x3;
len1 = strlen(s1);
len2 = strlen(s2);
char s3[100];
while (i <= len1) {
s3[i] = s1[i];
i++;
}
//x2=len2 j =len1
x1 = len1 + len2;
x3 = len2 + pos;
for (i = pos; i < x1; i++) {
x = s3[i];
if (l < len2) {
s1[i] = s2[l];
l++;
}
s1[x3] = x;
x3++;
}
return s1;
}
int main()
{
char s1[100] ;
char s2[100] ;
int pos = 0;
cout << "Enter The string of Source: \n";
cin.getline(s1,100);
cout << "Enter The string of Destination: \n";
cin.getline(s2, 100);
cout << "Enter The position of Destination: \n";
cin >> pos;
cout << my_strncat(s1, s2, pos) << endl;
return 0;
}
I cannot reproduce your garbage data but I see that you, in InsertStr() systematically forget, to add the zero at the end of strings. Your code goes in UB (Undefined Behaviour) so your garbage data a perfectly explained.
So, copying s1 in s3
while (s1[i] != '\0') {
s3[c] = s1[i];
c++;
i++;
}
s3[c] = '\0'; // add this line!
Copying s2 to s1+pos
while (s2[c] != '\0') {
s1[i] = s2[c];
c++;
i++;
}
s1[i] = '\0'; // add this line!
And copying the last part of s3 at the end of s1
for (int i = 0; i < len3; i++) {
s1[x3] = s3[i];
x3++;
}
s1[x3] = '\0'; // add this line!
Or, maybe, you can simply write your loops, using do/while, as follows
do
s3[c++] = s1[i];
while ( s1[i++] );
// ...
do
s1[i++] = s2[c];
while ( s2[c++] );
// ...
i = 0;
do
s1[x3++] = s3[i];
while ( s3[i++] );

Splitting char array into other arrays for using it later and ignoring numbers c++

So I have this assignment where you have to reposition letters in a char array by given number of repositions. The last letter must become first. For example:
Input: Hello 3
Output: lloHe
But if you have a sentence, you have to do it for each word seperately and, what is more, if there are numbers, you must ignore them. So I have trouble dealing with the check for numbers and dealing with seperate words(I use strtok to split them). This is what I have so far:
#include <iostream>
#include <cstring>
using namespace std;
void Reposition(char text[10000], int n, char result[10000])
{
int startIndex = strlen(text)-1;
int k = n-1;
int currentIndex = 0;
for(int i = 0; i < n; i++)
{
result[k] = text[startIndex];
k--;
startIndex--;
currentIndex++;
}
for(int i = 0; i <= startIndex; i++)
{
result[currentIndex] = text[i];
currentIndex++;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char *words;
words = strtok(text, " .,");
while(words != NULL)
{
Reposition(text, n, result);
words = strtok(NULL, " .,");
}
for(unsigned i = 0; i <= strlen(result); i++)
cout << result[i];
return 0;
}
Use std::string instead of C-style string
To remove numbers from a string, use std::remove_if from <algorithm>:
std::string s;
. . .
s.erase(std::remove_if(s.begin(), s.end(), ::isdigit), s.end());
To reposition characters in a string, use std::rotate:
std::rotate(s.begin(), s.begin() + 1, s.end());
I did your homework.
Don't know if you are familiar with all this code.
I Also rewrote your reposition code. It looked very messy.....
One time favour from me. Try to learn something from this.
#include <iostream>
#include <cstring>
#include <ctype.h>
using namespace std;
void Reposition(char * text, int len, int n, char * result)
{
int k = n - 1;
for(int i = 0; i < len; i++)
{
result[i] = text[k++];
if(k == len) k = 0;
}
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
char * word;
char * beginOfWord = text;
char * resultPointer = result;
int wordLen;
while(* beginOfWord)
{
// copy up to somthing from the alphabet
if(!isalpha(* beginOfWord))
{
*resultPointer++ = * beginOfWord++;
continue;
}
// Find the end of this word
word = strpbrk(beginOfWord, " .,0123456789");
if(word != NULL)
{
// len is distance between end of word and begin of word
wordLen = word - beginOfWord;
}
else
{
// Maybe it is the end of the string
wordLen = strlen(beginOfWord);
}
//reposition the word
Reposition(beginOfWord, wordLen, n, resultPointer);
// Move the pointers beyond the word
beginOfWord += wordLen;
resultPointer += wordLen;
}
//Always terminate
*resultPointer ='\x0';
cout << result;
return 0;
}
//reverse will reverse the string starting at position xn and ending at position (yn-1)
void reverse(char *str, int xn, int yn)
{
//positioning the pointers appropriately
char *start = str + xn;
char *end = str + yn - 1;
char temp;
while(start < end)
{
temp = *start;
*start = *end;
*end = temp;
++start;
--end;
}
}
//one of the logic to reposition
void reposition(char *str, int n)
{
int length = strlen(str);
n = (length > n) ? n : (n % length);
reverse(str, 0, n);
reverse(str, n, length);
reverse(str, 0, length);
}
int main()
{
char text[10000];
cin.getline(text,10000);
int n;
cin >> n;
char result[10000];
strcpy(result, text);
cout << "before: " << result << endl;
char *word;
word = strtok(text, " .,");
while(word != NULL)
{
//check if it is not a number
if(isdigit(word[0]) == 0)
{
reposition(word, n);
//find the word postion in text
int word_position = word - text;
//copy the repositioned word in result at its corresponding position.
int i = 0;
while(word[i])
{
result[word_position + i] = word[i];
++i;
}
}
word = strtok(NULL, " .,");
}
cout << "after : " << result << endl;
return 0;
}
Output:
abcd 345 pqrst 321
3
before: abcd 345 pqrst 321
after : dabc 345 stpqr 321

Vinegere Cipher with C++ having an issue with output

I am having some issues trying to get my code to work. It prints ALMOST the right data but maybe it isn't looping correctly? I don't think it repeats the key through the alphabet. It's all lowercase and doesn't exceed 26.
void vigenereEncrypt( const char plaintext[], char ciphertext[], const char key[] )
{
int idx;
int j;
for( idx = 0, j = 0; idx <= strlen(plaintext); idx++ )
{
if ( CHAR_OUT_OF_RANGE(plaintext[idx]) )
{
ciphertext[idx] = plaintext[idx];
}
else
{
ciphertext[idx] = plaintext[idx];
ciphertext[idx] += key[j] - MIN_ASCII_VALUE;
if (ciphertext[idx] >= MAX_ASCII_VALUE) ciphertext[idx] += -MAX_ASCII_VALUE + MIN_ASCII_VALUE - 1;
}
j = (j + 1) % strlen(key);
}
ciphertext[idx] = 0;
}
for instance: if I enter the plaintext toner with a key of jerry the output will be csevé. It should change it to csevp
Do everybody (especially yourself) a favor, and use std::string instead of C-style strings. Then use a standard algorithm instead of writing messing up the loops on your own.
#include <iostream>
#include <iterator>
#include <algorithm>
class crypt {
std::string key;
size_t pos;
public:
crypt(std::string const &k) : key(k), pos(0) { }
char operator()(char input) {
char ret = input ^ key[pos];
pos = (pos + 1) % key.size();
return ret;
}
};
int main() {
std::string input("This is some input to be encrypted by the crappy encryption algorithm.");
std::transform(input.begin(), input.end(),
std::ostream_iterator<char>(std::cout),
crypt("This is the key"));
return 0;
}
Your loop is going one-to-far. You should use < instead of <=. And I assume you should be testing for > MAX_ASCII_VALUE, not >= (but you haven't shown what MAX_ASCII_VALUE is).
But your basic problem is a signed vs. unsigned char problem. With signed chars, when it goes above 127 it wraps around and becomes negative, so the > test will fail when it should have passed.
void vigenereEncrypt(const char plaintext[], char ciphertext[], const char key[])
{
size_t i, j;
for(i = 0, j = 0; i < strlen(plaintext); ++i )
{
ciphertext[i] = plaintext[i];
if (!CHAR_OUT_OF_RANGE(plaintext[i]))
{
ciphertext[i] += (uchar)key[j] - (uchar)MIN_ASCII_VALUE;
if ((uchar)ciphertext[i] > (uchar)MAX_ASCII_VALUE)
ciphertext[i] -= (uchar)MAX_ASCII_VALUE - (uchar)MIN_ASCII_VALUE + 1;
}
j = (j + 1) % strlen(key);
}
ciphertext[i] = 0;
}

Reverse n characters in the string (there is no spaces in string) without using built-in functions in c++

I have a string like str="ABCDEFGHIJK";
need o/p like this str="CBAFEDIHGJK"
am getting "CBA" correctly after that its not printing anything.
can anyone check the following code and let me know where is the problem?
int main()
{
string str="ABCDEFGHIJK";
char str1[10],rev[10];
int n=str.length(),count=0,c=3,k=0,j=0;
for(int i=0;i<n;i++)
{
str1[i]=str[i];
count++;
cout<<str1[i]<<" and "<<count<<"and "<<c<<endl;
if(count==c)
{
cout<<"Entered into if loop"<<count<<"and"<<c<<"and "<<k<<endl;
cout<<c<<" and "<<k<<endl;
while(j<c)
{
rev[j]=str1[c-k-1];
cout<<rev[j]<<" and "<<str1[c-k-1]<<endl;
j++;
k++;
}
count=0;
}
/*else
{
if(count < c && str[i]=='\0')
{
for(int k=0;k<count;k++)
{
rev[k]=str1[count-1];
count--;
count=0;
}
}
}*/
}
cout<<"The string is: "<<rev<<endl;
return 0;
}
Please help me on this.
No need to use a c++ string object for this use-case; just use a normal char *.
Also, always make sure you store enough room for the string null-terminator character ('\0'). This is required as c string functions assume your string is terminated in this way.
Following will reverse string in ansi C89
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse(char *in, char *rev)
{
int i, n;
n = strlen(in);
for(i = n-1; i>=0; i--)
{
rev[n-i-1] = in[i];
}
/* add the null-terminator */
rev[n] = '\0';
}
int main()
{
char *str = "ABCDEFGHIJK";
char str1[12], temp;
char triplet[4];
char rev_triplet[4];
int index;
triplet[3] = '\0';
rev_triplet[3] = '\0';
str1[0] = '\0';
for(index = 0; index < strlen(str); index += 3)
{
memcpy(triplet, str + index, 3 * sizeof(char));
reverse(triplet, rev_triplet);
strcat(str1, rev_triplet);
}
printf("Initial string is: %s\n", str);
printf("Reverse string is: %s\n", str1);
return 0;
}
Outputs
$ ./test
Initial string is: ABCDEFGHIJK
Reverse string is: CBAFEDIHGKJ
If you intend to use C++ (and not C) for this:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_triples(std::string s)
{
const unsigned int N = 3;
for (int i = 0, j = N - 1; i < s.length() - (s.length() % N); i += N, j += N)
{
std::swap(s[i], s[j]);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s);
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
Whatever value of N you need can be modified (and even supplied as a function parameter if you want). You only need to swap the outer characters (so all the elements below N / 2 will be swapped with the elements above N / 2). For N == 3, it is just a single swap. If you want to do it more generically:
#include <algorithm>
#include <iostream>
#include <string>
std::string reverse_substrings(std::string s, unsigned int substring_size)
{
for (int i = 0, j = substring_size - 1; i < s.length() - (s.length() % substring_size); i += substring_size, j += substring_size)
{
std::reverse(s.begin() + i, s.begin() + j + 1);
}
return s;
}
int main()
{
std::string s = "ABCDEFGHIJK";
std::string rs = reverse_triples(s, 4); // passing 3 gets you the same results as before
std::cout << "Reversed Triples: " << rs << std::endl;
return 0;
}
First, let us examine how std::reverse might be implemented. It uses iterators.
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
We can extend the logic to use indices instead of iterators, where i and j represent iterators (positions) and s[i] and s[j] represent the data pointed to by the iterators.
void reverse(std::string& s)
{
int i = 0;
int j = s.size();
while ((i != j) && (i != (--j)))
{
std::swap(s[i], s[j]);
++i;
}
}
Now you want to reverse "chunks" rather than the entire string.
void reverse(int n, std::string& s)
{
int beg = 0;
int end = beg + n;
int size = s.size();
// We're going to modify s in place
// So store a copy
std::string copy = s;
s = "";
// Add + 1 to avoid the loop cutting off short
// Or do i <= size / n;
for (int i = 0; i < size / n + 1; i++)
{
std::string chunk(copy.begin() + beg, copy.begin() + end);
// If there's no n sized chunks left
// don't reverse
if (end < size)
reverse(chunk);
s += chunk;
beg += n;
// Don't go past the size of the string
end += (end + n > size ? size - end : n);
}
}
int main()
{
std::string s("ABCDEFGHIJK");
std::string target("CBAFEDIHGJK");
reverse(3, s);
std::cout << s << "|" << target <<"|\n";
std::cout << s.size() << " " << target.size() << "\n"; // 11 11
std::cout << std::boolalpha << (s == target); // true
return 0;
}

how to check whether 2 strings are rotations to each other ?

Given 2 strings, design a function that can check whether they are rotations to each other without making any changes on them ? The return value is boolean.
e.g ABCD, ABDC, they are not rotations. return false
ABCD, CDAB or DABC are rotations. return true.
My solution:
shift one of them to right or left one position and then compare them at each iteration.
If they are not equal at all iterations, return false. Otherwise, return true.
It is O(n). Are there other more efficient solutions ?
What if the contents of them cannot be changed ?
thanks
Concatenate the given string with the given string.
Search for the target string in the concatenated string.
Example:
Given = CDAB
After step 1, Concatenated = CDABCDAB
After step 2, Success CDABCDAB
^^^^
Rather than shifting one of them, it might be more efficient to use two index variables. Start one at 0 each time and the other at each of the possible positions (0 to N-1) and increment it mod N.
If you can't modify the strings, just take the first character of string1 and compare it to each character of string2. When you get a match, compare the second char of string1 to the next char of string2, and so on.
Pseudocode:
len = strlen(string1);
len2 = strlen(string2);
if( len != len2 )
printf("Nope.");
for( int i2=0; i2 < len; i2++ ) {
for( int i1=0; i1<len; i1++ ) {
if( string1[i1] != string2[(i2+i1)%len] )
break;
}
if( i1 == len ) {
print("Yup.");
break;
}
}
A simple one would be:
(s1+s1).find(s2) != string::npos && s1.size() == s2.size();
#include <iostream>
#include <cstring>
#include<string>
using namespace std;
void CompareString(string, string, int);
int ComputeStringLength(string str);
int main()
{
string str = ""; string str1 = ""; int len = 0, len1 = 0;
cout << "\nenter string ";
cin >> str;
cout << "\nenter string 2 to compare:- ";
cin >> str1;
len = ComputeStringLength(str);
len1 = ComputeStringLength(str1);
if (len == len1)
CompareString(str, str1, len);
else
cout << "rotation not possible";
getchar();
return 0;
}
int ComputeStringLength(string str)
{
int len = 0;
for (int i = 0; str[i] != '\0'; i++)
{
len++;
}
return len;
}
void CompareString(string str, string str1, int n)
{
int index = 0, flag = 0, curr_index = 0, count1 = 0, flagj = 0;
for (int i = 0; i<n; i++)
{
for (int j = flagj; j<n; j++)
{
if (str[i] == str1[j])
{
index = j;
flagj =j;
count1++;
flag++;
if (flag == 1)
{
curr_index = index;
}
break;
}
}
}
int temp = count1;
if (count1 != n)
{
if (curr_index>=0)
{
int k = 0;
for (int i = n - 1; i>n - curr_index - 1; i--)
{
if (str[i] == str1[k])
{
temp++;
k++;
}
}
}
if (temp == n)
{
cout << "\n\nstring is same after rotation";
}
else
{
cout << "\n\nstring is not same after rotation";
}
}
else
{
cout << "\n\nstring is same after rotation";
}
}
https://dsconceptuals.blogspot.in/2016/10/a-program-to-check-if-strings-are.html