decrementing arrays

B

Barry Schwarz

snip
Puts ("");

What's this function doing to your code? I have to break this down line by
line to understand what's going on.

You claimed in a previous post that you have a reference manual. Look
up puts. What does puts do with its argument? What else does it do
independent of its argument? What is the net effect of these two
activities given the original code of
puts("");
which you misquoted?


Remove del for email
 
B

Bartc

While(1). What's that mean?
Puts ("");

What's this function doing to your code? I have to break this down line by
line to understand what's going on.

while(1) is one way of writing an endless loop in C.

I use this sort of loop a lot. It gives me extra thinking time while I
figure out how to break out of the loop, which is easier if not constrained
to be at the beginning or end. So you start with this:

while (1) {
}

then fill in the space between { and }. In this case, you want to stop going
when the output shows 9999 9999 9999 9999. Ie. you're just about to roll
over to 0000 0000 0000 0000. (Although, for 16 digits, that would have taken
some 3000000 years on my computer, I of course tested with fewer digits
first.)

puts("") I assumed was a way of generating a new-line which is easier to
type than printf("\n") (however fputs("",F) is *not* equivalent to
fprintf(F,"\n"), as I've found out).
 
S

santosh

Bartc said:
while(1) is one way of writing an endless loop in C.

I use this sort of loop a lot. It gives me extra thinking time while I
figure out how to break out of the loop, which is easier if not
constrained to be at the beginning or end. So you start with this:

while (1) {
}

then fill in the space between { and }. In this case, you want to stop
going when the output shows 9999 9999 9999 9999. Ie. you're just about
to roll over to 0000 0000 0000 0000. (Although, for 16 digits, that
would have taken some 3000000 years on my computer, I of course tested
with fewer digits first.)

Interesting. Can you tell me how you calculated that figure of 3000000
years? For me on this machine the calculation came to just over 115
days.
puts("") I assumed was a way of generating a new-line which is easier
to type than printf("\n") (however fputs("",F) is *not* equivalent to
fprintf(F,"\n"), as I've found out).

Recalls to mind that famous quote: "C is quirky, flawed, and an enormous
success."
:)
 
B

Bill Cunningham

Bill Cunningham said:
Here's some more code. A bit simpler. It displays all possible
credit-card-style numbers, legal or not (including all of mine so
please take care distributing the output):

#include <stdio.h>
#include <stdlib.h>

int main(void) {
#define digits 16
char number[digits]={0};
int i;

while (1) {

for (i=0; i<digits; ++i) {
printf("%1d",number);
if ((i&3)==3) printf(" ");
};
puts("");

for (i=digits-1; i>=0; --i) {
number+=1;
if (number<10) break;
if (i==0) exit(0);
number-=10;

};
};
}


The iterations statement blocks above are alittle too much to chew in
one bite. Can you break them down alittle for me. Maybe instead of 16 digits
we can go with 4 or 5 that's easy to show permutations of by hand, C code
should be simple.

Bill
 
B

Bartc

santosh said:
Bartc wrote:

Interesting. Can you tell me how you calculated that figure of 3000000
years? For me on this machine the calculation came to just over 115
days.

Did you allow for any output?

My console can scroll text at some 700 lines per second (which I rounded up
to 1000; no need to show how slow my machine is..)

So showing 1e16 lines would take 1e13 seconds. Since there are only about
3e7 seconds in a year, there must be something amiss in your calculations,
or have a super-fast display.
Recalls to mind that famous quote: "C is quirky, flawed, and an enormous
success."
:)

That's good, not just me thinking it was odd.
 
B

Bartc

#include <stdio.h>
#include <stdlib.h>

int main(void) {
#define digits 16
char number[digits]={0};
int i;

while (1) {

for (i=0; i<digits; ++i) {
printf("%1d",number);
if ((i&3)==3) printf(" ");
};
puts("");

for (i=digits-1; i>=0; --i) {
number+=1;
if (number<10) break;
if (i==0) exit(0);
number-=10;

};
};
}


The iterations statement blocks above are alittle too much to chew in
one bite. Can you break them down alittle for me. Maybe instead of 16
digits we can go with 4 or 5 that's easy to show permutations of by hand,
C code should be simple.


Try changing the digits macro to 2 (or maybe just 1).

The while loop shows one combination per loop.

The first for loop just prints the digits in array number[].

The second for loop does the real work: adding one to the number, starting
from the right, and propagating any carry leftwards.
 
S

santosh

Bartc said:
Did you allow for any output?

My console can scroll text at some 700 lines per second (which I
rounded up to 1000; no need to show how slow my machine is..)

Actually I didn't count time for I/O. If I did, then mine would take a
similarly long time. The count is just for incrementing the registers
or memory location (which would be in L1 cache.)
So showing 1e16 lines would take 1e13 seconds. Since there are only
about 3e7 seconds in a year, there must be something amiss in your
calculations, or have a super-fast display.


That's good, not just me thinking it was odd.

Yes. Dennis Ritchie does capture the nature of C is a succinct way.
 
B

Bartc

santosh said:
Bartc wrote:

[printing to 1e16]
Actually I didn't count time for I/O. If I did, then mine would take a
similarly long time. The count is just for incrementing the registers
or memory location (which would be in L1 cache.)

Something amiss in my calculations too. It's more like 300000 years when you
count the digits properly...
Ok, still the machine will likely turn to dust before then, or someone will
unplug it accidentally.
 
B

Ben Bacarisse

Bartc said:
while(1) is one way of writing an endless loop in C.

I use this sort of loop a lot. It gives me extra thinking time while I
figure out how to break out of the loop, which is easier if not constrained
to be at the beginning or end. So you start with this:

while (1) {
}

then fill in the space between { and }. In this case, you want to stop going
when the output shows 9999 9999 9999 9999. Ie. you're just about to roll
over to 0000 0000 0000 0000.

In this case it leads to slightly obfuscated code. You do the same
thing again in a nested for (break out rather give the ending
condition) and that leaves you with no way to break out of the while
-- so you use exit!

Obviously your style is yours to choose, but you were giving code to
someone trying to learn (and not finding it easy). I would argue for
the greatest possible clarity in such cases.

My choice would be to add an extra digit so we always have a digit to
increment at the end. If you don't like that, the final increment
needs protecting with an if. I'd also use only one output function and
replace the mask with a remainder operation (this last is just a
matter of taste).

#include <stdio.h>

#define DIGITS 16

int main(void)
{
char number[DIGITS+1] = {0};
int d = DIGITS;

while (d > 0) {
for (int i = 1; i <= DIGITS; ++i) {
putchar('0' + number);
if (i % 4 == 0)
putchar(' ');
}
putchar('\n');

for (d = DIGITS; d > 0 && number[d] == 9; --d)
number[d] = 0;
number[d] += 1;
}
}

Of course, the tricky bit that has not been asked about is generating
only valid numbers. That requires incrementing only a 15-digit number
and adding the correct check-sum digit to the end:

#include <stdio.h>

#define DIGITS 16

int luhn_check(char *num)
{
int sum = 0;
int dsum[2][10] = {{0,2,4,6,8,1,3,5,7,9},{0,1,2,3,4,5,6,7,8,9}};
for (int i = 0; i < 15; i++)
sum += dsum[i&1][num];
sum %= 10;
return sum ? 10 - sum : 0;
}

int main(void)
{
char number[DIGITS+1] = {0};
int d = DIGITS;

while (d > 0) {
number[DIGITS] = luhn_check(number + 1);
for (int i = 1; i <= DIGITS; ++i) {
putchar('0' + number);
if (i % 4 == 0)
putchar(' ');
}
putchar('\n');

for (d = DIGITS - 1; d > 0 && number[d] == 9; --d)
number[d] = 0;
number[d] += 1;
}
}
 
S

santosh

Bartc said:
santosh said:
Bartc wrote:

[printing to 1e16]
Actually I didn't count time for I/O. If I did, then mine would take
a similarly long time. The count is just for incrementing the
registers or memory location (which would be in L1 cache.)

Something amiss in my calculations too. It's more like 300000 years
when you count the digits properly...
Ok, still the machine will likely turn to dust before then, or someone
will unplug it accidentally.

I did another test incrementing a uint_fast64_t object to 1000 million.
It took an average of 6 seconds. I derived from this that incrementing
the same object to 9999,9999,9999,9999 would take ~690 days on this
computer.

So from what you say it appears that your processor is about 150,000
times slower than mine. Mine is 1.5 GHz, so are you running a 10 KHz
processor? :)
 
K

Keith Thompson

Bill Cunningham said:
One at a time yes. If I am understanding correctly. A 16 digit number
generated off the system time.

You've said that (a) you want to generate them randomly, (b) you want
to generate all 10**16 numbers, and (c) that you want to use the
system time somehow. These are three very different things.

(And please use "**", not "^" to denote exponentiation. C has no
exponentation operator, but it does have a "^" operator; it means
bitwise exclusive-or.)

You keep introducing new and incompatible requirements.

If you generate random numbers in the range 0 .. 2**16-1, you're not
likely to get all of them, and you'll get repetitions long before
you've even gotten most of them.

I suspect you introduced "system time" because you have some vague
idea of using it to seed the random number generator. If that's what
you mean, please say so more clearly.

If all you want to do is generate all possible numbers in the range,
it's far easier to start at 0000000000000000 and repeatedly increment.
But if you generate 1 billion per second, it will take nearly 4
months.
 
B

Bartc

Ben Bacarisse said:
In this case it leads to slightly obfuscated code. You do the same

I don't know; I've stared at your second for loop for a while, I still don't
quite get it. So I would say yours is a little more obfuscated because of
the need to put the main loop test at the start of it.
thing again in a nested for (break out rather give the ending
condition) and that leaves you with no way to break out of the while
-- so you use exit!

That's also a valuable lesson: break can only be used for shallow exits from
loops. While I think Bill is familiar with exit().
I'd also use only one output function and
replace the mask with a remainder operation (this last is just a
matter of taste).

Well, no, I'd totally forgotten what the mod operator was. (I notice you
also have an extra space at the end of each line. Not really significant but
it does amount to an extra 10 petabytes of output in this case.)
Of course, the tricky bit that has not been asked about is generating
only valid numbers. That requires incrementing only a 15-digit number
and adding the correct check-sum digit to the end:

Well, this required some extra knowledge. I think a genuine valid number
would include a bank code for example.

The first number generated by your code is 0000 0000 0000 0000, which seems
unlikely to be on anyone's card (be cool though, if a little insecure).

Your code anyway goes through the sequences ten times faster because only 15
digits are significant.
 
K

Keith Thompson

Richard said:
Since you do no rule processing, and we are looking at base 10, all he
has to do is use a bignum library and loop from 0 to 10^16-1.
[...]

Why would he need a bignum library?
 
K

Keith Thompson

Bill Cunningham said:
I don't know if I'll need pointers for this or not. I wants numbers
10^16. Like a credit card 16 digits of possible 10 numbers, so I guess that
would be 10^16. So I have

int num [16][10];
These are of course declared and not initialized. Now I want to initialize
them all with '\0'. That I'm guessing would involve while ( --). Or maybe
for. Would pointers be involved in this?

With this excercise I would learn working with multi-dimensional
arrary, maybe pointers and initializing to zero. I tried to do this using
putchar so I obviously don't know what to do. Can someone help me learn
this?

Bill:

The most important thing you can do is to answer the following
question:

What exactly are you trying to do?

Don't talk about pointers, or decrementing, or while loops, or arrays,
or putchar, or '\0', or srand, or rand, or any other C language
concept. Pretend you've never heard of C. Tell us what *output* you
want your program to produce. Show us a short example if you can.

Describe the problem you're trying to solve *in plain English*. Don't
guess. Describe it in such a way that anyone implementing a solution,
based only on your description, will produce exactly the output you
want.

If you can't do this, then you don't really know what the problem is,
and you shouldn't even *begin* to think about implementing a solution.
 
B

Ben Bacarisse

Bartc said:
I don't know; I've stared at your second for loop for a while, I still don't
quite get it. So I would say yours is a little more obfuscated because of
the need to put the main loop test at the start of it.

I think that is because I chose a bad name for 'd'. I wanted to call
it something like 'most_sig_digit_incremented' so that it would
be clear that we loop until we increment the digit numbered 0. The
result was very, very long lines and I reverted to 'd'. Not a good
choice in retrospect.

I don't want a style war about while (1) loops, but when you have to
exit() from a nested 'for' inside one, I think it has gone a bit far!
 
B

Barry Schwarz

Bill Cunningham said:
Here's some more code. A bit simpler. It displays all possible
credit-card-style numbers, legal or not (including all of mine so
please take care distributing the output):

#include <stdio.h>
#include <stdlib.h>

int main(void) {
#define digits 16
char number[digits]={0};
int i;

while (1) {

for (i=0; i<digits; ++i) {
printf("%1d",number);
if ((i&3)==3) printf(" ");
};
puts("");

for (i=digits-1; i>=0; --i) {
number+=1;
if (number<10) break;
if (i==0) exit(0);
number-=10;

};
};
}


The iterations statement blocks above are alittle too much to chew in
one bite. Can you break them down alittle for me. Maybe instead of 16 digits
we can go with 4 or 5 that's easy to show permutations of by hand, C code
should be simple.


The only change would be to the #define directive.

Take a piece of paper, an eraser, and a pencil. Pretend you are the
computer. Execute each statement very carefully, noting the effect on
each variable.


Remove del for email
 
R

Richard

Bill Cunningham said:
Here's some more code. A bit simpler. It displays all possible
credit-card-style numbers, legal or not (including all of mine so
please take care distributing the output):

#include <stdio.h>
#include <stdlib.h>

int main(void) {
#define digits 16
char number[digits]={0};
int i;

while (1) {

for (i=0; i<digits; ++i) {
printf("%1d",number);
if ((i&3)==3) printf(" ");
};
puts("");

for (i=digits-1; i>=0; --i) {
number+=1;
if (number<10) break;
if (i==0) exit(0);
number-=10;

};
};
}


While(1). What's that mean?



*LOL*

You could not make it up. Sorry Bill, but this time it's definitely in
the bin with you. I simply can't laugh any more - my sides are sore.
 
R

Richard

Keith Thompson said:
Richard said:
Since you do no rule processing, and we are looking at base 10, all he
has to do is use a bignum library and loop from 0 to 10^16-1.
[...]

Why would he need a bignum library?

Good point. I dare say I was thinking he would be changing his
"requirements". ...
 
R

Richard

Keith Thompson said:
Bill Cunningham said:
I don't know if I'll need pointers for this or not. I wants numbers
10^16. Like a credit card 16 digits of possible 10 numbers, so I guess that
would be 10^16. So I have

int num [16][10];
These are of course declared and not initialized. Now I want to initialize
them all with '\0'. That I'm guessing would involve while ( --). Or maybe
for. Would pointers be involved in this?

With this excercise I would learn working with multi-dimensional
arrary, maybe pointers and initializing to zero. I tried to do this using
putchar so I obviously don't know what to do. Can someone help me learn
this?

Bill:

The most important thing you can do is to answer the following
question:

What exactly are you trying to do?

Don't talk about pointers, or decrementing, or while loops, or arrays,
or putchar, or '\0', or srand, or rand, or any other C language
concept. Pretend you've never heard of C. Tell us what *output* you
want your program to produce. Show us a short example if you can.

Describe the problem you're trying to solve *in plain English*. Don't
guess. Describe it in such a way that anyone implementing a solution,
based only on your description, will produce exactly the output you
want.

If you can't do this, then you don't really know what the problem is,
and you shouldn't even *begin* to think about implementing a solution.

Keith,

please stop parroting my posts. Thank you ....
 
K

Keith Thompson

Bill Cunningham said:
Wow. I think Richard says later in the thread that this kind of code is
dazzling and it is. Maybe something simple like the permutations of 1234.
That can be done by hand but how does C do it is the question.
[...]

You keep talking about "permutations". Are you sure that's the right
word? To be blunt, are you sure you know what the word means?

There are 24 permutations of 1234. Here they are:

1234 1243 1324 1342 1423 1432
2134 2143 2314 2341 2413 2431
3124 3142 3214 3241 3412 3421
4123 4132 4213 4231 4312 4321

(I did these manually, so there may be some errors.)

There are two important things to note. First, there are N! (N
factorial) permutations of N items; 4! is 24. Second, the definining
characteristic of each permutation is that no item is repeated.

You've been asking about 16 digits, with 10 possible values for each
digit. Given that description, there can be *no* permutations.

I've been able to figure out that you want to do *something* that
involves 16-digit decimal numbers (similar to credit card numbers).
I'm not sure whether you want to generate them randomly, generate all
possible numbers, or something else. I have no idea whether you want
to print each one as it's generated, or store them all, or do
something else.

Numerous people have spent considerable time and effort trying to help
you, based on *guesses* about what you're asking for. Throughout
this, you have been unable or unwilling to tell us just what you're
trying to do.

You have been wasting your time and ours.

Tell us what you want to do, and we'll try to help you do it.
Otherwise, I'm done.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,121
Latest member
LowellMcGu
Top