Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 months ago.
Improve this question
#include <stdio.h>
#include <math.h>
int main(void)
{
// input value
int num, lower, upper;
double squareroot;
int square;
int cube;
printf("enter your number:\n");
scanf_s("%d", &num);
do
{
printf("the lower value limit is ");
scanf_s("%d", &lower);
} while (lower < 0 || lower > 50);
do
{
printf("the upper value limit is ");
scanf_s("%d", &upper);
} while (upper < 0 || upper > 50);
// the formular to find the squareroot, square, cube
squareroot = sqrt(num);
square = num * num;
cube = num * num * num;
//a for loop
for (num = 0; num <= upper; num++) {
printf("*base number* || *square root* || *square* || *cube*\n");
printf("*%d* || *%f* || *%ld* || *%ld*\n",
lower, squareroot, square, cube);
}
return 0;
}
i try to make a table to display the base number, square root, square, and cube
and set a limit for the table.
for example, if I input the lower number is 1 and the upper number is 5 then the table will stop at 5 then display the square root, square, and cube
At least this problem:
Mismatched specifiers/type
int square;
int cube;
...
printf("*%d* || *%f* || *%ld* || *%ld*\n",
lower, squareroot, square, cube);
Use "%d" with int, not "%ld".
Move assignments
Following assignments need to be inside the loop.
for (num = 0; num <= upper; num++) {
square = num * num;
cube = num * num * num;
Save time. Enable all compiler warnings
Try the Below Code Make all Changes I have added Comments to Clarify why I made The
#include <stdio.h>
#include <math.h>
int main(void)
{
// input value
int lower, upper;
double squareroot;
int square;
int cube;
//Read the Limits First
printf("Enter the Lower Limit: ");
scanf("%d", &lower);
printf("Enter the Upper Limit: ");
scanf("%d", &upper);
//Instead of Declaring an Entire Loop You Can Just Use an If Statement this Reduces Code Complexity
//You can also Set Your Limits
if(upper > 0 && upper < 50 && lower > 0 && lower < 50)
{
//THen Enter Actual Code
//Also Dont Set Lower to 0 It will Change Your Actual Value Instead Take another Loop Var
for (int i = lower; i <= upper; i++)
{
//Then Perform all Functions on i
squareroot = sqrt(i);
square = i * i;
cube = i * i * i;
printf("*base number* || *square root* || *square* || *cube*\n");
printf("*%d* || *%f* || *%d* || *%d*\n", i, squareroot, square, cube);
}
}
return 0;
}
Several issues:
You go to the trouble of asking for lower, but you don't use it to control your loop - your loop should befor( int num = lower; num <= upper; num++)
{
...
}
Put another way, if you always intend for your loop to start from zero, then you don't need lower at all.
You need compute the square root, square, and cube of num for each iteration of the loop. Instead, you're doing it once before the loop and just printing those same values over and over again;
You only need to print your table header once, outside the body of the loop;
You can compute your square root, square, and cube all as part of the printf statement:
printf( "%d %f %d %d\n", num, sqrt((double) num), num * num, num * num * num );
Field width specifiers are your friends - you can tell printf exactly how wide you want each column to be. Example:
printf( "%6d%12.2f%12d%12d", num, sqrt((double) num), num * num, num * num * num );
This means the column for num is 6 characters wide, the column for square root is 12 characters wide, with 3 characters reserved for the decimal point and two following digits, and the columns for square and cube are 12 characters wide. Example:
printf( "%6s%12s%12s%12s\n", "base", "root", "square", "cube" );
printf( "%6s%12s%12s%12s\n", "----", "----", "------", "----" );
for (int i = lower; i <= upper; i++ )
printf( "%6d%12.2f%12d%12d\n", i, sqrt( (double) i ), i*i, i*i*i );
Which gives output like this (lower == 1, upper == 10):
base root square cube
---- ---- ------ ----
1 1.00 1 1
2 1.41 4 8
3 1.73 9 27
4 2.00 16 64
5 2.24 25 125
6 2.45 36 216
7 2.65 49 343
8 2.83 64 512
9 3.00 81 729
10 3.16 100 1000
Full example:
#include <stdio.h>
#include <math.h>
int main( void )
{
int lower = 0, upper = 0;
printf( "Gimme a lower value: " );
while ( scanf( "%d", &lower ) != 1 || (lower < 0 || lower > 50 ))
{
/**
* Clear any non-numeric characters from the input stream
*/
while ( getchar() != '\n' )
; // empty loop
printf( "Nope, try again: " );
}
printf( "Gimme an upper value: " );
while ( scanf( "%d", &upper ) != 1 || (upper < lower || upper > 50 ))
{
while( getchar() != '\n' )
; // empty loop
printf( "Nope, try again: " );
}
printf( "%6s%12s%12s%12s\n", "base", "root", "square", "cube" );
printf( "%6s%12s%12s%12s\n", "----", "----", "------", "----" );
for (int i = lower; i <= upper; i++ )
printf( "%6d%12.2f%12d%12d\n", i, sqrt( (double) i ), i*i, i*i*i );
return 0;
}
I've written the input section such that it will reject inputs like foo or a123. It will not properly handle inputs like 12w4, but that would make the example more complicated than it needs to be (you're not asking about input validation, you're asking about computation and formatting). Example run:
$ ./table
Gimme a lower value: foo
Nope, try again: a123
Nope, try again: 123
Nope, try again: 1
Gimme an upper value: 100
Nope, try again: 50
base root square cube
---- ---- ------ ----
1 1.00 1 1
2 1.41 4 8
3 1.73 9 27
4 2.00 16 64
5 2.24 25 125
6 2.45 36 216
7 2.65 49 343
8 2.83 64 512
9 3.00 81 729
10 3.16 100 1000
11 3.32 121 1331
12 3.46 144 1728
13 3.61 169 2197
14 3.74 196 2744
15 3.87 225 3375
16 4.00 256 4096
17 4.12 289 4913
18 4.24 324 5832
19 4.36 361 6859
20 4.47 400 8000
21 4.58 441 9261
22 4.69 484 10648
23 4.80 529 12167
24 4.90 576 13824
25 5.00 625 15625
26 5.10 676 17576
27 5.20 729 19683
28 5.29 784 21952
29 5.39 841 24389
30 5.48 900 27000
31 5.57 961 29791
32 5.66 1024 32768
33 5.74 1089 35937
34 5.83 1156 39304
35 5.92 1225 42875
36 6.00 1296 46656
37 6.08 1369 50653
38 6.16 1444 54872
39 6.24 1521 59319
40 6.32 1600 64000
41 6.40 1681 68921
42 6.48 1764 74088
43 6.56 1849 79507
44 6.63 1936 85184
45 6.71 2025 91125
46 6.78 2116 97336
47 6.86 2209 103823
48 6.93 2304 110592
49 7.00 2401 117649
50 7.07 2500 125000
int main(void)
{
/* Stop WDT */
MAP_WDT_A_holdTimer();
/* Selecting P1.2 and P1.3 in UART mode */
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
GPIO_PIN1 | GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
/* Setting DCO to 12MHz */
CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);
/* Configuring UART Module */
MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
/* Enable UART module */
MAP_UART_enableModule(EUSCI_A0_BASE);
/* Configuring GPIO2.4 as peripheral output for PWM and P6.7 for button
* interrupt */
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4,
GPIO_PRIMARY_MODULE_FUNCTION);
redirect();
/* Configuring P1.0 as output */
MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
/* Configuring Timer_A to have a period of approximately 500ms and
* an initial duty cycle of 10% of that (3200 ticks) */
//MAP_Interrupt_enableSleepOnIsrExit();
MAP_Interrupt_enableInterrupt(INT_TA0_0);
MAP_Timer_A_generatePWM(TIMER_A0_BASE,&pwmConfig);
MAP_Timer_A_clearInterruptFlag(TIMER_A0_BASE);
MAP_Timer_A_enableInterrupt(TIMER_A0_BASE);
MAP_Timer_A_enableCaptureCompareInterrupt
(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_0);
/* Enabling MASTER interrupts */
MAP_Interrupt_enableMaster();
/* Sleeping when not in use */
while (1)
{
//MAP_PCM_gotoLPM0();
}
}
const int bit_length = 33;
int period;
int times[33];
int values[32];
x=598;
number_bit=10;
// this function - period,times,values
// x is the 32 bit integer , number_bit is how many bits in that integer
void int_To_Arr(uint32_t x,int number_bit){
int i = 0;
period = BIT_LENGTH * 67 ; // 15fps -> 1/15=66.67m
for (i = 0; i < number_bit ; i++) {
if (((x >> i) & 1) == 0) /* shift right by i-bits, check on/off */
values[i] = 1000; /* assign to values[i] based on result */
else
values[i] = 11000;
times[i] = BIT_LENGTH * i; /* set times[i] */
}
times[i] = BIT_LENGTH * i;
}
void TA0_0_IRQHandler(void)
{
int i,value;
MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_0);
time=time+1;
if(time>=period){
time=0;
MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
}
for(i=0;times[i]!=-1;i++){
if(times[i]>time){
break;
}
value=values[i];
}
MAP_Timer_A_setCompareValue(TIMER_A0_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1, value);
}
So this function will take x (32-bit integer) and number_bit(how many bits in the integer) and will fill the array in the main. if the bit is 1 , values = 11000 which will turn on the led. if the bit is 0 ,values =1000 .Unfortunately, the LED doesnt blink or do anything. Before this I do it manually, yes the LED blinking.
int time=0;
const int BIT_LENGTH = 33;
int period;
int times[33]; //{x}
int values[32];//{y}
//new 1001010110
const int period=667; //15fps - bitlength*67
const int times[]={0,67,200,267,333,400,467,600,667,-1};
const int values[]={11000,1000,11000,1000,11000,1000,11000,1000};
If through the extended discussions we have had, you are seeking to fill the values array based on the number_bits in the uint32_t x value passed to your int_to_array function by shifting the value x to the right number_bits times and at each iteration determining whether that bit in x is 0 or 1 and setting values[i] = 1000 if the bit is 0 and to 11000 if the bit is 1, then you could do something like the following:
#define BIT_LENGTH 33 /* if you need a constant, define one (or more) */
#define FPS_MULT 33
...
/* fill values based on nbits bit-values in x,
* fill times based on BIT_LENGTH and index.
* note: CHAR_BIT defined in limits.h
* (defined as 8 for virtually all common systems)
*/
void int_to_array (uint32_t x, int nbits)
{
int i = 0; /* loop variable - can be declared in loop for C99+ */
period = BIT_LENGTH * FPS_MULT; // your 30fps-1/30=0.033
/* validate nbits <= 32 */
if (nbits > (int)(sizeof x * CHAR_BIT)) {
fprintf (stderr, "error: nbits out of range of uint32_t\n");
return;
}
for (i = 0; i < nbits; i++) {
if (((x >> i) & 1) == 0) /* shift right by i-bits, check on/off */
values[i] = 1000; /* assign to values[i] based on result */
else
values[i] = 11000;
times[i] = BIT_LENGTH * i; /* set times[i] */
}
times[i] = BIT_LENGTH * i; /* final times[BIT_LENGTH - 1] */
}
While I am still unclear where those values come from, based on our discussion, that should be what you are looking for. Otherwise, I'm still uncertain. note I have added a validation check to insure nbits cannot exceed 32 (the number of bits in x)
Validation Test
If you wanted to write a short bit of validation code for your function, you could just write a short program that passes the value provided on the command line as the first argument to your function as x (nbits won't change, it will always be sizeof x * CHAR_BIT). The following code passes the first argument to the function (passing 10 by default if no argument is given on the command line)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <limits.h>
#define BIT_LENGTH 33 /* if you need a constant, define one (or more) */
#define FPS_MULT 33
int period;
int times[BIT_LENGTH];
int values[BIT_LENGTH - 1];
/* fill values based on nbits bit-values in x,
* fill times based on BIT_LENGTH and index.
* note: CHAR_BIT defined in limits.h
* (defined as 8 for virtually all common systems)
*/
void int_to_array (uint32_t x, int nbits)
{
int i = 0; /* loop variable - can be declared in loop for C99+ */
period = BIT_LENGTH * FPS_MULT; // your 30fps-1/30=0.033
/* validate nbits <= 32 */
if (nbits > (int)(sizeof x * CHAR_BIT)) {
fprintf (stderr, "error: nbits out of range of uint32_t\n");
return;
}
for (i = 0; i < nbits; i++) {
if (((x >> i) & 1) == 0) /* shift right by i-bits, check on/off */
values[i] = 1000; /* assign to values[i] based on result */
else
values[i] = 11000;
times[i] = BIT_LENGTH * i; /* set times[i] */
}
times[i] = BIT_LENGTH * i; /* final times[BIT_LENGTH - 1] */
}
int main (int argc, char **argv) {
unsigned long tmp = argc > 1 ? strtoul (argv[1], NULL, 0) : 10;
uint32_t x;
int i, nbits = sizeof x * CHAR_BIT;
if (errno || tmp > UINT32_MAX) {
fprintf (stderr, "error: conversion error or value out of range.\n");
return 1;
}
x = (uint32_t)tmp;
int_to_array (x, nbits);
printf ("x: %u\n\nperiod: %d\n\n", x, period);
for (i = 0; i < nbits; i++)
printf ("values[%2d]: %5d times[%2d]: %5d\n",
i, values[i], i, times[i]);
printf (" times[%2d]: %5d\n", i, times[i]);
return 0;
}
(note: I tweaked the function by addition optional parenthesis to a check to get rid of a -pedantic signed/unsigned comparison warning and added a final times[i] = BIT_LENGTH * i; after the loop to handle times having 1 more element than values)
Example Test
Simple default value of 10 (1010)
$ ./bin/values_times
x: 10
period: 1089
values[ 0]: 1000 times[ 0]: 0
values[ 1]: 11000 times[ 1]: 33
values[ 2]: 1000 times[ 2]: 66
values[ 3]: 11000 times[ 3]: 99
values[ 4]: 1000 times[ 4]: 132
values[ 5]: 1000 times[ 5]: 165
values[ 6]: 1000 times[ 6]: 198
values[ 7]: 1000 times[ 7]: 231
values[ 8]: 1000 times[ 8]: 264
values[ 9]: 1000 times[ 9]: 297
values[10]: 1000 times[10]: 330
values[11]: 1000 times[11]: 363
values[12]: 1000 times[12]: 396
values[13]: 1000 times[13]: 429
values[14]: 1000 times[14]: 462
values[15]: 1000 times[15]: 495
values[16]: 1000 times[16]: 528
values[17]: 1000 times[17]: 561
values[18]: 1000 times[18]: 594
values[19]: 1000 times[19]: 627
values[20]: 1000 times[20]: 660
values[21]: 1000 times[21]: 693
values[22]: 1000 times[22]: 726
values[23]: 1000 times[23]: 759
values[24]: 1000 times[24]: 792
values[25]: 1000 times[25]: 825
values[26]: 1000 times[26]: 858
values[27]: 1000 times[27]: 891
values[28]: 1000 times[28]: 924
values[29]: 1000 times[29]: 957
values[30]: 1000 times[30]: 990
values[31]: 1000 times[31]: 1023
times[32]: 1056
or a larger value, 0xdeadbeef (11011110101011011011111011101111)
$ ./bin/values_times 0xdeadbeef
x: 3735928559
period: 1089
values[ 0]: 11000 times[ 0]: 0
values[ 1]: 11000 times[ 1]: 33
values[ 2]: 11000 times[ 2]: 66
values[ 3]: 11000 times[ 3]: 99
values[ 4]: 1000 times[ 4]: 132
values[ 5]: 11000 times[ 5]: 165
values[ 6]: 11000 times[ 6]: 198
values[ 7]: 11000 times[ 7]: 231
values[ 8]: 1000 times[ 8]: 264
values[ 9]: 11000 times[ 9]: 297
values[10]: 11000 times[10]: 330
values[11]: 11000 times[11]: 363
values[12]: 11000 times[12]: 396
values[13]: 11000 times[13]: 429
values[14]: 1000 times[14]: 462
values[15]: 11000 times[15]: 495
values[16]: 11000 times[16]: 528
values[17]: 1000 times[17]: 561
values[18]: 11000 times[18]: 594
values[19]: 11000 times[19]: 627
values[20]: 1000 times[20]: 660
values[21]: 11000 times[21]: 693
values[22]: 1000 times[22]: 726
values[23]: 11000 times[23]: 759
values[24]: 1000 times[24]: 792
values[25]: 11000 times[25]: 825
values[26]: 11000 times[26]: 858
values[27]: 11000 times[27]: 891
values[28]: 11000 times[28]: 924
values[29]: 1000 times[29]: 957
values[30]: 11000 times[30]: 990
values[31]: 11000 times[31]: 1023
times[32]: 1056
Look things over and let me know if you have further questions.
It seems you want to examine each bit of x and see if it is 1 or 0, using >> is correct however doing
x>>i; //x<<i
if(x&1==0){
will not work because x>>i just returns what the value of x shifted i bits is, it does not update the value of x. Instead, I would do the following
x = x >> 1;
if(x&1==0){
It will shift the value of x by one each time through the loop and then check the rightmost bit.
Also, your loop counter is incorrect, instead of
for(i=1;i<x;i++){
You most likely want
for(i = 1; i < number_bit; i++) {
Actually looking at this again, you special case setting times[0] and values[0] outside the loop, and then start your loop at 1, so if you want to keep the code structured like that, your loop counter must be
for(i = 1; i < number_bit - 1; i++) {
Though looking at the code, I see no reason to special case the setting of times[0] and values[0], if you examine it closely, you'll see you can loop from
for(i = 0; i < number_bit; i++) {
and include setting times[0] and values[0] within the loop. You would just have to do the shift AFTER setting values or use an if to not shift x when i is 0.
I want to create a C program to generate numbers from 0 to 999999, keeping in mind that the number generated should not have any digits that are repetitive within it. For example, "123" is an acceptable value but not "121" as the '1' is repeated. I have sourced other program codes that check if an integer has repeated digits:
Check if integer has repeating digits. No string methods or arrays
What is the fastest way to check for duplicate digits of a number?
However these do not really solve my problem and they are very inefficient solutions if I were to perform the check for 1,000,000 different values. Moreover, the solution provided is for int and not char[] and char *, which I use in my program. Below is my code thus far. As you can see I have no problems handling values of up to "012", however the possibilities for values with 3 digits and above are too many to list and too inefficient to code. Would appreciate some help.
int i, j;
char genNext[7] = "0";
printf("%s\n", genNext);
// loop through to return next pass in sequence
while (1) {
for (i = 0; i < sizeof(genNext) / sizeof(char); i++) {
if (genNext[i] == '9') {
char * thisPass = strndup(genNext, sizeof(genNext));
int countDigit = (int) strlen(thisPass);
switch (countDigit) {
case 1:
genNext = "01";
break;
case 2:
if (strcmp(genNext, "98")) {
if (i == 0) {
genNext[1] += 1;
} else {
genNext[0] += 1;
genNext[1] == '0';
}
} else {
genNext = "012";
}
break;
case 3:
if (strcmp(genNext, "987")) {
// code to handle all cases
} else {
genNext = "0123";
}
break;
case 4:
case 5:
case 6:
// insert code here
}
break;
} else if (genNext[i] == '\0') {
break;
} else if (genNext[i+1] == '\0') {
genNext[i] += 1;
for (j = 0; j < i; j++) {
if (genNext[i] == genNext[j]) {
genNext[i] += 1;
}
}
} else {
continue;
}
}
printf("%s\n", genNext);
if (strcmp(genNext, "987654") == 0) {
break;
}
}
The main problem that I am facing is the cases when '9' is part of the value that is being tested. For example, the next value in the sequence after "897" is "901" and after "067895" comes "067912" based on the rules of non-repetitiveness as well as sequential returning of the result.
A desired output would be as follows:
0
1
2
3
...
8
9
01
02
03
...
09
10
12
13
...
97
98
012
013
014
...
098
102
103
...
985
986
987
0123
0124
...
etc etc.
Any assistance is appreciated, and if any part of my question was unclear, feel free to clarify. Thanks!
EDIT: How do I generate all permutations of a list of numbers? does not solve my question as the increment from "120398" to "120435" as the next "legal" value in the sequence.
EDIT 2: Updated question to include desired output
There are three variant algorithms below. Adapt variant 3 to suit your requirements.
Variant 1
This is one way to do it. It implements a minor variant of the initialize a table of 10 digit counts to 0; scan the digits, increment the count for each digit encountered, then check whether any of the digit counts is more than 1 algorithm I suggested in a comment. The test function returns as soon as a duplicate digit is spotted.
#include <stdio.h>
#include <stdbool.h>
enum { MAX_ITERATION = 1000000 };
static bool duplicate_digits_1(int value)
{
char buffer[12];
snprintf(buffer, sizeof(buffer), "%d", value);
char digits[10] = { 0 };
char *ptr = buffer;
char c;
while ((c = *ptr++) != '\0')
{
if (++digits[c - '0'] > 1)
return true;
}
return false;
}
int main(void)
{
int count = 0;
for (int i = 0; i < MAX_ITERATION; i++)
{
if (!duplicate_digits_1(i))
{
count += printf(" %d", i);
if (count > 72)
{
putchar('\n');
count = 0;
}
}
}
putchar('\n');
return 0;
}
When run, it produces 168,571 values between 0 and 1,000,000, starting:
0 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29
30 31 32 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57
58 59 60 61 62 63 64 65 67 68 69 70 71 72 73 74 75 76 78 79 80 81 82 83 84
85 86 87 89 90 91 92 93 94 95 96 97 98 102 103 104 105 106 107 108 109 120
123 124 125 126 127 128 129 130 132 134 135 136 137 138 139 140 142 143 145
146 147 148 149 150 152 153 154 156 157 158 159 160 162 163 164 165 167 168
169 170 172 173 174 175 176 178 179 180 182 183 184 185 186 187 189 190 192
193 194 195 196 197 198 201 203 204 205 206 207 208 209 210 213 214 215 216
217 218 219 230 231 234 235 236 237 238 239 240 241 243 245 246 247 248 249
250 251 253 254 256 257 258 259 260 261 263 264 265 267 268 269 270 271 273
…
987340 987341 987342 987345 987346 987350 987351 987352 987354 987356 987360
987361 987362 987364 987365 987401 987402 987403 987405 987406 987410 987412
987413 987415 987416 987420 987421 987423 987425 987426 987430 987431 987432
987435 987436 987450 987451 987452 987453 987456 987460 987461 987462 987463
987465 987501 987502 987503 987504 987506 987510 987512 987513 987514 987516
987520 987521 987523 987524 987526 987530 987531 987532 987534 987536 987540
987541 987542 987543 987546 987560 987561 987562 987563 987564 987601 987602
987603 987604 987605 987610 987612 987613 987614 987615 987620 987621 987623
987624 987625 987630 987631 987632 987634 987635 987640 987641 987642 987643
987645 987650 987651 987652 987653 987654
Before you decide this is 'not efficient', measure it. Are you really exercising it often enough that the performance is a real problem?
Variant 2
Creating the alternative version I suggested in the comments: use strchr() iteratively, checking whether the first digit appears in the tail, and if not whether the second digit appears in the tail, and so on is very easy to implement given the framework of the first answer:
static bool duplicate_digits_2(int value)
{
char buffer[12];
snprintf(buffer, sizeof(buffer), "%d", value);
char *ptr = buffer;
char c;
while ((c = *ptr++) != '\0')
{
if (strchr(ptr, c) != NULL)
return true;
}
return false;
}
When the times are compared I got these results (ng41 uses duplicate_digits_1() and ng43 uses duplicate_digits_2().
$ time ng41 > /dev/null
real 0m0.175s
user 0m0.169s
sys 0m0.002s
$ time ng43 > /dev/null
real 0m0.201s
user 0m0.193s
sys 0m0.003s
$
Repeated timings generally showed similar results, but sometimes I got ng43 running faster than ng41 — the timing on just one set of one million numbers isn't clear cut (so YMMV — your mileage may vary!).
Variant 3
You could also use this technique, which is analogous to 'count digits' but without the conversion to string first (so it should be quicker).
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
enum { MAX_ITERATION = 1000000 };
static bool duplicate_digits_3(int value)
{
char digits[10] = { 0 };
while (value > 0)
{
if (++digits[value % 10] > 1)
return true;
value /= 10;
}
return false;
}
int main(void)
{
int count = 0;
const char *pad = "";
for (int i = 0; i < MAX_ITERATION; i++)
{
if (!duplicate_digits_3(i))
{
count += printf("%s%d", pad, i);
pad = " ";
if (count > 72)
{
putchar('\n');
count = 0;
pad = "";
}
}
}
putchar('\n');
return 0;
}
Because it avoids conversions to strings, it is much faster. The slowest timing I got from a series of 3 runs was:
real 0m0.063s
user 0m0.060s
sys 0m0.001s
which is roughly three times as fast as either of the other two.
Extra timing
I also changed the value of MAX_ITERATION to 10,000,000 and ran timing. There are many more rejected outputs, of course.
$ time ng41 >/dev/null
real 0m1.721s
user 0m1.707s
sys 0m0.006s
$ time ng43 >/dev/null
real 0m1.958s
user 0m1.942s
sys 0m0.008s
$ time ng47 >/dev/null
real 0m0.463s
user 0m0.454s
sys 0m0.004s
$ ng41 | wc
69237 712891 5495951
$ ng43 | wc
69237 712891 5495951
$ ng47 | wc
69237 712891 5495951
$ cmp <(ng41) <(ng43)
$ cmp <(ng41) <(ng47)
$ cmp <(ng43) <(ng47)
$
These timings were more stable; variant 1 (ng41) was always quicker than variant 2 (ng43), but variant 3 (ng47) beats both by a significant margin.
JFTR: testing was done on macOS Sierra 10.12.1 with GCC 6.2.0 on an old 17" MacBook Pro — Early 2011, 2.3GHz Intel Core i7 with 16 GB 1333 MHz DDR3 RAM — not that memory is an issue with this code. The program numbers are consecutive 2-digit primes, in case you're wondering.
Leading zeros too
This code generates the sequence of numbers you want (though it is only configured to run up to 100,000 — the change for 1,000,000 is trivial). It's fun in a masochistic sort of way.
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
enum { MAX_ITERATIONS = 100000 };
/* lz = 1 or 0 - consider that the number has a leading zero or not */
static bool has_duplicate_digits(int value, int lz)
{
assert(value >= 0 && value < MAX_ITERATIONS + 1);
assert(lz == 0 || lz == 1);
char digits[10] = { [0] = lz };
while (value > 0)
{
if (++digits[value % 10] > 1)
return true;
value /= 10;
}
return false;
}
int main(void)
{
int lz = 0;
int p10 = 1;
int log_p10 = 0; /* log10(0) is -infinity - but 0 works better */
int linelen = 0;
const char *pad = "";
/* The + 1 allows the cycle to reset for the leading zero pass */
for (int i = 0; i < MAX_ITERATIONS + 1; i++)
{
if (i >= 10 * p10 && lz == 0)
{
/* Passed through range p10 .. (10*p10-1) once without leading zeros */
/* Repeat, adding leading zeros this time */
lz = 1;
i = p10;
}
else if (i >= 10 * p10)
{
/* Passed through range p10 .. (10*p10-1) without and with leading zeros */
/* Continue through next range, without leading zeros to start with */
p10 *= 10;
log_p10++;
lz = 0;
}
if (!has_duplicate_digits(i, lz))
{
/* Adds a leading zero if lz == 1; otherwise, it doesn't */
linelen += printf("%s%.*d", pad, log_p10 + lz + 1, i);
pad = " ";
if (linelen > 72)
{
putchar('\n');
pad = "";
linelen = 0;
}
}
}
putchar('\n');
return 0;
}
Sample output (to 100,000):
0 1 2 3 4 5 6 7 8 9 01 02 03 04 05 06 07 08 09 10 12 13 14 15 16 17 18 19
20 21 23 24 25 26 27 28 29 30 31 32 34 35 36 37 38 39 40 41 42 43 45 46 47
48 49 50 51 52 53 54 56 57 58 59 60 61 62 63 64 65 67 68 69 70 71 72 73 74
75 76 78 79 80 81 82 83 84 85 86 87 89 90 91 92 93 94 95 96 97 98 012 013
014 015 016 017 018 019 021 023 024 025 026 027 028 029 031 032 034 035 036
037 038 039 041 042 043 045 046 047 048 049 051 052 053 054 056 057 058 059
061 062 063 064 065 067 068 069 071 072 073 074 075 076 078 079 081 082 083
084 085 086 087 089 091 092 093 094 095 096 097 098 102 103 104 105 106 107
108 109 120 123 124 125 126 127 128 129 130 132 134 135 136 137 138 139 140
…
901 902 903 904 905 906 907 908 910 912 913 914 915 916 917 918 920 921 923
924 925 926 927 928 930 931 932 934 935 936 937 938 940 941 942 943 945 946
947 948 950 951 952 953 954 956 957 958 960 961 962 963 964 965 967 968 970
971 972 973 974 975 976 978 980 981 982 983 984 985 986 987 0123 0124 0125
0126 0127 0128 0129 0132 0134 0135 0136 0137 0138 0139 0142 0143 0145 0146
0147 0148 0149 0152 0153 0154 0156 0157 0158 0159 0162 0163 0164 0165 0167
…
0917 0918 0921 0923 0924 0925 0926 0927 0928 0931 0932 0934 0935 0936 0937
0938 0941 0942 0943 0945 0946 0947 0948 0951 0952 0953 0954 0956 0957 0958
0961 0962 0963 0964 0965 0967 0968 0971 0972 0973 0974 0975 0976 0978 0981
0982 0983 0984 0985 0986 0987 1023 1024 1025 1026 1027 1028 1029 1032 1034
1035 1036 1037 1038 1039 1042 1043 1045 1046 1047 1048 1049 1052 1053 1054
1056 1057 1058 1059 1062 1063 1064 1065 1067 1068 1069 1072 1073 1074 1075
…
9820 9821 9823 9824 9825 9826 9827 9830 9831 9832 9834 9835 9836 9837 9840
9841 9842 9843 9845 9846 9847 9850 9851 9852 9853 9854 9856 9857 9860 9861
9862 9863 9864 9865 9867 9870 9871 9872 9873 9874 9875 9876 01234 01235 01236
01237 01238 01239 01243 01245 01246 01247 01248 01249 01253 01254 01256 01257
01258 01259 01263 01264 01265 01267 01268 01269 01273 01274 01275 01276 01278
01279 01283 01284 01285 01286 01287 01289 01293 01294 01295 01296 01297 01298
…
09827 09831 09832 09834 09835 09836 09837 09841 09842 09843 09845 09846 09847
09851 09852 09853 09854 09856 09857 09861 09862 09863 09864 09865 09867 09871
09872 09873 09874 09875 09876 10234 10235 10236 10237 10238 10239 10243 10245
10246 10247 10248 10249 10253 10254 10256 10257 10258 10259 10263 10264 10265
…
98705 98706 98710 98712 98713 98714 98715 98716 98720 98721 98723 98724 98725
98726 98730 98731 98732 98734 98735 98736 98740 98741 98742 98743 98745 98746
98750 98751 98752 98753 98754 98756 98760 98761 98762 98763 98764 98765 012345
012346 012347 012348 012349 012354 012356 012357 012358 012359 012364 012365
012367 012368 012369 012374 012375 012376 012378 012379 012384 012385 012386
…
098653 098654 098657 098671 098672 098673 098674 098675 098712 098713 098714
098715 098716 098721 098723 098724 098725 098726 098731 098732 098734 098735
098736 098741 098742 098743 098745 098746 098751 098752 098753 098754 098756
098761 098762 098763 098764 098765
Using a loop (from 0 to 999,999, inclusive), and rejecting values with repeating digits sounds like the most straightforward implementation to me.
The reject-if-duplicate-digits function can be made to be pretty fast. Consider, for example,
int has_duplicate_digits(unsigned int value)
{
unsigned int digit_mask = 0U;
do {
/* (value % 10U) is the value of the rightmost
decimal digit of (value).
1U << (value % 10U) refers to the value of
the corresponding bit -- bit 0 to bit 9. */
const unsigned int mask = 1U << (value % 10U);
/* If the bit is already set in digit_mask,
we have a duplicate digit in value. */
if (mask & digit_mask)
return 1;
/* Mark this digit as seen in the digit_mask. */
digit_mask |= mask;
/* Drop the rightmost digit off value.
Note that this is integer division. */
value /= 10U;
/* If we have additional digits, repeat loop. */
} while (value);
/* No duplicate digits found. */
return 0;
}
This is actually a classical combinatorial problem. Below is a proof of concept implementation using Algorithm L in TAOCP 7.2.1.2 and Algorithm T in TAOCP 7.2.1.3. There might be some errors. Refer to the algorithms for details.
Here is a bit of explanation. Let t be the number of digits. For t == 10, the problem is to generate all t! permutations of the set {0,1,2,...,9} in lexicographic order (Algorithm L).
For t > 0 and t < 10, this breaks down to 1) Generate all combinations of t digits from the 10 possible digits. 2). For each combination, generate all t! permutations.
Last, you can sort all 10! + 10! / 2 + 10! / 3! + .. + 10 results. The sorting might look expensive at first. But first, the combination generating is already in lexical order. Second, the permutation generating is also in lexical order. So the sequence is actually highly regular. A QSort is not really too bad here.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static inline int compare_str(const void *a, const void *b)
{
return strcmp(a, b);
}
static inline int compare_char(const void *a, const void *b)
{
char ca = *((char *) a);
char cb = *((char *) b);
if (ca < cb)
return -1;
if (ca > cb)
return 1;
return 0;
}
// Algorithm L in TAOCP 7.2.1.2
static inline char *algorithm_l(int n, const char *c, char *r)
{
char a[n + 1];
memcpy(a, c, n);
a[n] = '\0';
qsort(a, n, 1, compare_char);
while (1) {
// L1. [Visit]
memcpy(r, a, n + 1);
r += n + 1;
// L2. [Find j]
int j = n - 1;
while (j > 0 && a[j - 1] >= a[j])
--j;
if (j == 0)
break;
// L3. [Increase a[j - 1]]
int l = n;
while (l >= 0 && a[j - 1] >= a[l - 1])
--l;
char tmp = a[j - 1];
a[j - 1] = a[l - 1];
a[l - 1] = tmp;
// L4. [Reverse a[j]...a[n-1]]
int k = j + 1;
l = n;
while (k < l) {
char tmp = a[k - 1];
a[k - 1] = a[l - 1];
a[l - 1] = tmp;
++k;
--l;
}
}
return r;
}
// Algorithm T in TAOCP 7.2.1.2
static inline void algorithm_t(int t, char *r)
{
assert(t > 0);
assert(t < 10);
// Algorithm T in TAOCP 7.2.1.3
// T1. [Initialize]
char c[12]; // the digits
for (int i = 0; i < t; ++i)
c[i] = '0' + i;
c[t] = '9' + 1;
c[t + 1] = '0';
char j = t;
char x = '0';
while (1) {
// T2. [Visit]
r = algorithm_l(t, c, r);
if (j > 0) {
x = '0' + j;
} else {
// T3. [Easy case?]
if (c[0] + 1 < c[1]) {
++c[0];
continue;
}
j = 2;
// T4. [Find j]
while (1) {
c[j - 2] = '0' + j - 2;
x = c[j - 1] + 1;
if (x != c[j])
break;
++j;
}
// T5. [Done?]
if (j > t)
break;
}
// T6. [Increase c[j - 1]]
c[j - 1] = x;
--j;
}
}
static inline void generate(int t)
{
assert(t >= 0 && t <= 10);
if (t == 0)
return;
int n = 1;
int k = 10;
for (int i = 1; i <= t; ++i, --k)
n *= k;
char *r = (char *) malloc((t + 1) * n);
if (t == 10) {
algorithm_l(10, "0123456789", r);
} else {
algorithm_t(t, r);
}
qsort(r, n, t + 1, strcmpv);
for (int i = 0; i < n; ++i, r += t + 1)
printf("%s\n", r);
}
int main()
{
for (int t = 1; t <= 10; ++t)
generate(t);
}
Efficiency: This is implementation is not very efficient. It is a direct translation from the algorithm, for easier understanding. However it is still a lot more efficient than iterating over 10^10 numbers. It takes about 2.5 seconds to generate all numbers from 0 to 9876543210. This includes the time of writing them to a file, a 94MB output file, with one number a line. For up to 6 digits, it takes about 0.05 seconds.
If you want these numbers come in the order you want in program, it might be better to generate the numbers as above to prepare a table and use the table later. Even for the table from 0 to 9876543210, there are less than ten million numbers, which is not a really big number in today's computers. In your case, up to six digits, there are only less than one million numbers.
I am new to multithreaded programming and so I thought I would work on a project to help me learn it. Here are the details of the project:
Write a multithreaded sorting program in c that works as follows: A list of integers is divided into two smaller lists of equal size. Two separate threads (which we will term sorting threads) sort each sublist using a sorting algorithm of your choice. The two sublists are then merged by a third thread - a merging thread - which merges the two sublists into a single sorted list.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
#define NUMBER_OF_THREADS 3
void *sorter(void *params); /* thread that performs basic sorting algorithm */
void *merger(void *params); /* thread that performs merging of results */
int list[SIZE] = {7,12,19,3,18,4,2,6,15,8};
int result[SIZE];
typedef struct
{
int from_index;
int to_index;
} parameters;
int main (int argc, const char * argv[])
{
int i;
pthread_t workers[NUMBER_OF_THREADS];
/* establish the first sorting thread */
parameters *data = (parameters *) malloc (sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2) - 1;
pthread_create(&workers[0], 0, sorter, data);
/* establish the second sorting thread */
data = (parameters *) malloc (sizeof(parameters));
data->from_index = (SIZE/2);
data->to_index = SIZE - 1;
pthread_create(&workers[1], 0, sorter, data);
/* now wait for the 2 sorting threads to finish */
for (i = 0; i < NUMBER_OF_THREADS - 1; i++)
pthread_join(workers[i], NULL);
/* establish the merge thread */
data = (parameters *) malloc(sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2);
pthread_create(&workers[2], 0, merger, data);
/* wait for the merge thread to finish */
pthread_join(workers[2], NULL);
/* output the sorted array */
return 0;
}
void *sorter(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->from_index;
int end = p->to_index+1;
int z;
for(z = begin; z < end; z++){
printf("The array recieved is: %d\n", list[z]);
}
printf("\n");
int i,j,t,k;
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i-1; j++)
{
if(list[j] > list[j+1])
{
t = list[j];
list[j] = list[j+1];
list[j+1] = t;
}
}
}
for(k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
printf("\n");
pthread_exit(0);
}
void *merger(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->from_index;
int end = p->to_index+1;
int i,j,t;
printf("list[1]: %d",list[1]);
printf("result[1]: %d",result[1]);
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i; j++)
{
if(result[j] > result[j+1])
{
t = result[j];
result[j] = result[j+1];
result[j+1] = t;
}
}
}
int d;
for(d=0; d<SIZE; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(0);
}
I'm not sure what I'm doing wrong in my algorithms that its not working. It doesn't seem to catch the new sorted array. Any help on this problem would be appreciated VERY much! Thanks again in advance for all your help!
Your approach is incorrect. You should be splitting your partitions, then recursing or threading into them, joining the results, then merging. Its easy to screw this algorithm up, believe me.
Before anything else, make sure your merge algorithm is solid. If your merge has issues in a single-threaded arena, adding threads is only going to make it worse. In your case, you're making it worse because your merge thread appears to be running concurrently with your sorter threads.
That said, step back and consider this. Mergesort is about divide and conquer. To thread up a merge sort you should be doing the following:
Establish a maximum number of threads. Believe me, the last thing you want happening is spinning a thread for each partition. a sequence of 1024 values has 1023 partitions if you crunch the math hard enough. that many threads is not a solution. Establish some boundaries.
Establish a minimum partition size that you're willing to spin a thread for. This is as important as the first item above. Just like you don't want to be spinning 1023 threads to sort a 1024-slot sequence, you also don't want to be spinning a thread just to sort a sequence that has two items. There is zero benefit and much cost.
Have a solid merge algorithm. There are many efficient ways to do it, but do something simple and enhance it later. Right now we're just interested in getting the general threading down right. There is always time to enhance this with a fancy merge algorithm (like in-place, which believe me is harder than it sounds).
Having the above the idea is this:
The merge sort algorithm will have three parameters: a starting pointer, a length, and a thread-depth. For our purposes the thread depth will be N in a situation where we are using at-most 2N-1 threads. (more on that later, but trust me, it makes it easier to do the math this way).
If the thread depth has reached zero OR the sequence length is below a minimum threshold *we set), do not setup and run a new thread. Just recurse into our function again.
Otherwise, split the partition. Setup a structure that holds a partition definition (which for us will be a starting point and a length as well as the thread depth which will be N/2), launch a thread with that parameter block, then do NOT launch another thread. instead use the current thread to recurse into merge_sort_mt() for the "other" half.
Once the current thread returns from its recursion is must wait on the other thread via a join. once that is done both partitions will be done and they can be merged using your trivial merge algorithm.
Whew. Ok. so how does it look in practice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
struct Params
{
int *start;
size_t len;
int depth;
};
// only used for synchronizing stdout from overlap.
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
// forward declare our thread proc
void *merge_sort_thread(void *pv);
// a simple merge algorithm. there are *several* more efficient ways
// of doing this, but the purpose of this exercise is to establish
// merge-threading, so we stick with simple for now.
void merge(int *start, int *mid, int *end)
{
int *res = malloc((end - start)*sizeof(*res));
int *lhs = start, *rhs = mid, *dst = res;
while (lhs != mid && rhs != end)
*dst++ = (*lhs < *rhs) ? *lhs++ : *rhs++;
while (lhs != mid)
*dst++ = *lhs++;
// copy results
memcpy(start, res, (rhs - start) * sizeof *res);
free(res);
}
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
if (depth <= 0 || len < 4)
{
merge_sort_mt(start, len/2, 0);
merge_sort_mt(start+len/2, len-len/2, 0);
}
else
{
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, ¶ms);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
}
// merge the partitions.
merge(start, start+len/2, start+len);
}
// our thread-proc that invokes merge_sort. this just passes the
// given parameters off to our merge_sort algorithm
void *merge_sort_thread(void *pv)
{
struct Params *params = pv;
merge_sort_mt(params->start, params->len, params->depth);
return pv;
}
// public-facing api
void merge_sort(int *start, size_t len)
{
merge_sort_mt(start, len, 4); // 4 is a nice number, will use 7 threads.
}
int main()
{
static const unsigned int N = 2048;
int *data = malloc(N * sizeof(*data));
unsigned int i;
srand((unsigned)time(0));
for (i=0; i<N; ++i)
{
data[i] = rand() % 1024;
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
// invoke our multi-threaded merge-sort
merge_sort(data, N);
for (i=0; i<N; ++i)
{
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
free(data);
return 0;
}
The output for this looks something like this:
825 405 691 290 900 715 125 969
534 809 783 820 933 895 310 687
152 19 659 856 46 765 497 371
339 660 297 509 152 796 230 465
502 948 278 317 144 941 195 208
617 428 118 505 719 161 53 292
....
994 154 745 666 590 356 894 741
881 129 439 237 83 181 33 310
549 484 12 524 753 820 443 275
17 731 825 709 725 663 647 257
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 2 3 3
5 5 5 5 6 6 7 7
7 7 7 8 8 10 10 11
11 11 12 12 12 13 14 14
15 15 15 15 16 17 17 17
17 18 18 19 19 19 20 21
21 21 22 22 23 24 24 24
25 25 25 26 26 28 28 29
29 29 30 30 30 30 30 31
....
994 995 996 998 1000 1001 1001 1003
1003 1003 1003 1004 1004 1005 1007 1007
1010 1010 1010 1010 1011 1012 1012 1012
1012 1013 1013 1013 1015 1015 1016 1016
1016 1017 1018 1019 1019 1019 1020 1020
1020 1021 1021 1021 1021 1022 1023 1023
The most important part of this is the limiters that keep us from going thread-wild (which is easy to accidentally do with recursive threaded algorithms), and the join of the threads before merging their content with the other half of the partition (which we sorted on our thread, and may also have done the same thing).
It's a fun exercise, and I hope you got something out of it. Best of luck.
Update: Integrating qsort()
An interesting task would be performing this functionality using qsort() for sorting the smaller partitions or once the thread pool reaches exhaustion. qsort() is a pretty big hammer to bring to this party, and as such you're going to want to raise the minimum partition size to something respectful (in the example below, we use 256 elements).
So what would it take to integrate qsort() the the sub partitions rather than a hand-rolled merge-sort? Surprisingly, not much. Start with a qsort() compatible comparator:
// comparator for qsort
int cmp_proc(const void *arg1, const void* arg2)
{
const int *lhs = arg1;
const int *rhs = arg2;
return (*lhs < *rhs) ? -1 : (*rhs < *lhs ? 1 : 0);
}
Pretty brain-dead. Now, modify the mt-wrapper to look something like this:
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
// invoke qsort on the partition. no need for merge
if (depth <= 0 || len <= 256)
{
qsort(start, len, sizeof(*start), cmp_proc);
return;
}
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, ¶ms);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
// merge the paritions.
merge(start, start+len/2, start+len);
}
That's it. Seriously. That is all it takes. Proving this works is a simple test run with the original program, shown below:
986 774 60 596 832 171 659 753
638 680 973 352 340 221 836 390
930 38 564 277 544 785 795 451
94 602 724 154 752 381 433 990
539 587 194 963 558 797 800 355
420 376 501 429 203 470 670 683
....
216 748 534 482 217 178 541 242
118 421 457 810 14 544 100 388
291 29 562 718 534 243 322 187
502 203 912 717 1018 749 742 430
172 831 341 331 914 866 931 368
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 1 3 3
3 4 5 5 6 6 6 6
7 7 8 9 10 10 10 10
11 12 12 12 13 13 14 14
14 15 15 15 16 17 17 19
19 20 20 21 21 21 22 22
23 23 23 24 24 24 25 26
26 26 26 27 28 28 28 28
....
1000 1000 1000 1001 1001 1002 1003 1003
1004 1004 1004 1005 1005 1005 1006 1007
1008 1010 1010 1010 1010 1010 1011 1011
1011 1012 1012 1012 1012 1013 1013 1013
1015 1015 1015 1016 1016 1017 1017 1017
1018 1018 1018 1019 1019 1021 1021 1022
As you can see, the results are similar.
A couple of issues:
1 - What do you think this code is doing:
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
2 - Your merger currently looks exactly like your sorter. It should instead be merging the sorted values from the first half of the list and the second half of the list into the result.
Your code is correct i have modified your code and tried to figure out the error,
the loop indexes are not correctly mapped and you are assigning the null result list into actual data in one loop, so the list is taking zeroes.
Find below the modified code and output.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
void *sort(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->fromVal;
int end = p->toVal+1;
for(int i = begin; i < end; i++){
printf("The array recieved is: %d\n", list[i]);
}
printf("\n");
int temp=0;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(list[j] > list[j+1])
{
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}
}
}
for(int k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
for(int i=begin; i<end; i++)
{
result[i] = list[i];
}
printf("\n");
pthread_exit(NULL);
}
void *merging(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->fromVal;
int end = p->toVal+1;
int temp;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(result[j] > result[j+1])
{
temp= result[j];
result[j] = result[j+1];
result[j+1] = temp;
}
}
}
printf("\n\nFINAL RESULT IS:\n");
for(int d=begin+1; d<end; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(NULL);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
/*globle variables*/
/* structure for passing data to threads */
typedef struct
{
int *start;
int end;
int size;
} parameters;
int t = 1;
int *arr1, *arr2;
//for using quicksort
int comparator (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
void *merge(void *params){
//get data
int *len = params;
//SORT
int start = 0;
int end = *len/2;
int counter = end;
int size = *len;
int index = 0;
while (start < end && counter < size)
{
if (arr1[start] < arr1[counter])
{
arr2[index] = arr1[start];
start ++;
}
else
{
arr2[index] = arr1[counter];
counter ++;
}
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( start < end)
{
arr2[index] = arr1[start];
start ++;
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( counter < size)
{
arr2[index] = arr1[counter];
counter ++;
index ++;
}
}
void *sorting_thread(void *params){
printf("Thread %d ......\n", t);
t++;
//get data
parameters* data = (parameters *)params;
//SORT
int end = data->end;
int size = data->size;
//qsort
qsort(data->start, end, sizeof(*data->start), comparator);
printf("The array after sort : \n");
for(int i = size - end; i < size; i ++){
printf("arr1[%d]:%d, \n", i,arr1[i]);
}
printf("\n");
pthread_exit(0);
}
void *merge_sort_thread(void *params){
int *len = params;
//varaible allocation for two sorting threads.
parameters *data = (parameters *) malloc (sizeof(parameters));
parameters *data1 = (parameters *) malloc (sizeof(parameters));
if(data == NULL&& data1 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
//value for data passing
data->start= arr1;
data->end = *len/2;
data->size = *len/2;
data1->start = arr1 + *len/2;
data1->end = *len-*len/2;
data1->size = *len;
pthread_t left, right;/* the thread identifier */
printf("Entering merge_Sorting..\n");
/* create the sorting thread */
pthread_create(&left, NULL, sorting_thread, data);
pthread_create(&right, NULL, sorting_thread, data1);
/* wait for the thread to exit */
pthread_join(left, NULL);
//free memory
free(data);
pthread_join(right, NULL);
printf("Merging Thread %d ......\n", t);
merge(len);
printf("Process is done.\n");
printf("The final output: \n");
for(int i = 0; i < *len; i ++){
if(i%10==0){
printf("\n");
}
printf("%d, ", arr2[i]);
}
printf("\n");
//free memory
free(data1);
pthread_exit(0);
}
int main( int argc, char *argv[] ) {
long len;
int temp, c, j, k;
char *ptr;
//
//check if the right amount of argument
if( argc == 2 ) {
printf("The input array size is %s\n", argv[1]);
//covert the user input to integer
len = strtol(argv[1], &ptr, 10);
//check if the input is valid.
if(len == 0) {//if not, leave the program.
printf("Please enter a proper number. Leaving the program...\n");
}else{
//dynamically allocate memory
arr1 = (int*)malloc(len * sizeof(int));
arr2 = (int*)malloc(len * sizeof(int));
//check Memory
if(arr1 == NULL && arr2 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
printf("Memory allocated. \n");
//decide the value of data.
//generate random number to 100
srand(time(0));
printf("The array before sorting is: \n");
for(int i = 0; i < len; i ++){
arr1[i] = rand() % 100;
if(i%10==0){
printf("\n");
}
printf("%d, ", arr1[i]);
}
printf(" \n");
//merge sort handle all the threads
pthread_t tid;/* the thread identifier */
/* create the parent sorting thread */
pthread_create(&tid, NULL, merge_sort_thread, &len);
//wait for children thread
pthread_join(tid, NULL);
//printout array after merging threading
printf("\nThe program is finished. \n");
//free memory space
free(arr2);
free(arr1);
}
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
return 0;
}
I'm trying to find all combinations of x, where x = a^2 + b^2, and x is between 100 and 999.
So far i've got:
#include <stdio.h>
#include <stdlib.h>
#define MAX 31 // given that 31^2 = 961
int main(){
int i = 0;
int poss_n[] = {0};
for (int a=0; a <= MAX; a++){
for (int b=0; b <= MAX; b++){
if (a*a + b*b >= 100 && a*a + b*b <= 999){
poss_n[i] = a*a + b*b;
printf("%i\n", poss_n[i]);
i++;
}
}
}
}
However it's giving only partially correct output, and also prematurely ends with segmentation fault 11:
100
1380405074
144
169
196
225
256
289
324
361
400
441
484
529
576
625
676
729
784
841
900
961
101
122
145
170
197
226
257
290
325
362
401
442
485
530
577
626
677
730
785
842
901
962
104
125
148
173
200
229
260
293
328
365
404
445
488
533
580
629
680
733
788
845
904
965
109
130
153
178
205
234
265
298
333
370
409
450
493
538
585
634
685
738
793
850
909
970
116
137
160
185
212
241
272
305
340
377
416
457
500
545
592
641
692
745
800
857
916
977
106
125
146
169
194
221
250
281
314
349
386
425
466
509
554
601
650
701
754
809
866
925
986
100
117
136
157
180
205
232
261
292
325
360
397
436
477
520
Segmentation fault: 11
What modifications should I make to my code?
UPDATE
Other than the the array issue, is there anything else wrong with my code? for instance it's still printing 100 as the first value which doesn't appear to be any combination of a^2 + b^2, even when b = 0.
UPDATE 2
Never mind, forgot a = 10, b = 0, which would be 100.
Try:
int poss_n[(MAX + 1) * (MAX + 1)] = {0};
This way you allocate enough memory to store your answers.
Your error is that you don't allocate place to save you results.
try this:
#include <stdio.h>
#include <stdlib.h>
#define MAX 31 // given that 31^2 = 961
int main(){
int i = 0;
int poss_n[(MAX + 1) * (MAX + 1)] = {0}; //<<- Give it a size
int result; //<<- Using this to reduce calculation of the value multiple times.
for (int a=0; a <= MAX; a++){
for (int b=0; b <= MAX; b++){
result = a*a + b*b;
if (result >= 100 && result <= 999){
poss_n[i] = result ;
printf("%i\n", result);
i++;
}
}
}
}
int poss_n[] = {0};
This will define array holding one element, leading to Segfault later when you will try to access element with index > 1
Try this , it will work
#include <stdio.h>
#include <stdlib.h>
#define MAX 31 // given that 31^2 = 961
int main(){
int i = 0;
int poss_n[301];
int a,b;
for (a=0; a <= MAX; a++){
for (b=0; b <= MAX; b++){
if (a*a + b*b >= 100 && a*a + b*b <= 999){
poss_n[i] = a*a + b*b;
printf("%i\t i = %d , a = %d , b = %d\n", poss_n[i],i,a,b);
i++;
}
}
}
}
Lots of answers here, but none quite accurate.
Ff we assume that only unique output is printed out, loop should look like this (as Roee Gavirel stated):
for (int a=0; a <= MAX; a++){
for (int b=a; b <= MAX; b++){
poss_n will hold this number of elements: (32+(32-1)+(32-2)+..+1)=1/2*32*(32+1)
So it should be defined as:
int elements = MAX+1;
int *poss_n = (int*)malloc ((1/2)*(elements)*(elements+1));
It will have more elements because of rule 100< value <999, but without that rule it will hold exact number of elements.
As others already said you allocate too few space on stack. Stack goes from high addresses decreasing. So at first You overwrite the stack data corrupting it and then You reach the end of the stack and You try to write to a memory space not allocated to You, or not allocated at all. The CPU generates an exception and that's why the Segmentation fault error occurs.
Also You could allocate some memory with malloc(3) on the heap and not on the stack, and when You found more result You can extend using realloc. It uses more system CPU resources, but reduces the memory overallocation.
On some un*ces You can also dynamically allocate memory on stack, using the alloca(3) function. It behaves very similar then some_type array[some_value], but some_value can be calculated runtime and not compile time.
Also You can use C++ STL containers, like vector and list and You can push the found elements. The allocate memory segments automatically on the heap.
Some comments:
Addition can be used instead of multiplication counting squares. (a+1)^2 - a^2 = 2a + 1. So add (a<<1) + 1 to a temp variable starting from 0. Similar can be applied to b.
Also from the inner loop can be jumped with break if the sum is over 999. You do not need to check the remaining values.
The value b could start from (int)sqrt(100-a*a) (or use a temp varible to keep track of the first b value) to reduce the number of inner loops.