Neumann's Random Generator - c++

Please read the task first: http://codeabbey.com/index/task_view/neumanns-random-generator
I have to keep track of the number of iterations, but I get very strange results. In the example after the task we have the numbers 0001 and 4100 and they should come to loop after 2 and 4 iterations. But my results are 1, 4 or if I change the place of the counter 2 or 5 but never 2 and 4. Here is my code:
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int value;
int counter;
int result;
int setvalue = 1; // use to exit the loop if setvalue == 0;
cin >> n;
vector<int> new_results(0); // use to store all the results from iterations
vector<int> results_vec(0); // use to store the number of iterations for each number
for (int i = 0; i < n ; i++)
{
cin >> value;
while(setvalue == 1)
{
value = value*value;
value = (value % 1000000) / 100;
if(find(results_vec.begin(), results_vec.end(), value) == results_vec.end())
{
results_vec.push_back(value);
}
else
{
counter = results_vec.size();
new_results.push_back(counter);
setvalue = 0;
}
}
results_vec.clear();
}
for (int i = 0; i < new_results.size() ; i++)
{
cout << new_results[i] << " ";
}
}

Going in and out of a string the way you have is really very ugly and extremely expensive computationally.
Use
(value % 1000000) / 100;
instead to extract the middle four digits. This works by (1) taking the modulus to remove the leading two digits then (2) removing the last two with integer division.
As it's so much simpler, I suspect that will fix your bugs too.

Here is the correct code, thank you for all your help.
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int value;
int counter;
int result;
cin >> n;
vector<int> new_results(0); // use to store all the results from iterations
vector<int> results_vec(0); // use to store the number of iterations for each number
for (int i = 0; i < n ; i++)
{
cin >> value;
results_vec.push_back(value);
while(true)
{
value = value*value;
value = (value % 1000000) / 100;
if(find(results_vec.begin(), results_vec.end(), value) == results_vec.end())
{
results_vec.push_back(value);
}
else
{
counter = results_vec.size();
new_results.push_back(counter);
break;
}
}
results_vec.clear();
}
for (int i = 0; i < new_results.size() ; i++)
{
cout << new_results[i] << " ";
}
}

Related

Bad Access on Sieve

My block of code runs, but whenever I type in input, it returns Thread 1: EXC_BAD_ACCESS (code=1, address=0x4). I'm fairly new to coding, and was wondering what's wrong.
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int x, count = 1;
cin >> x;
vector<int> sieve;
fill(sieve.begin(), sieve.begin()+x-1, 1);
while (count <= x) {
for (int i = count+1; i <= x; i++) {
if (sieve[i-1] == 1) {
count = i;
break;
}
}
for (int i = count*count; i < x; i+=count) {
sieve[i-1] = 0;
}
}
for (int i = 0; i < x-1; i++) {
if (sieve[i] == 1) {
cout << i+1 << endl;
}
}
}
You need to allocate space for your sieve. So you might want vector<int> sieve(x). Or, you can even do vector<int> sieve(x, 1), which will allocate space for x ints and fill them all with 1s already, so you won't need the fill afterwards.

Sieve of Eratosthenes not working beyond 200,000

My C++ program to calculate all the prime numbers using sieve of Eratosthenes method stops after 200,000. But I need to calculate the primes up to 2 million. Help would be appreciated if someone could tell me where I went wrong with my code.
#include <iostream>
#include<math.h>
using namespace std;
void isprime(long long int prime[],long int n)
{
for(long long int i=0;i<=n;i++)
{
prime[i]=1;
}
prime[0]=prime[1]=0;
for(long long int i=2;i<=sqrt(n);i++)
{
if(prime[i]==1)
{
for(long long int j=2;i*j<=n;j++)
prime[i*j]=0;
}
}
for(long long int i=0;i<=n;i++)
{
if(prime[i]==1)
cout<<i<<endl;
}
}
int main()
{
long long int n;
cout<<"enter number";
cin>>n;
long long int prime[n+1];
isprime(prime,n);
return 0;
}
Since each sieve element contains only a 0 or 1, there is no need to use a long long int to store each one. std::vector<bool> potentially uses 1 bit per element and thus is optimal for memory efficiency.
Here is your code with a very few modifications to use a std::vector<bool>. Since some bit manipulation is required to get and set individual elements, this version may be slower than code which uses one byte or int per sieve element. You can benchmark various versions and decide the right trade-off for your needs.
#include <cmath>
#include <cstddef>
#include <exception>
#include <iostream>
#include <string>
#include <vector>
// returns the number of primes <= n
long isprime(long n) {
std::vector<bool> prime(n + 1);
for (long i = 0; i <= n; i++) {
prime[i] = 1;
}
prime[0] = prime[1] = 0;
long upper_bound = std::sqrt(n);
for (long i = 2; i <= upper_bound; i++) {
if (prime[i] == 1) {
for (long j = 2; i * j <= n; j++)
prime[i * j] = 0;
}
}
long num_primes = 0;
for (long i = 0; i <= n; i++) {
if (prime[i] == 1) {
++num_primes;
// std::cout << i << std::endl;
}
}
return num_primes;
}
int main() {
std::cout << "Enter the sieve size: ";
std::string line;
std::getline(std::cin, line);
std::cout << std::endl;
long len = std::stol(line);
long num_primes = isprime(len);
std::cout << "There are " << num_primes << " primes <= " << len << std::endl;
return 0;
}

Picking about random character without repetition c++

I need to pick m amount of random characters(letters) without repetition and im completely stuck, i keep getting only 1 random letter. How can i fix my code? Is there even a way to fix this or should i just scrap this idea and look for a solution from some kinf od tutorials?
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
using namespace std;
int main()
{
cout << "number below 27" << endl;
int m;
cin >> m;
srand(time(NULL));
bool repeat = false;
char letters[m];
char letter;
for(int i = 0; i < m; i++){
letter = rand()%26 +97;
repeat = true;
for(int j = 0; j < m; j++){
if(letters[m] == letters[j]){
repeat = false;
break;
}
}
if(repeat){
letters[m] = letter;
}
}
for (int i = 0; i < m; i++){
cout << letters[m];
}
}
You can use suffle -
#include <random>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main ()
{
char charSet[]={'a','b','c'};//You can add all the charecters
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(charSet,charSet+3,g);
for(auto c : charSet)
{
std::cout<<c;
}
std::cout<<endl;
return 0;
}
bool repeat = false;
vector<char> letters(m);
char letter;
for(int i = 0; i < m; i++){
do
{
repeat = false;
letter = rand()%26 +97; // generate new random number
for(int j = 0; j<=i; j++) // iterate through the already generated numbers
{
if (letter == letters[j]){ // if the generated number already exists, do the while again
repeat = true;
break;
}
}
} while(repeat);
letters[i] = letter; // assign the unique number
cout << letter;
repeat = false;
}
You repeat the random number generator until you have a unique random number.
And to output your values use i because m is constant and out of bounds:
for (int i = 0; i < m; i++){
cout << letters[i];
}
I think the direct method is to use set in C++. The following solution is done just now utilising set to ensure the unique. Hope it could be helpful.
#include <iostream>
#include <ctime>
#include <set>
#include <random>
using namespace std;
int main()
{
cout << "number below 27" << endl;
int m;
cin >> m;
srand(time(NULL));
set<char> letters_set;
while(letters_set.size() < m){
char c = rand()%26+'a';
letters_set.insert(c);
}
for(auto c: letters_set)
cout<<c<<endl;
}
A more efficient solution which also ensure the equal possibility for each letter.
#include <iostream>
#include <ctime>
#include <set>
#include <random>
using namespace std;
int main()
{
cout << "number below 27" << endl;
int m;
cin >> m;
srand(time(NULL));
vector<int> all_letters(26, 'a');
for(int i = 0; i < 26; ++i) all_letters[i] += i;
vector<char> letters_set;
for(int i = 0; i < m; ++i){
int select = rand()%all_letters.size();
letters_set.push_back(all_letters[select]);
all_letters.erase(all_letters.begin()+select);
}
for(auto c: letters_set)
cout<<c<<endl;
}
There is an obvious error in the logic of your code: when you test for repetition you compare to the beyond the end letter only, instead to all those sampled so far. The correct test would be
for(int i = 0; i < m; i++) {
bool repeating;
char tryletter;
do {
tryletter = rand()%26 +97;
repeating = false;
for(auto j=0; j!=i && !repeating; ++j)
repeating = tryletter == letters[j];
} while(repeating);
letters[i] = tryletter;
}
Though this is not the most efficient way to do what you've been asked to do. A more efficient way would be to start with all 26 letters, pick one at random and remove it from the set, then continue to pick and remove random letters. For example
std::string random_letters_without_repetition(std::size_t m)
{
std::string letters;
std::string all = "abcdefghijklmnopqrstuvwxyz";
assert(m <= all.size());
std::random_device r;
std::default_random_engine rng(r());
while(m--) {
std::uniform_int_distribution<std::size_t> uni{0,all.size()-1};
auto index = uni(rng);
letters += all[index];
all.erase(index);
}
return letters;
}

I want to print out the last result done by the loop C++

#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
int i;
int n=0;
int F[10];
F[0]=0;
F[1]=1;
cin>>n;
for(i=2; i<n+1; ++i)
{
F[i]=(F[i-1])+F[i-2];
cout <<F[i]<<endl;
}
getch();
return 0;
}
now this is a sort of a fibonacci number generator, but it outputs all previous numbers in the fibonacci series. I want it to print the last one. For example, if the input is 8, i want it to output "21" instead of 1 2 3 5 8 13 21.
#include <iostream>
#include <conio.h>
int main()
{
int F[10];
F[0] = 0;
F[1] = 1;
int n = 0;
cin >> n;
for (int i = 2; i <= n; ++i)
{
F[i] = F[i-1] + F[i-2];
}
std::cout << F[n] << std::endl;
getch();
}
Since you already know the index of the last element (n), you can just print that after the loop. I also did some other cleanup that didn't change the functionality of the program.
Note that the program originally and still assumes that n is less than 10.
Just store only 2 last values:
#include <iostream>
using namespace std;
int main()
{
int F[2] = { 1, 1 };
int n = 0;
cin>>n;
for(int i=2; i<n; ++i)
{
swap( F[0], F[1] );
F[1] += F[0];
}
std::cout << F[1] << std::endl;
return 0;
}

stuck on dynamic programming

Heres the problem:
A Milkman serves milk in packaged bottles of varied sizes. The possible size of the bottles are {1, 5, 7 and 10} litres. He wants to supply desired quantity using as less bottles as possible irrespective of the size. Your objective is to help him find the minimum number of bottles required to supply the given demand of milk.
Input Format:
First line contains number of test cases N
Next N lines, each contain a positive integer Li which corresponds to the demand of milk.
Output Format:
For each input Li, print the minimum number of bottles required to fulfill the demand
I have written this code for the problem.
#include <iostream>
#include <vector>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
#include <iomanip>
#include <locale>
#include <stdlib.h>
#include <cstring>
#include <cmath>
#include <tgmath.h>
using namespace std;
const int INF = 1000000000;
int m[4] = { 1, 5, 7, 10 };
int r[100000000];
int milk(int n) {
int q;
if (r[n] < INF)
return r[n];
if (n <= 0)
q = 0;
else {
q = INF;
for (int i = 0; i < 4; i++) {
if (n >= m[i])
q = min(q, 1 + milk(n - m[i]));
}
}
r[n] = q;
return q;
}
int main() {
int t, n;
cin >> t;
while (t--) {
cin >> n;
memset(r, INF, sizeof(r));
cout << milk(n) << endl;
}
return` 0;
}
I have used dynamic programming for this.But I only get an output zero for every input.I am new to dp.Please help.
int milk(int n) {
int min;
memset(r, 0, sizeof(r));
for (int i = 1; i <= n; i++) {
min = 10000000; // some very large value greater than n
for (j = 0; j <= 3; j++) {
if (m[j] > i)
continue;
else if (r[i - m[j]] < min)
min = r[i - m[j]];
}
r[i] = min;
}
return r[n];
}
I hope this works and it would help you , comment if you have any doubts.