Converting to ASCII in C - c

Using a microcontroller (PIC18F4580), I need to collect data and send it to an SD card for later analysis. The data it collects will have values between 0 and 1023, or 0x0 and 0x3FF.
So what I need to do is convert 1023 into a base 10 string of literal ASCII values (0x31, 0x30, 0x32, 0x33, ...).
My problem is that the only way I can think of to split the digits apart requires a lot of division.
char temp[4];
temp[0] = 1023 % 10;
temp[1] = (1023 % 100) / 10;
temp[2] = (1023 % 1000) / 100;
temp[3] = (1023 % 10000) / 1000;
Using this method, finding the ASCII values of an n digit decimal number requires 2n-1 divisions. Is there a method that would be faster?
The end goal of this is to wind up with a .csv file on the SD card that can quickly be plugged into any laptop to see a graph of the data in Excel.

The obvious solution is not to convert the data to ASCII at all but store it in binary format. That way all you need to worry about is the endianness of the data. If the system performing the later analysis is far more powerful than your embedded target, then it would make sense to let that deal with the conversion and and byte order.
On the other hand, it is possible that the execution time of the / and % is insignificant compared to the time taken to transfer the data to the SD card; so make sure that you are optimising the right thing.

There's certainly a much faster way: have an array of 1024 pre-computed strings. Then you can just do bounds checking, followed by an index into the array.
It's unclear from your question whether your code is running on the microcontroller though. If that's the case, you may not have enough memory for this approach.

I agree with what Clifford said, that you shouldn't worry about optimizing it if you don't have to, and that you can push the log cleanup to your analysis platform, rather than worrying about formatting in an embedded application.
That being said, here's an article that might be useful to you. It uses a loop, shifts, additions and branches, with linear/constant complexity: http://www.johnloomis.org/ece314/notes/devices/binary_to_BCD/bin_to_bcd.html
Also, I thought it would be fun to make some code that doesn't perform any divides, multiplies, or branches, but still gives the correct answer [0 - 1024). No promises that this is any faster than other options. This sort of code is just an option to explore.
I'd love to see if anyone can provide some tricks to make the code smaller, require less memory, or require fewer operations, while keeping the rest of the counts equal, or shrinking them :)
Stats:
224 bytes in constants (no idea on the code size)
5 bit-shift-rights
3 subtracts
5 bitwise-ands
4 bitwise-ors
1 greater-than comparison
Perf:
Using the perf comparisons and itoa routines in Jonathan Leffler's answer, here are the stats I got:
Division 2.15
Subtraction 4.87
My solution 1.56
Brute force lookup 0.36
I increased the iteration count to 200000 to ensure I didn't have any problems with timing resolution, and had to add volatile to the function signatures so that the compiler didn't optimize out the loop. I used VS2010 express w/ vanilla "release" settings, on a 3ghz dual core 64 bit Windows 7 machine (tho it compiled to 32 bit).
The code:
#include "stdlib.h"
#include "stdio.h"
#include "assert.h"
void itoa_ten_bits(int n, char s[])
{
static const short thousands_digit_subtract_map[2] =
{
0, 1000,
};
static const char hundreds_digit_map[128] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
0, 0, 0,
};
static const short hundreds_digit_subtract_map[10] =
{
0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
};
static const char tens_digit_map[12] =
{
0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9,
};
static const char ones_digit_map[44] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3
};
/* Compiler should optimize out appX constants, % operations, and + operations */
/* If not, use this:
static const char ones_digit_append_map[16] =
{
0, 6, 2, 8, 4, 10, 6, 12, 8, 14, 10, 16, 12, 18, 14, 20,
};
*/
static const char a1 = 0x10 % 10, a2 = 0x20 % 10, a3 = 0x40 % 10, a4 = 0x80 % 10;
static const char ones_digit_append_map[16] =
{
0, a1, a2, a1 + a2,
a3, a1 + a3, a2 + a3, a1 + a2 + a3,
a4, a1 + a4, a2 + a4, a1 + a2 + a4,
a3 + a4, a1 + a3 + a4, a2 + a3 + a4, a1 + a2 + a3 + a4,
};
char thousands_digit, hundreds_digit, tens_digit, ones_digit;
assert(n >= 0 && n < 1024 && "n must be between [0, 1024)");
/* n &= 0x3ff; can use this instead of the assert */
thousands_digit = (n >> 3 & 0x7f) > 0x7c;
n -= thousands_digit_subtract_map[thousands_digit];
ones_digit = ones_digit_map[
(n & 0xf)
+ ones_digit_append_map[n >> 4 & 0xf]
+ ones_digit_append_map[n >> 8 & 0x3]
];
n -= ones_digit;
hundreds_digit = hundreds_digit_map[n >> 3 & 0x7f];
n -= hundreds_digit_subtract_map[hundreds_digit];
tens_digit = tens_digit_map[n >> 3];
s[0] = '0' | thousands_digit;
s[1] = '0' | hundreds_digit;
s[2] = '0' | tens_digit;
s[3] = '0' | ones_digit;
s[4] = '\0';
}
int main(int argc, char* argv)
{
int i;
for(i = 0; i < 1024; ++i)
{
char blah[5];
itoa_ten_bits(i, blah);
if(atoi(blah) != i)
printf("failed %d %s\n", i, blah);
}
}

There's a way of doing it using subtractions, but I am not convinced it's faster than using subtractions and modulus on a "normal" CPU (may be different in an embedded environment).
Something like this:
char makedigit (int *number, int base)
{
static char map[] = "0123456789";
int ix;
for (ix=0; *number >= base; ix++) { *number -= base; }
return map[ix];
}
char *makestring (int number)
{
static char tmp[5];
tmp[0] = makedigit(&number, 1000);
tmp[1] = makedigit(&number, 100);
tmp[2] = makedigit(&number, 10);
tmp[3] = makedigit(&number, 1);
tmp[4] = '\0';
return tmp;
}
Then, a call to makestring() should result in a (static, so copy it before overwriting) string with the converted number (zero-prefixed, at 4 characters width, as the original assumption is a value in the 0-1023 range).

With some care in finding the right number(s) to use, you can multiply by the reciprocal of the base rather than dividing by the base. Terje's code is for an x86, but porting the general idea to a PIC shouldn't be tremendously difficult.

If the values are correctly in range (0..1023), then your last conversion is unnecessarily wasteful on the divisions; the last line could be replaced with:
temp[3] = 1023 / 1000;
or even:
temp[3] = 1023 >= 1000;
Since division is repeated subtraction, but you have a very special case (not a general case) division to deal with, I'd be tempted to compare the timings for the following code with the division version. I note that you put the digits into the string in 'reverse order' - the least significant digit goes in temp[0] and the most in temp[4]. Also, there is no chance of null-terminating the string given the storage. This code uses a table of 8 bytes of static data - considerably less than many of the other solutions.
void convert_to_ascii(int value, char *temp)
{
static const short subtractors[] = { 1000, 100, 10, 1 };
int i;
for (i = 0; i < 4; i++)
{
int n = 0;
while (value >= subtractors[i])
{
n++;
value -= subtractors[i];
}
temp[3-i] = n + '0';
}
}
Performance testing - Intel x86_64 Core 2 Duo 3.06 GHz (MacOS X 10.6.4)
This platform is probably not representative of your microcontroller, but the test shows that on this platform, the subtraction is considerably slower than the division.
void convert_by_division(int value, char *temp)
{
temp[0] = (value % 10) + '0';
temp[1] = (value % 100) / 10 + '0';
temp[2] = (value % 1000) / 100 + '0';
temp[3] = (value % 10000) / 1000 + '0';
}
void convert_by_subtraction(int value, char *temp)
{
static const short subtractors[] = { 1000, 100, 10, 1 };
int i;
for (i = 0; i < 4; i++)
{
int n = 0;
while (value >= subtractors[i])
{
n++;
value -= subtractors[i];
}
temp[3-i] = n + '0';
}
}
#include <stdio.h>
#include <timer.h>
#include <string.h>
static void time_convertor(const char *tag, void (*function)(void))
{
int r;
Clock ck;
char buffer[32];
clk_init(&ck);
clk_start(&ck);
for (r = 0; r < 10000; r++)
(*function)();
clk_stop(&ck);
printf("%s: %12s\n", tag, clk_elapsed_us(&ck, buffer, sizeof(buffer)));
}
static void using_subtraction(void)
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
convert_by_subtraction(i, temp1);
}
}
static void using_division(void)
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
convert_by_division(i, temp1);
}
}
int main()
{
int i;
for (i = 0; i < 1024; i++)
{
char temp1[4];
char temp2[4];
convert_by_subtraction(i, temp1);
convert_by_division(i, temp2);
if (memcmp(temp1, temp2, 4) != 0)
printf("!!DIFFERENCE!! ");
printf("%4d: %.4s %.4s\n", i, temp1, temp2);
}
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
time_convertor("Using division ", using_division);
time_convertor("Using subtraction", using_subtraction);
return 0;
}
Compiling with GCC 4.5.1, and working in 32-bit, the average timings were (optimization '-O'):
0.13 seconds using division
0.65 seconds using subtraction
Compiling and working in 64-bit, the average timings were:
0.13 seconds using division
0.48 seconds using subtraction
Clearly, on this machine, using subtraction is not a winning proposition. You would have to measure on your machine to make a decision. And removing the modulo 10000 operation will only skew results in favour of the division (it knocks about 0.02 seconds off the time with division when replaced with the comparison; that's a 15% saving and worth having).

Is there some reason that you're particularly concerned about this?
If your compiler and C library provide an itoa() function, use that, and then worry about writing this code (and associated tests and so forth to make sure you got it right!) if for some reason that turns out to be too slow or doesn't fit into RAM or something.

I've replaced my previous answer with a better one. This code creates a 4-character string in the proper order, most significant digit in output[0] to least significant in output[3] with a zero terminator in output[4]. I don't know anything about your PIC controller or C compiler, but this code doesn't require anything more than 16-bit integers, addition/subtraction, and shifting.
int x;
char output[5];
output[4] = 0;
x = 1023;
output[3] = '0' + DivideByTenReturnRemainder(&x);
output[2] = '0' + DivideByTenReturnRemainder(&x);
output[1] = '0' + DivideByTenReturnRemainder(&x);
output[0] = '0' + x;
The key to this is the magical function DivideByTenReturnRemainder. Without using division explicitly it's still possible to divide by powers of 2 by shifting right; the problem is that 10 isn't a power of 2. I've sidestepped that problem by multiplying the value by 25.625 before dividing by 256, letting integer truncation round down to the proper value. Why 25.625? Because it's easily represented by powers of 2. 25.625 = 16 + 8 + 1 + 1/2 + 1/8. Again, multiplying by 1/2 is the same as shifting right one bit, and multiplying by 1/8 is shifting right by 3 bits. To get the remainder, multiply the result by 10 (8+2) and subtract it from the original value.
int DivideByTenReturnRemainder(int * p)
{
/* This code has been tested for an input range of 0 to 1023. */
int x;
x = *p;
*p = ((x << 4) + (x << 3) + x + (x >> 1) + (x >> 3)) >> 8;
return x - ((*p << 3) + (*p << 1));
}

Are you required to use an ASCII string of the decimal representation? It would be much easier to store it in hexadecimal format. No division required, only (relatively cheap) shift operations. Excel should be able to read it if you prepend a '0x' to each number.

Related

How can I reduce the execution time in this code?

Problem
Consider the sequence D of the last decimal digits of the first N Fibonacci numbers, i.e. D = (F0%10,F1%10,…,FN−1%10).
Now, you should perform the following process:
Let D=(D1,D2,…,Dl)
If l=1, the process ends.
Create a new sequence
E=(D2,D4,…,D2⌊l/2⌋)
In other words, E is the sequence created by removing all odd-indexed elements from D
Change D to E
When this process terminates, the sequence D
contains only one number. You have to find this number.
Input
The first line of the input contains a single integer T
denoting the number of test cases.
The description of T test cases follows.
The first and only line of each test case contains a single integer N
Output
For each test case, print a single line containing one integer ― the last remaining number.
Code
#include <stdio.h>
#include <stdlib.h>
int test(int *arr, int n);
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
int *arr;
arr = (int *)malloc((n + 1) * sizeof(int));
arr[1] = 0;
arr[2] = 1;
for (int i = 3; i <= n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
/*
for(int k=1;k<=n;k++){
printf("%d ",arr[k] );
}
printf("\n");
*/
printf("%d\n", (test(arr, n)) % 10);
}
}
int test(int *arr, int n) {
if (n == 1) {
return arr[1];
} else {
for (int i = 1; i <= (n / 2); i++) {
arr[i] = arr[2 * i];
}
return test(arr, n / 2);
}
}
Using the algorithm from https://math.stackexchange.com/questions/681674/recursively-deleting-every-second-element-in-a-list,
Find the largest integer A, such that 2^A < N.
Find Fibonnaci(2^A - 1) % 10
Adding to Bill Lynch's answer, which is itself based on this other answer by happymath:
You will always end up getting 2n − 1 where n is maximum integer such that 2n < K
I'd like to point out another useful mathematical property.
In number theory, the nth Pisano period, written π(n), is the period with which the sequence of Fibonacci numbers taken modulo n repeats.
(https://en.wikipedia.org/wiki/Pisano_period)
Here we need to consider the case where n = 10, π(10) = 60 and the last decimal digits correspond to the OEIS sequence A003893:
0, 1, 1, 2, 3, 5, 8, 3, 1, 4, 5, 9, 4, 3, 7, 0, 7, 7, 4, 1, 5, 6, 1, 7, 8, 5, 3, 8, 1, 9, 0, 9, 9, 8, 7, 5, 2, 7, 9, 6, 5, 1, 6, 7, 3, 0, 3, 3, 6, 9, 5, 4, 9, 3, 2, 5, 7, 2, 9, 1
So that there's no need to calculate the actual Fibonacci number, nor to generate all the sequence up to N.

C: speed up for permutation of bits from given permutation table; searching for the minimum

I'm searching for a fast permutation of bits within a number in C.
I have an integer value and table of permutation positions. Not all possible permutations are listet, just n!*2n of the 2n! possible permutations.
For simplicity I will show the data as 4-Bit numbers (n=2, lutsize = 8), in reality they are 32-Bit numbers (n=5, lutsize=3840):
static const uint8_t lut[lutsize][4] = {
{0, 1, 2, 3},
{1, 0, 3, 2},
{2, 3, 0, 1},
{3, 2, 1, 0},
{0, 2, 1, 3},
{1, 3, 0, 2},
{2, 0, 3, 1},
{3, 1, 2, 0}};
So the first entry is the identity, for the second entry the bits 1&2 and 2&3 switch places and so on. I wrote a method which calculates the values and returns the minimal value:
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
enum { n = 2 };
enum { expn = 1<<n };
enum { lutsize = 8 };
static const uint8_t lut[lutsize][4] = {
{0, 1, 2, 3},
{1, 0, 3, 2},
{2, 3, 0, 1},
{3, 2, 1, 0},
{0, 2, 1, 3},
{1, 3, 0, 2},
{2, 0, 3, 1},
{3, 1, 2, 0}
};
uint32_t getMin(uint32_t in, uint32_t* ptr){
uint32_t pos, i, tmp, min;
uint8_t bits[expn];
tmp = in;
for (i = 0; i < expn; ++i){ // extract bits into array
bits[i] = tmp & 1;
tmp = tmp >> 1;
}
min = in;
for (pos = 0; pos < lutsize; ++pos){ // for each row in the permutation table
tmp = 0;
for (i = 0; i < expn; ++i){ // for each bit
tmp = tmp | (bits[i] << lut[pos][i]); // put bit i on position lut[pos][i]
}
ptr[pos] = tmp; // store result (optional)
//printf("%d: %d\n", pos, tmp);
if (tmp<min) { min = tmp; } // track minimum
}
//printf("min: %d\n", min);
return min;
}
void main(int argc, const char * argv[]) {
uint32_t ptr[lutsize];
printf("%u\n", (unsigned)getMin(5, ptr));
assert(getMin(5, ptr) == 3);
assert(getMin(0b0110, ptr) == 6);
}
gives the output for the example number 5 if you uncomment the printf's:
0: 5
1: 10
2: 5
3: 10
4: 3
5: 3
6: 12
7: 12
min: 3
I do calculate each permutation in a naive way by separating the bits into an array and then pushing them into their new position. I write the results into an array and keep track of the minimum which is returned at the end.
How do improve the performance of the procedure getMin for n=5?
I'm primarily interested in the minimum.
Additional input:
the permutation table can be read as "bit value comes from position" or "bit value shifts to position". The results are the same, just the order of the entries differs.
it is not necessary (but a bonus) to use the array (ptr)
the goal is to reduce the time to compute the smallest bit permutation number for all 32-bit numbers in random order. Precalculating all possible minimum numbers is ok. Using multiple versions of the lut is ok. Anything is ok as long it does not take more than 4GB of ram like storing all possible input/output pairs would do.
sorry for the not so c-like code. I'm out of training.
Here is the python code to generate the look up table for n=5:
from itertools import permutations
import numpy as np
import math
for n in [5]:
expn = 1<<n #2:4 3:8; 4:16; 5:32
order = np.zeros((int(math.factorial(n))*expn, expn), dtype=np.int8) # n!*2^n x 2^n matrix
cnt = 0 # current entry
permneg = np.zeros(expn, dtype=int)
for perm in permutations(list(range(n))): #shuffle order
ini = np.array(list(range(expn)), dtype=int) # list 0 to expn-1
out = np.zeros(expn, dtype=int)
for i in range(n): # apply permutation on position level
tmp = ini & 1 # get value on least bit
out += tmp << perm[i] #put it on the right postion
ini = ini >> 1 # next bit as least bit
for neg in range(expn): # include 0/1 swaps (negation)
for i in range(len(out)): # for all 2^n negation cases
permneg[i] = out[i] ^ neg # negate on negation bits
order[cnt]=permneg # store
cnt += 1 # increase counter
print("enum { lutsize = "+str(len(order))+" };")
s='},\n{'.join(', '.join(map(str,sl)) for sl in order)
print("static const uint8_t lut[lutsize]["+str(expn)+"] = {\n{"+s+"}\n};")
I would suggest two optimizations : 1) store the value of the set bit in the table instead. 2) Don't store each bit in an array but compute it on the fly instead. The result is the same, but it's probably a little bit faster.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define lutsize 8
static const uint8_t lutn[lutsize][4] = {
{1, 2, 4, 8},
{2, 1, 8, 4},
{4, 8, 1, 2},
{8, 4, 2, 1},
{1, 4, 2, 8},
{2, 8, 1, 4},
{4, 1, 8, 2},
{8, 2, 4, 1}};
uint32_t getMin(uint32_t in, uint32_t* ptr)
{
uint32_t pos, i, tmp, min;
uint8_t bits[expn];
tmp = in;
min = in;
for (pos = 0; pos < lutsize; ++pos){
tmp = 0;
for (i = 0; i < expn; ++i) {
// If the bit is set
if (in & (1<<i))
// get the value of the permuted bit in the table
tmp = tmp | lutn[pos][i];
}
ptr[pos] = tmp;
//printf("%d: %d\n", pos, tmp);
if (tmp<min) { min = tmp; } // track minimum
}
//printf("min: %d\n", min);
return min;
}
void main(int argc, const char * argv[]) {
uint32_t *ptr;
ptr = (uint32_t*) malloc(lutsize * sizeof(uint32_t));
getMin(5, ptr);
}
It seems to me that, not having all the possible permutations, you need to check all of those you have. Calculating the best permutation is not fruitful if you aren't sure that permutation is available.
So, the two optimizations remaining you can hope for are:
Stop the search if you achieve a minimum.
For example, if I have understood, you have the binary number 11001101. What is the minimum permutation value? Obviously 00011111, with all ones to the right. What exact permutation does this for you - whether the last 1 is the first, second, fifth, sixth or eight bit - matters not to you.
As soon as a permutation hits the magic value, that is the minimum and you know you can do no better, so you can just as well stop searching.
In your own example you hit the minimum value 3 (or 0011, which is the minimum from 1001 or 5) at iteration 4. You gained nothing from iterations five to seven.
If you have 1101, Go from { 0, 1, 3, 2 } to the bit-permutated value "1110" as fast as possible.
Not sure about the performances, but you could try precalculating the values from the table, even if this requires a 32x32 = 1024 32-value table - 4M of memory.
Considering the first position (our number is 1101), the permutation can have in position 0 only these values: 0, 1, 2, or 3. These have a value of 1___, 1___, 0___ or 1___. So our position 0 table is { 1000, 1000, 0000, 1000 }.
The second position is identical: { 1_, 1_, 0_, 1_ } and so we have { 0100, 0100, 0000, 0100 }.
The next two rows are { 0010, 0010, 0000, 0010 }
{ 0001, 0001, 0000, 0001 }.
Now, you want to calculate the value if permutation { 3, 0, 1, 2 } is applied:
for (i = 0; i < 4; i++) {
value |= table[i][permutation[i]];
}
===
But (again, if I understood the problem), let us say that the number has one fourth zeroes (it is made up of 24 1's, 8 0's) and the table is sizeable enough.
There is a very significant chance that you very soon hit both a permutation that puts a bit 1 in the 31st position, yielding some 2 billion, and another that puts a 0 there, yielding one billion.
The minimum will then surely be below two billions, so from now on, as soon as you check the first permutated bit and find it is a 1, you can stop calculating, you won't get a better minimum out of that permutation. Skip immediately to the next.
If you do this check at every cycle instead of only the first,
for (i = 0; i < 4; i++) {
value |= table[i][permutation[i]];
if (value > minimum) {
break;
}
}
I fear that you might eat any gains, but on the other hand, since values are automatically ordered in descending order, the first bits would get eliminated the most, avoiding the subsequent checks. It might be worth checking.
Nothing stops you from doing the calculation in two steps:
for (i = 0; i < 8; i++) {
value |= table[i][permutation[i]];
if (value > minimum) {
break;
}
}
if (value < minimum) {
for (; i < 32; i++) {
value |= table[i][permutation[i]];
}
}

Moving average in static array in C

I have an array of 10 elements, and I need to make that array into its moving average equivalent.
Using 3 elements each time (eg average of elements at indices 0-2, then 1-3 and so on up to indices from 10 then back to 0 and 1 to make the new array have exactly 10 elements as well).
What is the best approach to this without using pointers to wrap the array around (ring buffer).
Just do some bounds checking and wrap the index in code.
The example code below can be made more efficient, but it's written like this for clarity (sort of). Also there may be some minor mistake since I'm typing into StackOverflow rather than compiling it.
int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int averages[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for (int i = 0; i < 10; i++)
{
int a = i;
int b = i + 1 > 9 ? i - 10 + 1;
int c = i + 2 > 9 ? i - 10 + 2;
int count = array[a] + array[b] + array[c];
int average = count / 3; // note this will truncate any decimal part
averages[i] = average;
}

Replace number by sum of other numbers in a list without subtraction

I was asked:
Replace each number in a list by sum of remaining elements, the list is not sorted.
So suppose if we have a list of numbers like {2, 7, 1, 3, 8}, now we are to replace each element with sum of rest of elements. The output should be:
{(7 + 1 + 3 + 8), (2 + 1 + 3 + 8), (2 + 7 + 3 + 8), (2 + 7 + 1 + 8), (2 + 7 + 1 + 3)}
== {19, 14, 20, 18, 13}
I answered an obvious solution:
First evaluate sum of all numbers then subtract each element from sum.
So for above list sum is 2 + 7 + 1 + 3 + 8 = 21, then for output do like:
{sum - 2, sum - 7, sum - 1, sum - 3, sum - 8}
{21 - 2, 21 - 7, 21 - 1, 21 - 3, 21 - 8}
== {19, 14, 20, 18, 13}
It needs only two iterations of list.
Then Interviewer asked me: Now do it without subtraction? and I couldn't answer :(
Is other solution possible? Can some share any other trick? A better trick is possible?
Lets extra memory space can be used (I asked after a few minutes of try, even then I couldn't answer).
One possibility would be to compute prefix and suffix sums of your array and then combine the appropriate entries. This would still be O(n) but needs more memory space so I think your original method is better.
In other words, from {2, 7, 1, 3, 8} compute {2, 2+7, 2+7+1, 2+7+1+3, 2+7+1+3+8} and {2+7+1+3+8, 7+1+3+8, 1+3+8, 3+8, 8} and then add the appropriate entries.
The solution is to sum everything but the element. Then you don't have to subtract after the fact. You just skip adding the element at the current index.
Alternatively, you could get a subset of the list that excludes the element at the current index, then just sum the subset together. Pretty much the same thing as my first suggestion with more implementation detail.
C++ implementation. O(n) and done by keeping sums of all elements before and after a certain index.
#include <iostream>
int main() {
int a[] = {2,7,1,3,8};
int prefix[5]; // Sum of all values before current index
int suffix[5]; // Sum of all values after current index
prefix[0] = 0;
suffix[4] = 0;
for(int i = 1; i < 5; i++) {
prefix[i] = prefix[i-1] + a[i-1];
suffix[4 - i] = suffix[4 - i + 1] + a[4 - i + 1];
}
// Print result
for (int i = 0; i < 5; i++) {
std::cout << prefix[i] + suffix[i] << " ";
}
std::cout << std::endl;
}
I can't think anything better than yours.
But how about this :
Create a (n-1)xn matrix:
[ 2, 7, 1, 3, 8 ]
| 7, 1, 3, 8, 2 | rotate by 1
| 1, 3, 8, 2, 7 | by 2
| 3, 8, 2, 7, 1 | by 3
| 8, 2, 7, 1, 3 | by 4
Then Sum up the columns
C++'s std::rotate_copy can be used to create matrix
std::vector<int> v1 {2, 7, 1, 3, 8 };
std::vector<int> v2 (v1.size());
int i,j;
std::vector< std::vector<int> > mat;
for (int i=1; i<v1.size();++i){
std::rotate_copy(v1.begin(),v1.begin()+i,v1.end(),v2.begin());
mat.push_back(v2);
}
for(j=0;j<v1.size();++j)
for(i=0;i<v1.size()-2;++i)
v2[j]+=mat[i][j];
for(i=0;i<v2.size();++i)
std::cout<<v2[i]<<" ";
#include <iostream.h>
#include <stdio.h>
int main() {
int a[] = {2,7,1,3,8};
int sum[5]={0};
for(int j = 0; j < 5; j++){
for(int i = 1; i < 5; i++) {
sum[j]=sum[j]+a[(j+i+5)%5];
}
printf("%d ", sum[j]); }
}
Instead of subtracting the element you can add the element multiplied by -1. Multiplication and addition are allowed operations, I guess.

Getting each individual digit from a whole integer

Let's say I have an integer called 'score', that looks like this:
int score = 1529587;
Now what I want to do is get each digit 1, 5, 2, 9, 5, 8, 7 from the score using bitwise operators(See below edit note).
I'm pretty sure this can be done since I've once used a similar method to extract the red green and blue values from a hexadecimal colour value.
How would I do this?
Edit
It doesn't necessarily have to be bitwise operators, I just thought it'd be simpler that way.
You use the modulo operator:
while(score)
{
printf("%d\n", score % 10);
score /= 10;
}
Note that this will give you the digits in reverse order (i.e. least significant digit first). If you want the most significant digit first, you'll have to store the digits in an array, then read them out in reverse order.
RGB values fall nicely on bit boundaries; decimal digits don't. I don't think there's an easy way to do this using bitwise operators at all. You'd need to use decimal operators like modulo 10 (% 10).
Agree with previous answers.
A little correction: There's a better way to print the decimal digits from left to right, without allocating extra buffer. In addition you may want to display a zero characeter if the score is 0 (the loop suggested in the previous answers won't print anythng).
This demands an additional pass:
int div;
for (div = 1; div <= score; div *= 10)
;
do
{
div /= 10;
printf("%d\n", score / div);
score %= div;
} while (score);
Don't reinvent the wheel. C has sprintf for a reason.
Since your variable is called score, I'm guessing this is for a game where you're planning to use the individual digits of the score to display the numeral glyphs as images. In this case, sprintf has convenient format modifiers that will let you zero-pad, space-pad, etc. the score to a fixed width, which you may want to use.
This solution gives correct results over the entire range [0,UINT_MAX]
without requiring digits to be buffered.
It also works for wider types or signed types (with positive values) with appropriate type changes.
This kind of approach is particularly useful on tiny environments (e.g. Arduino bootloader) because it doesn't end up pulling in all the printf() bloat (when printf() isn't used for demo output) and uses very little RAM. You can get a look at value just by blinking a single led :)
#include <limits.h>
#include <stdio.h>
int
main (void)
{
unsigned int score = 42; // Works for score in [0, UINT_MAX]
printf ("score via printf: %u\n", score); // For validation
printf ("score digit by digit: ");
unsigned int div = 1;
unsigned int digit_count = 1;
while ( div <= score / 10 ) {
digit_count++;
div *= 10;
}
while ( digit_count > 0 ) {
printf ("%d", score / div);
score %= div;
div /= 10;
digit_count--;
}
printf ("\n");
return 0;
}
Usually, this problem resolve with using the modulo of a number in a loop or convert a number to a string. For convert a number to a string, you may can use the function itoa, so considering the variant with the modulo of a number in a loop.
Content of a file get_digits.c
$ cat get_digits.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// return a length of integer
unsigned long int get_number_count_digits(long int number);
// get digits from an integer number into an array
int number_get_digits(long int number, int **digits, unsigned int *len);
// for demo features
void demo_number_get_digits(long int number);
int
main()
{
demo_number_get_digits(-9999999999999);
demo_number_get_digits(-10000000000);
demo_number_get_digits(-1000);
demo_number_get_digits(-9);
demo_number_get_digits(0);
demo_number_get_digits(9);
demo_number_get_digits(1000);
demo_number_get_digits(10000000000);
demo_number_get_digits(9999999999999);
return EXIT_SUCCESS;
}
unsigned long int
get_number_count_digits(long int number)
{
if (number < 0)
number = llabs(number);
else if (number == 0)
return 1;
if (number < 999999999999997)
return floor(log10(number)) + 1;
unsigned long int count = 0;
while (number > 0) {
++count;
number /= 10;
}
return count;
}
int
number_get_digits(long int number, int **digits, unsigned int *len)
{
number = labs(number);
// termination count digits and size of a array as well as
*len = get_number_count_digits(number);
*digits = realloc(*digits, *len * sizeof(int));
// fill up the array
unsigned int index = 0;
while (number > 0) {
(*digits)[index] = (int)(number % 10);
number /= 10;
++index;
}
// reverse the array
unsigned long int i = 0, half_len = (*len / 2);
int swap;
while (i < half_len) {
swap = (*digits)[i];
(*digits)[i] = (*digits)[*len - i - 1];
(*digits)[*len - i - 1] = swap;
++i;
}
return 0;
}
void
demo_number_get_digits(long int number)
{
int *digits;
unsigned int len;
digits = malloc(sizeof(int));
number_get_digits(number, &digits, &len);
printf("%ld --> [", number);
for (unsigned int i = 0; i < len; ++i) {
if (i == len - 1)
printf("%d", digits[i]);
else
printf("%d, ", digits[i]);
}
printf("]\n");
free(digits);
}
Demo with the GNU GCC
$~/Downloads/temp$ cc -Wall -Wextra -std=c11 -o run get_digits.c -lm
$~/Downloads/temp$ ./run
-9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
-10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-1000 --> [1, 0, 0, 0]
-9 --> [9]
0 --> [0]
9 --> [9]
1000 --> [1, 0, 0, 0]
10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Demo with the LLVM/Clang
$~/Downloads/temp$ rm run
$~/Downloads/temp$ clang -std=c11 -Wall -Wextra get_digits.c -o run -lm
setivolkylany$~/Downloads/temp$ ./run
-9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
-10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-1000 --> [1, 0, 0, 0]
-9 --> [9]
0 --> [0]
9 --> [9]
1000 --> [1, 0, 0, 0]
10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Testing environment
$~/Downloads/temp$ cc --version | head -n 1
cc (Debian 4.9.2-10) 4.9.2
$~/Downloads/temp$ clang --version
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix
#include<stdio.h>
int main() {
int num; //given integer
int reminder;
int rev=0; //To reverse the given integer
int count=1;
printf("Enter the integer:");
scanf("%i",&num);
/*First while loop will reverse the number*/
while(num!=0)
{
reminder=num%10;
rev=rev*10+reminder;
num/=10;
}
/*Second while loop will give the number from left to right*/
while(rev!=0)
{
reminder=rev%10;
printf("The %d digit is %d\n",count, reminder);
rev/=10;
count++; //to give the number from left to right
}
return (EXIT_SUCCESS);}
First convert your integer to a string using sprintf, then do whatever you want with its elements, that are chars. Assuming an unsigned score:
unsigned int score = 1529587, i;
char stringScore [11] = { 0 };
sprintf( stringScore, "%d, score );
for( i=0; i<strlen(stringScore); i++ )
printf( "%c\n", stringScore[i] );
Please note how:
It prints digits starting from the most significant one
stringScore is 11 characters long assuming that the size of int, in your platform, is 4 bytes, so that the maximum integer is 10 digits long. The eleventh one is for the string terminator character '\0'.
sprintf makes all the work for you
Do you need to have an integer for every single digit?
Since we are sure that stringScore contains only digits, the conversion is really easy. If dig is the character containing the digit, the corresponding integer can be obtained in this way:
int intDigit = dig - '0';
//this can be easily understandable for beginners
int score=12344534;
int div;
for (div = 1; div <= score; div *= 10)
{
}
/*for (div = 1; div <= score; div *= 10); for loop with semicolon or empty body is same*/
while(div>1)
{
div /= 10;
printf("%d\n`enter code here`", score / div);
score %= div;
}
I've made this solution, it-s simple instead read an integer, i read a string (char array in C), then write with a for bucle, the code also write the sum of digits
// #include<string.h>
scanf("%s", n);
int total = 0;
for (int i = 0; i< strlen(n); i++){
printf("%c", n[i]);
total += (int)(n[i]) -48;
}
printf("%d", total);

Resources