C++ overloading * for polynomial multiplication - c++

So I have been developing a polynomial class where a user inputs: 1x^0 + 2x^1 + 3x^2... and 1,2,3 (the coefficients) are stored in an int array
My overloaded + and - functions work, however, * doesnt work. No matter the input, it always shows -842150450
when is should be (5x^0 + x^1) * (-3x^0 + x^1) = -15x^0 + 2x^1 + 1x^2
or (x+5)(x-3) = x^2 +2x - 15
I'm using the overloaded * function like : Polynomial multiply = one * two;
Im guessing the problem is strtol(p, &endptr, 10) since it uses a long int, however, adding and subtracting works perfectly
My constructor
Polynomial::Polynomial(char *s)
{
char *string;
string = new char [strlen(s) + 1];
int length = strlen(string);
strcpy(string, s);
char *copy;
copy = new char [length];
strcpy(copy, string);
char *p = strtok(string, " +-");
counter = 0;
while (p)
{
p = strtok(NULL, " +-");
counter++;
}
coefficient = new int[counter];
p = strtok(copy, " +");
int a = 0;
while (p)
{
long int coeff;
char *endptr;
coeff = strtol(p, &endptr, 10); //stops at first non number
if (*p == 'x')
coeff = 1;
coefficient[a] = coeff;
p = strtok(NULL, " +");
a++;
}
}
and the overloaded * function
Polynomial Polynomial::operator * (const Polynomial &right)
{
Polynomial temp;
//make coefficient array
int count = (counter + right.counter) - 1;
temp.counter = count;
temp.coefficient = new int [count];
for (int i = 0; i < counter; i++)
{
for (int j = 0; j < right.counter; j++)
temp.coefficient[i+j] += coefficient[i] * right.coefficient[j];
}
return temp;
}
And heres my entire code: http://pastie.org/721143

You don't appear to initialise the temp.coefficient[i+j] to zero in your operator * ().
temp.coefficient = new int [count];
std::memset (temp.coefficient, 0, count * sizeof(int));

Convert -842150450 to hex to find back one of the magic values used in the CRT in the debug build. That helps finding the bug in your code:
temp.coefficient = new int [count];
// Must initialize the memory
for (int ix = 0; ix < count; ++ix) temp.coefficient[ix] = 0;
There are plenty other bugz btw, good luck fixing them.

Does
temp.coefficient = new int [count];
give you an array of zeroes?
Otherwise in your for loop you're adding stuff to garbage.

Replace
temp.coefficient = new int [count];
by
temp.coefficient = new int [count]();
in order to zero-initialize the array values.

Related

How to read binary files properly?

I have a problem with the NIST/Diehard Binary Matrix test. It's about dividing a binary sequence into a 32x32 matrix and calculating its rank. After calculating ranks I need to compute a xi^2 value and then calculate p-value(must be from 0 to 1). I'm getting p-value extremely small even in a random sequence.
I've tried to hardcode some small examples and getting my p-value right though I think my problem is in reading a binary sequence file and getting bits from it.
This is reading from a file and converting to bits sequence.
ifstream fin("seq1.bin", ios::binary);
fin.seekg(0, ios::end);
int n = fin.tellg();
unsigned int start, end;
char *buf = new char[n];
fin.seekg(0, ios::beg);
fin.read(buf, n);
n *= 8;
bool *s = new bool[n];
for (int i = 0; i < n / 8; i++) {
for (int j = 7; j >= 0; j--) {
s[(i) * 8 + 7 - j] = (bool)((buf[i] >> j) & 1);
}
}
Then I form my matrix and calculate it's rank
int *ranks = new int[N];
for (int i = 0; i < N; i++) {
bool *arr = new bool[m*q];
copy(s + i * m*q, s +(i * m*q) + (m * q), arr);
ranks[i] = binary_rank(arr, m, q);
}
Cheking occurance in ranks
int count_occurrences(int arr[], int n, int x){
int result = 0;
for (int i = 0; i < n; i++)
if (x == arr[i])
result++;
return result;
}
Calculating xi^2 and p-value
double calculate_xi(int fm, int fm_1, int remaining, int N) {
double N1 = 0.2888*N;
double N2 = 0.5776*N;
double N3 = 0.1336*N;
double x1 = (fm - N1)*(fm - N1) / N1;
double x2 = (fm_1 - N2)*(fm_1 - N2) / N2;
double x3 = (remaining - N3)*(remaining - N3) / N3;
return x1 + x2 + x3;
}
double calculate_pvalue(double xi2) {
return exp(-(xi2 / 2));
}
I expect p-value between 0 and 1 but getting 0 every time. It's because of the extremely big xi^2 value and I couldn't find what I've done wrong. Could you please help me to get things right.
For this part:
for (int i = 0; i < n / 8; i++) {
for (int j = 7; j >= 0; j--) {
s[(i) * 8 + 7 - j] = (bool)((buf[i] >> j) & 1);
}
}
when you add elements to s array, looks like you switch the position of bytes inside each character: the last bit in character in buf goes into the first bit in character in s array, because the shift initially is 7, so you take first bit in char from buf[], but for s[] it looks to be 0, resulting in swapping. It is easy to verify with debugger though, as from code it is not so obvious. Thanks.

Convert string to float or integer without using built in functions (like atoi or atof)

I'm new to C++ and our teacher asked us to get a function that does the above title. So far I've got a function that converts a string to an integer, but I have no idea about how to modify it to make it work if the numbers in the string would represent a float.
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
If I run:
char myString[] = "12345";
convert(myString, 5);
I get:
12345
But if I run:
char myString[] = "123.45";
convert(myString, 5);
I get:
122845
How could I modify my program to work with floats too? I know convert function is meant to return an int so, should I use two more functions?
I was thinking about one that determinates if the string is inteded to be converted to an integer or a string, and the other that'll actually convert the string to a float.
Here is the function for doing so...
template<class T, class S>
T convert_string_to_number(S s)
{
auto result = T(0.l);
if (s.back() == L'F' || s.back() == L'f')
s = s.substr(0u, s.size() - 1u);
auto temp = s;
auto should_add = false;
if (!std::is_floating_point<T>::value)
{
should_add = temp.at(temp.find_first_of(L'.') + 1) >= '5';
temp.erase(temp.begin() + temp.find_first_of(L'.'), temp.end());
}
else if (temp.find_first_of(L'.') != S::npos)
temp.erase(temp.begin() + temp.find_first_of(L'.'));
for (int i = temp.size() - 1u; i >= 0; --i)
if (temp[i] >= L'0' && temp[i] <= L'9')
result += T(std::powl(10.l, temp.size() - i - 1.l) * (temp[i] - L'0'));
else
throw std::invalid_argument("Invalid numerical string!");
if (s.find(L'-') != S::npos)
result = -T(std::fabs(result));
if (s.find(L'.') != S::npos && std::is_floating_point<T>::value)
result /= T(std::powl(10.l, s.size() - s.find(L'.') - 1.l));
return std::is_floating_point<T>::value ? T(result) : T(result + T(should_add));
}
Just use it like you typically would...
auto some_number = convert_string_to_number<float>(myString);...
For the floating point part of the assignment: what about regular expressions? It is also kind of built-in functionality, but general purpose, not designed for your particular task, so I hope your teacher will be fine with this idea.
You can use the following regex: [+-]?([0-9]*[.])?[0-9]+ (I got it from this answer) to detect if provided string is a floating point number. Then you can modify the expression a little bit to capture the +/- signs and parts before/after the dot separator. Once you extract these features the task should be relatively simple.
Also please change your method signature to: float convert(const std::string& str).
Try this :
int convert(char str[], int size) {
int number = 0;
for (int i = 0; i < size; ++i) {
number += (str[i] - 48)*pow(10, (size - i - 1));
}
return number;
}
int pow10(int radix)
{
int r = 1;
for (int i = 0; i < radix; i++)
r *= 10;
return r;
}
float convert2float(char str[], int size) { //size =6
// convert to string_without_decimal
char str_without_decimal[10];
int c = 0;
for (int i = 0; i < size; i++)
{
if (str[i] >= 48 && str[i] <= 57) {
str_without_decimal[c] = str[i];
c++;
}
}
str_without_decimal[c] = '\0'; //str_without_decimal = "12345"
//adjust size if dot present or not. If no dot present => size = c
size = (size != c ?) size - 1 : size; //size = 5 = 6-1 since dot is present
//convert to decimal
int decimal = convert(str_without_decimal, size); //decimal = 12345
//get divisor
int i;
for (i = size; i >= 0; i--) {
if (str[i] == '.') break;
}
int divisor = pow10(size - i); //divisor = 10;
return (float)decimal/(float) divisor; // result = 12345 /10
}
int main()
{
char str[] = "1234.5";
float f = convert2float(str, 6);
cout << f << endl;
return 0;
}

C++: Convert Win32 textbox char -> int -> char and put back in another textbox

I want to accept text input using a text box, then change the characters to integers and do fun math with my integers, and then put them back into a char array to be printed in another text box.
Here is my code:
int len = GetWindowTextLength(textbox) + 1;
char* text = new char[len];
GetWindowText(textbox, &text[0], len);
int x = 0;
int INTmessage[len];
int ENClen = (len * 2);
char ENCmessage[ENClen];
while (x < len) {
INTmessage[x] = int(text[x]) - 32;
x++;
}
int z = 0;
int y = 0;
while (z < ENClen) {
ENCmessage[z] = (INTmessage[y] % 9);
ENCmessage[z + 1] = (INTmessage[y] % 10);
z += 2;
y++;
}
SetWindowText(textreturn, "");
SetWindowText(textreturn, ENCmessage[0]);
The last line displays a compiler error:
invalid conversion from 'char' to LPCSTR.
Please specify What you mean by 'I don't know why this does not work'. One Error in your code is this:
//This line is incorrect because it converts an address to integer, which has no relation to value of textbox, making decryption impossible.
INTmessage[x] = int(&text[x]) - 32;
//Maybe you may want to use this code:
INTmessage[x] = int(text[x]) - 32;
The last line fails because you are passing a single char to SetWindowText() (accessing ENCmessage[0] returns the first char in the ENCmessage array). SetWindowText() expects a char* pointer to a null-terminated string instead. You can drop the [0]:
SetWindowText(textreturn, ENCmessage);
Just make sure that ENCmessage contains a null character after your digit characters.
That being said, your code can be re-written to something more like this:
int len = GetWindowTextLength(textbox) + 1;
char* text = new char[len];
len = GetWindowText(textbox, text, len);
int *INTmessage = new int[len];
for(int x = 0; x < len; ++x) {
INTmessage[x] = int(text[x]) - 32;
}
int ENClen = (len * 2) + 1;
char *ENCmessage = new char[ENClen];
for(int x = 0, y = 0; x < len; ++x, y += 2) {
ENCmessage[y] = (INTmessage[x] % 9);
ENCmessage[y + 1] = (INTmessage[x] % 10);
}
ENCmessage[ENCLen-1] = '\0';
SetWindowText(textreturn, ENCmessage);
delete[] INTmessage;
delete[] ENCmessage;
delete[] text;
Or, since you tagged the question as C++, like this instead:
#include <string>
#include <vector>
int len = GetWindowTextLength(textbox) + 1;
std::string text;
text.resize(len);
len = GetWindowText(textbox, &text[0], len);
std::vector<int> INTmessage(len);
for(int x = 0; x < len; ++x) {
INTmessage[x] = int(text[x]) - 32;
}
int ENClen = (len * 2);
std::string ENCmessage;
ENCmessage.resize(ENClen);
for (int x = 0; y = 0; x < len; ++x, y += 2) {
ENCmessage[y] = (INTmessage[x] % 9);
ENCmessage[y + 1] = (INTmessage[x] % 10);
}
SetWindowText(textreturn, ENCmessage.c_str());

How to get the lexical rank of a string? [duplicate]

I'm posting this although much has already been posted about this question. I didn't want to post as an answer since it's not working. The answer to this post (Finding the rank of the Given string in list of all possible permutations with Duplicates) did not work for me.
So I tried this (which is a compilation of code I've plagiarized and my attempt to deal with repetitions). The non-repeating cases work fine. BOOKKEEPER generates 83863, not the desired 10743.
(The factorial function and letter counter array 'repeats' are working correctly. I didn't post to save space.)
while (pointer != length)
{
if (sortedWordChars[pointer] != wordArray[pointer])
{
// Swap the current character with the one after that
char temp = sortedWordChars[pointer];
sortedWordChars[pointer] = sortedWordChars[next];
sortedWordChars[next] = temp;
next++;
//For each position check how many characters left have duplicates,
//and use the logic that if you need to permute n things and if 'a' things
//are similar the number of permutations is n!/a!
int ct = repeats[(sortedWordChars[pointer]-64)];
// Increment the rank
if (ct>1) { //repeats?
System.out.println("repeating " + (sortedWordChars[pointer]-64));
//In case of repetition of any character use: (n-1)!/(times)!
//e.g. if there is 1 character which is repeating twice,
//x* (n-1)!/2!
int dividend = getFactorialIter(length - pointer - 1);
int divisor = getFactorialIter(ct);
int quo = dividend/divisor;
rank += quo;
} else {
rank += getFactorialIter(length - pointer - 1);
}
} else
{
pointer++;
next = pointer + 1;
}
}
Note: this answer is for 1-based rankings, as specified implicitly by example. Here's some Python that works at least for the two examples provided. The key fact is that suffixperms * ctr[y] // ctr[x] is the number of permutations whose first letter is y of the length-(i + 1) suffix of perm.
from collections import Counter
def rankperm(perm):
rank = 1
suffixperms = 1
ctr = Counter()
for i in range(len(perm)):
x = perm[((len(perm) - 1) - i)]
ctr[x] += 1
for y in ctr:
if (y < x):
rank += ((suffixperms * ctr[y]) // ctr[x])
suffixperms = ((suffixperms * (i + 1)) // ctr[x])
return rank
print(rankperm('QUESTION'))
print(rankperm('BOOKKEEPER'))
Java version:
public static long rankPerm(String perm) {
long rank = 1;
long suffixPermCount = 1;
java.util.Map<Character, Integer> charCounts =
new java.util.HashMap<Character, Integer>();
for (int i = perm.length() - 1; i > -1; i--) {
char x = perm.charAt(i);
int xCount = charCounts.containsKey(x) ? charCounts.get(x) + 1 : 1;
charCounts.put(x, xCount);
for (java.util.Map.Entry<Character, Integer> e : charCounts.entrySet()) {
if (e.getKey() < x) {
rank += suffixPermCount * e.getValue() / xCount;
}
}
suffixPermCount *= perm.length() - i;
suffixPermCount /= xCount;
}
return rank;
}
Unranking permutations:
from collections import Counter
def unrankperm(letters, rank):
ctr = Counter()
permcount = 1
for i in range(len(letters)):
x = letters[i]
ctr[x] += 1
permcount = (permcount * (i + 1)) // ctr[x]
# ctr is the histogram of letters
# permcount is the number of distinct perms of letters
perm = []
for i in range(len(letters)):
for x in sorted(ctr.keys()):
# suffixcount is the number of distinct perms that begin with x
suffixcount = permcount * ctr[x] // (len(letters) - i)
if rank <= suffixcount:
perm.append(x)
permcount = suffixcount
ctr[x] -= 1
if ctr[x] == 0:
del ctr[x]
break
rank -= suffixcount
return ''.join(perm)
If we use mathematics, the complexity will come down and will be able to find rank quicker. This will be particularly helpful for large strings.
(more details can be found here)
Suggest to programmatically define the approach shown here (screenshot attached below) given below)
I would say David post (the accepted answer) is super cool. However, I would like to improve it further for speed. The inner loop is trying to find inverse order pairs, and for each such inverse order, it tries to contribute to the increment of rank. If we use an ordered map structure (binary search tree or BST) in that place, we can simply do an inorder traversal from the first node (left-bottom) until it reaches the current character in the BST, rather than traversal for the whole map(BST). In C++, std::map is a perfect one for BST implementation. The following code reduces the necessary iterations in loop and removes the if check.
long long rankofword(string s)
{
long long rank = 1;
long long suffixPermCount = 1;
map<char, int> m;
int size = s.size();
for (int i = size - 1; i > -1; i--)
{
char x = s[i];
m[x]++;
for (auto it = m.begin(); it != m.find(x); it++)
rank += suffixPermCount * it->second / m[x];
suffixPermCount *= (size - i);
suffixPermCount /= m[x];
}
return rank;
}
#Dvaid Einstat, this was really helpful. It took me a WHILE to figure out what you were doing as I am still learning my first language(C#). I translated it into C# and figured that I'd give that solution as well since this listing helped me so much!
Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace CsharpVersion
{
class Program
{
//Takes in the word and checks to make sure that the word
//is between 1 and 25 charaters inclusive and only
//letters are used
static string readWord(string prompt, int high)
{
Regex rgx = new Regex("^[a-zA-Z]+$");
string word;
string result;
do
{
Console.WriteLine(prompt);
word = Console.ReadLine();
} while (word == "" | word.Length > high | rgx.IsMatch(word) == false);
result = word.ToUpper();
return result;
}
//Creates a sorted dictionary containing distinct letters
//initialized with 0 frequency
static SortedDictionary<char,int> Counter(string word)
{
char[] wordArray = word.ToCharArray();
int len = word.Length;
SortedDictionary<char,int> count = new SortedDictionary<char,int>();
foreach(char c in word)
{
if(count.ContainsKey(c))
{
}
else
{
count.Add(c, 0);
}
}
return count;
}
//Creates a factorial function
static int Factorial(int n)
{
if (n <= 1)
{
return 1;
}
else
{
return n * Factorial(n - 1);
}
}
//Ranks the word input if there are no repeated charaters
//in the word
static Int64 rankWord(char[] wordArray)
{
int n = wordArray.Length;
Int64 rank = 1;
//loops through the array of letters
for (int i = 0; i < n-1; i++)
{
int x=0;
//loops all letters after i and compares them for factorial calculation
for (int j = i+1; j<n ; j++)
{
if (wordArray[i] > wordArray[j])
{
x++;
}
}
rank = rank + x * (Factorial(n - i - 1));
}
return rank;
}
//Ranks the word input if there are repeated charaters
//in the word
static Int64 rankPerm(String word)
{
Int64 rank = 1;
Int64 suffixPermCount = 1;
SortedDictionary<char, int> counter = Counter(word);
for (int i = word.Length - 1; i > -1; i--)
{
char x = Convert.ToChar(word.Substring(i,1));
int xCount;
if(counter[x] != 0)
{
xCount = counter[x] + 1;
}
else
{
xCount = 1;
}
counter[x] = xCount;
foreach (KeyValuePair<char,int> e in counter)
{
if (e.Key < x)
{
rank += suffixPermCount * e.Value / xCount;
}
}
suffixPermCount *= word.Length - i;
suffixPermCount /= xCount;
}
return rank;
}
static void Main(string[] args)
{
Console.WriteLine("Type Exit to end the program.");
string prompt = "Please enter a word using only letters:";
const int MAX_VALUE = 25;
Int64 rank = new Int64();
string theWord;
do
{
theWord = readWord(prompt, MAX_VALUE);
char[] wordLetters = theWord.ToCharArray();
Array.Sort(wordLetters);
bool duplicate = false;
for(int i = 0; i< theWord.Length - 1; i++)
{
if(wordLetters[i] < wordLetters[i+1])
{
duplicate = true;
}
}
if(duplicate)
{
SortedDictionary<char, int> counter = Counter(theWord);
rank = rankPerm(theWord);
Console.WriteLine("\n" + theWord + " = " + rank);
}
else
{
char[] letters = theWord.ToCharArray();
rank = rankWord(letters);
Console.WriteLine("\n" + theWord + " = " + rank);
}
} while (theWord != "EXIT");
Console.WriteLine("\nPress enter to escape..");
Console.Read();
}
}
}
If there are k distinct characters, the i^th character repeated n_i times, then the total number of permutations is given by
(n_1 + n_2 + ..+ n_k)!
------------------------------------------------
n_1! n_2! ... n_k!
which is the multinomial coefficient.
Now we can use this to compute the rank of a given permutation as follows:
Consider the first character(leftmost). say it was the r^th one in the sorted order of characters.
Now if you replace the first character by any of the 1,2,3,..,(r-1)^th character and consider all possible permutations, each of these permutations will precede the given permutation. The total number can be computed using the above formula.
Once you compute the number for the first character, fix the first character, and repeat the same with the second character and so on.
Here's the C++ implementation to your question
#include<iostream>
using namespace std;
int fact(int f) {
if (f == 0) return 1;
if (f <= 2) return f;
return (f * fact(f - 1));
}
int solve(string s,int n) {
int ans = 1;
int arr[26] = {0};
int len = n - 1;
for (int i = 0; i < n; i++) {
s[i] = toupper(s[i]);
arr[s[i] - 'A']++;
}
for(int i = 0; i < n; i++) {
int temp = 0;
int x = 1;
char c = s[i];
for(int j = 0; j < c - 'A'; j++) temp += arr[j];
for (int j = 0; j < 26; j++) x = (x * fact(arr[j]));
arr[c - 'A']--;
ans = ans + (temp * ((fact(len)) / x));
len--;
}
return ans;
}
int main() {
int i,n;
string s;
cin>>s;
n=s.size();
cout << solve(s,n);
return 0;
}
Java version of unrank for a String:
public static String unrankperm(String letters, int rank) {
Map<Character, Integer> charCounts = new java.util.HashMap<>();
int permcount = 1;
for(int i = 0; i < letters.length(); i++) {
char x = letters.charAt(i);
int xCount = charCounts.containsKey(x) ? charCounts.get(x) + 1 : 1;
charCounts.put(x, xCount);
permcount = (permcount * (i + 1)) / xCount;
}
// charCounts is the histogram of letters
// permcount is the number of distinct perms of letters
StringBuilder perm = new StringBuilder();
for(int i = 0; i < letters.length(); i++) {
List<Character> sorted = new ArrayList<>(charCounts.keySet());
Collections.sort(sorted);
for(Character x : sorted) {
// suffixcount is the number of distinct perms that begin with x
Integer frequency = charCounts.get(x);
int suffixcount = permcount * frequency / (letters.length() - i);
if (rank <= suffixcount) {
perm.append(x);
permcount = suffixcount;
if(frequency == 1) {
charCounts.remove(x);
} else {
charCounts.put(x, frequency - 1);
}
break;
}
rank -= suffixcount;
}
}
return perm.toString();
}
See also n-th-permutation-algorithm-for-use-in-brute-force-bin-packaging-parallelization.

filling a string made by new in a function

#include <iostream>
using namespace std;
void generCad(int n, char* cad){
int longi = 1, lastchar, m = n; // calculating lenght of binary string
char actual;
do{
longi++;
n /= 2;
}while(n/2 != 0);
cad = new char[longi];
lastchar = longi - 1;
do{
actual = m % 2;
cad[lastchar] = actual;
m /= 2;
lastchar--;
}while(m/2 != 0);
cout << "Cadena = " << cad;
}
Hi! I'm having a problem here because I need a function that creates a binary string for a number n. I think the process is "good" but cout doesn't print anything, I don't know how to fill the string I've created using the new operator
The code should look like this:
void generCad(int n, char** cad)
{
int m = n, c = 1;
while (m >>= 1) // this divides the m by 2, but by shifting which is faster
c++; // here you counts the bits
*cad = new char[c + 1];
(*cad)[c] = 0; // here you end the string by 0 character
while (n)
{
(*cad)[--c] = n % 2 + '0';
n /= 2;
}
cout << "Cadena = " << *cad;
}
Note that cad is now char ** and not char *. If it is just char * then you do not get the pointer as you expect outside the function. If you do not need the string outside this function, then it may be passed as char *, but then do not forget to delete the cad before you leave the function (good habit ;-))
EDIT:
This code will probably be more readable and do the same:
char * toBin(int n)
{
int m = n, c = 1;
while (m >>= 1) // this divides the m by 2, but by shifting which is faster
c++; // here you counts the bits
char *cad = new char[c + 1];
cad[c] = 0; // here you end the string by 0 character
while (n)
{
cad[--c] = n % 2 + '0';
n /= 2;
}
cout << "Cadena = " << cad;
return cad;
}
int main()
{
char *buff;
buff = toBin(16);
delete [] buff;
return 1;
}
actual contains the numbers 0 and 1, not the characters '0' and '1'. To convert, use:
cad[lastchar] = actual + '0';
Also, since you're using cad as a C string, you need to allocate an extra character and add a NUL terminator.
actual = m % 2;
should be:
actual = m % 2 + '0';