Undesired results from calculating powers of 2 [C++] - c++

Okay, I'm done banging my head against my desk. I'm trying to compute huge powers of 2 [beyond what's capable of being held in the uint64_t data type] by holding digits in a vector of 'char's. Here is my program, followed by my actual outputs:
/*
This program doubles a very large number by using a vector of char types
Usage: program.exe [number]
Output will be 2^[number]
*/
#include <iostream>
#include <vector>
#include <stdlib.h>
using namespace std;
int main(int argc, char *argv[])
{
vector<char> BigNum;
BigNum.push_back('2');
int carry=0, digit;
int power=atoi(argv[1]);
power-=1;
for(int x=0;x<power;x++) //Example: going from 16 to 32. x==4
{
for(int y=BigNum.size()-1;y>=0;y--) //Go from BigNum[1] to BigNum[0] ('6' then '1')
{
digit=atoi(&BigNum[y]); //digit = 6, then digit=1
BigNum[y]=(char)(((digit*2+carry)%10)+48); //BigNum[1]=(char)(6*2+0)%10+48 = '2' in char
//BigNum[0]=(char)(1*2+1)%10+48 = '3' in char
carry=digit*2/10; //carry=1, then 0
}
if(carry==1) //does not execute. BigNum=={'3','2'}
{
BigNum.push_back('0');
for(int y=BigNum.size()-1;y>0;y--)
{
BigNum[y]=BigNum[y-1];
}
BigNum[0]='1';
carry=0;
}
}
for(int x=0;x<BigNum.size();x++) cout<<BigNum[x];
}
Compiled with:
g++ program.cpp -o program
So here are my results when I run the program:
C:\MyApps\program 2
4
C:\MyApps\program 3
8
C:\MyApps\program 4
16
Okay, looks good so far... even my "if(carry==1)" section, where I push a number to the FRONT of the vector works, since we "carried the 1" to get into double digits. Let's continue:
C:\MyApps\program 5
52
What?
C:\MyApps\program 6
26
What what?
C:\MyApps\program 654
84
C:\MyApps\program 654444
00
It never gets to triple digits... and what the heck is going on?

You're applying atoi to something that isn't a null-terminated string. In practice, it may well look in memory like a null-terminated string, but not the one you actually want it to look like.
The cleanest way to fix this is probably to store actual digit values 0..9 rather than ASCII '0'..'9' in your vector. You'll find that the code is nicer that way too.

Related

I am unable to understand the output to my c++ code

I was doing a problem the part of the problem is to shift the a given string of 0 and 1 of a given number n to a given amount (here sft variable taken). T queries. I was getting error in right shift while left shift had no problem. The whole code is below -
#include<iostream>
#include<bitset>
using namespace std;
int main()
{
const int m=16;
int n,t;
cin>>t;
int sft;
char ch;
int arr[m];
while(t--)
{
cin>>n;
cin>>sft;
cin>>ch;
bitset<m>bt(n);
cout<<bt<<endl;
if(ch=='R')
{
for(int i=0;i<m;i++)
{
arr[i]=bt[((i+sft)%m)]; // problem is here
// cout<<((i+sft)%m)<<"-"<<bt[((i+sft)%m)]<<" "; // to check what is happening
}
}}}
PROBLEM - The problem is that for a given position in bt string , I am not getting what I am supposed to get it is giving wrong bit I do not know why?
input :
1(queries)
16(number) 3 (sft) R(right)
Output
bt string = 0000000000010000
Position-Bit in bt = 3-0 4-1 5-0 6-0 7-0 8-0 9-0 10-0 11-0 12-0 13-0 14-0 15-0 0-0 1-0 2-0
The least significant bit is 0, so that should be on the right side, so your output should be:
2-0 1-0 0-0 15-0 ... 5-0 4-1 3-0
or 0000000000000010 (2) which is the right shift for 3 positions of 0000000000010000 (16)
So your processing is okay for circular right shifting (rolling), but your output is confusing.
For non-circular (logical) shifting, introduce 0 for invalid positions.
See also: https://en.wikipedia.org/wiki/Bitwise_operation#Bit_shifts

Reading text fies with inconsistent format

I am trying to perform some operations on a text file containing a repetition of a C based string and some numbers. My code successfully carried out the operation on the first set but it would not get to the remaining sets.
Please see the content of the text file below:
Max Scherzer 2017
6.2 4 2 2 2 7
6.0 4 3 1 2 10
mod Cameron 2018
6.4 4 1 2 1 3
6.0 4 3 5 2 8
John Brandonso 2019
6.1 1 3 5 2 7
6.5 4 7 3 4 10
I have used .eof() and it completely messed up what i am doing.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
char playername [25];
int season;
ifstream gamefilein;
gamefilein.open("C:\\Users\\troy\\Desktop\\GAME_SCORE\\gameinfo.txt");
if(!gamefilein)
{
cout<<"unable to open file";
}
double IP;
int H,R,ER,BB,K;
int counter=0;
double totalscore=0;
while(!gamefilein.fail())
{
gamefilein.get(playername,25);
gamefilein>>season;
cout<<playername<<season<<endl;
cout<<"Game Scores:"<<endl;
while(gamefilein>>IP>>H>>R>>ER>>BB>>K)
{
int IPa=IP;
int IPb=(IP-IPa)*10;
int IPc=0;
if(IPa>4)
{
IPc=IPa-4;
}
int score=50+(IPa*3)+(IPb*1)+(IPc*2)+(K*1)-(H*2)-(ER*4)-((R-ER)*2)-(BB*1);
cout<<score<<endl;
counter++;
totalscore+=score;
}
cout<<"Number of Games Started: "<<counter<<endl;
cout<<fixed<<setprecision(2)<<"Average Game Score:
<<(totalscore/counter)<<endl<<endl;
}
gamefilein.close();
return 0;
}
I get the below result, but I want the same result for the rest of the information in the text file, for example, I am expecting two more results like the one I have below.
Max Scherzer 2017
Game Scores:
63
64
Number of Games Started: 2
Average Game Score: 63.50
Aren't you reading the file as a char array?
If I read this correctly you try to shift an int and double over a char array with numbers in a STRING right?
e.g. "6.2" string is different than a 6.2 double number in your memory, hence why it cant work.
You also seem to have a lot of spaces which should not forget as well.
Where do you get that string to begin with? I would recommend you change the creation of that file to a more convenient format e.g. cv or json
I just solved my problem myself. The problem occurred when the loop operating on the integers and double completes its run and sees the character-based string that is in the next dataset. So i inserted a clear member function just at the point where i check for end of file
(gamefilein.clear())
and that solved my problem.
Thanks for attempting to help

Why does long shows wrong output in finding second maximum of three integers?

I am a novice to CP and while I was doing this problem of finding the second maximum among three numbers I wrote this code which however works for int but doesn't work for long even though they are the same data types.
Input Format:
The first line contains the number of triples, N.
The next N lines which follow each have three space separated integers.
Input Used:
3
1 2 3
10 15 5
100 999 500
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >>n ;
while(n--){
long a,b,c,d;//if i change long to int output is correct
scanf("%i%i%i",&a,&b,&c);
d=min(max(a,b),max(a,c));
printf("%i\n",d);// outputs 1 \n 10 \n 100 \n(\n means new line)
}
return 0;
}
Perhaps because you're using the wrong specifier. %i is for ints, but %li is for longs.

Reading an ASCII file with fstream

Have an ASCII text file with some integer numbers in it, each separated by a space, and sometimes the numbers go on to a new line. For example:
// my_file.txt
23 45 973 49
44 1032 33 99
43 8 4 90824
I want to read 100 of these numbers into an array of "ints". Thus far, I have the following code:
int x[100];
fstream file_in("my_file.txt", ios::in);
for (int i = 0; i < 100; i++)
{
file_in >> x[i];
}
However, I now want to do a couple of other things that I am not sure about.
What if I want to just read the entire file in, without having to go through the loop? If this was binary data, I know that I can just write file_in.read((char*)&x[0], 100 * sizeof(int)). But how can I do this with an ASCII file?
What if I want to skip the first 3 numbers in the file, and start reading from the fourth? Again, if this was binary data, I could just use file_in.seekg(3 * sizeof(char)). But I don't know how to skip in an ASCII file.
No raw loops!
Reading the entire file:
#include <fstream>
#include <iterator>
#include <vector>
int main()
{
std::ifstream f("data.txt");
std::vector<int> v(std::istream_iterator<int>(f), {});
Skipping over the first three:
v.erase(v.begin(), v.begin() + 3);

find all palindromes inside a string

I am stuck and cant seem to figure out where I should go from here.
I would appreciate any hints or tips on how I should approach this problem. Been trying to figure this out for over 9 hrs no luck.
The question is as follows:
A string s is said to be palindromic if it reads the same backwards and forwards. A decomposition of s is a set of non-overlapping sub-strings of s whose concatenation is s.
Write a C++ program that takes as input a string and computes all its palin-
dromic decompositions. For example.if s is the string 0204451881 then the
decomposition 020, 44 5 1881 is a palindromic decomposition. So is
0 2 0 4 4 5 1 8 8 1
0 2 0 4 4 5 1 88 1
0 2 0 4 4 5 1881
0 2 0 44 5 1 8 8 1
0 2 0 44 5 1 88 1
020 4 4 5 1 8 8 1
020 4 4 5 1 88 1
020 4 4 5 1881
020 44 5 1 8 8 1
020 44 5 1 88 1
020 44 5 1881
this is a class project.
so far I have:
#include <iostream>
#include <string>
using namespace std;
void palDecom(string str1);
bool isPal(const string &str);
void subPal(string str1);
int main()
{
string s = "0204451881";
palDecom(s);
subPal(s);
return 0;
}
//shows the decomposition as the single char of the string
//takes a string as input
void palDecom(string str1)
{
int stringLastIndex = (str1.length());
for (int i = 0; i < stringLastIndex; i++)
{
cout<< str1[i] <<" ";
}
cout<<endl;
}
void subPal(string str1)
{
int stringLastIndex = (str1.length());
for (int curIndx = 0; curIndx < stringLastIndex; curIndx++)
{
for(int comparIndx = 1; comparIndx < stringLastIndex; comparIndx++)
{
//cout<< "i was in this loop"<<endl;
if (isPalindrome((str1,curIndx,comparIndx)))
//cout<<str1.substr(0,curIndx-1)<<" "<< str1.substr(curIndx,comparIndx) <<" "<< str1.substr(comparIndx,stringLastIndex)<<endl;
}
}
}
bool isPal(const string &str)
{
int start=0, end=str.length()-1;
while (start < end) {
if (str[start++] != str[end--])
return false;
}
return true;
}
Actually, I just managed to realize this:
Palindromes decompose to combination splits.
What this means is that each palindrome will "split" into additional sub-palindromes based on how many "layers" of palindrome it possesses.
For example: The sequence
12213443
-> 1221 + 3443
-> 1 + 22 + 1 + 3 + 44 + 3
-> 1 + 2 + 2 + 1 + 3 + 44 + 3
As you parse down the string, the possibilities will just increase by the amount of palindromes a larger one can decompose to until you have palindromes of 1 character width.
Granted, I realize that palindromes can overlap:
1221221
-> 1221 + 22 + 1
OR -> 1 + 22 + 1221
This is an additional quandary, but is definitely solvable.
Additionally, you can choose to think about smaller palindromes coming together to create larger ones.
Personally, I think this line of thought will lead to a better algorithm and method of solving from the above, as composing new palindromes while iterating in one direction is probably easier than decomposing them in just one direction.
I think the best course is to start playing with palindromes and map out the possible decompositions. By analysing this, you should be able to find a repetitive pattern that can then be mapped to a recursive solution.
Regardless, this answer definitely can use recursion. There is a clear pattern here; you just need to explore it more and find it.
I wish I had a more definitive answer but I myself am struggling with the problem. I hope someone else can edit this and pick up the threads?
Use recursion to solve this problem by scanning the string from left to right.
Keep a stack of the previous palindrome partitions that have already been found "to the left" of the "current position" in the overall string. This stack could be an array or std::vector of pointers to the ends (i.e. - one past the last character) of each previously found palindrome. In this case, the "current position" is indicated by the top element of the stack, or the beginning of the string if the stack is empty.
The base/exit case of the recursion is when the current position refers to the end of the entire string. In that case you've already exhausted the string. Print out the palindromes as indicated by the palindrome stack (starting from the bottom) and then return. (Hint: Don't alter the original string to insert nul terminators to print each palindrome as a string. Instead, just print each palindrome character-by-character according to the partitions on the stack, print spaces between the palindromes and a newline at the end of the stack.)
Otherwise, have a loop that goes from 1 up through the number of characters remaining in the string starting from the current position. At each iteration, test if the current position is a palindrome of length equal to your loop index. If it is such a palindrome, then push a partition for that palindrome onto the stack and recurse down to one level deeper.
That should do it.
I wouldn't use a std::stack to implement the stack. Instead use a std::vector or an array. If you use std::vector, then don't do structural operations (e.g. - push_back, pop_back, etc.) on it in the recursion. Instead, just resize() it to hold up to strlen(str) partition elements before you begin recursing because the deepest stack will be when each character of the string is a palindrome. Then in your recursion, you simply pass the logical, current size of the stack. This tells you the index where the next palindrome partition should be placed (i.e. - at index size) and allows you to access any previously existing top element of the stack (i.e. - at index size - 1). This approach will work for an array or a std::vector.
If you do want to use std::vector::push_back() (or std::stack), then you just need to remember to std::vector::pop_back() after you return from each recursion. This approach would allow you to not need to pass the "logical" size of the stack explicitly around as the vector itself would know its correct size.
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <iomanip>
using std:: cin;
using std:: cout;
using std:: endl;
using std:: setw;
const int MAX_LEN = 100;
int palDecom(const char str[]);
bool isPal(const char str[], int start, int end);
int main()
{
char str[MAX_LEN];
cin >> setw(MAX_LEN) >> str;
cout << palDecom(str) ;
return EXIT_SUCCESS;
}
int palDecom(const char str[])
{
int counter=0;
for (int i = 1; i < strlen(str) ; i++)
for(int lastindex = strlen(str)-1; lastindex < strlen(str) ; lastindex--)
{
if(isPal(str, i , lastindex-1))
counter ++;
}
return counter;
}
bool isPal(const char str[], int start, int end)
{
if(start == strlen(str))
return 1;
if (str[start] == str[end]){
isPal(str, str[start], str[end-1]);
return true;
}
return false;
}