Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - NoviParagon

Pages: [1]
1
You're right about std::vector<unsigned int>; I have no intention of using this to generate negative primes, and if I did for some reason want negative primes I would probably just create a new vector where these already-generated primes are altered to be negative - and then if I wanted I could merge the two together into a single vector of primes (-n to n). 

As for using MSVS, well I got the professional version for free (insert joke about free food tasting better), and it's required by Unreal Engine's editor, something else I'm learning to use, which I also got for free...I use it because I really like the IDE, and support for C#/VC# but because I'm fresh I realise there may be much better options out there, maybe you can point me in the right direction?

Anyways, I'm pleased with the useful discussion generated on this thread, I think in the future I'll post more Euler problem solutions and other coding problems, as I don't make the most efficient or neat code the first time through, I'm happy to see the green 'check'! But I always like to look back on my solutions afterwards to try and make them better.

2
Thanks for the tips Xires, this improved function is gonna be very useful since a bunch of Euler problems deal with primes. I took your advice and modded it a bit. I have the primelist function contained in its own hpp/cpp file for other programs. Here is how the program for this specific problem looks now.

Euler7.cpp
(contains main)
Code: (cpp) [Select]
#include <iostream>
#include <vector>
using std::cout; using std::cin; using std::endl;

#include "primelister.hpp"

int main(){

    unsigned int recallNth = 0;
    std::vector<int> vPrimes;
    char keepGoing = 'y';

    cout << "Setting aside memory...";
    vPrimes.reserve(9999999);           //it's cool to use reserve() with push_back() for vecs
    for (int i = 2; i < 10000001; i++)
        vPrimes.push_back(i);
    cout << "\nCreating list of primes up to 10 million...";
    primeList(vPrimes);
    cout << "Done! size of list is " << vPrimes.size() << ".";

    do {
        cout << "\nEnter a number 'n' to find the 'nth' prime: ";

        cin >> recallNth;        //goes to this nth position in the vector, so long as it is a valid number
        if (cin.fail() || recallNth > vPrimes.size() || recallNth < 0) {
            cin.clear();    //clear failure state
            cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');    //ignore and discard failed input
            //limits of           maximum input stream size, and newline

            cout << "\nInput failed. Trying again..." << endl;
            continue;        //bring us back to the top of do/while loop to ask again
        }
       
        cout << endl;
        switch (recallNth) {
        case 0:
            cout << "Can't test for 0th prime!";
            break;
        default:
            cout << vPrimes[recallNth - 1] << " is the no. " << recallNth << " prime in the series of prime numbers.\n";
            break;
        }

        cout << "\nTest again? ('y' for yes, anything else to quit): ";
        cin >> keepGoing;
    } while (keepGoing == 'y');

    cin.ignore();
    return 0;
}

And then the code for primeList. I didn't use your method for removing the marked 0s, Xires (although I like it), but instead took advantage of the algorithm library and the erase-remove idiom. I also decided not to use the register keyword, because from what I researched online, the compiler will use the cpu registers automatically, and usually with better selection than a human. (I am using the most recent VC++ compiler in VS2013)
primelist.cpp
Code: (cpp) [Select]
#include <algorithm>
#include <vector>
#include "primelister.hpp"

/* "void primelist (vector<int>&)"
This function sieves through a vector of numbers 2-n and marks all non-primes by changing them to 0.
The zeroes can then be removed or ignored. In this implementation, they will be removed before the function exits.
*/

#define C(l, i, p) (l + (i * p))    //N.B.: refers to (loc + (i * pVal))

void primeList(std::vector<int> &rvPrimes){
    unsigned int loc = 0, sz = rvPrimes.size();    // 'loc' is current place in vector
    int pVal;

    #define D(i) C(loc, i, pVal)

    while (loc < sz){
        if (rvPrimes[loc]){
            pVal = rvPrimes[loc];
            for (unsigned int i = 1; D(i) < sz; ++i)
                rvPrimes[D(i)] = 0;
        }
        loc++;
    }
    rvPrimes.erase(std::remove(std::begin(rvPrimes), std::end(rvPrimes), 0), std::end(rvPrimes));    //erase-remove idiom; removes all 0s
    rvPrimes.shrink_to_fit();    //free up a little memory by reducing capacity() down to actual size()

    return;
}

and, if anyone is interested, the header file for primelist:
primelist.hpp
Code: (cpp) [Select]
#ifndef PRIMELISTER_HPP
#define PRIMELISTER_HPP

void primeList(std::vector<int>&);

#endif

3
Eh, sorry I didn't reply to this or update the post in a while, I've been busy. But I did implement a different method for finding primes using Eratosthenes' Sieve (the interface is also different), and the result is that it's WAYYYYYY faster, I can find primes up to the millions no problem, it's near instant.

This is the function I wrote for anyone interested, first you have to create a vector of ints from 2 to some n and pass by reference in main or some other function beforehand.

Code: (cpp) [Select]
/* "void primelist (vector<int>&)"
This function sieves through a vector of numbers 2-n and marks all non-primes by changing them to 0.
The zeroes can then be ignored/removed elsewhere in the program.
*/

void primeList(std::vector<int> &rvPrimes){
    int loc = 0;    //current place in vector
    int pVal;
    while (loc < rvPrimes.size()){
        if (rvPrimes[loc] == 0)
            loc++;
        else {
            pVal = rvPrimes[loc];
            for (int i = 1; (loc + (i * pVal)) < rvPrimes.size(); ++i){
                rvPrimes[loc + (i * pVal)] = 0;
            }
            loc++;
           
        }
    }
    std::cout << "done!\n";
}

4
Found it on the Webs / Re: Student pack from git
« on: October 22, 2014, 10:14:27 am »
Just signed up for this and they said I should hear back in about a week? Hopefully it's a yes since all of that stuff seems pretty useful.
Anyways thanks a lot for sharing, I appreciate it.

5
Ah, I didn't look into the arguments I could provide to cin.ignore(), that helped. And testing if(cin>>something) instead of cin.fail() is insightful, so thanks. As for the Sieve of Eratosthenes (?) , that looks pretty interesting and I'll try to implement it later, I really would like to see the compute time go down when trying to find n over 10k or so (it takes about 15 seconds for me on my computer to find n = 10001 using my own method).

I guess normally I wouldn't care about bad input for things like this but I really want to see if I can catch/correct them.

6
What is the best way of checking input from cin>> to see if it matches the target type & won't overflow? In the programs I've done so far with C++ I haven't really been checking this, and so if I enter a character like '+' or 'p' when I'm asking for a number, the program flips and usually gets stuck in a loop. I've been using cppreference.com to see what kind of functions I can use, I tried using cin.fail() (alongside clear and ignore) to check for mismatch types and it works mostly, but if a user enters more than one character like 'ep+rg'  then the loop runs for each invalid character which I rather dislike. If a mix of valid and invalid characters are entered such as "95ne" it can mess up the program since it'll run with the numbers and then with the text characters.

Also, I'm sure my method for finding primes is far from optimal, I tried to avoid just googling 'how to find primes quickly'. So I'm all for criticism/advice there.

Code: (cpp) [Select]
#include <iostream>
#include <ctime>

using std::cout; using std::cin; using std::endl;

bool isPrime(unsigned int givenNumber){        //actually determines if something is prime or not
    unsigned int divisor = 2;
    bool qPrime = true;
    while ((divisor < givenNumber) && (qPrime == true)){
        if (givenNumber % divisor == 0)
            qPrime = false;
        else
            ++divisor;
    }

    return qPrime;
}

int fnPrimes(int nthPrimeLim){    //interface for isPrime(), tests up to the nth prime set by the user in main --- see 'unsigned int recallNth'
   
    unsigned int nthPrime = nthPrimeLim;
    unsigned int testForPrime = 1;

    while (nthPrime > 1) {
        testForPrime += 2;
        if (isPrime(testForPrime) == true){
            --nthPrime;
            cout<< testForPrime << " is prime!\n";
        }
    }
    return testForPrime;
}

int main(){

    int recallNth = 0;
   
    char keepGoing = 'y';

    do {
        cout << "Enter a number 'n' to find the 'nth' prime: ";
        cin >> recallNth;        //tests up to this nth prime
        if (cin.fail()) {
            cin.clear();    //clear failure state
            cin.ignore();    //ignore and discard failed input
            cout << "\nInput failed. Try again" << endl;
            continue;        //bring us back to the top of do/while loop to ask again
        }
        cout << endl;
        cout << "We already know 2 is a prime...\n";

        std::time_t passedTime = std::time(NULL);    //set time for performance review
       
        cout << fnPrimes(recallNth) << " is the no. " << recallNth << " prime in the series of prime numbers.\n";    //notice fnPrimes called here, calls isPrime in itself
        cout << std::time(NULL) - passedTime << " seconds to solution.";

        cout << "\nTest again? ('y' for yes, anything else to quit): ";
        cin >> keepGoing;
    } while (keepGoing == 'y');

cin.ignore();
return 0;
}

7
C - C++ / Re: Basic C++ Calculator
« on: October 16, 2014, 04:40:30 pm »
Hey HTH, thanks for the note about namespaces, you bring up a good point about keeping the 'using' directive in the relevant scope so I'll update my source to reflect that.

8
C - C++ / Re: Basic C++ Calculator
« on: October 16, 2014, 02:13:34 pm »
Hey KillerAmor I hope you don't mind but I edited things a bit to show some programming concepts I think the forum could learn from :)

<snip>

<some code>


Hey, I was just browsing this forum to look for code examples and stuff, and I came across this. I tried to compile your code but it didn't work. There were some errors and weird stuff which I changed, to get it working. I also opted to use vectors instead of C-style arrays, hopefully that won't draw too much ire...

should probably look at this in a proper editor so you can see everything.

(also this is my first post, so, ah....hello)

Code: (cpp) [Select]

#include <iostream>
#include <vector>    //needed for vectors, which we will use instead of c-style arrays

/*using namespace std;
This is convenient but is generally bad programming practice, you're saying USE STD FOR EVERYTHING
But 99% of the time all you really mean is: using std::cout; It's not awful and you certainly wont have an issue with it up till about... second or third year university level But it is worth mentioning

void subtract(float[],int);
void multiply(float[],int);
void add(float[],int);
void divide(float[],int);
was all replaced with:

Once again no real issue with that, it's just not exactly efficient, or
really required to have four functions which are only wrappers for basic operations
*/

double arithmeticOperation(char, std::vector<double>, int); //changed from type float to double for enhanced accuracy
   
int main()
{
    using std::cout;      //'using' directive put inside main - try to keep namespaces restrained to their relevant scope (which isn't always global)
    using std::cin;

    char iAgain = 'y';
    int  cNumbers = 0; //Hungarian Notation for COUNT of Numbers

    do{

        do {
            cout << "How many numbers would you like to input? ";
            cin >> cNumbers;
        } while (cNumbers < 2);    //this makes sure that we always have at least 2 numbers to operate on, as anything less would be meaningless
               
        char chOper; //Once again, a variable notation scheme really helps.

        std::vector<double> rgfpNumbers;    //we C++ now, no need for that new array stuff here
        //If anyone cares, "rgfp" is range (array) of floating point

   
        for (int i = 0; i < cNumbers; ++i)
        {
            double z = 0;
            cout << "\nEnter number " << i + 1 << ": ";
            cin >> z;
            rgfpNumbers.push_back(z);    //add the input to the end of the vector, new elements are created dynamically as needed
        }
       
        do
        {
            cout << "\nEnter a math symbol you would like(+,-,/,*): ";
            cin >> chOper;

        } while (!(chOper == '+' || chOper == '-' || chOper == '*' || chOper == '/')); //Any time you are operating off of user input... verify that shit!

        /*cout<<"Would you like to do another calculation?(Y or N) ";
            cin>> answer;
            if (answer == ("Y") || answer == ("y"))
            again=true;
            else if (answer == ("N") || ("n"))
            again=false;
            else
            cout<< "Invalid response";    You have to act upon the invalid responses */
       
        cout << "The result of the operation is: " << arithmeticOperation(chOper, rgfpNumbers, cNumbers) << std::endl;
       
       
        cout << "Would you like to go again? (input 'y' for yes, any other letter for no)\n";
        cin >> iAgain;
       
    } while (iAgain == 'y');
   

    //system("PAUSE"); NEBER EBER USE THIS!!!111!!!!1 (why? because "system" behavior is dependent on platform, in a different console on a different OS this may not work)
    cout << "~press enter to exit~";
    cin.get();   
    cin.ignore();    //simple alternative to using system, lets us look over the output before closing
    return 0;
}

double arithmeticOperation(char chOper, std::vector<double> rgfpNumbers, int cNumbers)    //made a new version of this, works a lot better
{
    double fpAnswer = 0;
    int i = 0;
    switch (chOper)
    {
    case '-':
        fpAnswer = rgfpNumbers[i];
        ++i;
        for (; i < cNumbers; i++)
            fpAnswer -= rgfpNumbers[i];
        break;
    case '*':
        fpAnswer = rgfpNumbers[i];
        ++i;
        for (; i < cNumbers; i++)
            fpAnswer *= rgfpNumbers[i];
    case '+':
        for (; i<cNumbers; i++)
            fpAnswer = (rgfpNumbers[i] + fpAnswer);
        break;
    case '/':
        fpAnswer = rgfpNumbers[i];
        ++i;
        for (; i < cNumbers; i++)
            fpAnswer /= rgfpNumbers[i];
    default:
        std::cout << "error in "<< __FUNCSIG__;        //because what if we do something like divide by zero?
    }
    return (fpAnswer);
}

/****************************************************************************
This code didn't do anything right except for addition, so I changed it a lot.
/////////////////////////////////////////////////////////////////////////////

float arithmeticOperation(char chOper, float rgfpNumbers[] , int cNumbers)
{
float fpAnswer = 0;
switch(chOper)
{
case '-':
for (int i=0;i<cNumbers;i++)
fpAnswer=(rgfpNumbers[i] - fpAnswer);
break;
case '*':
for (int i=0;i<cNumbers;i++)
fpAnswer=(rgfpNumbers[i] * fpAnswer);
break;
case '+':
for (int i=0;i<cNumbers;i++)
fpAnswer=(rgfpNumbers[i] + fpAnswer);
break;
case '/':
for (int i=0;i<cNumbers;i++)
fpAnswer=(rgfpNumbers[i] / fpAnswer);
}
return (fpAnswer);
}

********************************************************************************/

Pages: [1]