Why is my solution to the 3n+1 puzzle being rejected? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to solve algorithmic problems on the UVa online judge but I am stuck on the 3n+1 problem. I see the right output every time, but the judge says it is a wrong answer. Why?
Also, how can I optimize this code so that it does not take a long time for 1000000?
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main(){
int a;
int b;
int cyclelength(int i);
while (scanf("%d %d\n",&a,&b)==2){
int max = 0;
if (b < a){
for (int i = b; i < a; i++){
if (cyclelength(i) > max)
max = cyclelength(i);
}
}
else
{
for (int i = a; i < b; i++){
if (cyclelength(i) > max)
max = cyclelength(i);
}
}
cout << a << " " << b << " " << max << endl;
}
}
int cyclelength(int i){
if(i==1)
return 1;
if(!(i%2))
return cyclelength(i/2)+1;
else
return cyclelength(3*i+1)+1;
}

Your submission is incorrect because you aren't iterating over the range from a to b, inclusive.
The problem statement reads:
For each pair of input integers i and j you should output i, j, and the maximum cycle length for integers between and including i and j.
Your code loops over
for (int i = b; i < a; i++)
and
for (int i = a; i < b; i++)
thus omitting a in the former case and b in the latter.
You should change the loops to
for (int i = b; i <= a; i++)
and
for (int i = a; i <= b; i++)
You can speed up your code somewhat by memoizing the results of cyclelength. This lets you look up previously computed values instead of spending time on computing them again.
Here is a memoized version of cyclelength:
#include <map>
using namespace std;
map<long long, int> memo;
int cyclelength(long long i) {
if (i == 1) {
return 1;
}
if (memo.count(i) == 1) {
return memo[i];
}
if (i%2 == 0) {
return memo[i] = 1 + cyclelength(i/2);
} else {
return memo[i] = 1 + cyclelength(3*i + 1);
}
}
An unordered_map would be faster, but the UVA judge returned a compilation error for #include <unordered_map>.
Note that my version of cyclelength takes a long long argument. That lets me calculate cyclelength(999999), which eventually causes an integer overflow due to repeated 3n+1 operations if you limit yourself to 32-bit integer values. The problem statement promises that "no operation overflows a 32-bit integer" and you can get your submission accepted if you only use int values, but you have to use a larger integer type if you want to compute cyclelength for values in the range [1, 1000000).

Related

Limit on array size

I wrote the following code in c++ which was supposed to print as well as calculate all the prime numbers till n.
The code is perfectly working for n<=10000 but is not working for n>=100000.
#include "iostream"
#include "vector"
using namespace std;
int main(){
int n,ans=0;
cin>>n;
vector <bool> v(n+1,true);
for(int i=2;i<=n;i++){
if(v[i]){
cout<<i<<endl;
ans++;
for(int j=i*i;j<=n;j+=i)
v[j]=false;
}
}
cout<<endl<<ans;
return 0;
}
Kindly state the reason.
Thank you.
In your inner look, j=i*i will overflow a 32-bit signed integer at around 46341. The easiest fix there is to use a long long for j and also cast i correctly before multiplication.
So, change the inner loop to
for (auto j = static_cast<long long>(i) * i; j <= n; j += i)
And that should be it.
As a side note, please don't #include standard headers with double quotes; prefer <vector> and <iostream>.
UPDATE: As a more robust way of doing the same thing (and still using roughly the same code,) I'd suggest the following:
#include <iostream>
#include <vector>
using namespace std;
int main(){
size_t n, ans = 0; // A) Switch to size_t, which can accommodate the largest
// size of a vector; if your number is larger, then we
// can't make an array for it...
cin >> n;
vector<bool> v (n, true); // B) Remove the chance of overflow; indices are
// now shifted by one
for(size_t i = 2; i <= n; i++) {
if (v[i - 1]) {
cout << i << endl;
ans++;
if (n / i >= i) { // C) Check for possibility of overflow in `i*i`
// D) Switch j to correct type
// E) Check if `j+=i` overflowed
for (size_t j = i * i; j <= n && j > i; j += i)
v[j - 1] = false;
}
}
}
cout << endl << ans;
return 0;
}
The really important changes are A, C, and D. The other two, B and E are needed for complete correctness, but they only matter when you have enough actual memory in your system to almost overflow size_t (otherwise, the ctor for vector would throw.) This is completely probably on 32-bit systems, but impossible on 64-bit builds for now.
Also note that A, B, and D are "essentially" free (perf-wise,) but C and E do have some impact on running time (although probably tiny; E is the more onerous.)

Hey, I am trying to submit the source code of codechef sept challange Q code - "MNDIGSM2". But it reject my answer as "Runtime error"

When i run the source code on sample cases of their example it runs fine but when I submit the question It says runtime error.
Here is my Source code and link of the question.
Question link - https://www.codechef.com/SEPT21C/submit/MNDIGSM2
Below is the code.
#include <iostream>
#include <vector>
// #include <bits/stdc++.h>
using namespace std;
// #define fast ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int converter(int n , int b){
vector<int> vec;
int sum = 0;
while(n>0){
vec.push_back(n%b);
n = n / b;
}
int vecSize = vec.size();
for(int i = 0;i<vecSize;i++){
// cout<<
sum = sum + vec[i];
}
return sum;
}
int minVal(vector<int> arr , int len){
int min = arr[0], c = 0;
// if(arr)
for(int i = 1 ; i< len;i++){
if (arr[i] < min){
min = arr[i];
c = i;
}
}
return c;
}
int main() {
// your code goes here
// fast;
int test;
cin>>test;
while(test--){
int n ,r;
cin>>n>>r;
int l = 2;
// ll copy = l;
int arSize = (r-2)+1;
vector<int> arr(arSize);
for(int i = 0;i< arSize ;i++){
arr[i] = converter(n,l);
l++;
}
int tobe = minVal(arr , arSize);
cout<<tobe + 2<<endl;
}
return 0;
}
Maybe I do not understand the question fully. There is not enough information available.
It could be that the program slows down because the usage of the std::vector. First you calculate, then store the values and then iterate again over all values.
This is not necessary. You can do all calculations inline without the need for additional storage.
And, additionally, all these "contest" questions do not have the intention, to improve your programming skills.
Basically the language doesn't matter. The important thing is the algorithm. They want you to find a "good" algorithm.
Bruteforcing is nearly never a feasible solution. If you read about big numbers like 10^12, then you know already in advance that you will get a TLE with the brute force solution.
Regarding this horrible and non compliant C++ slang that is used on this "competetion" sides, please note that this is nearly never necessary. You have no time contraints to submit a solution. So, you could use also real C++ code.
Anyway. I corrected your code and added meaningful varibale names, comments and formatting. So, logically, the approach is the same, but it is readable.
Of course it may fail as well, because it is still brute forcing . . .
#include <iostream>
#include <limits>
constexpr unsigned long long BaseStart = 2ull;
int main() {
// Get number of test cases
unsigned int numberOfTestCases{};
std::cin >> numberOfTestCases;
// Work on all test cases
for (unsigned int testCase{}; testCase < numberOfTestCases; ++testCase) {
// Get the value to check and the upper limit for the base
unsigned long long valueToCheck{}, upperLimitBase{};
std::cin >> valueToCheck >> upperLimitBase;
// Here we will store the minimum sum to check
unsigned long long minimumsumOfDigits{std::numeric_limits<unsigned long long>::max()};
// Here we will store the result
unsigned long long minimumBase{};
for (unsigned long long base{BaseStart}; base <= upperLimitBase; ++base) {
// And this will be the running sumOfDigits
unsigned long long runningSumOfDigits{};
// get the digits of the value and calculate the running sum
unsigned long long value{valueToCheck};
while (value > 0) {
// Get digits via modulo division and add up
runningSumOfDigits += value % base;
value /= base;
}
// Get current minimum
if (runningSumOfDigits < minimumsumOfDigits) {
minimumsumOfDigits = runningSumOfDigits;
minimumBase = base;
}
}
std::cout << minimumBase << '\n';
}
return 0;
}
This code can of course be optimized further, but for this I would need more information . . .

Why is this one, pointless line of code the only thing that makes this function work? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm learning C++ and decided to make a bunch of small, short functions to practice. This following bit of code will give me an incorrect answer:
float pairwiseSum(float data[], int arraySize, int naive_sum_size=8) {
if (arraySize <= naive_sum_size) {
return naiveSum(data, arraySize);
} else {
int m = arraySize / 2;
return pairwiseSum(&data[0], m) + pairwiseSum(&data[m], arraySize-m);
}
}
naiveSum in this case just iterates through an array accumulates the sum and appears to work fine. If I have an array of 64 1s, it will tell me the sum is 288.
However, this version of the code works perfectly every time:
float pairwiseSum(float data[], int arraySize, int naive_sum_size=8) {
if (arraySize <= naive_sum_size) {
cout << "";
return naiveSum(data, arraySize);
} else {
int m = arraySize / 2;
return pairwiseSum(&data[0], m) + pairwiseSum(&data[m], arraySize-m);
}
}
I'm using Fedora 21 and compiling with g++ 4.9.2
Why does one function work, but the other one fail?
Edit: the complete program as it appears in my main.cpp file is below.
#include <iostream>
#include <stdlib.h>
using namespace std;
float naiveSum(float data[], int arraySize) {
float sum;
for (int i = 0; i < arraySize; i++)
sum += data[i];
return sum;
}
// Divide-and-conquer algorithm is a little faster than the
// Kahan Summation Algorithm, but also less accurate.
float pairwiseSum(float data[], int arraySize, int naive_sum_size=8) {
if (arraySize <= naive_sum_size) {
//cout << "";
return naiveSum(data, arraySize);
} else {
int m = arraySize / 2;
return pairwiseSum(&data[0], m) + pairwiseSum(&data[m], arraySize-m);
}
}
int main() {
const int SIZE = 64;
const int rndRange = 100;
// generate random array
srand(time(NULL));
float xs[SIZE];
for (int i=0; i<SIZE; i++)
// +1 prevents division by zero
//xs[i] = rand() % rndRange / (float)(rand() % rndRange + 1);
xs[i] = 1;
// Print kahan sum of random array
//cout << "Kahan Sum: " << kahanSum(xs, SIZE) << endl << endl;
cout << endl << pairwiseSum(xs, SIZE) << endl;
return 1;
}
Edit: yes, it was indeed a problem with sum not being intialized. Thanks for your help.
sum is not initialized in naiveSum. The rest is just undefined behavior (caused by indeterminate value in sum) manifesting itself differently with or without that irrelevant cout << "" line.
There are many different ways cout << "" can cause that indeterminate initial value of sum to end up being zero and thus create an appearance of naiveSum working properly.

Why is my C++ program not working? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to build a program that reads numbers from "bac.txt" and returns the 2 digit number/numbers (10,11,12,...,99) that appear most frequently. For example if the file "bac.txt" contains 393 17775787 72194942 12121774 it will return 77 and 21. I have managed to build a working function counter(int n) that can count how many times n is found in the file and returns i which is the number of times n has been found. Now I can't seem to find a way to print to the screen the number/numbers that are found most often. I tried to use some kind of for loop but it doesn't work.
Here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int counter(int n){
int i=0,j=0;
char x1=n/10+'0';
char x2=n%10+'0';
char a;
char b=NULL;
fstream fisier("bac.txt", fstream::in);
while (fisier >> noskipws >> a) {
if(b==x1&&a==x2)
i++;
b=a;
}
return i;
}
int main()
{
int v[90];
int v1[90];
int i,maxim=0,nr;
for(i=10;i<100;i++)
{
v[i]=counter(i);
if(v[i]>maxim)maxim=v[i];
}
for(i=10;i<100;i++)
if(v[i]==maxim)
cout<<i;
}
I have corrected the code.It works now.
You may check the changes.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int counter(int n)
{
int i = 0, j = 0;
char x1 = n / 10 + '0';
char x2 = n % 10 + '0';
char a;
char b;
fstream fisier("bac.txt", fstream::in);
fisier >> b;
while (fisier >> a) {
if (b == x1 && a == x2)
i++;
b = a;
}
return i;
}
int main()
{
int v[101];
int i, maxim = 0, nr;
for (i = 10; i < 100; i++) {
v[i] = counter(i);
if (v[i] > maxim)
maxim = v[i];
}
for (i = 10; i < 100; i++)
if (v[i] == maxim)
cout << i;
}
i can't say you why your program's not working, but i can say you how i'd solve it. you have to store in an int vector the 2 digit number that you read from file (ex. if file contains 1234 the int vector will contains 12 23 34) than you have to find the 2 number that appear most times, so, you have read the first vector element and store it in a variable, than you count how many times it appear in the vector and you save the number you were searching in max_a and the times it appear in max_times_a (remember that when you find in the vector the number you're searching you have to put a -1 on it) than you search in the vector another number and count how many times it appear (putting -1 on that number) than you store that number in max_b and the times it appears in max_times_b. than what you have to do is to slide the vector and if you reach the end becouse you only read -1 you have max_a and max_b as result, but if you find a number you have to count how many times it appear and checking if it appear most times of max_a or max_b, and in case it appear most times you have to swap the values. i hope to have been useful to you.
Tommaso

Project Euler task #8, code starts returning wrong answers after certain point [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am having some sort of a problem in a task from
https://projecteuler.net/problem=8, (finding highest product of 13 consecutive numbers from a 1000-number string) where up to some point the program gives me predictable results and then the function returns a number very close to the unsigned long long int range. The point where it occurs depends on the values which were read, for instance if the string of numbers consisted mostly of 8s and 9s, it would happen sooner than it would if it had only 5s and 6s. Why does it happen?
#include <iostream>
#include <fstream>
using namespace std;
int product (int res, int a, char buffer[]){
for (int i = 0; i < a; i++){
//simple char to int conversion
res*=(buffer[i] - '0');
}
return res;
}
int main () {
char check;
int res = 1;
fstream plik;
plik.open ("8.txt");
unsigned long long int high;
unsigned long long int result;
//main function in the program
if (plik.good()){
char buffer [13];
for (int i = 0; i < 13; i++){
plik >> buffer[i];
}
result = product (res, 13, buffer);
high = result;
cout << high << endl;
//the main checking loop
while (!plik.eof()){
//just an interruption to make it possible to view consecutive products
//the iteration in the buffer
for (int i = 0; i < 12; i++){
buffer[i] = buffer[i+1];
}
plik >> buffer[12];
result = product (res, 13, buffer);
//comparison between the current product and highest one
if (high < result){
high = result;
}
cin >> check;
cout << high << endl;
//again a tool for checking where the problem arises
for (int i = 0; i < 13; i++){
cout << buffer[i] << " ";
}
cout << endl;
}
plik.close();
cout << high << endl;
}
return 0;
}
The program prints out the currently highest product and all the numbers currently contained in the array.
It looks like this:
The error
Use unsigned long long int instead of int to calculate the product. The product of 13 digits can easily become larger than the largest int.