Spiral matrix diagonal element sum - c++

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

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.

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>");

Unexpected behaviour/bug in function to find radical of an integer [duplicate]

This question already has answers here:
std::pow with integer parameters, comparing to an integer type
(4 answers)
Closed 5 years ago.
I have written a short C++ function which is trying to return similar to the the radical of an integer, but instead the smallest integer which is some root of the the given number. The general logic is that the function decomposes the integer into prime powers, looks for the gcd of all the exponents of the prime powers, then finds the radical by dividing all the exponents by this gcd. I thought the function was working as intended, however I noticed that when passing the function 13 as an argument it returns 12, I have put the output for 2 to 20 below; everything is correct apart from 13. When trying to debug this both "primes" and "powers" hold the correct values (13 and 1 respectively, both vectors of size 1) as well as "power" being 1 as it should. So the problem must be in the last loop, but I am really very confused as to what could be happening as it should be calculating pow(13, 1/1).
#include<vector>
#include<cmath>
int radical(int n){
int power = 0;
std::vector<int> primes;
std::vector<int> powers;
for(int i = 2; n != 1 ; ++i){
int t_pow = 0;
while(n % i == 0){
++t_pow;
n /= i;
}
if(t_pow != 0){
primes.push_back(i);
powers.push_back(t_pow);
}
power = (power == 0 ? t_pow : gcd(power, t_pow));
}
int rad = 1;
for(unsigned i = 0u; i < primes.size(); ++i){
rad *= pow(primes.at(i), powers.at(i)/power);
}
return rad;
}
2 2
3 3
4 2
5 5
6 6
7 7
8 2
9 3
10 10
11 11
12 12
13 12
14 14
15 15
16 2
17 17
18 18
19 19
20 20
EDIT: The most efficient way to implement an integer based power function pow(int, int)
The naive algorithm looks pretty simple actually:
rad = 1
i = 1
While n > 1:
increase i
if i divides n:
multiply rad by i
while i divides n, divide n by i
You're already performing all these steps, the fact is you're doing much more than that (and using much more space), so why not just get rid of unnecessary actions?
define your own int powi(int,int) function and check if the error petsists

Longest Increasing Sub sequence in a range

I have come across a problem where we want to tell the maximum size of the longest increasing sub-sequence.
an array A consisting of N integers.
M queries (Li, Ri)
for each query we wants to find the length of the longest increasing subsequence in
array A[Li], A[Li + 1], ..., A[Ri].
I implemented finding the sub-sequence using dp approach
// mind the REPN, LLD, these are macros I use for programming
// LLD = long long int
// REPN(i, a, b) = for (int i = a; i < b; ++i)
LLD a[n], dp[n];
REPN(i, 0, n)
{
scanf("%lld", &a[i]);
dp[i] = 1;
}
REPN(i, 1, n)
{
REPN(j, 0, i)
{
if(a[i] > a[j])
dp[i] = std::max(dp[j] + 1, dp[i]);
}
}
For example:
Array: 1 3 8 9 7 2 4 5 10 6
dplis: 1 2 3 4 3 1 3 4 5 5
max: 5
But if it was for range Li=2 & Ri=9
Then:
Array: 3 8 9 7 2 4 5 10
dplis: 1 2 3 2 1 2 3 4
max: 4
How can i determine the maximum longest increasing sub-sequence in a sub array?
PS: I don't want to recompute the whole dplis array, I want to use the original one because too much computation will kill the purpose of the question.
One of the approaches was to construct a complete 2D DP array that consists of sub-sequence from position i where range of i is from 0 to n, but it fails on many cases due to TLE(Time limit exceeded)
REPN(k,0,n) {
REPN(i,k+1,n) {
REPN(j,k,i) {
if(a[i]>a[j]) dp[k][i]=std::max(dp[k][j]+1, dp[k][i]);
}
}
}
REPN(i,0,q) {
read(l); read(r);
LLD max=-1;
REPN(i,0,r) {
if(max<dp[l-1][i]) max=dp[l-1][i];
}
printf("%lld\n", max);
}
If you have any new logic/implementation, I will gladly study it in-depth. Cheers.

Nearest Neighbor Operation on 1D array elements

I have 2D array and want to convert it into 1D array.
The 2D array is:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
to 1D array:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
How do I access nearest neighbor of the element number 6 in 1D array, so that I can get the same result when I access in 2D array, such as
1 2 3
5 6 7
9 10 11
in C++?
If you have a 2D array that is M items long by N items tall, you need a 1D array that has M*N elements.
When trying to find the neighbors of element x:
left(x) = (x - 1) % M
right(x) = (x + 1) % M
above(x) = (x - M) % (M * N)
below(x) = (x + M) % (M * N)
Note that the above solution makes the bottom and top of your array adjacent, as well as the right edge and left edge. To get rid of that, simply omit the modular math and detect when your index has moved past the right / left / top / bottom edges.