This assignment is about a ship race on a lake.
I have an N array, where I input wind speed.
I have to give a K number, which determines how many consecutive days have the speed of wind between 10 and 100.
If I find the K amount of consecutive elements, I have to console out the first element's index of this sequence.
The goal is to find which day the "race" can be started.
For example:
S[10] = {50,40,0,5,0,80,70,90,100,120}
K=3
The output has to be 6, because it is the 6th element of the array, where this sequence started.
I don't know any method how can I implement this examination.
I tried this:
for (int i=0; i<N-2; i++){
if (((10<=S[i]) && (S[i]<=100)) && ((10<=S[i+1]) && (S[i+1]<=100)) && ((10<=S[i+2]) && (S[i+2]<=100))){
canBeStarted = true;
whichDayItCanBeStarted = i;
}
}
cout << whichDayItCanBeStarted << endl;
But I realised that K can be any number, so I have to examine K elements at once.
Making use of the algorithms standard library
(Restriction: the following answer provides an approach valid for C++17 and beyond)
For a problem such as this one, rather than re-inventing the wheel, you might want to consider turning to the algorithms library in the standard library, making use of std::transform and std::search_n to
produce an integer -> bool transform over wind speeds to validity of said wind speeds, followed by
searching over the result of the transform for a number of (K) sub-sequent true (valid wind speed) elements,
respectively.
E.g.:
#include <algorithm> // std::search_n, std::transform
#include <cstdint> // uint8_t (for wind speeds)
#include <iostream> // std::cout
#include <iterator> // std::back_inserter, std::distance
#include <vector> // std::vector
int main() {
// Wind data and wind restrictions.
const std::vector<uint8_t> wind_speed{50U, 40U, 0U, 5U, 0U,
80U, 70U, 90U, 100U, 120U};
const uint8_t minimum_wind_speed = 10U;
const uint8_t maximum_wind_speed = 100U;
const std::size_t minimum_consecutive_days = 3;
// Map wind speeds -> wind speed within limits.
std::vector<bool> wind_within_limits;
std::transform(wind_speed.begin(), wind_speed.end(),
std::back_inserter(wind_within_limits),
[](uint8_t wind_speed) -> bool {
return (wind_speed >= minimum_wind_speed) &&
(wind_speed <= maximum_wind_speed);
});
// Find the first K (minimum_consecutive_days) consecutive days with
// wind speed within limits.
const auto starting_day =
std::search_n(wind_within_limits.begin(), wind_within_limits.end(),
minimum_consecutive_days, true);
if (starting_day != wind_within_limits.end()) {
std::cout << "Race may start at day "
<< std::distance(wind_within_limits.begin(), starting_day) + 1
<< ".";
} else {
std::cout
<< "Wind speeds during the specified days exceed race conditions.";
}
}
Alternatively, we can integrate the transform into a binary predicate in the std::search_n invocation. This yields a more compact solution, but with, imo, somewhat worse semantics and readability.
#include <algorithm> // std::search_n
#include <cstdint> // uint8_t (for wind speeds)
#include <iostream> // std::cout
#include <iterator> // std::distance
#include <vector> // std::vector
int main() {
// Wind data and wind restrictions.
const std::vector<uint8_t> wind_speed{50U, 40U, 0U, 5U, 0U,
80U, 70U, 90U, 100U, 120U};
const uint8_t minimum_wind_speed = 10U;
const uint8_t maximum_wind_speed = 100U;
const std::size_t minimum_consecutive_days = 3;
// Find any K (minimum_consecutive_days) consecutive days with wind speed
// within limits.
const auto starting_day = std::search_n(
wind_speed.begin(), wind_speed.end(), minimum_consecutive_days, true,
[](uint8_t wind_speed, bool) -> bool {
return (wind_speed >= minimum_wind_speed) &&
(wind_speed <= maximum_wind_speed);
});
if (starting_day != wind_speed.end()) {
std::cout << "Race may start at day "
<< std::distance(wind_speed.begin(), starting_day) + 1 << ".";
} else {
std::cout
<< "Wind speeds during the specified days exceed race conditions.";
}
}
Both of the programs above, given the particular (hard-coded) wind data and restrictions that you've provided, results in:
Race may start at day 6.
You'd need to have a counter variable that's initially set to 0, and another variable to store the index where the sequence begins. and iterate through the array one element at a time. If you find an element between 10 and 100, check if the counter is equal to '0'. If it is, store the index in the other variable. Increment the counter by one. If the counter is equal to K, you're done, so break from the loop. Otherwise, if the element isn't between 10 and 100, set the counter to 0.
Related
I have arrays of types int, bool and float:
std::array<int, 3>myInts = {15, 3, 6};
std::array<bool, 2>myBools = {true, false};
std::array<float,5>myFloats = {0.1, 15.2, 100.6, 10.44, 5.5};
I would like to generate a random integer(I know how to do that) from 0 to the total number of elements (3 + 2 + 5) so the generated random Integer represents one of the values. Next based on that integer I would like to retrieve my value and do further calculations with it. The problem I am facing is that I don't want to use if else statements like these:
int randInt = RandIntGen(0, myInts.size() + myBools.size() + myFloats.size());//Generates a random Integer
if(randInt<myInts.size()){//if the random integer is less than the size of the integers array I can choose
// from the the integers array
int myValue = myInts[RandInt]
}
else if(randInt>=myInts.size() && randInt<myBools.size() + myInts.size()){//if the random integer
//is between the size o the integer's array and the size of the bool's array + the size of the integers array
//then I can choose from the bool's array
bool myValue = myBools(RandInt - myInts.size())
}
.
.
.
Then if for example randInt=2 then myValue=6 or if randInt=4 then myValue=false
However I would like that the selection algorithm was more straightforward something like:
int randInt = RandIntGen(0, myInts.size() + myBools.size() + myFloats.size());
allValues = {myInts, myBools, myFloats}
if(type_id(allValues[randInt]).name=="int")
int myValue = allValues[randInt] //(this value will be used for further calculations)
if(type_id(allValues[randInt]).name=="bool")
bool myValue = allValues[randInt] //(this value will be used for further calculations)
I've tried with a mix of templates, inheritance and linked lists however I cannot implement what I want. I think the solution should be really simple but at this time I cannot think of something else.
I am novice in C++ I've been learning already for 1 and half months, before I was doing stuff in python and everything was way easier but then I decided to try C++. I am not a experienced programmer I know some basic things and I am trying to learn new things, thanks for the help.
Most probably, you need to think how to satisfy your requirements in a simpler way, but it is possible to get literally what you want with C++17. If your compiler doesn't support C++17, you can use corresponding boost libraries. Here is the code:
#include <array>
#include <iostream>
#include <tuple>
#include <variant>
using Result = std::variant<int, bool, float>;
template<class T>
bool take_impl(int& i, const T& vec, Result& result)
{
if (i < static_cast<int>(std::size(vec)))
result = vec[i];
i -= std::size(vec);
return i < 0;
}
template<class T>
Result take(int i, const T& arrays)
{
if (i < 0)
throw std::runtime_error("i is too small");
Result res;
std::apply([&i, &res](const auto&... array) { return (take_impl(i, array, res) || ...); }, arrays);
if (i >= 0)
throw std::runtime_error("i is too large");
return res;
}
std::ostream& operator<<(std::ostream& s, const Result& v)
{
if (std::holds_alternative<int>(v))
std::cout << "int(" << std::get<int>(v);
else if (std::holds_alternative<bool>(v))
std::cout << "bool(" << std::get<bool>(v);
else
std::cout << "float(" << std::get<float>(v);
return std::cout << ')';
}
auto arrays = std::make_tuple(
std::array<int, 3>{15, 3, 6},
std::array<bool, 2>{true, false},
std::array<float,5>{0.1, 15.2, 100.6, 10.44, 5.5}
);
int main()
{
for (int i = 0; i < 10; ++i)
std::cout << take(i, arrays) << '\n';
}
If you are not required to keep separate arrays of different types, you can make one uniform array of std::variant<int, bool, float>. This will be significantly more efficient than using std::shared_ptr-s.
I have a Time limit exceeded issue in problem 100 from UVa.
the question is here:
https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=36
Here is my code. Please help me find a solution. How can I avoid such problems?
I don't know if it is the problem with cin and cout or the while loops? this program works well in my terminal when I run it.
#include <iostream>
using namespace std;
int main()
{
int i , j, temp, n;
while (cin >> i >> j) //asking for user input
{
int x, y;
x = i;
y = j;
if (i > j) //sorting i and j to fix the order of numbers
{
temp = j;
j = i;
i = temp;
}
int answer = 0;
int counter;
while (i <= j)
{
n = i;
counter = 1; // make the value of counter to 1 because it increases if i is 1
while (1)
{
if(n == 1) { //if n = 1 then stop
break;
} else if (n % 2 == 0) //cheak if i is odd
{
n = (3 % n) + 1;
} else {
n = n / 2; //cheak if i is even
}
counter++; //increase by one for every number that is not 1
}
if (counter > answer)
{
answer = counter;
}
i++;
}
cout << x << " " << y << " " << answer << "\n";
}
return 0;
}
Thanks in advance
In my humble opinion this problem is not about calculating the resulting values using the given algorithm. Because of the simplicity this is just some noise. So,maybe we are talking about a XY Problem here.
Maybe I am wrong, but the main problem here seems to be memoization.
It maybe that values need to be calculated over and over again, because they are in some overlapped range. And this is not necessary.
So, we could memorize already calculated values, for example in a std::unordered_map (or std::map). So, something like in the below:
unsigned int getSteps(size_t index) noexcept {
unsigned counter{};
while (index != 1) {
if (index % 2) index = index * 3 + 1;
else index /= 2;
++counter;
}
return counter+1;
}
unsigned int getStepsMemo(size_t index) {
// Here we will memorize whatever we calculated before
static std::unordered_map<unsigned int, unsigned int> memo{};
// Resulting value
unsigned int result{};
// Look, if we did calculate the value in the past
auto iter = memo.find(index);
if (iter != memo.end())
// If yes, then reuse old value
result = iter->second;
else {
// If no, then calculate new and memorize it
result = getSteps(index);
memo[index] = result;
}
return result;
}
This will help with many given input pairs. It will avoid recalculating steps for already calculated values.
But having thought in this direction, we can also calculate all values at compile time and store them in a constexpr std::array. Then no calculation will be done during runtime. All steps for any number up to 10000 will be precalculated. So, the algorithm will never be called during runtime.
It should be clear that this is the fastest possible algorithm, because we do nothing. Just get the value from a lookup table.
And if we want to make things nice, then we pack everything in a class and let the class encapsulate the problem. Even input and output operatores will be overwritten and used for our own purposes.
And in the end, we will have an ultra fast one liner in our function main. Please see:
#include <iostream>
#include <utility>
#include <sstream>
#include <array>
#include <algorithm>
#include <iterator>
#include <unordered_map>
// All done during compile time -------------------------------------------------------------------
constexpr unsigned int getSteps(size_t index) noexcept {
unsigned counter{};
while (index != 1) {
if (index % 2) index = index * 3 + 1;
else index /= 2;
++counter;
}
return counter+1;
}
// Some helper to create a constexpr std::array initilized by a generator function
template <typename Generator, size_t ... Indices>
constexpr auto generateArrayHelper(Generator generator, std::index_sequence<Indices...>) {
return std::array<decltype(std::declval<Generator>()(size_t{})), sizeof...(Indices) > { generator(Indices+1)... };
}
template <size_t Size, typename Generator>
constexpr auto generateArray(Generator generator) {
return generateArrayHelper(generator, std::make_index_sequence<Size>());
}
constexpr size_t MaxIndex = 10000;
// This is the definition of a std::array<unsigned long long, 10000> with all step counts
constexpr auto steps = generateArray<MaxIndex>(getSteps);
// End of: All done during compile time -----------------------------------------------------------
// Some very simple helper class for easier handling of the functionality
struct StepsForPair {
// A pair with special functionality
unsigned int first{};
unsigned int second{};
// Simple extraction operator. Read 2 values
friend std::istream& operator >> (std::istream& is, StepsForPair& sfp) {
return is >> sfp.first >> sfp.second;
}
// Simple inserter. Sort first and second value and show result
friend std::ostream& operator << (std::ostream& os, const StepsForPair& sfp) {
unsigned int f{ sfp.first }, s{ sfp.second };
if (f > s) std::swap(f, s);
return os << sfp.first << ' ' << sfp.second << ' ' << *std::max_element(&steps[f], &steps[s]);
}
};
// Some test data. I will not use std::cin, but read from this std::istringstream here
std::istringstream testData{ R"(1 10
100 200
201 210
900 1000
22 22)" };
int main() {
// Read all input data and generate output
std::copy(std::istream_iterator<StepsForPair>(testData), {}, std::ostream_iterator<StepsForPair>(std::cout,"\n"));
}
Please note, since I do not have std::cin here on SO, I read the test values from a std::istringstream. Because of the overwritten extractor operator, this is easily possible.
If you want to read from std::cin then please replace in the std::copy statement in main "testData" eith "std::cin".
If you want to read from a file, then put a fileStream variable in there.
In this line n = (3 % n) + 1;, (3 % n) means that you take the remainder of 3 divided by n, which is probably not what you want. Change that to 3 * n
Do you have an idea how to optimize the following function while still using std::sort().
It sorts the suffixes of a text to create a suffix array. I think the problem is in the compare function as not much more can be done for the rest. compare is basically the lexicographical < operator for a string.
I added the function I use to test the time in the main() and the segment is now reproducible. I hope the comments make it easier to understand the logic. The function works fine but is too slow because of the multiple ifs. Construction time is now around 101 ms (on my CPU), but we aim at around 70.
// compile with: g++ -std=c++17 -Wall -pedantic -fsanitize=address -O3 test.cpp -o test
#include <string>
#include <vector>
#include <iostream>
#include <chrono>
#include <algorithm>
/// Build suffix array from text.
/// Input: the text (might be empty)
/// Output: a suffix array (sorted). The variable 'sa' is cleared before it's filled and returned.
void construct(std::vector<uint32_t>& sa, const std::string& text) {
sa.clear();
unsigned tsize = text.size();
for (unsigned i = 0; i < tsize; ++i) {
sa.push_back(i);
}
// with this function we compare the suffix at position 'a' to the suffix at position 'b' in the text.
// we do this letter by letter calling compare recursively
std::function<bool(uint32_t, uint32_t)> compare = [&](uint32_t a, uint32_t b) {
if (a>tsize) return true; //if we reach the end of the vector on a it means a<b
else if (b>tsize) return false; // if we reach the end on b it means b>a
else if (text[a] < text[b]) return true; // case a<b
else if (text[a] == text[b]) return compare(a + 1, b + 1); //if a and b are the same call compare on the next letters in both suffixes
else return false; // only the case b>a is left
};
std::sort(sa.begin(), sa.end(), compare);
}
// main tests the construction speed
int main(){
std::vector<uint32_t> sa;
srand(0);
std::string big(100000, ' '); // 'large' random text
for (auto& c : big) c = rand() % 128;
// time the construction
auto begin = std::chrono::steady_clock::now();
construct(sa, big);
auto end = std::chrono::steady_clock::now();
size_t time = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
std::cout << "Construction time: " << time << "\n";
}
I haven't profiled it, but - depending on how clever your compiler is - I think a non-recursive formulation might be more efficient:
std::function<bool(uint32_t, uint32_t)> compare = [&](uint32_t a, uint32_t b) {
do
{
if (a>=tsize) return true;
else if (b>=tsize) return false;
else if (text[a] < text[b]) return true;
else if (text[a] > text[b]) return false;
a += 1;
b += 1;
} while (true);
};
The code in compare compares strings according to their characters, in lexicographical order. This is very similar to how numbers are compared - most significant bits/bytes, if different, force the result of the comparison, and if equal, defer the result to less significant bits/bytes. So, if your strings are usually long, you can compare 8 bytes at once, using uint64_t.
To do that, you must pad your strings (with zero-valued bytes), to prevent out-of-bounds reads (alternatively, do the 8-byte comparison only when far from the string's end, otherwise do the original 1-byte comparison). Also, if your system is little-endian (most likely), you have to reverse bytes in your uint64_t numbers.
I'm trying to make a simple benchmarking algorithm, to compare different operations. Before I moved on to the actual functions i wanted to check a trivial case with a well-documented outcome : multiplication vs. division.
Division should lose by a fair margin from the literature i have read. When I compiled and ran the algorithm the times were just about 0. I added an accumulator that is printed to make sure the operations are actually carried out and tried again. Then i changed the loop, the numbers, shuffled and more. All in order to prevent any and all things that could cause "divide" to do anything but floating point division. To no avail. The times are still basically equal.
At this point I don't see where it could weasel its way out of the floating point divide and I give up. It wins. But I am really curious why the times are so close, what caveats/bugs i missed, and how to fix them.
(I know filling the vector with random data and then shuffling is redundant but I wanted to make sure the data was accessed and not just initialized before the loop.)
("String compares are evil", i am aware. If it is the cause of the equal times, i will gladly join the witch hunt. If not, please don't mention it.)
compile:
g++ -std=c++14 main.cc
tests:
./a.out multiply
2.42202e+09
1000000
t1 = 1.52422e+09 t2 = 1.52422e+09
difference = 0.218529
Average length of function : 2.18529e-07 seconds
./a.out divide
2.56147e+06
1000000
t1 = 1.52422e+09 t2 = 1.52422e+09
difference = 0.242061
Average length of function : 2.42061e-07 seconds
the code :
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <random>
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
double multiply(double lhs, double rhs){
return lhs * rhs;
}
double divide(double lhs, double rhs){
return lhs / rhs;
}
int main(int argc, char *argv[]){
if (argc == 1)
return 0;
double grounder = 0; //prevent optimizations
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(1.0, 100.0);
size_t loop1 = argc > 2 ? std::stoi (argv[2]) : 1000;
size_t loop2 = argc > 3 ? std::stoi (argv[3]) : 1000;
std::vector<size_t>vecL1(loop1);
std::generate(vecL1.begin(), vecL1.end(), [generator, distribution] () mutable { return distribution(generator); });
std::vector<size_t>vecL2(loop2);
std::generate(vecL2.begin(), vecL2.end(), [generator, distribution] () mutable { return distribution(generator); });
double (*fp)(double, double);
std::string function(argv[1]);
if (function == "multiply")
fp = (*multiply);
if (function == "divide")
fp = (*divide);
std::random_shuffle(vecL1.begin(), vecL1.end());
std::random_shuffle(vecL2.begin(), vecL2.end());
double t1 = get_time();
for (auto outer = vecL1.begin(); outer != vecL1.end(); outer++)
for (auto inner = vecL2.begin(); inner != vecL2.end(); inner++)
grounder += (*fp)(*inner, *outer);
double t2 = get_time();
std::cout << grounder << '\n';
std::cout << (loop1 * loop2) << '\n';
std::cout << "t1 = " << t1 << "\tt2 = " << t2
<< "\ndifference = " << (t2 - t1) << '\n';
std::cout << "Average length of function : " << (t2 - t1) * 1/(loop1 * loop2) << " seconds \n";
return 0;
}
You aren't just measuring the speed of multiplication/divide. If you put your code into https://godbolt.org/ you can see the assembly generated.
You are measuring the speed of calling a function and then doing multiply/divide inside the function. The time taken for the single multiply/divide instruction is tiny compared to the cost of the function calls so gets lost in the noise. If you move your loop to inside your function you'll probably see more of a difference. Note that with the loop inside your function your compiler may decide to vectorise your code which will still show whether there is a difference between multiply and divide but it wont be measuring the difference for the single mul/div instruction.
This Problem Has Now Been Resolved - Revised Code is Shown Below
I have a problem here which I'm sure will only require a small amount of tweaking the code but I do not seem to have been able to correct the program.
So, basically what I want to do is write a C++ program to construct a histogram with nbin = 20 (number of bins), for the number of counts of a Geiger counter in 10000 intervals of a time interval dt (delta t) = 1s; assuming an average count rate of 5 s^(-1). In order to determine the number of counts in some time interval deltat I use a while statement of the form shown below:
while((t-=tau*log(zscale*double(iran=IM*iran+IC)))<deltat)count++;
As a bit of background to this problem I should mention that the total number of counts is given by n*mu, which is proportional to the total counting time T = n*deltat. Obviously, in this problem n has been chosen to be 10000 and deltat is 1s; giving T = 10000s.
The issue I am having is that the output of my code (which will be shown below) simply gives 10000 "hits" for the element 0 (corresponding to 0 counts in the time deltat) and then, of course, 0 "hits" for every other element of the hist[] array subsequently. Whereas, the output which I am expecting is a Poisson Distribution with the peak "hits" at 5 counts (per second).
Thank you in advance for any help you can offer, and I apologise for my poor explanation of the problem at hand! My code is shown below:
#include <iostream> // Pre-processor directives to include
#include <ctime> //... input/output, time,
#include <fstream> //... file streaming and
#include <cmath> //... mathematical function headers
using namespace std;
int main(void) {
const unsigned IM = 1664525; // Integer constants for
const unsigned IC = 1013904223; //... the RNG algorithm
const double zscale = 1.0/0xFFFFFFFF; // Scaling factor for random double between 0 and 1
const double lambda = 5; // Count rate = 5s^-1
const double tau = 1/lambda; // Average time tau is inverse of count rate
const int deltat = 1; // Time intervals of 1s
const int nbin = 20; // Number of bins in histogram
const int nsteps = 1E4;
clock_t start, end;
int count(0);
double t = 0; // Time variable declaration
unsigned iran = time(0); // Seeds the random-number generator from the system time
int hist[nbin]; // Declare array of size nbin for histogram
// Create output stream and open output file
ofstream rout;
rout.open("geigercounterdata.txt");
// Initialise the hist[] array, each element is given the value of zero
for ( int i = 0 ; i < nbin ; i++ )
hist[i] = 0;
start = clock();
// Construction of histogram using RNG process
for ( int i = 1 ; i <= nsteps ; i++ ) {
t = 0;
count = 0;
while((t -= tau*log(zscale*double(iran=IM*iran+IC))) < deltat)
count++; // Increase count variable by 1
hist[count]++; // Increase element "count" of hist array by 1
}
// Print histogram to console window and save to output file
for ( int i = 0 ; i < nbin ; i++ ) {
cout << i << "\t" << hist[i] << endl;
rout << i << "\t" << hist[i] << endl;
}
end = clock();
cout << "\nTime taken for process completion = "
<< (end - start)/double(CLOCKS_PER_SEC)
<< " seconds.\n";
rout.close();
return 1;
} // End of main() routine
I do not entirely follow you on the mathematics of your while loop; however the problem is indeed in the condition of the while loop. I broke your while loop down as follows:
count--;
do
{
iran=IM * iran + IC; //Time generated pseudo-random
double mulTmp = zscale*iran; //Pseudo-random double 0 to 1
double logTmp = log(mulTmp); //Always negative (see graph of ln(x))
t -= tau*logTmp; //Always more than 10^4 as we substract negative
count++;
} while(t < deltat);
From the code it is apparent that you will always end up with count = 0 when t > 1 and run-time error when t < 1 as you will be corrupting your heap.
Unfortunately, I do not entirely follow you on mathematics behind your calculation and I don't understand why Poisson distribution shall to be expected. With the issue mentioned above, you should either go ahead and solve your problem (and then share your answer for the community) or provide me with more mathematical background and references and I will edit my answer with corrected code. If you decide for the earlier, keep in mind that Poisson distribution's domain is [0, infinity[ so you will need to check whether the vale of count is smaller than 20 (or your nbin for that matter).