Decreasing Loop Interval by 1 in C/C++ - c++

Let's say I have 15 elements. I want to group them such a way that:
group1 = 1 - 5
group2 = 6 - 9
group3 = 10 - 12
group4 = 13 - 14
group5 = 15
This way I'll get elements in each group as below:
group1 = 5
group2 = 4
group3 = 3
group4 = 2
group5 = 1
As you can see loop interval is decreasing.
I took 15 just for an example. In actual programme it's user driven parameter which can be anything (hopefully few thousand).
Now what I'm looking for is:
Whatever is in group1 should have variable "loop" value 0, group2 should have 1, group3 should have 2 and so on... "loop" is an int variable which is being used to calculate some other stuff.
Let's put in other words too
I have an int variable called "loop". I want to assign value to it such a way that:
First n frames loop value 0 next (n -1) frames loop value 1 then next (n - 2) frames loop value 2 all the way to loop value (n - 1)
Let's say I have 15 frames on my timeline.
So n will be 5 ====>>>>> (5 + 4 + 3 + 2 + 1 = 15; as interval is decreasing by 1)
then
first 5 frames(1 - 5) loop is 0 then next 4 frames(6 - 9) loop is 1 then next 3 frames(10 - 12) loop is 2 then next 2 frames(13 - 14) loop is 3 and for last frame(15) loop is 4.
frames "loop" value
1 - 5 => 0
6 - 9 => 1
10 - 12 => 2
13 - 14 => 3
15 => 4
I've tried with modulo(%). But the issue is on frame 12 loop is 2 so (12 % (5 - 2)) remainder is 0 so it increments loop value.
The following lines are sample code which is running inside a solver. #loop is by default 0 and #Frame is current processing frame number.
int loopint = 5 - #loop;
if (#Frame % loopint == 0)
#loop += 1;

If I understand this correctly, then
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
for(int i = 1; i <= n; ++i) {
printf("%d: %f\n", i, ceil((sqrt(8 * (n - i + 1) + 1) - 1) / 2));
}
}
is an implementation in C.
The math behind this is as follows: The 1 + 2 + 3 + 4 + 5 you have there is a Gauß sum, which has a closed form S = n * (n + 1) / 2 for n terms. Solving this for n, we get
n = (sqrt(8 * S + 1) - 1) / 2
Rounding this upward would give us the solution if you wanted the short stretches at the beginning, that is to say 1, 2, 2, 3, 3, 3, ...
Since you want the stretches to become progressively shorter, we have to invert the order, so S becomes (n - S + 1). Therefore the formula up there.
EDIT: Note that unless the number of elements in your data set fits the n * (n+1) / 2 pattern precisely, you will have shorter stretches either at the beginning or in the end. This implementation places the irregular stretch at the beginning. If you want them at the end,
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int n2 = (int) ceil((sqrt(8 * n + 1) - 1) / 2);
int upper = n2 * (n2 + 1) / 2;
for(int i = 1; i <= n; ++i) {
printf("%d: %f\n", i, n2 - ceil((sqrt(8 * (upper - i + 1) + 1) - 1) / 2));
}
}
does it. This calculates the next such number beyond your element count, then calculates the numbers you would have if you had that many elements.

Related

919B | nth Numbers having digit sum as 10 | Codeforces

Here is the link to the question. Essentially, it asks to find the kth number having digit sum as 10. I have tried multiple solutions and also looked upon solutions online. Specifically this one (also shared below). The one with constant time talks about outliers in Arithmetic Progression and uses it to find the nth number having sum as 10. Obviously, the code is incorrect as it fails for test cases when k=1000 etc.
#include <bits/stdc++.h>
using namespace std;
int findNth(int n)
{
int nthElement = 19 + (n - 1) * 9;
int outliersCount = (int)log10(nthElement) - 1;
// find the nth perfect number
nthElement += 9 * outliersCount;
return nthElement;
}
int main()
{
cout << findNth(5) << endl;
return 0;
}
Eventually, I ended up writing combination of Arithmetic Progression + brute force as below
#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long
int main() {
int n;
cin >> n;
int count = 0;
ll i = 19;
for (; ; i += 9) {
int curr = i;
int localSum = 0;
while (curr) {
localSum += curr%10;
curr /= 10;
}
if (localSum == 10) {
count += 1;
}
if (count == n) {
break;
}
}
cout << i << endl;
return 0;
}
I am wondering, if there is no constant time or better algorithm that does not require me to calculate the sum, but my algorithm always hops in a way that I have number whose digit sum is 10?
Here is a Python solution that you can translate into C++.
cached_count_ds_l = {}
def count_digit_sum_length (s, l):
k = (s, l)
if k not in cached_count_ds_l:
if l < 2:
if s == 0:
return 1
elif l == 1 and s < 10:
return 1
else:
return 0
else:
ans = 0
for i in range(min(10, s+1)):
ans += count_digit_sum_length(s-i, l-1)
cached_count_ds_l[k] = ans
return cached_count_ds_l[k]
def nth_of_sum (s, n):
l = 0
while count_digit_sum_length(s, l) < n:
l += 1
digits = []
while 0 < l:
for i in range(10):
if count_digit_sum_length(s-i, l-1) < n:
n -= count_digit_sum_length(s-i, l-1)
else:
digits.append(str(i))
s -= i
l -= 1
break
return int("".join(digits))
print(nth_of_sum(10, 1000))
The idea is to use dynamic programming to find how many numbers there are of a given maximum length with a given digit sum. And then to use that to cross off whole blocks of numbers on the way to finding the right one.
The main logic goes like this:
0 numbers of length 0 sum to 10
- need longer
0 numbers of length 1 sum to 10
- need longer
9 numbers of length 2 sum to 10
- need longer
63 numbers of length 3 sum to 10
- need longer
282 numbers of length 4 sum to 10
- need longer
996 numbers of length 5 sum to 10
- need longer
2997 numbers of length 6 sum to 10
- answer has length 6
Looking for 1000th number of length 6 that sums to 10
- 996 with a leading 0 sum to 10
- Need the 4th past 99999
- 715 with a leading 1 sum to 10
- Have a leading 1
Looking for 4th number of length 5 that sums to 9
- 495 with a leading 0 sum to 9
- Have a leading 10
Looking for 4th number of length 4 that sums to 9
- 220 with a leading 0 sum to 9
- Have a leading 100
Looking for 4th number of length 3 that sums to 9
- 55 with a leading 0 sum to 9
- Have a leading 1000
Looking for 4th number of length 2 that sums to 9
- 1 with a leading 0 sum to 9
- Need the 3rd past 9
- 1 with a leading 1 sum to 9
- Need the 2nd past 19
- 1 with a leading 2 sum to 9
- Need the 1st past 29
- 1 with a leading 3 sum to 9
- Have a leading 10003
Looking for 1st number of length 1 that sums to 6
- 0 with a leading 0 sum to 6
- Need the 1st past 0
- 0 with a leading 1 sum to 6
- Need the 1st past 1
- 0 with a leading 2 sum to 6
- Need the 1st past 2
- 0 with a leading 3 sum to 6
- Need the 1st past 3
- 0 with a leading 4 sum to 6
- Need the 1st past 4
- 0 with a leading 5 sum to 6
- Need the 1st past 5
- 1 with a leading 6 sum to 6
- Have a leading 100036
And it finishes in a fraction of a second.
Incidentally the million'th is 20111220000010, the billionth is 10111000000002000000010000002100, and the trillionth is 10000000100000100000100000000000001000000000000100000000010110001000.

Spiral matrix diagonal element sum

Let n=5, then for matrix
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
then sum of diagonal elements is:
=1+17+25+21+9+5+19+23+13
Sum for n=15?
One way is to make the spiral matrix and then by a loop, we get the answer, but its time and space complexity is large.
Like this https://www.geeksforgeeks.org/sum-diagonals-spiral-odd-order-square-matrix/
but the problem here starts 1 from the center.
Consider the outer "shell" of the matrix. The sum of the values at the four vertices, given a size of n (5 in your example) and a starting value of s (1 in your example) is
s + (s + (n-1)) + (s + (n-1)*2) + (s + (n-1)*3) = 4*s + (n - 1)*6
The same applies to the inner values, once updated n and s:
s = s + 4 * (n - 1)
n = n - 2
If n becomes less then 2, well, either we have the central element or nothing (n is even).
Based on Bob_'s answer, Here is a recursive code in CPP as requested by OP
int shellcalc(int n,int s){
if(n==1)
return s;
else if(n==0)
return 0;
else
{
int sum=4*s+(n-1)*6;
int snew=s+4*(n-1);
int nnew=n-2;
return sum+shellcalc(nnew,snew);
}
}
try it out here https://rextester.com/FLJD46264
Python - https://rextester.com/MDMV32855

how can we find the nth 3 word combination from a word corpus of 3000 words

I have a word corpus of say 3000 words such as [hello, who, this ..].
I want to find the nth 3 word combination from this corpus.I am fine with any order as long as the algorithm gives consistent output.
What would be the time complexity of the algorithm.
I have seen this answer but was looking for something simple.
(Note that I will be using 1-based indexes and ranks throughout this answer.)
To generate all combinations of 3 elements from a list of n elements, we'd take all elements from 1 to n-2 as the first element, then for each of these we'd take all elements after the first element up to n-1 as the second element, then for each of these we'd take all elements after the second element up to n as the third element. This gives us a fixed order, and a direct relation between the rank and a specific combination.
If we take element i as the first element, there are (n-i choose 2) possibilities for the second and third element, and thus (n-i choose 2) combinations with i as the first element. If we then take element j as the second element, there are (n-j choose 1) = n-j possibilities for the third element, and thus n-j combinations with i and j as the first two elements.
Linear search in tables of binomial coefficients
With tables of these binomial coefficients, we can quickly find a specific combination, given its rank. Let's look at a simplified example with a list of 10 elements; these are the number of combinations with element i as the first element:
i
1 C(9,2) = 36
2 C(8,2) = 28
3 C(7,2) = 21
4 C(6,2) = 15
5 C(5,2) = 10
6 C(4,2) = 6
7 C(3,2) = 3
8 C(2,2) = 1
---
120 = C(10,3)
And these are the number of combinations with element j as the second element:
j
2 C(8,1) = 8
3 C(7,1) = 7
4 C(6,1) = 6
5 C(5,1) = 5
6 C(4,1) = 4
7 C(3,1) = 3
8 C(2,1) = 2
9 C(1,1) = 1
So if we're looking for the combination with e.g. rank 96, we look at the number of combinations for each choice of first element i, until we find which group of combinations the combination ranked 96 is in:
i
1 36 96 > 36 96 - 36 = 60
2 28 60 > 28 60 - 28 = 32
3 21 32 > 21 32 - 21 = 11
4 15 11 <= 15
So we know that the first element i is 4, and that within the 15 combinations with i=4, we're looking for the eleventh combination. Now we look at the number of combinations for each choice of second element j, starting after 4:
j
5 5 11 > 5 11 - 5 = 6
6 4 6 > 4 6 - 4 = 2
7 3 2 <= 3
So we know that the second element j is 7, and that the third element is the second combination with j=7, which is k=9. So the combination with rank 96 contains the elements 4, 7 and 9.
Binary search in tables of running total of binomial coefficients
Instead of creating a table of the binomial coefficients and then performing a linear search, it is of course more efficient to create a table of the running total of the binomial coefficient, and then perform a binary search on it. This will improve the time complexity from O(N) to O(logN); in the case of N=3000, the two look-ups can be done in log2(3000) = 12 steps.
So we'd store:
i
1 36
2 64
3 85
4 100
5 110
6 116
7 119
8 120
and:
j
2 8
3 15
4 21
5 26
6 30
7 33
8 35
9 36
Note that when finding j in the second table, you have to subtract the sum corresponding with i from the sums. Let's walk through the example of rank 96 and combination [4,7,9] again; we find the first value that is greater than or equal to the rank:
3 85 96 > 85
4 100 96 <= 100
So we know that i=4; we then subtract the previous sum next to i-1, to get:
96 - 85 = 11
Now we look at the table for j, but we start after j=4, and subtract the sum corresponding to 4, which is 21, from the sums. then again, we find the first value that is greater than or equal to the rank we're looking for (which is now 11):
6 30 - 21 = 9 11 > 9
7 33 - 21 = 12 11 <= 12
So we know that j=7; we subtract the previous sum corresponding to j-1, to get:
11 - 9 = 2
So we know that the second element j is 7, and that the third element is the second combination with j=7, which is k=9. So the combination with rank 96 contains the elements 4, 7 and 9.
Hard-coding the look-up tables
It is of course unnecessary to generate these look-up tables again every time we want to perform a look-up. We only need to generate them once, and then hard-code them into the rank-to-combination algorithm; this should take only 2998 * 64-bit + 2998 * 32-bit = 35kB of space, and make the algorithm incredibly fast.
Inverse algorithm
The inverse algorithm, to find the rank given a combination of elements [i,j,k] then means:
Finding the index of the elements in the list; if the list is sorted (e.g. words sorted alphabetically) this can be done with a binary search in O(logN).
Find the sum in the table for i that corresponds with i-1.
Add to that the sum in the table for j that corresponds with j-1, minus the sum that corresponds with i.
Add to that k-j.
Let's look again at the same example with the combination of elements [4,7,9]:
i=4 -> table_i[3] = 85
j=7 -> table_j[6] - table_j[4] = 30 - 21 = 9
k=9 -> k-j = 2
rank = 85 + 9 + 2 = 96
Look-up tables for N=3000
This snippet generates the look-up table with the running total of the binomial coefficients for i = 1 to 2998:
function C(n, k) { // binomial coefficient (Pascal's triangle)
if (k < 0 || k > n) return 0;
if (k > n - k) k = n - k;
if (! C.t) C.t = [[1]];
while (C.t.length <= n) {
C.t.push([1]);
var l = C.t.length - 1;
for (var i = 1; i < l / 2; i++)
C.t[l].push(C.t[l - 1][i - 1] + C.t[l - 1][i]);
if (l % 2 == 0)
C.t[l].push(2 * C.t[l - 1][(l - 2) / 2]);
}
return C.t[n][k];
}
for (var total = 0, x = 2999; x > 1; x--) {
total += C(x, 2);
document.write(total + ", ");
}
This snippet generates the look-up table with the running total of the binomial coefficients for j = 2 to 2999:
for (var total = 0, x = 2998; x > 0; x--) {
total += x;
document.write(total + ", ");
}
Code example
Here's a quick code example, unfortunately without the full hardcoded look-up tables, because of the size restriction on answers on SO. Run the snippets above and paste the results into the arrays iTable and jTable (after the leading zeros) to get the faster version with hard-coded look-up tables.
function combinationToRank(i, j, k) {
return iTable[i - 1] + jTable[j - 1] - jTable[i] + k - j;
}
function rankToCombination(rank) {
var i = binarySearch(iTable, rank, 1);
rank -= iTable[i - 1];
rank += jTable[i];
var j = binarySearch(jTable, rank, i + 1);
rank -= jTable[j - 1];
var k = j + rank;
return [i, j, k];
function binarySearch(array, value, first) {
var last = array.length - 1;
while (first < last - 1) {
var middle = Math.floor((last + first) / 2);
if (value > array[middle]) first = middle;
else last = middle;
}
return (value <= array[first]) ? first : last;
}
}
var iTable = [0]; // append look-up table values here
var jTable = [0, 0]; // and here
// remove this part when using hard-coded look-up tables
function C(n,k){if(k<0||k>n)return 0;if(k>n-k)k=n-k;if(!C.t)C.t=[[1]];while(C.t.length<=n){C.t.push([1]);var l=C.t.length-1;for(var i=1;i<l/2;i++)C.t[l].push(C.t[l-1][i-1]+C.t[l-1][i]);if(l%2==0)C.t[l].push(2*C.t[l-1][(l-2)/2])}return C.t[n][k]}
for (var iTotal = 0, jTotal = 0, x = 2999; x > 1; x--) {
iTable.push(iTotal += C(x, 2));
jTable.push(jTotal += x - 1);
}
document.write(combinationToRank(500, 1500, 2500) + "<br>");
document.write(rankToCombination(1893333750) + "<br>");

rand() produces 1 number too high?

It is my understanding that rand() % a + b will return numbers between a and b including both a and b. I must be misunderstanding this though, because when I run the code below int r will return 2, 3, or 4. I, of course, am expecting it to return 2 or 3. I'm calling srand(time(NULL)); in main and I'm using
#include <time.h> and #include <stdlib.h>
Am I missing something?
int r = (rand() % 3) + 2;
if (r ==2)
g_fan.draw(r); // skin == 2
else
g_fan.draw(1 + r); //skin == 4
It is my understanding that rand() % a + b will return numbers between a and b including both a and b.
No. It will result in a number between b and (a+b-1), both including.
Range of values of rand() % a is 0 and a-1, both including.
Hence, the range of values of rand() % a + b is b and (a-1+b), both including.
To get random values between a and b, both including, use:
auto interval = (b-a+1);
auto result = a + rand() % interval;
let num be any number you get by calling rand() and if you do % with 3 , there is a possibility of getting one of these number 0, 1, 2.
therefore you are getting 2 ,3, 4 for :
int r = (rand() % 3) + 2;
int r = (rand() % 3) + 2;
The rand() % 3 will return a number between 0 and 2. When you add t2 to each number, that means it will return 2 to 4. The rand() % afunction in general returns a value form 0 to a - 1. When you do rand() % a + b, then the resulting value will range from 0 + b to a - 1 + b.
To get a value between 2 and 3, use:
int r = (rand() % 2) + 2;
The folloing rand() function gives a number from 0 to 2 - 1, which is 1. When you add 2 to each number, you get a range of 0 + 2, which is 2, to 2 - 1 + 2, which is 3.

Write a program that outputs the total of 5-digit numbers with a five in them, but not with an 8

My challenge is to output the total number of five-digit numbers that have a digit 5, but no digits 8. My only two answers so far have been 0, or 90000. Can anyone help me?
#include <iostream>
using namespace std;
int main() {
int number;
int counter=10000;
int ncounter=0;
while (counter >= 10000 && counter <= 99999) {
int n1,n2,n3,n4,n5;
counter = counter + 1;
n1 = number%10;
number /= 10;
n2 = number%10;
number /= 10;
n3 = number%10;
number /= 10;
n4 = number%10;
number /=10;
n5 = number%10;
number /= 10;
if (n1 == 5||n2 == 5||n3 == 5||n4 == 5||n5 == 5)
if (n1!=8)
if (n2!=8)
if (n3!=8)
if(n4!=8)
if (n5!=8)
ncounter=ncounter+1;
}
cout<<ncounter<<endl;
return 0;
}
(num with 5 but not 8) = (num without 8) - (num with neither 8 nor 5) = 8*9*9*9*9 - 7*8*8*8*8= 23816
Each number is a selection of 5 digits (with repetitions).
Since you cannot select the digit 8, you have 9 possible digits, so this problem is equivalent to the same problem, base 9 (instead of base 10).
If you make 1 digit a 5, there are 4 non-5 and non-8 digits remaining. The number of these can be calculated as 8^4 (because there are 8 available digits to choose from, and you need to choose 4 of these). With a single 5, there are 5 ways to position the 5, so multiply by 5.
Similarly with 2 5's, there are 10 ways to position the 5s relative to other digits.
Therefore, we have the following table:
number of digits==5 remaining digits ways to position 5s
1 8^4 5
2 8^3 10 = 5*4/2
3 8^2 10
4 8^1 5
5 8^0 1
There are 5*8^4 + 10*8^3 + 10*8^2 + 5*8^1 + 8^0 = 26281 numbers <10^5 with a 5 but not an 8.
There are 4*8^3 + 6*8^2 + 4*8^1 + 8^0 = 2465 numbers <10^4 with a 5 but not an 8. Therefore, there are 23816 numbers satisfying your criteria.
This is actually a mathematical problem. Here we have three conditions:
First digit is not zero, as it should be a five-digit number.
No digits are 8
One or more digits are 5
There can be numbers with one to five 5s, where first digit is or is not 5 (except for 55555). That's nine cases to count.
If first digit is not 5, it has 7 options: [1234679]; if any other digit is not 5, it has 8 options: [12346790].
Here C(5) is number of combinations to place 5s, and C(o) - to place other digits.
N(5). 1st? C(5) C(o)
1 Y 1 * 8^4
1 N 4 * 7*8^3
2 Y 4 * 8^3
2 N 6 * 7*8^2
3 Y 6 * 8^2
3 N 4 * 7*8
4 Y 4 * 8
4 N 1 * 7
5 Y 1
Sum: 23816