Need help understanding a word jumble for loop - c++

This code is part of a program that jumbles a word. I need help understanding how the for loop is working and creating the jumbled word. For example if theWord = "apple" the output would be something like: plpea. So I want to know whats going on in the for loop to make this output.
std::string jumble = theWord;
int length = theWord.size();
for (int i = 0; i < length; i++)
{
int index1 = (rand() % length);
int index2 = (rand() % length);
char temp = jumble[index1];
jumble[index1] = jumble[index2];
jumble[index2] = temp;
}
std::cout << jumble << std::endl;

I'll add comments on each line of the for loop:
for (int i = 0; i < length; i++) // basic for loop syntax. It will execute the same number of times as there are characters in the string
{
int index1 = (rand() % length); // get a random index that is 0 to the length of the string
int index2 = (rand() % length); // Does the same thing, gets a random index
char temp = jumble[index1]; // Gets the character at the random index
jumble[index1] = jumble[index2]; // set the value at the first index to the value at the second
jumble[index2] = temp; // set the value at the second index to the vaue of the first
// The last three lines switch two characters
}
You can think of it like this: For each character in the string, switch two characters in the string.
Also the % (or the modulus operator) just gets the remainder Understanding The Modulus Operator %
It's also important to understand that myString[index] will return whatever character is at that index. Ex: "Hello world"[1] == "e"

Related

How a for loop works without printing

I've seen someone post this same for loop, but my problem is slightly different. Wouldn't the variable temp be changed on each iteration, so just leaving one character that keeps getting changed? How are the characters stored? Also, how does the loop know that rand() won't generate the same number for both index1 and index2? Sorry if this isn't so clear, i'm a bit of a newbie!
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
int main()
{
enum { WORD, HINT, NUM_FIELDS };
const int NUM_WORDS = 3;
const std::string WORDS[NUM_WORDS][NUM_FIELDS] = {
{ "Redfield", "Main Resident Evil character" },
{ "Valentine", "Will you be mine?" },
{ "Jumbled", "These words are..." }
};
srand(static_cast<unsigned int>(time(0)));
int choice = (rand() % NUM_WORDS);
std::string theWord = WORDS[choice][WORD];
std::string theHint = WORDS[choice][HINT];
std::string jumble = theWord;
int length = jumble.size();
for (int i = 0; i < length; ++i) {
int index1 = (rand() % length);
int index2 = (rand() % length);
char temp = jumble[index1];
jumble[index1] = jumble[index2];
jumble[index2] = temp;
}
std::cout << jumble << '\n'; // Why 'jumbled word' instead of just a character?
std::cin.get();
}
Wouldn't the variable temp be changed on each iteration, so just leaving one character that keeps getting changed?
It depends. Notice that you're trying to come up with a new random index1 and a new random index2 in each iteration. What happens if your jumble variable is Redfield, and index1 = 1 and index2 = 5? You would be swapping two e's.
But because in every iteration you're trying to access chars in a random position of your jumble string on positions index1 and index2:
int index1 = (rand() % length);
int index2 = (rand() % length);
The value of those indexes are unpredictable on each iteration. It could happen that you get a 1 and a 5 again.
Nevertheless, remember that you're creating a variable tempin every iteration, thereby you wouldn't be changing its value, you would be assigning a new variable in each iteration.
How are the characters stored?
I'm not sure what do you mean here, but every char is stored within 1 byte. Therefore, a string would be a sequence of bytes (char). This sequence is a contiguous block of memory. Every time you're accessing jumble[index1], you're accessing the char on position index1 within your string jumble.
If jumble = "Valentine" and index1 = 1, then you will be accessing an a, because your V is on position 0.
Also, how does the loop know that rand() won't generate the same number for both index1 and index2?
It doesn't. You would have to come up with a strategy to ensure that this doesn't happen. One approach, but not an efficient one, would be:
int index1 = (rand() % length);
int index2 = (rand() % length);
while (index1 == index2) {
index1 = (rand() % length);
index2 = (rand() % length);
}

In c++, how can I grab the next few characters from a string?

My goal is to grab a specific part of a very large number and concatenate that part with another number, then continue. Since integers only go so high, I have a string of the number. I do NOT know what this number could be, so I can't input it in myself. I can use substr for the first part, but I am stuck shortly after.
An example
"435509590420924949"
I want to take the first 5 characters out, convert to integer, do my own calculation to them, then concatenate them with the rest of the string. So I will take 43550 out, do formula to get 49, then add 49 to another 5 in a row after the original string "95904" so the new answer will be "4995904".
This is my code for the first part I made up,
string temp;
int number;
temp = data.substr(0, 5);
number = atoi(temp.c_str());
This grabs the first first characters in the strings, converts to integers where I can calculate it, but I don't know how to grab the next 5 of the long string.
You can get the length of the string, so something like:
std::size_t startIndex = 0;
std::size_t blockLength = 5;
std::size_t length = data.length();
while(startIndex < length)
{
std::string temp = data.substr(startIndex, blockLength);
// do something with temp
startIndex += blockLength;
// TODO: this will skip the last "block" if it is < blockLength,
// so you need to modify it a bit for this case.
}
You can use loops. For example:
std::size_t subStrSize = 5;
for (std::size_t k = 0; k < data.size(); k+=subStrSize) {
std::size_t h = std::min(k + subStrSize - 1, data.size() - 1);
int number = 0;
for (std::size_t l = k; l <= h; ++l)
number = number * 10 + data[l] - '0';
//-- Some work with number --
}

Insert symbol into string C++

I need to insert symbol '+' into string after its each five symbol.
st - the member of class String of type string
int i = 1;
int original_size = st.size;
int count = 0;
int j;
for (j = 0; j < st.size; j++)
{
if (i % 5)
count++;
}
while (st.size < original_size + count)
{
if (i % 5)
{
st.insert(i + 1, 1, '+');
st.size++;
}
i++;
}
return st;
I got an error in this part of code. I think it is connected with conditions of of the while-cycle. Can you help me please how to do this right?
If I've understood you correctly then you want to insert a '+' character every 5 chars in the original string. One way to do this would be to create a temporary string and then reassign the original string:
std::string st("A test string with some chars");
std::string temp;
for (int i = 1; i <= st.size(); ++i)
{
temp += st[i - 1];
if (i % 5 == 0)
{
temp += '+';
}
}
st = temp;
You'll notice I've started the loop at 1, this is to avoid the '+' being inserted on the first iteration (0%5==0).
#AlexB's answer shows how to generate a new string with the resulting text.
That said, if your problem is to perform in-place insertions your code should look similar to this:
std::string st{ "abcdefghijk" };
for(auto i = 4; i != st.size(); i += 5)
st.insert(i+1, 1, '+'); // insert 1 character = '+' at position i
assert(st == "abcde+fghij+k");
std::string InsertEveryNSymbols(const std::string & st, size_t n, char c)
{
const size_t size(st.size());
std::string result;
result.reserve(size + size / n);
for (size_t i(0); i != size; ++i)
{
result.push_back(st[i]);
if (i % n == n - 1)
result.push_back(c);
}
return result;
}
You don't need a loop to calculate the length of the resulting string. It's going to be simply size + size / 5. And doing multiple inserts makes it a quadratic-complexity algorithm when you can just as easily keep it linear.
Nothing no one else has done, but eliminates the string resizing and the modulus and takes advantage of a few new and fun language features.
std::string temp(st.length() + st.length()/5, '\0');
// preallocate string to eliminate need for resizing.
auto loc = temp.begin(); // iterator for temp string
size_t count = 0;
for (char ch: st) // iterate through source string
{
*loc++ = ch;
if (--count == 0) // decrement and test for zero much faster than
// modulus and test for zero
{
*loc++ = '+';
count = 5; // even with this assignment
}
}
st = temp;

To find the longest substring with equal sum in left and right in C++

I was solving a question, with which I am having some problems:
Complete the function getEqualSumSubstring, which takes a single argument. The single argument is a string s, which contains only non-zero digits.
This function should print the length of longest contiguous substring of s, such that the length of the substring is 2*N digits and the sum of the leftmost N digits is equal to the sum of the rightmost N digits. If there is no such string, your function should print 0.
int getEqualSumSubstring(string s) {
int i=0,j=i,foundLength=0;
for(i=0;i<s.length();i++)
{
for(j=i;j<s.length();j++)
{
int temp = j-i;
if(temp%2==0)
{
int leftSum=0,rightSum=0;
string tempString=s.substr(i,temp);
for(int k=0;k<temp/2;k++)
{
leftSum=leftSum+tempString[k]-'0';
rightSum=rightSum+tempString[k+(temp/2)]-'0';
}
if((leftSum==rightSum)&&(leftSum!=0))
if(s.length()>foundLength)
foundLength=s.length();
}
}
}
return(foundLength);
}
The problem is that this code is working for some samples and not for the others. Since this is an exam type question I don't have the test cases either.
This code works
int getEqualSumSubstring(string s) {
int i=0,j=i,foundLength=0;
for(i=0;i<s.length();i++)
{
for(j=i;j<s.length();j++)
{
int temp = j-i+1;
if(temp%2==0)
{
int leftSum=0,rightSum=0;
string tempString=s.substr(i,temp);
// printf("%d ",tempString.length());
for(int k=0;k<temp/2;k++)
{
leftSum=leftSum+tempString[k]-48;
rightSum=rightSum+tempString[k+(temp/2)]-48;
}
if((leftSum==rightSum)&&(leftSum!=0))
if(tempString.length()>foundLength)
foundLength=tempString.length();
}
}
}
return(foundLength);
}
The temp variable must be j-i+1. Otherwise the case where the whole string is the answer will not be covered. Also, we need to make the change suggested by Scott.
Here's my solution that I can confirm works. The ones above didn't really work for me - they gave me compile errors somehow. I got the same question on InterviewStreet, came up with a bad, incomplete solution that worked for 9/15 of the test cases, so I had to spend some more time coding afterwards.
The idea is that instead of caring about getting the left and right sums (which is what I initially did as well), I will get all the possible substrings out of each half (left and right half) of the given input, sort and append them to two separate lists, and then see if there are any matches.
Why?
Say the strings "423" and "234" have the same sum; if I sorted them, they would both be "234" and thus match. Since these numbers have to be consecutive and equal length, I no longer need to worry about having to add them up as numbers and check.
So, for example, if I'm given 12345678, then on the left side, the for-loop will give me:
[1,12,123,1234,2,23,234,3,34]
And on the right:
[5,56,567,5678,...]
And so forth.
However, I'm only taking substrings of a length of at least 2 into account.
I append each of these substrings, sorted by converting into a character array then converting back into a string, into ArrayLists.
So now that all this is done, the next step is to see if there are identical strings of the same numbers in these two ArrayLists. I simply check each of temp_b's strings against temp_a's first string, then against temp_a's second string, and so forth.
If I get a match (say, "234" and "234"), I'll set the length of those matching substrings as my tempCount (tempCount = 3). I also have another variable called 'count' to keep track of the greatest length of these matching substrings (if this was the first occurrence of a match, then count = 0 is overwritten by tempCount = 3, so count = 3).
As for the odd/even string length with the variable int end, the reason for this is because in the line of code s.length()/2+j, is the length of the input happened to be 11, then:
s.length() = 11
s.length()/2 = 11/5 = 5.5 = 5
So in the for-loop, s.length()/2 + j, where j maxes out at s.length()/2, would become:
5 + 5 = 10
Which falls short of the s.length() that I need to reach for to get the string's last index.
This is because the substring function requires an end index of one greater than what you'd put for something like charAt(i).
Just to demonstrate, an input of "47582139875" will generate the following output:
[47, 457, 4578, 24578, 57, 578, 2578, 58, 258, 28] <-- substrings from left half
[139, 1389, 13789, 135789, 389, 3789, 35789, 789, 5789, 578] <-- substrings from right half
578 <-- the longest one that matched
6 <-- the length of '578' x 2
public static int getEqualSumSubtring(String s){
// run through all possible length combinations of the number string on left and right half
// append sorted versions of these into new ArrayList
ArrayList<String> temp_a = new ArrayList<String>();
ArrayList<String> temp_b = new ArrayList<String>();
int end; // s.length()/2 is an integer that rounds down if length is odd, account for this later
for( int i=0; i<=s.length()/2; i++ ){
for( int j=i; j<=s.length()/2; j++ ){
// only account for substrings with a length of 2 or greater
if( j-i > 1 ){
char[] tempArr1 = s.substring(i,j).toCharArray();
Arrays.sort(tempArr1);
String sorted1 = new String(tempArr1);
temp_a.add(sorted1);
//System.out.println(sorted1);
if( s.length() % 2 == 0 )
end = s.length()/2+j;
else // odd length so we need the extra +1 at the end
end = s.length()/2+j+1;
char[] tempArr2 = s.substring(i+s.length()/2, end).toCharArray();
Arrays.sort(tempArr2);
String sorted2 = new String(tempArr2);
temp_b.add(sorted2);
//System.out.println(sorted2);
}
}
}
// For reference
System.out.println(temp_a);
System.out.println(temp_b);
// If the substrings match, it means they have the same sum
// Keep track of longest substring
int tempCount = 0 ;
int count = 0;
String longestSubstring = "";
for( int i=0; i<temp_a.size(); i++){
for( int j=0; j<temp_b.size(); j++ ){
if( temp_a.get(i).equals(temp_b.get(j)) ){
tempCount = temp_a.get(i).length();
if( tempCount > count ){
count = tempCount;
longestSubstring = temp_a.get(i);
}
}
}
}
System.out.println(longestSubstring);
return count*2;
}
Heres my solution to this question including tests. I've added an extra function just because I feel it makes the solution way easier to read than the solutions above.
#include <string>
#include <iostream>
using namespace std;
int getMaxLenSumSubstring( string s )
{
int N = 0; // The optimal so far...
int leftSum = 0, rightSum=0, strLen=s.size();
int left, right;
for(int i=0;i<strLen/2+1;i++) {
left=(s[i]-int('0')); right=(s[strLen-i-1]-int('0'));
leftSum+=left; rightSum+=right;
if(leftSum==rightSum) N=i+1;
}
return N*2;
}
int getEqualSumSubstring( string s ) {
int maxLen = 0, substrLen, j=1;
for( int i=0;i<s.length();i++ ) {
for( int j=1; j<s.length()-i; j++ ) {
//cout<<"Substring = "<<s.substr(i,j);
substrLen = getMaxLenSumSubstring(s.substr(i,j));
//cout<<", Len ="<<substrLen;
if(substrLen>maxLen) maxLen=substrLen;
}
}
return maxLen;
}
Here are a few tests I ran. Based upon the examples above they seem right.
int main() {
cout<<endl<<"Test 1 :"<<getEqualSumSubstring(string("123231"))<<endl;
cout<<endl<<"Test 2 :"<<getEqualSumSubstring(string("986561517416921217551395112859219257312"))<<endl;
cout<<endl<<"Test 3:"<<getEqualSumSubstring(string("47582139875"))<<endl;
}
Shouldn't the following code use tempString.length() instead of s.length()
if((leftSum==rightSum)&&(leftSum!=0))
if(s.length()>foundLength)
foundLength=s.length();
Below is my code for the question... Thanks !!
public class IntCompl {
public String getEqualSumSubstring_com(String s)
{
int j;
int num=0;
int sum = 0;
int m=s.length();
//calculate String array Length
for (int i=m;i>1;i--)
{
sum = sum + m;
m=m-1;
}
String [] d = new String[sum];
int k=0;
String ans = "NULL";
//Extract strings
for (int i=0;i<s.length()-1;i++)
{
for (j=s.length();j>=i+1;k++,j--)
{
num = k;
d[k] = s.substring(i,j);
}
k=num+1;
}
//Sort strings in such a way that the longest strings precede...
for (int i=0; i<d.length-1; i++)
{
for (int h=1;h<d.length;h++)
{
if (d[i].length() > d[h].length())
{
String temp;
temp=d[i];
d[i]=d[h];
d[h]=temp;
}
}
}
// Look for the Strings with array size 2*N (length in even number) and such that the
//the sum of left N numbers is = to the sum of right N numbers.
//As the strings are already in decending order, longest string is searched first and break the for loop once the string is found.
for (int x=0;x<d.length;x++)
{
int sum1=0,sum2=0;
if (d[x].length()%2==0 && d[x].length()<49)
{
int n;
n = d[x].length()/2;
for (int y=0;y<n;y++)
{
sum1 = sum1 + d[x].charAt(y)-'0';
}
for (int y=n;y<d[x].length();y++)
{
sum2 = sum2 + d[x].charAt(y)-'0';
}
if (sum1==sum2)
{
ans = d[x];
break;
}
}
}
return ans;
}
}
Here is the complete Java Program for this question.
Complexity is O(n^3)
This can however be solved in O(n^2).For O(n^2) complexity solution refer to this link
import java.util.Scanner;
import static java.lang.System.out;
public class SubStringProblem{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
out.println("Enter the Digit String:");
String s = sc.nextLine();
int n = (new SubStringProblem()).getEqualSumSubString(s);
out.println("The longest Sum SubString is "+n);
}
public int getEqualSumSubString(String s){
int N;
if(s.length()%2==0)
{
//String is even
N = s.length();
}
else{
//String is odd
N=s.length()-1;
}
boolean flag =false;
int sum1,sum2;
do{
for(int k=0;k<=s.length()-N;k++){
sum1=0;
sum2=0;
for(int i =k,j=k+N-1;i<j;i++,j--)
{
sum1=sum1 + Integer.parseInt(s.substring(i,i+1));
sum2+=Integer.parseInt(s.substring(j,j+1));
}
if(sum1==sum2){
return N;
}
}
N-=2;
flag =true;
}while(N>1);
return -1;
}
}
What is your rationale for the number 48 on these two lines?
for(int k=0;k<temp/2;k++)
{
leftSum=leftSum+tempString[k]-48;
rightSum=rightSum+tempString[k+(temp/2)]-48;
}
I am just overly curious and would like to hear the reasoning behind it, because I have a similar solution, but without the 48 and it still works. However, I added the 48 an still got the correct answer.
Simple solution. O(n*n). s - input string.
var longest = 0;
for (var i = 0; i < s.length-1; i++) {
var leftSum = rightSum = 0;
for (var j = i, k = i+1, l = 2; j >=0 && k < s.length; j--, k++, l+=2) {
leftSum += parseInt(s[j]);
rightSum += parseInt(s[k]);
if (leftSum == rightSum && l > longest) {
longest = l;
}
}
}
console.log(longest);

Shifting a string of characters?

I'm writing a program that solves Caesar ciphers in C++. It takes a string of the alphabet and shifts it to the left each loop: "abc....yz" --> "bcd.....yza". The problem is after another loop it goes: "bcd.....yza" --> "cde.....yzaa".
char temp; // holds the first character of string
string letters = "abcdefghijklmnopqrstuvwxyz";
while (true)
{
temp = letters[0];
for (int i = 0; i < 26; i++)
{
if (i == 25)
{
letters += temp;
}
letters[i] = letters[i + 1];
cout << letters[i];
}
cin.get();
}
Copy and paste that code and you'll see what I'm talking about. How do I fix this mysterious problem?
If I'm not mistaken, your loop does precisely the same as the following code:
letters = letters.substr(1,25) + letters.substr(0,1);
// [skip 1, take 25] + [first char goes last]
I think you need letters to be 27 characters, not 26, and instead of letters += temp (which grows the string every time), use letters[26] = temp[0].
...at which point you can just ditch temp entirely:
string letters = "abcdefghijklmnopqrstuvwxyz.";
while (true)
{
letters[26] = letters[0];
for (int i = 0; i < 26; i++)
{
letters[i] = letters[i + 1];
cout << letters[i];
}
cin.get();
}
[edit]
Although the more natural way to handle this is to use arithmetic on the characters themselves. The expression 'a' + ((c - 'a' + n) % 26) will shift a char c by n places Caesar-style.
You can achieve this easily using valarray< char >::cshift(n) (cyclical shift) method.