For Loop That Starts At Middle Of Range And Loops Around - c++

Is it possible to have a for loop that starts at the middle of a range and then loops around to the beginning of the range and continues until it loops through the whole range? For example, assuming we have a range of 0 to 63, I want the loop to start at 22, continue looping until it reaches 63, then start at 0 and loop until it reaches 21. Is this possible with a for loop? Or would I require a while loop?

I'd use two loop variables: one to count the number of repetitions and one to handle the desired index. Like this:
for (int i = 0, j = 22; i < 64; ++i, j = (j + 1) % 64)
// do something with j
Of course, in real code you'd replace the magic numbers (22, 64) with something that more clearly reflects the actual objects involved.

Yes, you can use a range-based for loop for this. A C++20 STL example (with using namespace std::ranges):
constexpr void foo(auto&& range) {
auto middle = range.begin() + 22;
auto parts = {subrange{middle, range.end()}, subrange{range.begin(), middle}};
for (auto&& elem: parts | views::join) bar(elem);
}
Maybe there's a better looking way / library. With a proper API, it should be something like
constexpr void foo(auto&& range) {
for (auto&& elem: range | drop(22) | chain(range | take(22))) bar(elem);
}
Edit: almost the same "proper API" can be found ready in ranges::v3::view (concat here is an "unpipable" version of my imaginary chain):
constexpr void foo(auto&& range) {
for (auto&& elem: concat(range | drop(22), range | take(22))) bar(elem);
}

Yes, for example:
for( int i = 22, max = 63, end = i-1 ; i!=-1 ; i=i==end?-1:i==max?0:i+1 )
{
// do something with i
}

Related

How can I optimize my code from O(n^2) to nlog(n)

Given an array of numbers, arrange them in a way that yields the largest value.
For example, if the given numbers are {54, 546, 548, 60}, the arrangement 6054854654 gives the largest value.
And if the given numbers are {1, 34, 3, 98, 9, 76, 45, 4}, then the arrangement 998764543431 gives the largest value.
So, the provided function declaration is
string printLargest(vector<string> &arr)
The solution that I wrote is provided below.
string printLargest(vector<string> &arr) {
for (int i=0; i<arr.size()-1; i++) {
for (int j=i+1; j<arr.size(); j++) {
string y = arr[i] + arr.at(j);
string z = arr[j] + arr[i];
if (z>y) swap(arr[j], arr[i]);
}
}
string y="";
for(string x:arr) y +=x;
return y;
}
The online compiler says "Time Limit Exceeded"
Please optimize your code and submit again.
I think my solution take O(n^2).
Expected Time Complexity: O(NlogN),
How can I optimize my code?
This can be done using std::map
struct classcomp{ // The comparison class that allow std::map to do comparison between keys of type std::string
bool operator() (const std::string &a, const std::string &b)const {return (a+b>b+a);}
};
̀
std::string printLargest(std::vector<std::string> &arr) {
std::map<std::string, unsigned int, classcomp> orderedString; // a map of the form string : number of occurance in the vector
for (auto i = arr.begin(); i != arr.end(); i++){ // O(n)
if (orderedString.count(*i)) orderedString[*i]++; // O(log(n)) or O(1) depending of the implementation of std::map
else orderedString.insert(std::pair<std::string, unsigned int>(*i, 1)); // O(log(n)) or O(1) depending of the implementation of std::map
}
std::string r="";
for (auto i = orderedString.begin(); i != orderedString.end(); i++){ //this works since our map container is such that the first element is the highest
for (unsigned j=0; j < i->second; j++){ //The overall complexity is O(n)
r+=i->first;
}
}
return r;
}
̀
The overall complexity is O(mnlog(n)) where m is the maximum length of a string in your vector and n the size of the vector itself
Solving this by hand, what I'd do is to take the numbers which start with the highest digits in their sequences, right? So, in other words, what I'd do by hand is to sort them by this criterion and then appending them.
As soon as you are able to describe the criterion, this becomes nothing more than a sorting algorithm, with the criterion as a custom comparator.
So basically, in the end, the code can look somewhat like:
inline bool better_digits(const string& a, const string& b);
string print_largest(vector<string> data)
{
std::sort(data.begin(), data.end(), better_digits); // sort
string result = std::accumulate(data.begin(), data.end(), std::string{}); // append
return result;
}
In other words, I did the same as you already did, but with a better sorting algorithm, simply trusting that std::sort is efficient (which it is). No need to reinvent the wheel.
Note: the line with std::accumulate requires C++20. Otherwise, simply append by using a loop like you did in your own code.
Also, I removed the reference from the input to avoid the function having a side effect, but if it is allowed to, do that by all means.
The only thing left to do is to define better_digits. For that, we can use what you already did and what TUI lover also used:
inline bool better_digits(const string& a, const string& b)
{
return a+b > b+a;
}
Note that I haven't compared my variant with that of that of TUI lover. That would prove to be quite interesting. I posted mine because I think it is more readable, but TUI lovers variant might easily be more efficient. (Both are Θ(nlogn), but the overall factor also matters.)
Here is an algorithm in O(ns) where n is the length of the array and s the maximum length of the strings. It uses the trie method. Instead of padding with spaces or zeros, it pads with fake numbers.
If the numbers 544, 54 are present in a group then 54 is equivalent to 545, and should go in front (we pad 54 with a fake 5 in its last digit).
To compare [5, 554, 45],
first round (most significant digit), splits it into [5, 554], [45]
second round [5, 554], [45]
third round [5], [554], [45] (because 5 are padded with fake 5s)
def pad_with_fake(L):
outL = []
for x in L:
while len(str(x)) < maxlen:
lead = x[0]
if lead not in fake_digits:
x = x + fake_digits[int(lead)]
else:
x = x + lead
outL.append(x)
return outL
def arrange_number_at_digit_position(pos,inL):
outL = []
for digit in digits:
subL = []
for x in inL:
if str(x)[pos] == digit:
subL.append(x)
if subL != []:
outL.append(subL)
return outL
def arrange(inL):
maxlen = max([len(l) for l in inL])
i = 0
outLs = [[inL]]
while i < maxlen:
outL = []
for l in outLs[i]:
outL = outL + (arrange_number_at_digit_position(i,l))
outLs = outLs + [outL]
i = i+1
return outLs
def main():
inL = [559, 5, 55, 59, 549, 544, 54]
L = [str(l) for l in inL]
digits = [0,1,2,3,4,5,6,7,8,9]
fake_digits = ['a','b','c','d','e','f','g','h','i','j']
digits = ['9','j','8','i','7','h','6','g','5','f','4','e','3','d','2','c','1','b','a','0']
L = pad_with_fake(L)
outLs = arrange(L)
for l in outLs:
print(l)
final_string = ""
for l in outLs[-1]:
final_string = final_string + "|" + l[0]
for i in range(0,10):
final_string = final_string.replace(fake_digits[i],"")
print("input", inL, "--> output", final_string)
main()
Example
[['559', '5ff', '55f', '59f', '549', '544', '54f']]
[['559', '5ff', '55f', '59f', '549', '544', '54f']]
[['59f'], ['559', '55f'], ['5ff'], ['549', '544', '54f']]
[['59f'], ['559'], ['55f'], ['5ff'], ['549'], ['54f'], ['544']]
input [559, 5, 55, 59, 549, 544, 54] --> output |59|559|55|5|549|54|544
You can try to use a faster sorting algorithm like merge sort which is O(n log n).
Alternatively, by using a trie this problem could be solved in O(s), where s is the sum of character counts across all strings.

Difference between for loop and the range based loop in C++

I am confused as to what what the difference is between for loop and for each loop in C++.
I read tutorials and some books but I am yet to see how for each loop is different.
With arrays, examples I have seen seem to suggest for each loop loops through the whole elements at a go. Could that be the special advantage range based loop has?
The main difference is that the ordinary for-loop uses an additional variable used as an index inside the array and has the scope of the loop and you can yourself write the condition of the for loop.
For example let's assume that you need to output either all even elements of an array or until an element with a zero value is encountered. You can write
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N && a[i] != 0; i++ )
{
if ( a[i] % 2 == 0 ) std::cout << i << ": " << a[i] << '\n';
}
return 0;
}
The program output is
1: 2
3: 4
5: 6
7: 8
How to do this with the range-based for loop? For starters before the loop you need to declare a variable that will play the role of the index. One drawback of this is the variable is not declared in the scope where it is used.
Also to stop the iterations of the loop you need to use a break statement within the loop. That also makes the code more complicated.
Compare the above program with this
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t i = 0;
for ( const auto &item : a )
{
if ( item == 0 )
{
break;
}
else if ( item % 2 == 0 )
{
std::cout << i << ": " << item << '\n';
}
++i;
}
return 0;
}
In general to use the range based for loop the used container either shall have member functions begin and end or the general functions begin and end shall support the container. For arrays begin and end mean expressions a and a + N.
The difference between a for loop and a range based for loop is roughly analogous to the difference between goto and a for loop. Former is a more generic control flow, while the latter is more structured. Every range based loop can be written as a for loop and every for loop can be written as a goto. But the reverse is not true.
Goto encapsulates the idea of jumping elsewhere. Loop encapsulates the idea of repetition (which involves jumping back). Range based loop encapsulates the idea of iterating over a range from begin until end (which involves repetition).
If your intention is to iterate over an entire range, then the range based loop is typically syntactically simpler, and easier to understand than a for loop. Likewise, a for loop is easier to understand than a goto loop. This is what makes structured approach superior. Compare for example the following, and consider which one is easier to understand:
for (auto it = list.begin(), end = list.end(); it != end; ++it) {
auto& element = *it;
// do stuff with element
}
for (auto& element : list) {
// do stuff with element
}
loops through the whole elements at a go. Could that be the special advantage range based loop has?
Looping through an entire range is what range based loop can do. A for loop can do that too. But a for loop can do much more: it can iterate indices, it can iterate indefinitely, it can iterate until a terminator etc.

Slice view for C++20 ranges

Python's itertools has the islice(seq, start, stop, step) procedure that takes a sequence and returns an iterator of every stepth value of the sequence values between start and stop.
Does the Ranges library of C++20 provide a similar functionality, e.g. a function like slice that takes a random access iterator start, a sentinel stop, and a step value step, and that returns a random access iterator that iterates over every stepth value between start and stop?
In case it does not, can such an iterator adapter be implemented using the primitives provided by the Ranges library?
(I know how I can implement such an adapter by hand, so this is not the question.)
Not quite.
C++20 will have view::iota which gives you a sequence from a starting value to a sentinel. However, it does not have the stride functionality. It only increments (via ++).
However, you can combine it with range-v3's view::stride to add in the steps. That is:
auto evens = view::iota(0, 100) | view::stride(2); // [0, 2, 4, 6, ... ]
For existing ranges, there's view::slice, which also doesn't take a stride. But these are orthogonal and layer nicely:
auto even_teens = view::iota(0, 100)
| view::slice(10, 20)
| view::stride(2); // [10, 12, 14, 16, 18]
Unfortunaltely, slice and stride of Range-v3, as presented in Barry'sanswer, are not (yet) available in the Ranges library of C++20.
However, you can replace slice by combining std::views::drop_while and std::views::take_while. To replace stride, you can use the range adaptor std::views::filter and pass a specific lambda expression to it. To filter for every other element as in Barry's example, I would use a stateful lambda expression with an init capture. You can put everything together to represent the range [10, 12, 14, 16, 18] as follows:
auto even_teens = std::views::iota(0, 100)
| std::views::drop_while([](int i) { return i < 10; })
| std::views::take_while([](int i) { return i < 20; })
| std::views::filter([s = false](auto const&) mutable { return s = !s; });
For a more universal stride solution, you can use a counter along with the modulo operator in the lambda expression. To be able to specify the stride size n in a readable way, I would use the following lambda expression, which provides another lambda expression that keeps track of the stride operation:
auto stride = [](int n) {
return [s = -1, n](auto const&) mutable { s = (s + 1) % n; return !s; };
};
All in all, the final solution looks like this:
auto even_teens = std::views::iota(0, 100)
| std::views::drop_while([](int i) { return i < 10; })
| std::views::take_while([](int i) { return i < 20; })
| std::views::filter(stride(2));
Code on Wandbox

Fastest way to find smallest missing integer from list of integers

I have a list of 100 random integers. Each random integer has a value from 0 to 99. Duplicates are allowed, so the list could be something like
56, 1, 1, 1, 1, 0, 2, 6, 99...
I need to find the smallest integer (>= 0) is that is not contained in the list.
My initial solution is this:
vector<int> integerList(100); //list of random integers
...
vector<bool> listedIntegers(101, false);
for (int theInt : integerList)
{
listedIntegers[theInt] = true;
}
int smallestInt;
for (int j = 0; j < 101; j++)
{
if (!listedIntegers[j])
{
smallestInt = j;
break;
}
}
But that requires a secondary array for book-keeping and a second (potentially full) list iteration. I need to perform this task millions of times (the actual application is in a greedy graph coloring algorithm, where I need to find the smallest unused color value with a vertex adjacency list), so I'm wondering if there's a clever way to get the same result without so much overhead?
It's been a year, but ...
One idea that comes to mind is to keep track of the interval(s) of unused values as you iterate the list. To allow efficient lookup, you could keep intervals as tuples in a binary search tree, for example.
So, using your sample data:
56, 1, 1, 1, 1, 0, 2, 6, 99...
You would initially have the unused interval [0..99], and then, as each input value is processed:
56: [0..55][57..99]
1: [0..0][2..55][57..99]
1: no change
1: no change
1: no change
0: [2..55][57..99]
2: [3..55][57..99]
6: [3..5][7..55][57..99]
99: [3..5][7..55][57..98]
Result (lowest value in lowest remaining interval): 3
I believe there is no faster way to do it. What you can do in your case is to reuse vector<bool>, you need to have just one such vector per thread.
Though the better approach might be to reconsider the whole algorithm to eliminate this step at all. Maybe you can update least unused color on every step of the algorithm?
Since you have to scan the whole list no matter what, the algorithm you have is already pretty good. The only improvement I can suggest without measuring (that will surely speed things up) is to get rid of your vector<bool>, and replace it with a stack-allocated array of 4 32-bit integers or 2 64-bit integers.
Then you won't have to pay the cost of allocating an array on the heap every time, and you can get the first unused number (the position of the first 0 bit) much faster. To find the word that contains the first 0 bit, you only need to find the first one that isn't the maximum value, and there are bit twiddling hacks you can use to get the first 0 bit in that word very quickly.
You program is already very efficient, in O(n). Only marginal gain can be found.
One possibility is to divide the number of possible values in blocks of size block, and to register
not in an array of bool but in an array of int, in this case memorizing the value modulo block.
In practice, we replace a loop of size N by a loop of size N/block plus a loop of size block.
Theoretically, we could select block = sqrt(N) = 12 in order to minimize the quantity N/block + block.
In the program hereafter, block of size 8 are selected, assuming that dividing integers by 8 and calculating values modulo 8 should be fast.
However, it is clear that a gain, if any, can be obtained only for a minimum value rather large!
constexpr int N = 100;
int find_min1 (const std::vector<int> &IntegerList) {
constexpr int Size = 13; //N / block
constexpr int block = 8;
constexpr int Vmax = 255; // 2^block - 1
int listedBlocks[Size] = {0};
for (int theInt : IntegerList) {
listedBlocks[theInt / block] |= 1 << (theInt % block);
}
for (int j = 0; j < Size; j++) {
if (listedBlocks[j] == Vmax) continue;
int &k = listedBlocks[j];
for (int b = 0; b < block; b++) {
if ((k%2) == 0) return block * j + b;
k /= 2;
}
}
return -1;
}
Potentially you can reduce the last step to O(1) by using some bit manipulation, in your case __int128, set the corresponding bits in loop one and call something like __builtin_clz or use the appropriate bit hack
The best solution I could find for finding smallest integer from a set is https://codereview.stackexchange.com/a/179042/31480
Here are c++ version.
int solution(std::vector<int>& A)
{
for (std::vector<int>::size_type i = 0; i != A.size(); i++)
{
while (0 < A[i] && A[i] - 1 < A.size()
&& A[i] != i + 1
&& A[i] != A[A[i] - 1])
{
int j = A[i] - 1;
auto tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
for (std::vector<int>::size_type i = 0; i != A.size(); i++)
{
if (A[i] != i+1)
{
return i + 1;
}
}
return A.size() + 1;
}

Subset sum (Coin change)

My problem is, I need to count how many combination of array of integers sums to a value W.`
let say:
int array[] = {1,2,3,4,5};
My Algorithm is just find all combinations of lengths from 1 to W / minimum(array), which is equal to W because minimum is 1.
And checking each combination if its sum equal to W then increment a counter N.
any other algorithm to solve this ? should be faster :)
Update:
ok, the subset problem and the Knapsack Problem are good, but my problem is that the combinations of the array repeats the elements, like this:
1,1,1 -> the 1st combination
1,1,2
1,1,3
1,1,4
1,1,5
1,2,2 -> this combination is 1,2,2, not 1,2,1 because we already have 1,1,2.
1,2,3
1,2,4
1,2,5
1,3,3 -> this combination is 1,3,3, not 1,3,1 because we already have 1,1,3.
1,3,4
.
.
1,5,5
2,2,2 -> this combination is 2,2,2, not 2,1,1 because we already have 1,1,2.
2,2,3
2,2,4
2,2,5
2,3,3 -> this combination is 2,3,3, not 2,3,1 because we already have 1,2,3.
.
.
5,5,5 -> Last combination
these are all combinations of {1,2,3,4,5} of length 3. the subset-sum problem gives another kind of combinations that I'm not interested in.
so the combination that sums to W, lets say W = 7,
2,5
1,1,5
1,3,3
2,2,3
1,1,2,3
1,2,2,2
1,1,1,1,3
1,1,1,2,2
1,1,1,1,1,2
1,1,1,1,1,1,1
Update:
The Real Problem is in the repeated of the elements 1,1,1 is need and the order of the generated combination are not important, so 1,2,1 is the same as 1,1,2 and 2,1,1 .
No efficient algorithm exist as of now, and possibly never will (NP-complete problem).
This is (a variation of) the subset-sum problem.
This is coin change problem. It could be solved by dynamic programming with reasonable restrictions of W and set size
Here is code, in Go, that solves this problem. I believe it runs in O(W / min(A)) time. The comments should be sufficient to see how it works. The important detail is that it can use an element in A multiple times, but once it stops using that element it won't ever use it again. This avoids double-counting things like [1,2,1] and [1,1,2].
package main
import (
"fmt"
"sort"
)
// This is just to keep track of how many times we hit ninjaHelper
var hits int = 0
// This is our way of indexing into our memo, so that we don't redo any
// calculations.
type memoPos struct {
pos, sum int
}
func ninjaHelper(a []int, pos, sum, w int, memo map[memoPos]int64) int64 {
// Count how many times we call this function.
hits++
// Check to see if we've already done this computation.
if r, ok := memo[memoPos{pos, sum}]; ok {
return r
}
// We got it, and we can't get more than one match this way, so return now.
if sum == w {
return 1
}
// Once we're over w we can't possibly succeed, so just bail out now.
if sum > w {
return 0
}
var ret int64 = 0
// By only checking values at this position or later in the array we make
// sure that we don't repeat ourselves.
for i := pos; i < len(a); i++ {
ret += ninjaHelper(a, i, sum+a[i], w, memo)
}
// Write down our answer in the memo so we don't have to do it later.
memo[memoPos{pos, sum}] = ret
return ret
}
func ninja(a []int, w int) int64 {
// We reverse sort the array. This doesn't change the complexity of
// the algorithm, but by counting the larger numbers first we can hit our
// target faster in a lot of cases, avoid a bit of work.
sort.Ints(a)
for i := 0; i < len(a)/2; i++ {
a[i], a[len(a)-i-1] = a[len(a)-i-1], a[i]
}
return ninjaHelper(a, 0, 0, w, make(map[memoPos]int64))
}
func main() {
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
w := 1000
fmt.Printf("%v, w=%d: %d\n", a, w, ninja(a, w))
fmt.Printf("Hits: %v\n", hits)
}
Just to put this to bed, here are recursive and (very simple) dynamic programming solutions to this problem. You can reduce the running time (but not the time complexity) of the recursive solution by using more sophisticated termination conditions, but the main point of it is to show the logic.
Many of the dynamic programming solutions I've seen keep the entire N x |c| array of results, but that's not necessary, since row i can be generated from just row i-1, and furthermore it can be generated in order left to right so no copy needs to be made.
I hope the comments help explain the logic. The dp solution is fast enough that I couldn't find a test case which didn't overflow a long long which took more than a few milliseconds; for example:
$ time ./coins dp 1000000 1 2 3 4 5 6 7
3563762607322787603
real 0m0.024s
user 0m0.012s
sys 0m0.012s
// Return the number of ways of generating the sum n from the
// elements of a container of positive integers.
// Note: This function will overflow the stack if an element
// of the container is <= 0.
template<typename ITER>
long long count(int n, ITER begin, ITER end) {
if (n == 0) return 1;
else if (begin == end || n < 0) return 0;
else return
// combinations which don't use *begin
count(n, begin + 1, end) +
// use one (more) *begin.
count(n - *begin, begin, end);
}
// Same thing, but uses O(n) storage and runs in O(n*|c|) time,
// where |c| is the length of the container. This implementation falls
// directly out of the recursive one above, but processes the items
// in the reverse order; each time through the outer loop computes
// the combinations (for all possible sums <= n) for sum prefix of
// the container.
template<typename ITER>
long long count1(int n, ITER begin, ITER end) {
std::vector<long long> v(n + 1, 0);
v[0] = 1;
// Initial state of v: v[0] is 1; v[i] is 0 for 1 <= i <= n.
// Corresponds to the termination condition of the recursion.
auto vbegin = v.begin();
auto vend = v.end();
for (auto here = begin; here != end; ++here) {
int a = *here;
if (a > 0 && a <= n) {
auto in = vbegin;
auto out = vbegin + a;
// *in is count(n - a, begin, here).
// *out is count(n, begin, here - 1).
do *out++ += *in++; while (out != vend);
}
}
return v[n];
}