Length of the longest consecutive 1's in a binary number - bit-manipulation

I need to implement a digital logic circuit with logic gates such as AND, OR, NOT, ADDER (and so on..), that gets an 8 bits binary number and return the number of the longest consecutive 1's in the input.
For example:
11110011 - will return 4
10101111 - will also return 4
01111111 - will return 7
I would really appreciate some help, as I'm struggling for days to find solution to this problem.
Thanks!

I generated a truth table with 256 terms and reduced it to 47 terms using the Espresso minimizer:
Then, I converted the compressed table into a multi-level circuit (too big to be displayed here as image). For this, I used Logic Friday 1.
It might be possible to derive a simpler circuit by mapping my C# routine into gates:
private static int countConsecutiveBits(int i)
{
int bMax = 0;
int b = 0;
for (int j = 0; j < 8; j++)
{
if (((i >> j) & 1) == 1)
{
b++;
if (bMax < b)
{
bMax = b;
}
}
else
{
b = 0;
}
}
return bMax;
}
This would involve adders and comparators as indicated in your question.
The following circuit - hand crafted and not verified - is a bit-slice which takes as inputs the so-far maximum bit count, the current bit count and the respective bit. The outputs are the new maximum bit count and the current bit count. All counts are 4-bit wide. This could be optimized for the first slices, where the count is smaller.

Related

Maximize XOR Equation

Problem statement:
Given an array of n elements and an integer k, find an integer x in
the range [0,k] such that Xor-sum(x) is maximized. Print the maximum
value of the equation.
Xor-sum(x)=(x XOR A1)+(x XOR A[2])+(x XOR A[3])+…………..+(x XOR A[N])
Input Format
The first line contains integer N denoting the number of elements in
A. The next line contains an integer, k, denoting the maximum value
of x. Each line i of the N subsequent lines(where 0<=i<=N) contains
an integer describing Ai.
Constraints
1<=n<=10^5
0<=k<=10^9
0<=A[i]<=10^9
Sample Input
3
7
1
6
3
Sample Output
14
Explanation
Xor_sum(4)=(4^1)+(4^6)+(4^3)=14.
This problem was asked in Infosys requirement test. I was going through previous year papers &
I came across this problem.
I was only able to come up with a brute-force solution which is just to calculate the equation
for every x in the range [0,k] and print the maximum. But, the solution won't work for the
given constraints.
My solution
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, k, ans = 0;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i <= k; i++) {
int temp = 0;
for (int j = 0; j < n; j++) {
temp += (i ^ a[j]);
}
ans = max(temp, ans);
}
cout << ans;
return 0;
}
I found the solution on a website. I was unable to understand what the code does but, this solution gives incorrect answer for some test cases.
Scroll down to question 3
The trick here is that XOR works on bits in parallel, independently. You can optimize each bit of x. Brute-forcing this takes 2*32 tries, given the constraints.
As said in other comments each bit of x will give an independent contribution to the sum, so the first step is to calculate the added value for each possible bit.
To do this for the i-th bit of x count the number of 0s and 1s in the same position of each number in the array, if the difference N0 - N1 is positive then the added value is also positive and equal to (N0-N1) * 2^i, let's call such bits "useful".
The number x will be a combination of useful bits only.
Since k is not in the form 2^n - 1, we need a strategy to find the best combination (if you don't want to use brute force on the k possible values).
Consider then the binary representation of k and loop over its bits starting from the MSB, initializing two variables: CAV (current added value) = 0, BAV (best added value) = 0.
If the current bit is 0 loop over.
If the current bit is 1:
a) calculate the AV sum of all useful bits with lower index plus the CAV, if the result is greater then the BAV then replace BAV
b) if the current bit is not useful quit loop
c) add the current bit added value to CAV
When the loop is over, if CAV is greater than BAV replace BAV
EDIT: A sample implementation (in Java, sorry :) )
public class XorSum {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int k=sc.nextInt();
int[] a=new int[n];
for (int i=0;i<n;i++) {
a[i]=sc.nextInt();
}
//Determine the number of bits to represent k (position of most significant 1 + 1)
int msb=0;
for (int kcopy=k; kcopy!=0; kcopy=kcopy>>>1) {
msb++;
}
//Compute the added value of each possible bit in x
int[] av=new int[msb];
int bmask=1;
for (int bit=0;bit<msb;bit++) {
int count0=0;
for (int i=0;i<n;i++) {
if ((a[i]&bmask)==0) {
count0++;
}
}
av[bit]=(count0*2-n)*bmask;
bmask = bmask << 1;
}
//Accumulated added value, the value of all positive av bits up to the index
int[] aav=new int[msb];
for (int bit=0;bit<msb;bit++) {
if (av[bit]>0) {
aav[bit]=av[bit];
}
if (bit>0) {
aav[bit]+=aav[bit-1];
}
}
//Explore the space of possible combinations moving on the k boundary
int cval=0;
int bval=0;
bmask = bmask >>> 1;
//Start from the msb
for (int bit=msb-1;bit>=0;bit--) {
//Exploring the space of bit combination we have 3 possible cases:
//bit of k is 0, then we must choose 0 as well, setting it to 1 will get x to be greater than k, so in this case just loop over
if ((k&bmask)==0) {
continue;
}
//bit of k is 1, we can choose between 0 and 1:
//- choosing 0, we can immediately explore the complete branch considering that all following bits can be set to 1, so just set to 1 all bits with positive av
// and get the meximum possible value for this branch
int val=cval+(bit>0?aav[bit]:0);
if (val>bval) {
bval=val;
}
//- choosing 1, if the bit has no positive av, then it's forced to 0 and the solution is found on the other branch, so we can stop here
if (av[bit]<=0) break;
//- choosing 1, with a positive av, then store the value and go on with this branch
cval+=av[bit];
}
if (cval>bval) {
bval=cval;
}
//Final sum
for (int i=0;i<n;i++) {
bval+=a[i];
}
System.out.println(bval);
}
}
I think you can consider solving for each bit. The number X should be the one that can turn on many high-order bits in the array. So you can count the number of bits 1 for 2^0, 2^1, ... And for each position in the 32 bits consider turning on the ones that many number has that position to be bit 0.
Combining this with the limit K should give you an answer that runs in O(log K) time.
Assuming k is unbounded, this problem is trivial.
For each bit (assuming 64-bit words there would be 64 for example) accumulate the total count of 1's and 0's in all values in the array (for that bit), with c1_i and c0_i representing the former and latter respectively for bit i.
Then define each bit b_i in x as
x_i = 1 if c0_i > c1_i else 0
Constructing x as described above is guaranteed to give you the value of x that maximizes the sum of interest.
When k is specific number, this can be solved using a dynamic programming solution. To understand how, first derive a recurrence.
Let z_0,z_1,...,z_n be the positions of ones occuring in k's binary representation with z_0 being the most significant position.
Let M[t] represent the maximum sum possible given the problem's array and defining any x such that x < t.
Important note: the optimal value of M[t] for t a power of 2 is obtained by following the procedure described above for an unbounded k, but limiting the largest bit used.
To solve this problem, we want to find
M[k] = max(M[2^z_0],M[k - 2^z_0] + C_0)
where C_i is defined to be the contribution to the final sum by setting the position z_i to one.
This of course continues as a recursion, with the next step being:
M[k - 2^z_0] = max(M[2^z_1],M[k - 2^z_0 - 2^z_1] + C_1)
and so on and so forth. The dynamic programming solution arises by converting this recursion to the appropriate DP algorithm.
Note, that due to the definition of M[k], it is still necessary to check if the sum of x=k is greater than M[k], as it may still be so, but this requires one pass.
At bit level it is simple 0 XOR 0, 1 XOR 1 = 0 and last one 0 XOR 1 = 1, but when these bit belongs to a number XOR operations have addition and subtraction effect. For example if third bit of a number is set and num XOR with 4 (0100) which also have third bit set then result would be subtraction from number by 2^(3-1), for example num = 5 then 0101 XOR 0100 = 0001, 4 subtracted in 5 , Similarly if third bit of a number is not set and num XOR with 4 then result would be addition for example num = 2 then 0010 XOR 0100 = 0101, 4 will be added in 2. Now let’s see this problem,
This problem can’t be solved by applying XOR on each number individually, rather the approach to solve this problem is Perform XOR on particular bit of all numbers, in one go! . Let’s see how it can be done?
Fact 1: Let’s consider we have X and we want to perform XOR on all numbers with X and if we know second bit of X is set, now suppose somehow we also know that how many numbers in all numbers have second bit set then we know answer 1 XOR 1 = 0 and we don’t have to perform XOR on each number individually.
Fact 2: From fact 1, we know how many numbers have a particular bit set, let’s call it M and if X also have that particular bit set then M * 2^(pos -1) will be subtracted from sum of all numbers. If N is total element in array than N - M numbers don’t have that particular bit set and due to it (N – M) * 2^(pos-1) will be added in sum of all numbers.
From Fact 1 and Fact 2 we can calculate overall XOR effect on a particular bit on all Numbers by effect = (N – M)* 2^(pos -1) – (M * 2^(pos -1)) and can perform the same for all bits.
Now it’s time to see above theory in action, if we have array = {1, 6, 3}, k = 7 then,
1 = 0001 (There are total 32 bits but I am showing only relevant bits other bits are zero)
6 = 0110
3 = 0011
So our bit count list = [0, 1, 2, 2] as you can see 1 and 3 have first bit set, 6 and 3 have second bit set and only 6 have third bit set.
X = 0, …, 7 but X = 0 have effect = 0 on sum because if bit is not set then it doesn’t not affect other bit in XOR operation, so let’s star from X = 1 which is 0001,
[0, 1, 2, 2] = count list,
[0, 0, 0, 1] = X
As it is visible in count list two numbers have first bit set and X also have first bit set, it means 2 * 2^(1 – 1) will be subtract in sum and total numbers in array are three, so (3 – 2) * 2^(1-1) will be added in sum. Conclusion is XOR of first bit is, effect = (3 – 2) * 2^(1-1) - 2 * 2^(1 – 1) = 1 – 2 = -1. It is also overall effect by X = 1 because it only has first bit set and rest of bits are zero. At this point we compare effect produced by X = 1 with X = 0 and -1 < 0 which means X = 1 will reduce sum of all numbers by -1 but X = 0 will not deduce sum of all numbers. So until now X = 0 will produce max sum.
The way XOR is performed for X = 1 can be performed for all other values and I would like to jump directly to X = 4 which is 0100
[0, 1, 2, 2] = count list,
[0, 1, 0, 0] = X
As it is visible X have only third bit set and only one number in array have first bit set, it means 1 * 2^(3 – 1 ) will be subtracted and (3 – 1) * 2^(3-1) will be added and overall effect = (3 – 1) * 2^(3-1) - 1 * 2^(3 – 1 ) = 8 – 4 = 4. At this point we compare effect of X = 4 with known max effect which is effect = 0 so 4 > 0 and due to this X = 4 will produce max sum and we considered it. When you perform this for all X = 0,…,7, you will find X = 4 will produce max effect on sum, so the answer is X = 4.
So
(x XOR arr[0]) + ( x XOR arr[1]) +….. + (x XOR arr[n]) = effect + sum(arr[0] + sum[1]+ …. + arr[n])
Complexity is,
O(32 n) to find for all 32 bits, how many number have a particular bit set, plus,
O(32 k) to find effect of all X in [0, k],
Complexity = O(32 n) + O(32 k) = O(c n) + O(c k), here c is constant,
finally
Complexity = O(n)
#include <iostream>
#include <cmath>
#include <bitset>
#include <vector>
#include <numeric>
std::vector<std::uint32_t> bitCount(const std::vector<std::uint32_t>& numList){
std::vector<std::uint32_t> countList(32, 0);
for(std::uint32_t num : numList){
std::bitset<32> bitList(num);
for(unsigned i = 0; i< 32; ++i){
if(bitList[i]){
countList[i] += 1;
}
}
}
return countList;
}
std::pair<std::uint32_t, std::int64_t> prefXAndMaxEffect(std::uint32_t n, std::uint32_t k,
const std::vector<std::uint32_t>& bitCountList){
std::uint32_t prefX = 0;
std::int64_t xorMaxEffect = 0;
std::vector<std::int64_t> xorBitEffect(32, 0);
for(std::uint32_t x = 1; x<=k; ++x){
std::bitset<32> xBitList(x);
std::int64_t xorEffect = 0;
for(unsigned i = 0; i< 32; ++i){
if(xBitList[i]){
if(0 != xorBitEffect[i]){
xorEffect += xorBitEffect[i];
}
else{
std::int64_t num = std::exp2(i);
xorBitEffect[i] = (n - bitCountList[i])* num - (bitCountList[i] * num);
xorEffect += xorBitEffect[i];
}
}
}
if(xorEffect > xorMaxEffect){
prefX = x;
xorMaxEffect = xorEffect;
}
}
return {prefX, xorMaxEffect};
}
int main(int , char *[]){
std::uint32_t k = 7;
std::vector<std::uint32_t> numList{1, 6, 3};
std::pair<std::uint32_t, std::int64_t> xAndEffect = prefXAndMaxEffect(numList.size(), k, bitCount(numList));
std::int64_t sum = 0;
sum = std::accumulate(numList.cbegin(), numList.cend(), sum) + xAndEffect.second;
std::cout<< sum<< '\n';
}
Output :
14

I don't understand a solution about Gray Code on LeetCode

Here is the description:
******The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
**Note:
For a given n, a gray code sequence is not uniquely defined.
For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.****
Actually this point is totally a new thing to me,So I look through its introduction on WIKI,then I find a solution (maybe called Mirror Construct
Methond),here is a graph about it:Mirror. And there is the code writing in this method :
// Mirror arrangement
class Solution {
public:
vector<int> grayCode(int n) {
vector<int> res{0};
for (int i = 0; i < n; ++i) {
int size = res.size();
for (int j = size - 1; j >= 0; --j) {
res.push_back(res[j] | (1 << i));
}
}
return res;
}
};
The problem now is that I can't figure out what's the meaning of *res.push_back(res[j] | (1 << i)). I can't understand and use the logic character very well.
res.push_back(res[j] | (1 << i));
The parameter passed to res.push_back() is the contents of res[j] with the ith bit set.
If i is 2, the bit representing the value 4 is set. The parameter will also have all the bits that were set in res[j] set.

How to fast identify contiguous range of 1’s(Index) in huge binary data?

Could anyone suggest faster algorithm to identify continuous range of 1's in large binary data ?
Is traversing the data is the only solution? Traversing will give O(n) in worst case which I really don't want.
Does anyone can suggest faster algorithm?
As shown in below fig. I need to find the index 4000 which is start position of continuous range of 1's
index 0
|
00000000000000000000000000000000000000000011111100000
I could not think of anything that would not be O(n), since the data is always unsorted.
But, i can think of shortcuts, since you want a set of at least 3, and is binary data.
#include <iostream>
using namespace std;
int main()
{
unsigned int seed = 3758096384; //11100000000000000000000000000000
unsigned int testvar = 419307644; //00011000111111100010000001111100
int result = 0;
int continuous = 0;
while (seed != 7 && (continuous == 1 || result == 0)) {
if (seed == (testvar & seed)) {
result |= seed;
continuous = 1;
} else
continuous = 0;
seed >>= 1;
}
// result = 16646144 or 00000000111111100000000000000000
cout << result << endl;
//the index, 8388608 or 00000000100000000000000000000000
cout << (int)((result ^ (result >> 1)) & ~(result >> 1)) << endl;
return 0;
}
How it works:
It is a binary filter, it creates a mask of 3 bits, and continuous shift to left by 1 in every step of the loop.
So you have these numbers as filters:
3758096384 - 11100000000000000000000000000000
1879048192 - 01110000000000000000000000000000
939524096 - 00111000000000000000000000000000
...
14 - 00000000000000000000000000001110
7 - 00000000000000000000000000000111
Then it checks if the seed match with the result of a logical AND between the number tested and the seed itself (this filters all the numbers that don't match the filter).
If the seed and the AND match, it moves the seed to the result using a logical OR, and set a continuous to control the continuity of the sequence. The first time the result is not continuous, it breaks the loop.
In the end, you have the result and can calculate the index by:
1110
0111 SHIFT TO LEFT by 1 and XOR
1001
0111 NOT (SHIFT TO LEFT by 1) and AND
------------
1000
You will need to scan your 50gb data in 32bits chunks (easy to adapt to 64bits, or even do vectorization of it).
Well, you can't avoid going through the entire data at least once (you have to look at everything at least!), but you can avoid going through it multiple times if you e.g. run-length encode the data.

Iterate through all combinations in Gray code order [duplicate]

This question already has answers here:
Gray code increment function
(4 answers)
Closed 8 years ago.
Let's say i have n integers in an array a, and i want to iterate through all possible subsets of these integers, find the sum, and then do something with it.
What i immedieatelly did, was to create a bit field b, which indicated which numbers were included in the subset, and iterate through its possible values using ++b. Then, to compute the sum in each step, i had to iterate through all bits like this:
int sum = 0;
for (int i = 0; i < n; i++)
if (b&1<<i)
sum += a[i];
Then i realized that if i iterated through the possible values of b in a Gray code order, so that each time only a single bit is flipped, i wouldn't have to reconstruct the sum completely, but only needed to add or subtract the single value that is being added or removed from the subset. It should work like this:
int sum = 0;
int whichBitToFlip = 0;
bool isBitSet = false;
for (int k = 0; whichBitToFlip < n; k++) {
sum += (isBitSet ? -1 : 1)*a[whichBitToFlip];
// do something with sum here
whichBitToFlip = ???;
bool isBitSet = ???;
}
But i can't figure out how to directly and efficiently compute whichBitToFlip. The desired values are basically sequence A007814. I know that i can compute the Gray code using the formula (k>>1)^k and xor it with the previous one, but then i need to find the position of the changed bit, which might not be much faster.
So is there any better way to determine these values (index of flipped bit), preferably without a cycle, faster than recomputing the whole sum (of at most 64 values) every time?
To convert a bitmask to a bit index, you can use the ffs function (if you have one), which corresponds to a machine opcode on some machines.
Otherwise, the bit changed in the gray code corresponds to the ruler function:
0, 1, 0, 2, 0, 1, 0, 3, 0, 1...
for which there is a simple recursion. You can simulate the recursion with a stack (it will have maximum depth O(log N), so it's not much space), but probably ffs is a lot faster.
(By the way, even if you were to count bits one at a time from right-to-left, the increment function would be O(1) on average because the total number of trailing 0s in the integers from 1 to 2k is 2k-1.)
So i came up with this:
int sum = 0;
unsigned long grayPos = 0;
int graySign = 1;
for (uint64 k = 2; grayPos < n; k++) {
sum += graySign*a[grayPos];
// Do something with sum
#ifdef _M_X64
grayPos = n;
_BitScanForward64(&grayPos, k);
#else
for (grayPos = 0; !(k&1ull<<grayPos); grayPos++);
#endif
graySign = 2-(k>>grayPos&0x3);
}
It works really well, brought down the execution time (in comparison to always recomputing the whole sum) from 254 to only 7 seconds for n = 32. I also found that counting trailing zeroes with the for cycle is only slightly (~15%) slower than using _BitScanForward64 for the reasons mentioned by rici. So thanks.

How make this even count code faster?

The following code is meant to find total numbers between l and r whose product of digits is even (for multiple test cases t). This code runs perfectly but is extremely slow for r greater than 100000. Can anyone suggest a better alternative?
#include <iostream>
#include <algorithm>
using namespace std;
long long int nd(long long int x, int n) //return the digit at a particular index staring with zero as index for unit place
{
while (n--) {
x /= 10;
}
return (x % 10);
}
int ng(long long int number) //returns total number of digits in an integer
{
int digits = 0;
if (number < 0) digits = 1;
while (number) {
number /= 10;
digits++;
}
return digits;
}
int main()
{
int t;
cin>>t;
long long int l[t], r[t], c;
for(long long int j=0;j<t;j++)
{
cin>>l[j]>>r[j];
}
for(long long int k=0;k<t;k++)
{
long long int sum=0;
long long int t=0;
for(long long int i=l[k];i<=r[k];i++)
{
while(t<ng(i))
{
c=nd(i,t);
if((c%2)==0)
{
++sum;
break;
}
++t;
}
t=0;
}
cout<<sum<<endl;
}
cin.ignore();
cin.get();
return 0;
}
The basic idea is to loop through each digit of a number and see if it's even. If it is, the whole product will be even and there's no need to check the remaining digits.
The problem with your code is that you run trough the number multiple times looking for a digit with index i. You should simply run through the number's digits once checking for evenness along the way.
Here's a self-explanatory Go code implementing the algorithm:
package main
func iseven(num int) bool {
for num > 0 {
digit := num % 10
if digit&1 == 0 { # same as digit%2 == 0, only simpler
return true
}
num /= 10
}
return false
}
func main() {
sum := 0
for n := 1; n < 1000000; n++ {
if iseven(n) {
sum++
}
}
println(sum)
}
Performance on my machine:
λ time go run main.go
980469
go run main.go 0.05s user 0.01s system 81% cpu 0.073 total
Update
If you need to work with ginormous numbers, then a more efficient approach can be used.
Let's call the numbers that have the product of their digits odd dodd numbers. So, 135 is a dodd number, 134 is not. Similarly, numbers that have the product of their digits even are called deven. So 134 is a deven number.
As has been mentioned earlier, only numbers that consist of odd digits are dodd. So instead of enumerating numbers, we can just count the numbers comprised of digits 1, 3, 5, 7, and 9. For integer N > 1, there are exactly 10^N - 10^(N-1) numbers that have N digits. And of those numbers, 5 ^ N are dodd, and therefore 10^N - 10^(N-1) - 5^N are deven.
The approach is to count how many dodd numbers there are in between the left and right bounds and then subtract that count from the total count of numbers between left and right. You could also count just deven numbers, but that is a bit trickier.
Effectively, you're going to loop through digits with this approach, instead of through numbers. My implementation in Python is able to compute the number of deven numbers between 1 and int("1" * 100000) (a number with 10000 digits) in under one second.
All numbers starting with, e.g., 10…, 12…, 14…, …, 2…, 30…, already are known to have an even product of digits. I would therefore start from the left (more significant digits) and count in blocks. There are only a few numbers whose product of digits is odd (such as 1111111111), only here you have to dig deeper.
Here is some pseudocode:
int count(String prefix, int digits) {
int result = 0;
if (digits == 0)
return 0;
for (int d = 0; d < 10; d++) {
if (d%2 == 0)
result += 10**(digits-1);
else
result += count(prefix . toString(d), digits-1);
}
return result;
}
This would be called like count("2", 8) to get the count for the interval from 200000000 to 299999999.
Here is a Haskell implementation for a whole block (i.e., all d-digit numbers):
blockcount :: Integer -> Integer
blockcount 0 = 0
blockcount d = 5 * 10^(d-1) + 5 * blockcount (d-1)
E.g., blockcount 1000 is calculated to be 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999066736381496781121009910455276182830382908553628291975378285660204033089024224365545559672902118897640405010069675757375784512478645967605158479182796069243765589333861674849726004924014098168488899509203734886881759487485204066209194821728874584896189301621145573518880530185771339040777982337089557201543830551112852533471993671631547352570738170137834797206804710506392882149336331258934560194469281863679400155173958045898786770370130497805485390095785391331638755207047965173135382342073083952579934063610958262104177881634921954443371555726074612482872145203218443653596285122318233100144607930734560575991288026325298250137373309252703237464196070623766166018953072125441394746303558349609375 in much less than a second.
You’d still have to add code that breaks your range into suitable blocks.
An optimisation based on the following would work:
Multiplying two numbers together gets you oddness / evenness according to the rule
even * even = even
odd * even = even * odd = even
odd * odd = odd
Therefore you only need to track the last digit of your number numbers.
I'm too old to code this but I bet it would be blisteringly quick as you only need to consider numbers between 0 and 9.
The only thing you need to check is if one of digits in the number is even. If it is, it will have 2 as a factor, and hence be even.
You also don't seem to remember where you are up to in digits - every time you increment t in your for loop, and then call nd(i,t), you count down from that t to zero in nd. This is quadratic in number of digits in the worst case. Better would be to simply break up the number into its component digits at the beginning.
I can't figure out what your code is doing, but the basic
principles are simple:
value % 10 is the low order digit
value /= 10 removes the low order digit
if any digit is even, then the product will be even.
This should lead to a very simple loop for each value. (You may
have to special case 0.)
Further optimizations are possible: all even numbers will have
a product of digits which is even, so you can iterate with
a step of 2, and then add in the number of evens (one half of
the range) afterwards. This should double the speed.
One further optimization: if the low order digit is even, the number itself is even, so you don't have to extract the low order digit to test it.
Another thing you could do is change
while(t<ng(i))
to
int d = ng(i);
while (t < d)
So ng is only called once per loop.
Also ng is just log(number)+1 (log base 10 that is)
I don't know is that will be quicker though.
First, please fix your indentation
Your code uses too many division and loops which cause a lot of delays
long long int nd(long long int x, int n) //return the digit at a particular index staring with zero as index for unit place
{
while (n--) {
x /= 10;
}
return (x % 10);
}
This can be fixed easily by a table lookup
long long int nd(long long int x, int n) //return the digit at a particular index staring with zero as index for unit place
{
long long int pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
100000000, 1000000000, 10000000000, 100000000000,
1000000000000, 10000000000000, 100000000000000,
1000000000000000, 10000000000000000,
100000000000000000, 1000000000000000000};
return ((x / pow10[n]) % 10);
}
Likewise, the ng function to get total number of digits in an integer can be changed to a fast log10, no need to repeatedly divides and count. Ofcourse it'll need a small change to adapt 64 bit numbers
int ng(long long int number) //returns total number of digits in an integer
{
int digits = 0;
if (number < 0) digits = 1;
while (number) {
number /= 10;
digits++;
}
return digits;
}