output error: different outputs on two different compilers: Prime Cryptarithm USACO - c++

The following cryptarithm is a multiplication problem that can be solved by substituting digits from a specified set of N digits into the positions marked with *. If the set of prime digits {2,3,5,7} is selected, the cryptarithm is called a PRIME CRYPTARITHM. Example:
* * *
x * *
-------
* * * <-- partial product 1
* * * <-- partial product 2
-------
* * * *
These stars can be replaced only by a defined set of integers N which is given by the USACO grader.
The partial products must be three digits long.
Data given:
4 /* <-- This is the given size of set N from which the multiplicand and multiplier is taken */
2 3 5 7 /* <-- Set N */
The task is to calculate the number of possible outcomes and output the number.
My question:
In my compiler,The output is 0,which is correct,but in the USACO grader my program outputs 1. I am not able to identify what the problem is.
Could someone help me resolve this issue?
Thanks in advance.
MY PROGRAM CODE:
#include <iostream>
#include <fstream>
using namespace std;
int *sortInput(int arrSetN[], int numofDigs)
{
for(int ictr=0;ictr<numofDigs;ictr++)
{
for(int jctr=ictr+1;jctr<numofDigs;jctr++)
{
if(arrSetN[ictr]>arrSetN[jctr])
{
swap(arrSetN[ictr],arrSetN[jctr]);
}
}
}
return arrSetN;
}
bool checkNum(int num,int arrSetN[],int numofDigs)
{
int countDigits=0,tempNum=num,ictr=0,jctr=0;
int *arrDigits,*digitTally;
/*
Counting the number of digits in num.
*/
for(;tempNum>0;)
{
tempNum=tempNum/10;
countDigits++;
}
arrDigits=new int[countDigits];
digitTally=new int[countDigits];
/*
making digitTally = 0
*/
for(ictr=0;ictr<countDigits;ictr++)
digitTally[ictr]=0;
/*
retrieving the digits of num.
*/
for(ictr=0;ictr<countDigits;ictr++)
{
arrDigits[ictr]=num%10;
num=num/10;
}
/*
checking if all digits of num are part of set N.
*/
for(ictr=0;ictr<countDigits;ictr++)
{
for(jctr=0;jctr<=numofDigs;jctr++)
{
if(arrDigits[ictr]==arrSetN[jctr])
digitTally[ictr]=1;
}
}
for(int cfc=0;cfc<countDigits;cfc++)
{
if(digitTally[cfc]==0)
return false;
}
return true;
}
int main()
{
ofstream fout("crypt1.out");
ifstream fin("crypt1.in");
int numofDigs,ictr=0,a,b,c,d, e,p1,p2,sum,p2test;
int actr=0,bctr=0,cctr=0,dctr=0,ectr=0,tally=0;
bool sumCheck,p1Check,p2Check;
fin>>numofDigs;
int *arrSetN;
arrSetN = new int[numofDigs];
for(ictr=0;ictr<numofDigs;ictr++)
{
fin>>arrSetN[ictr];
}
arrSetN=sortInput(arrSetN,numofDigs);
for(actr=0;actr<numofDigs;actr++)
{
a=arrSetN[actr];
for(bctr=0;bctr<numofDigs;bctr++)
{
b=arrSetN[bctr];
for(cctr=0;cctr<numofDigs;cctr++)
{
c=arrSetN[cctr];
for(dctr=0;dctr<numofDigs;dctr++)
{
d=arrSetN[dctr];
for(ectr=0;ectr<numofDigs;ectr++)
{
e=arrSetN[ectr];
p1=((a*100)+(b*10)+c)*e;
p2=((a*1000)+(b*100)+(c*10))*d;
p2test=((a*100)+(b*10)+c)*d;
p1Check=checkNum(p1,arrSetN,numofDigs);
p2Check=checkNum(p2test,arrSetN,numofDigs);
if(p1>999 || p2test>999 || p1<100 || p2test<100)
{
continue;
}
sum=p1+p2;
sumCheck=checkNum(sum,arrSetN,numofDigs);
if(sumCheck==true && p1Check==true && p2Check==true)
{
tally++;
//fout<<a<<" "<<b<<" "<<c<<" "<<d<<" "<<e;
//fout<<"\t"<<p1<<" "<<p2<<" "<<sum<<"\n";
}
}
}
}
}
}
fout<<tally<<"\n";
}

Generally, when the results of a program are different with different compilers, that usually means somewhere in your program you are running into Undefined Behavior.
In your case, the comparison of j<=numofDigs in checkNum is incorrect. You are accessing past the end of arrSetN when j==numofDigs. Since this is undefined, you can get different results.
There may be other similar places, but this is the one I noticed.

Related

Understanding the dp on tree

I was recently solving a problem from Codeforces. After giving it a lot of tries I was not able to get how in tree dp the matrix calculation works in the editorial solution. The following is the code where I have added comments to the parts I don't understand in it.
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int f[2][10010][110];//0 max 1 min
char s[10010];
int tr[10010][2],size,n,fa[10010],p,m,minn,pre;
void dfs(int x)
{
//cout<<x<<" "<<f[0][x][0]<<endl;
if (!tr[x][0]) return;
int l=tr[x][0],r=tr[x][1];
dfs(l),dfs(r);
/*The part which gets complicated need help why and how this calculation works*/
for (int i=0;i<=minn;i++)
for (int j=0;i+j<=minn;j++)
{
f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
f[0][x][i+j+(p>=m)]=max(f[0][x][i+j+(p>=m)],f[0][l][i]-f[1][r][j]);
f[1][x][i+j+(p<m)]=min(f[1][x][i+j+(p<m)],f[1][l][i]+f[1][r][j]);
f[1][x][i+j+(p>=m)]=min(f[1][x][i+j+(p>=m)],f[1][l][i]-f[0][r][j]);
}
}
int main()
{
scanf("%s",s+1);
scanf("%d%d",&p,&m);
memset(f[0],-63,sizeof(f[0]));
memset(f[1],63,sizeof(f[1]));
/* Why we have used min of the two and how does it handle both condition */
minn=min(p,m);
n=strlen(s+1);
size=1;pre=size;
for (int i=1;i<=n;i++)
{
if (s[i]=='('||s[i]=='?')
{
tr[pre][tr[pre][0]?1:0]=++size;
fa[size]=pre;
pre=size;
}
else if (s[i]==')') pre=fa[pre];
else f[0][size][0]=f[1][size][0]=s[i]-'0',pre=fa[pre];
}
dfs(1);
printf("%d",f[0][1][minn]);
}
The part where I get lost is this
f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
f[0][x][i+j+(p>=m)]=max(f[0][x][i+j+(p>=m)],f[0][l][i]-f[1][r][j]);
f[1][x][i+j+(p<m)]=min(f[1][x][i+j+(p<m)],f[1][l][i]+f[1][r][j]);
f[1][x][i+j+(p>=m)]=min(f[1][x][i+j+(p>=m)],f[1][l][i]-f[0][r][j]);
I always struggle with such types of problems. Can someone give the link to approach such problems.
Which part of the lines don't you understood? I take one line
f[0][x][i+j+(p<m)]=max(f[0][x][i+j+(p<m)],f[0][l][i]+f[0][r][j]);
and rewrite it
const int index_max = 0;
int y = i+j + (p<m? 1: 0); // in your code p<m is cast to int, true=1, false=0
int old_max = f[index_max][x][y];
int next_value = f[index_max][l][i] + f[index_max][r][j]:
f[index_max][x][y] = max(old_max, next_value);
You are looking for the maximum of the next_values of your double-loop. As l, r are fixed the next_values are sums of values in two rows.
Similar for the other 3 lines.

What is wrong with this recursive function?

I have to write a recursive function (not using vector or string) to reverse a number and return it. For example if I enter 35, it should return 53. My code is (which is not working):
int reverse( int number )
{
if( number < 10 )
return number;
number = fmod(number,10);
return reverse( number );
}
If I enter 35 for example, this code gives me only 5... what happens to 3??
You cannot expect that a recursive function taking one single int and returning an int and making last digit first could successfully reverse a number. Let's imagine f does it, and see what happens for resp 1234 and 4123.
if you turn right, f(1234) should return f(4123) which is a non sense because we know that they will have different values. And if you turn lest f(4123) should return f(1234) exhibiting same problem.
That means that the recursive function should have at least 2 parameters, and the simpler is number_to_convert, number_converted_so_far, because now you have a correct stop point when the number to convert has no more digits.
In your code, the problem is that after first recursion, your number has only one single digit (the last one) so all other digits are irremidiably lost.
Are you allowed to pull in math library functions like log10?
#include <math.h>
int reverse(int number) {
if (number == 0) {
return number;
}
return (number % 10) * pow(10, floor(log10(number))) + reverse(number / 10);
}
Here is the correct function.
int fun(int a)
{
if(a<10)
return a;
int no=0,b=a;
while(b)
{
no++;
b/=10;
}
int l=a%10;
return l*pow(10,no-1)+fun(a/10);
}

Task similar to happy number

I am solving a c++ algorithmic problem and I don't know why I don't get a right answer. The problem consists in : there is given a row of n numbers. The you need to take each number and add the square of its digits till you get the sum 4 or 1. Then you need to print how many times you have added that number. His is an example: you have a row of 2 numbers: 89 and 68. You start with 89:
64 + 81 = 145;(1) 1 + 16 + 25 = 42;(2) 16 + 4 = 20;(3) 4 + 0 = 4;(4)
and we stop because it is 4. We need to print 4 because we added 4 times again and again till we got 4 or 1.The same with 68. My code is in c++ but it uses for files c.
#include<stdio.h>
#include<math.h>
FILE *f,*g;
int n,i,a[500],sqr,nr;
int main()
{
f = fopen("unupatru.in","r");
fscanf(f,"%d\n",&n);
for(i=1;i<=n;i++)fscanf(f,"%d",&a[i]);
fclose(f);
for(i=1;i<=n;i++)
{
nr=0;
sqr=0;
while(sqr!=4 || sqr !=1)
{
while(a[i])
{
sqr+=pow(a[i]%10,2);
a[i]/=10;
}
a[i]=sqr;
nr++;
}
g=fopen("unupatru.out", "w");
fprintf(g,"%d\n",nr);
fclose(g);
}
return 0;
}
Please help me
The problem with my code is that when I click on run and compile it doesn't stop running please help
Not sure is enough but...
You should put sqr = 0 also inside the external while and (as pointed by Igor Tandetnik) modify the test using && instead ||
Or better: you shuold use do/while (with sqr=0 only inside)
do
{
sqr=0;
while(a[i])
{
sqr+=pow(a[i]%10,2);
a[i]/=10;
}
a[i]=sqr;
nr++;
}
while(sqr!=4 && sqr !=1)
#include<iostream>
#include<cmath>
#include<fstream>
using namespace std;
FILE *f,*g;
int n,i,a[500],sqr,nr,b[500];
int main()
{
f = fopen("unupatru.in","r");
fscanf(f,"%d\n",&n);
for(i=1;i<=n;i++)fscanf(f,"%d",&a[i]);
fclose(f);
for(i=1;i<=n;i++)
{
nr=0;
sqr=0;
while(sqr!=4 && sqr !=1)
{
sqr=0;
while(a[i])
{
sqr+=pow(a[i]%10,2);
a[i]/=10;
}
a[i]=sqr;
nr++;
b[i]=nr;
}
}
g=fopen("unupatru.out", "w");
for(i=1;i<=n;i++)
fprintf(g,"%d ",b[i]);
fclose(g);
return 0;
}

getting TLE from mouse maze in c++

I keep getting TLE in this question.I have tried to use scanf printf instead of cin cout but it didnt work.Then,I tried another question which has same
description,the only different is input N which means test case change from 1000 to 10^6.However, I got all AC there.I just cant figure out why.
following is the question
Description
Write a program that simulates a mouse in a maze. The program must count the steps taken by the mouse from the starting point to the final point.
The maze type is shown in following figure:
S$###
$$#$$
$$$##
##$$F
it consists of S (starting point), #(walls), $(road) and F (final point).
In above case, it needs 7 steps from S to F as following figure,
S$###
$$#$$
$$$##
##$$F
and the mouse can move in the four directions: up, down, left, right. There may be more than one way to reach final point, the program only need to print the least steps.
If there is no way from S to F, then print -1.
Input
The first line has an integer N(1<=N<=1000), which means the number of test cases.
For each case, the first line has two integers. The first and second integers R and C (3<=R, C<=500) represent the numbers of rows and columns of the maze, respectively. The total number of elements in the maze is thus R x C.
The following R lines, each containing C characters, specify the elements of the maze.
Output
Print out the least steps for each case, and there is a new line character at the end of each line.
Sample Input
3
4 5
S$###
$$#$$
$$$##
##$$F
4 5
S$$##
#$$$#
#$#$#
#$$$F
4 5
##S$#
$##$$
$$$##
#F###
Sample Output
7
7
-1
following is my code
#include <iostream>
#include <climits>
using namespace std;
int least_step;
void maze(char a[501][501],int,int,int,int,int);
#define wall '#'
int main(){
int ncase;
cin>>ncase;
char a[501][501];
while(ncase--){
int num1,num2;
cin>>num1>>num2;
least_step = INT_MAX;
int si,sj;
for(int i=0;i<num1;i++){
for(int j=0;j<num2;j++){
cin >> a[i][j];
if(a[i][j]=='S'){
si = i;
sj = j;
}
}
}
maze(a,si,sj,num1,num2,0);
if(least_step==INT_MAX){
least_step = -1;
}
cout<<least_step<<endl;
}
return 0;
}
void maze(char a[501][501],int i,int j,int num1,int num2,int step){
if(a[i][j] == 'F'){
if(step<least_step){
least_step = step;
}
return;
}
a[i][j] = wall;
if(i+1<num1&&a[i+1][j] != wall){
maze(a,i+1,j,num1,num2,step+1);
}
if(j+1<num2&&a[i][j+1] != wall){
maze(a,i,j+1,num1,num2,step+1);
}
if(i-1>=0&&a[i-1][j] != wall){
maze(a,i-1,j,num1,num2,step+1);
}
if(j-1>=0&&a[i][j-1] != wall){
maze(a,i,j-1,num1,num2,step+1);
}
a[i][j] = '$';
return;
}

Predicting next char in 'random' text generation based on some input file

I am writing a program that generates random text based on the Markov model. I am running into a problem, with some files that have a lot of spaces in between words, the initial seed is seen to be a space. The problem is that all the next characters are seen as spaces as well and so the random text that is generated is just a blank documents as nextChosenChar is always a space.
Can someone suggest some solution to this problem?
I tried to come up with a solution as seen the latter part of the code below, but to no avail.
char ChooseNextChar(string seed, int order, string fileName){
Map<string, Vector<char> > nextCharMap;
ifstream inputStream;
inputStream.open(fileName.c_str());
int offset = 0;
Vector<char> charsFollingSeedVector;
inputStream.clear();
char* buffer = new char [order + 1];
char charFollowingSeed;
static int consecutiveSpaces = 0;
while (!inputStream.eof()) {
inputStream.seekg(offset);
inputStream.read(buffer, order + 1);
string key(buffer, order);
if (equalsIgnoreCase(key, seed)) {
//only insert key if not present otherwise overwriting old info
if (!nextCharMap.containsKey(seed)) {
nextCharMap.put(seed, charsFollingSeedVector);
}
//read the char directly following seed
charFollowingSeed = buffer[order];
nextCharMap[seed].push_back(charFollowingSeed);
}
offset++;
}
//case where no chars following seed
if (nextCharMap[seed].isEmpty()) {
return EOF;
}
//determine which is the most frequent following char
char nextChosenChar = MostFequentCharInVector(seed, nextCharMap);
//TRYING TO FIX PROBLEM OF ONLY OUTPUTTING SPACES**********
if (nextChosenChar == ' ') {
consecutiveSpaces++;
if (consecutiveSpaces >= 1) {
nextChosenChar = nextCharMap[seed].get(randomInteger(0, nextCharMap[seed].size()-1));
consecutiveSpaces = 0;
}
}
return nextChosenChar;
}
If you really want a character-based model, you won't get very natural looking text as output, but it is definitely possible, and that model will fundamentally be able to deal with sequences of space characters as well. There is no need to remove them from the input if you consider them a natural part of the text.
What is important is that a Markov model does not always fall back to predicting the one character that has the highest probability at any given stage. Instead, it must look at the entire probability distribution of possible characters, and chooses one randomly.
Here, randomly means it picks a character not pre-determined by the programmer. Still, the random distribution is not the uniform distribution, i.e. not all characters are equally likely. It has to take into account the relative probabilities of the various possible characters. One way to do this is to generate a cumulative probability distribution of characters, i.e. for example, if the probabilities are
p('a') == 0.2
p('b') == 0.4
p('c') == 0.4
we represent them as
p('a') == 0.2
p('b') == p('a') + 0.4 == 0.6
p('c') == p('a') + p('b') == 1.0
Then to generate a random character, we first generate a uniformly distributed random number N between 0 and 1, and then choose the first character whose cumulative probability is no less than N.
I have implemented this in the example code below. The train() procedure generates a cumulative probability distribution of the following-characters, for every character in the training input. The 'predict()' procedure applies this to generate random text.
For a full implementation, this still lacks:
A representation of the probability distribution for the initial character. As you see in the 'main()' function, my output simply always starts with 't'.
A representation of the length of the output string, or the final character. 'main()' simply always generates a string of length 100.
The code was tested with GCC 4.7.0 (C++11 option) on Linux. Example output below.
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <map>
#include <numeric>
#include <algorithm>
#include <random>
template <typename Char>
class Markov
{
public:
/* Data type used to count the frequencies (integer!) of
characters. */
typedef std::map<Char,unsigned> CharDistributionMap;
/* Data type used to represent a cumulative probability (float!)
distribution. */
typedef std::vector<std::pair<Char,float>> CharDistribution;
/* Data type used to represent the Markov model. Each character is
mapped to a probality distribution of the characters that follow
it. */
typedef std::map<Char,CharDistribution> MarkovModel;
/* The model. */
MarkovModel _model;
/* Training procedure. */
template <typename Iterator>
void train(Iterator from, Iterator to)
{
_model = {};
if (from == to)
return;
std::map<Char,CharDistributionMap> proto_model {};
/* Count frequencies. */
Char current = *from;
while (true) {
++from;
if (from == to)
break;
Char next = *from;
proto_model[current][next] += 1;
current = next;
}
/* Transform into probability distribution. */
for (const auto &entry : proto_model) {
const Char current = entry.first;
const CharDistributionMap &freq = entry.second;
/* Calculate total frequency of current character. */
unsigned total =
std::accumulate(std::begin(freq),std::end(freq),0,
[](unsigned res,const std::pair<Char,unsigned> &p){
return res += p.second;
});
/* Determine the probability distribution of characters that
follow the current character. This is calculated as a cumulative
probability. */
CharDistribution dist {};
float probability { 0.0 };
std::for_each(std::begin(freq),std::end(freq),
[total,&probability,&dist](const std::pair<Char,unsigned> &p){
// using '+=' to get cumulative probability:
probability += static_cast<float>(p.second) / total;
dist.push_back(std::make_pair(p.first,probability));
});
/* Add probability distribution for current character to the model. */
_model[current] = dist;
}
}
/* Predict the next character, assuming that training has been
performed. */
template <typename RandomNumberGenerator>
Char predict(RandomNumberGenerator &gen, const Char current)
{
static std::uniform_real_distribution<float> generator_dist { 0, 1 };
/* Assume that the current character is known to the model. Otherwise,
an std::out_of_range exception will be thrown. */
const CharDistribution &dist { _model.at(current) };
/* Generate random number between 0 and 1. */
float random { generator_dist(gen) };
/* Identify the character that has the greatest cumulative probabilty
smaller than the random number generated. */
auto res =
std::lower_bound(std::begin(dist),std::end(dist),
std::make_pair(Char(),random),
[](const std::pair<Char,float> &p1, const std::pair<Char,float> &p2) {
return (p1.second < p2.second);
});
if (res == std::end(dist))
throw "Empty probability distribution. This should not happen.";
return res->first;
}
};
int main()
{
/* Initialize random-number generator. */
std::random_device rd;
std::mt19937 gen(rd());
std::string input { "this is some input text with many spaces." };
if (input.empty())
return 1;
/* We append the first character to the end, to ensure that even the
last character of the text gets a non-empty probability
distribution. A more proper way of dealing with character that
have empty distributions would be _smoothing_. */
input += input[0];
Markov<char> markov {};
markov.train(std::begin(input),std::end(input));
/* We set the initial character. In a real stochastic model, there
would have to be a separate probality distribution for initial
character and we would choose the initial character randomly,
too. */
char current_char { 't' };
for (unsigned i = 0 ; i < 100 ; ++i) {
std::cout << current_char;
current_char = markov.predict(gen,current_char);
}
std::cout << current_char << std::endl;
}
Some example output generated by this program:
t mext s.t th winy iny somaces sputhis inpacexthispace te iny me mext mexthis
tes is manputhis.th is wis.th with it is is.t s t winy it mext is ispany
this maces somany t s it this winy sputhisomacext manput somanputes macexte iso
t wispanpaces maces tesomacexte s s mes.th isput t wit t somanputes s withit sput ma
As you can see, the distribution of space characters follows, sort of naturally, the distribution found in the input text.
One solution would be to stream the characters one by one from the file so that your reading loop would look more like this:
char buffer[order];
inputStream.get(buffer,order);
char next_char;
while ( inputStream.get(next_char) )
{
string key(buffer, order);
if (equalsIgnoreCase(key, seed)) {
// only insert key if not present otherwise overwriting old info
if (!nextCharMap.containsKey(seed)) {
nextCharMap[seed] = Vector(charFollowingSeed);
}
else
{
nextCharMap[seed].push_back(charFollowingSeed);
}
// Update the buffer.
for(unsigned int i=1; i<order; ++i) buffer[i-1]=buffer[i];
buffer[order-1]=next_char;
}
Then you can discard extra spaces like this:
....
while ( inputStream.get(next_char) )
{
//Remove multiple spaces from input.
if( next_char==' ' and buffer[order-1]==' ') continue
string key(buffer, order);
....