Lets say combinationlength=4.
My logic is create the array {0,0,0,0} add 1 to the last element until first element gets the value 1.Until then if with the addition of 1 the array[3] ends up in a 2 result then make it 0 and then traverse the array(reversed) given a counter variable and every first non 1 element make it 0 while making all elements before the value that first non 1 equal to 0.This is for 8 repetitions.How close am i?Can someone help me finish this?
Also this doesnt run for some reason.Nothing gets printed and ends after 2 seconds.
I just noticed i am skipping a step but anyways.
I want in every iteration to have an array like the sequence.And not added printf("0"); and shortcuts like that.
void print(int combinationlength){
int i,j,count;
int a=combinationlength-1;
int c=combinationlength-1;
int b;
int array[4]={0};
while(array[0]!=1){
array[a]++;
if(array[a]==2){
array[a]=0;
for(b=a;b<=c-1;b--){
if(array[b]==0)
array[b]=1;
}
c--;
}
for(count=0;count<combinationlength;count++){
printf("%d",array[count]);
}
printf("\n");
}
return 0;
}
UPDATED:(also updated my explanation above this ^^ block of code)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i,j,count;
int a=4-1;
int c=4-1;
int b;
int array[4]={0};
while(array[0]!=1){
array[a]++;
if(array[a]==2){
array[a]=0;
for(b=a-1;b>c-1;b--){
if(array[b]==0) array[b]=1;
else array[b]=0;
}
c--;
}
for(count=0;count<4;count++){
printf("%d",array[count]);
}
printf("\n");
}
return 0;
}
The hardcoded number 4 is supposed to be the input variable.
So, I'm still not entirely sure I understand what you want. If I understood correctly, you want every combination of bits (i.e. zeros and ones) of a certain length. Doing the additions manually in an array feels very wasteful, so lets instead use what the CPU already has to offer - integer addition.
An example program, printing all the combinations of a certain length would look something like this:
#include <stdio.h>
void print(int len){
for (unsigned long sortOfAnArray = 0; sortOfAnArray < (1U << len); sortOfAnArray++) {
for (int i = len - 1; i >= 0; i--) {
printf("%lu", (sortOfAnArray >> i) & 1);
}
printf("\n");
}
}
int main(void) {
print(5);
return 0;
}
To explain the steps, sortOfAnArray is our integer, stored in binary, we add 1 to it on every iteration so that we get the different combinations.
In order to print it, we have to access elements individually, we do this with a combination of a bitshift and logical and (sortOfAnArray >> i) & 1. So, we shift the bits in the array by i to the right, and check if it has a 1 on the first position, in other words, we checked if sortOfAnArray[i]==1 (if this was an array).
We use unsigned due to the standard and long in case you want up to 64 bits available (although long long would be even safer there).
EDIT
To further explain how we extract a bit from the integer.
Assume we have the integer
`unsigned long long foo = 27`
if we look at the bit representation of that, we get 00...011011, where the total number of bits is 64, but there's just a lot of zeros, hence the dots. Now, say we want to know the value of the 1st bit from the right. We can find that out by using the logical and operation
`foo & 1`
This will apply the logical and to every pair of bits at the same position in the two integers (foo and 1), in this case this will give us 1:
foo -- 00...011011
1 -- 00...000001
foo & 1 -- 00...000001
If foo had 0 as the rightmost bit, the result would instead be 0, so this essentially allows us to read whether the first bit is set to 0 or 1.
How do we generalise this to the other bits?
We have two options, we can either move the bit in the 1 (1 << n shifts the 1 bit n moves to the left), if we use the logical and then, we will get 0 if foo has a 0 in the n-th position or some nonzero value (2^n) if it has a 1.
The other option is to instead shift the bits of foo to the right, the upside of doing this is if foo had a 1 in the n-th position, the result will now be 1 rather than 2^n, whereas if it was 0 the result is still 0. Other than that the two approaches are equivalent.
This is how we come up with the final solution, that is, to access the n-th element (0-based counting) as follows:
(foo >> n) & 1
we move the bits of foo to the right by n and look if the first bit is set to 0 or 1. Essentially, the integer is storing 64 bits (we don't need to use all of them, of course) the same way we would do that in an array, but the approach is much more efficient. Among other things, we don't need to implement our own addition for the array, as you had attempted initially.
Your problem statement is confusing:
if with the addition of 1 the array[3] ends up in a 2 result then make it 0 and then traverse the array(reversed) given a counter variable and every first non 1 element make it 0 while making all elements before the value that first non 1 equal to 0.
This basically means you want the first 0 element to remain 0 while making all elements before that first 0 set to 0.
As a consequence, the array contents would alternate between { 0, 0, 0, 0 } and { 0, 0, 0, 1 }, which is probably not the intent.
Let's assume your problem is to simulate a base-2 counter with 4 binary digits and you count from 0 to 8. Your code is a bit too complicated (pun intended ;-). You should simplify and use fewer index variables:
#include <stdio.h>
int main() {
int i;
int array[4] = { 0 };
while (array[0] != 1) {
for (i = 0; i < 4; i++) {
printf("%d ", array[i]);
}
printf("\n");
for (i = 4; i-- > 0; ) {
array[i] += 1;
if (array[i] == 2) {
array[i] = 0;
} else {
break;
}
}
}
return 0;
}
Output:
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
Note how you can write a for loop that counts down from the length of the array, enumerating all valid index values while using the exact length of the array and using a test i-- > 0 that is correct for both signed and unsigned types. This trick is sometimes referred to as the downto operator, not a real operator but one can make it look like one as i --> 0.
EDIT: to print the complete set of binary combinations, keep looping until i is -1:
#include <stdio.h>
int main() {
int i;
int array[4] = { 0 };
for (;;) {
for (i = 0; i < 4; i++) {
printf("%d ", array[i]);
}
printf("\n");
for (i = 4; i-- > 0; ) {
array[i] += 1;
if (array[i] == 2) {
array[i] = 0;
} else {
break;
}
}
if (i < 0) {
/* the array is too small, all combinations exhausted */
break;
}
}
return 0;
}
An integer already consists (most of the time) of 4 bytes = 32 bits. You can use a simple integer instead of an array.
However printing an integer in binary format is a bit tricky, I used the answer of this question to do it.
#include <stdio.h>
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
int main(void) {
int a = 0;
int limit = 4;
while( (a & (1 << limit)) == 0)
{
printf("0b"BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(a));
a++;
}
return 0;
}
Output:
0b00000000
0b00000001
0b00000010
0b00000011
0b00000100
0b00000101
0b00000110
0b00000111
0b00001000
0b00001001
0b00001010
0b00001011
0b00001100
0b00001101
0b00001110
0b00001111
Little explanation:
In the while loop I use a so called bit mask. (1 << limit) results in a binary 1 at the position limit, so in this case it would be 0b00010000. With the binary & I check if a has that bit, if yes the while loop ends.
Whenever I have to do something involving iteration over combinations, I automatically think of Grey Codes / reverse binary coding. Below is my own implementation (it uses a different formula than the wiki, but still covers all the values). Note they won't be in order, but it does cover all combinations 0->2^n-1 and it is very fast since it only needs to change one value each time.
#include <stdio.h>
int main(int argc, char** argv) {
unsigned int length = 4;
unsigned int array[4] = {0, 0, 0, 0};
int i, j;
for (i = 0; i < 1 << length; i++) {
array[__builtin_ctz(i)] ^= 1;
printf("Array Values: ");
for (j = 0; j < length; j++) {
printf("%d ", array[j]);
}
printf("\n");
}
return 0;
}
Output:
Array Values: 0 0 0 0
Array Values: 1 0 0 0
Array Values: 1 1 0 0
Array Values: 0 1 0 0
Array Values: 0 1 1 0
Array Values: 1 1 1 0
Array Values: 1 0 1 0
Array Values: 0 0 1 0
Array Values: 0 0 1 1
Array Values: 1 0 1 1
Array Values: 1 1 1 1
Array Values: 0 1 1 1
Array Values: 0 1 0 1
Array Values: 1 1 0 1
Array Values: 1 0 0 1
Array Values: 0 0 0 1
Note I use the __builtin_ctz() method to count trailing zeros quickly. I don't know if its implemented on any other compilers, but GCC supports it.
Related
I want to add a value (potentially larger than 255) to an array of uint8_t. Currently, my implementation does not allow to exceed 255 as the value is of type uint8_t. Ideally I would like to have this value of type int.
This code must be compilable with standard libraries and be exclusively in C99. I don't have access to uint32_t or uint_64t types either.
How could I modify the following snippet to change value from uint8t to int ?
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void addArray(uint8_t *dest, size_t sizeDest, uint8_t value){
uint8_t remaining = value;
uint8_t sum;
for (size_t i = 0; i < sizeDest; ++i){
sum = dest[i] + remaining;
if (dest[i] > sum){
remaining -= UINT8_MAX - (dest[i] - sum);
dest[i]=sum;
}
else{
dest[i]=sum;
return;
}
}
}
void printArray(uint8_t *t, size_t arrayLength){
for (int i = 0; i < arrayLength; ++i)
{
printf("%d ", t[i]);
}
printf("\n");
}
int main() {
printf("Max value of uint8_t is %d\n",UINT8_MAX);
int arrayLength = 16;
uint8_t key[] = {
252,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,2
};
uint8_t *testArray = (uint8_t *) malloc(sizeof(uint8_t) * arrayLength);
memcpy(testArray, key, sizeof(uint8_t)*arrayLength);
printf("Before addition\n");
printArray(testArray, arrayLength);
addArray(testArray,arrayLength,15);
printf("After addition\n");
printArray(testArray, arrayLength);
return 0;
}
You say you're not allowed to use uint32_t or uint64_t, but you are allowed to use int. If so, this is simple enough. Just use int to pass in your new value and to keep track of the partial, running sum.
I did it like this; it's quite similar to the code #chux posted. I also simplified the logic: you don't actually need to keep separate sum and remaining values, so I boiled it down to just one variable, which I'm calling carry, of type int.
void addArray(uint8_t *dest, size_t sizeDest, int value){
int carry = value;
for (size_t i = 0; i < sizeDest; ++i){
carry = dest[i] + carry;
dest[i] = carry & 0xff;
carry >>= 8;
}
}
During each trip through the loop, carry is either the value we're adding in, or the carry that's leftover from the previous "digit". We add the carry to the current digit, stash as much of it as will fit — the low-order 8 bits — back into the current digit, and keep what's leftover (that is, after using >>= to discard the low-order 8 bits, which are they ones we've just stored in dest[i]) in the carry variable for next time.
Why does this work? Well, it's the same thing you do when you add a column of numbers by hand, using the technique we all learned back in elementary school. Suppose you're adding
6
14
7
23
13
+ 4
----
After you add up the one's column, you get 27, and you say, "okay, that's 7, carry the 2". (You do not say, "carry the 20".) Your partial sum was 27, and the "bottom half" of it (7, or 27 % 10) is the digit in the one's place of the final sum, and the "top half" (2, or 27 / 10) is the carry into the ten's column.
So if you're not familiar or not comfortable with those "bitwise" operators, you can perform the equivalent operations using % and /, except using factors of 256 instead of 10:
void addArray(uint8_t *dest, size_t sizeDest, int value){
int carry = value;
for (size_t i = 0; i < sizeDest; ++i){
carry = dest[i] + carry;
dest[i] = carry % 256;
carry /= 256;
}
}
Basically you're performing addition here in base 256.
Depending on your needs and constraints, there might be some value in using types int16_t, unsigned int, or uint16_t for value and carry, instead of plain int.
I tested this by calling
addArray(testArray,arrayLength,300);
and it printed
Before addition
252 255 255 255 255 255 255 255 255 255 255 255 255 255 255 2
After addition
40 1 0 0 0 0 0 0 0 0 0 0 0 0 0 3
which looks right. As a second test,
addArray(testArray,arrayLength,123456789);
prints
After addition
17 205 91 7 0 0 0 0 0 0 0 0 0 0 0 3
(More on these tests in the "addendum" below.)
As #chux points out in a comment, this code does have its limitations. If the value you tried to add in was close to the maximum an int can hold, the carry variable might overflow (that is, on the carry = dest[i] + carry line). But as long as value is less than or equal to INT_MAX - 255 (and greater than or equal to zero!), you should be fine.
Of course, if the value you're trying to add in might be large, it might also be larger than a single int can hold, in which case you'd need to pass it in some other way, likely as a second array of uint8_t, just like dest — and then you'd find yourself writing a fully general multiprecision adder.
Addendum: To double-check these results, and to demonstrate what's actually going on, we can perform the same arithmetic in dc, the Unix/Linux arbitrary-precision calculator. I have determined that #Tifa's initial key value is 3987683987354747618711421180841033724. We'll use dc to print that number out in various bases, and as we add 15, 300, and 123456789 to it.
$ dc
3987683987354747618711421180841033724 # original key
p # print it
3987683987354747618711421180841033724
16o p # set output base to 16 and print
2FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC
256o p # set output base to 256 and print
002 255 255 255 255 255 255 255 255 255 255 255 255 255 255 252
15 + p # add 15 and print (still base 256)
003 000 000 000 000 000 000 000 000 000 000 000 000 000 000 011
3987683987354747618711421180841033724 # original key again
300 + p # add 300 and print
003 000 000 000 000 000 000 000 000 000 000 000 000 000 001 040
3987683987354747618711421180841033724 # original key again
123456789 + p # add and print
003 000 000 000 000 000 000 000 000 000 000 000 007 091 205 017
dc's base-256 rendition corresponds to the output of Tifa's printArray function, albeit in a more conventional left-to-right order.
How to add a value greater than 255 to an array of uint_8t?
" Ideally I would like to have this value of type int. " --> As the goal is "a value greater than 255", we can simplify and use unsigned.
Add the unsigned to the uint8_t indexed in the array. As overflow may occur, use wider than unsigned math.
// Return overflow amount
// void addArray(uint8_t *dest, size_t sizeDest, uint8_t value){
unsigned addArray(uint8_t *dest, size_t sizeDest, unsigned value){
unsigned long long sum = value; // Use some type wider than unsigned
for (size_t i = 0; i < sizeDest; ++i) {
sum += dest[i];
dest[i] = (uint8_t) sum; // Save 8 lower bits
sum >>= 8; // Continue with the upper bits
}
return (unsigned) sum;
}
... or more like OP's code with no wider integer math used.
unsigned addArray(uint8_t *dest, size_t sizeDest, unsigned value){
#define UINT_MAX_PLUS1_DIV256 ((UINT_MAX - UINT_MAX/2) >> 7)
unsigned remaining = value;
for (size_t i = 0; i < sizeDest; ++i) {
unsigned sum = remaining + dest[i];
dest[i] = sum; // Save lower bits
if (sum < remaining) { // Overflow occurred in remaining + dest[i]
remaining = sum >> 8;
remaining += UINT_MAX_PLUS1_DIV256 // add back overflow bit / 256
} else{
remaining = sum >> 8; // Continue with the upper bits
}
}
return remaining
}
community, I have little experience with C and I am on the learning curve right now.
I am working on a little project that involves dividing a 32-char string into 4 strings of 8 chars each in C.
The 32-char string should resemble a 32-bit instruction. Those "32 bits" are divided into 4 "8-bit" strings that I want to print out as Hex. The code below is what I got so far. The data types I am using are the ones I am using in the rest of my code. I intend to feed the unsigned char t variable into an Substitution Box program that will give me equivalent of that t char from the S-Box lookup table.
The code below seems to me like it should work
unsigned char inst[] = "10101010101010101111111100111101";
unsigned char in[8];
for (int i = 0; i < 33; i++){
if (i%8 == 0 && i != 0) {
unsigned char t = (unsigned char) strtol(in, NULL, 2);
printf("%x \n", t);
}
in[i%8] = inst[i];
printf("%c ", in[i%8]);
}
but the output looks like this:
1 0 1 0 1 0 1 0 3d
1 0 1 0 1 0 1 0 3d
1 1 1 1 1 1 1 1 3d
0 0 1 1 1 1 0 1 3d
I can see that in[i%8] = inst[i]; line is reading the chars from inst[] correctly, but the
if (i%8 == 0 && i != 0) {
unsigned char t = (unsigned char) strtol(in, NULL, 2);
printf("%x \n", t);
}
conditional statement prints the wrong hex.
The output should look like something like this
1 0 1 0 1 0 1 0 aa
1 0 1 0 1 0 1 0 aa
1 1 1 1 1 1 1 1 ff
0 0 1 1 1 1 0 1 3d
Any help would be appreciated.
Problems with the current code:
"4 strings of 8 chars each" is char in[4][8+1]; and not char in[8]. You need room for null termination.
32 bits means iterate from 0 to 31, not from 0 to 32.
There's no need to copy byte per byte. It's slow and makes everything needlessly complicated.
This seems to be the requirements:
Split the original string in 4 sub strings.
Convert each sub string to an integer.
Display the result as hex
In which case you can simply iterate 4 times over the input string:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
const char* inst = "10101010101010101111111100111101";
char in [4][8+1];
puts("Bin Hex");
for(size_t i=0; i<4; i++)
{
memcpy(in[i], &inst[i*8], 8);
in[i][8] = '\0';
unsigned long val = strtoul(in[i], NULL, 2);
printf("%.8s %.2lX\n", in[i], val);
}
}
Output:
Bin Hex
10101010 AA
10101010 AA
11111111 FF
00111101 3D
The problem is your in is not NUL terminated.
Thus passing in to strol invokes the undefined behavior.
Do as below.
unsigned char in[9]; //+1 to hold the NUL char.
....
if (i%8 == 0 && i != 0) {
in[8] = '\0'; //NUL terminate the string.
unsigned char t = (unsigned char) strtol(in, NULL, 2);
printf("%x \n", t);
}
I need to iterate over an array of n elements (dynamic size thus), for example 4, as if it were a binary number, starting with all zeros ({0,0,0,0}). Every time this needs to increment as if it is binary, {0,0,0,0} -> {0,0,0,1} -> {0,0,1,0} -> {0,0,1,1} -> {0,1,0,0}, etc...
I have trouble generating an algorithm that does so with array values, I thought about using recursion but cannot find the method to do so other than hard-coding in ifs. I suppose I could generate an n-digit number and then apply any algorithm discussed in this post, but that would be inelegant; the OP asked to print n-digit numbers while I need to work with arrays.
It would be great if someone could point me in the right direction.
Context:
int n;
scans("%d", &n);
int *arr = calloc(n, sizeof(int));
Algorithm:
Start at the rightmost element.
If it's a zero, then set it to one and exit
It must be a one; set it to zero
If you are at the left-most element, then exit.
You aren't already at the left-most element; move left one element and repeat.
I'm sorry, I'm not in a position to provide a code sample.
Algorithm:
Start at the rightmost element.
If it's a zero, then set it to one and exit
It must be a one; set it to zero
If you are at the left-most element, then exit.
You aren't already at the left-most element; move left one element and repeat.
Here's Hymie's algorithm, I'll try making a code out of it :
#include <stdlib.h>
#include <stdio.h>
int my_algo(int *arr, int size) {
for (int i = size - 1; i >= 0; i--) { // Start at the rightmost element
if (arr[i] == 0) { // If it's a zero, then set it to one and exit
arr[i] = 1;
return 1;
} else if (arr[i] == 1) { // If it's a one, set it to zero and continue
arr[i] = 0;
}
}
return 0; // stop the algo if you're at the left-most element
}
int main() {
int n;
scanf("%d", &n);
int *arr = calloc(n, sizeof(int));
do {
for (int i = 0; i < n; i++) {
putchar(arr[i] + '0');
}
putchar('\n');
} while (my_algo(arr, n));
return (0);
}
This algorithm is dynamic and work with scanf.
Here's the result for 4 :
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
What you seem to want to do is implement binary addition (or more precisely a binary counter), which is anyway implemented in the CPU's digital circuit using logic gates. It can be done using combination of logical operations (nand and xor to be exact).
But the most elegant approach according to my sense of elegance would be to use the CPU's innate ability to increment numbers and write a function to decompose a number to a bit array:
void generate_bit_array(unsigned int value, uint8_t *bit_array, unsigned int bit_count) {
for (unsigned int i=0; i<bit_count; i++) {
bit_array[i] = value >> (bit_count - i - 1) & 0x01;
}
}
int main(int argc, void **argv) {
unsigned int i;
uint8_t my_array[4];
/* Iterate and regenerate array's content */
for (i=0; i<4; i++) {
generate_bit_array(i, my_array, 4);
/* Do something */
}
return 0;
}
You can do:
#include <stdio.h>
#include <stdlib.h>
void gen_bit_array(int *numarr, int n, int arr_size) {
if(n > 0) {
numarr[arr_size-n] = 0;
gen_bit_array(numarr, n-1, arr_size);
numarr[arr_size-n] = 1;
gen_bit_array(numarr, n-1, arr_size);
} else {
int i;
for(i=0; i<arr_size; i++)
printf("%d", numarr[i]);
printf ("\n");
}
}
int main() {
int n,i;
printf ("Enter array size:\n");
scanf("%d", &n);
int *numarr = calloc(n, sizeof(int));
if (numarr == NULL)
return -1;
gen_bit_array(numarr, n, n);
return 0;
}
Output:
Enter array size:
2
00
01
10
11
Enter array size:
4
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
If I have understood you correctly then what you need is something like the following
#include <stdio.h>
#define N 4
void next_value( unsigned int a[], size_t n )
{
unsigned int overflow = 1;
for ( size_t i = n; i != 0 && overflow; i-- )
{
overflow = ( a[i-1] ^= overflow ) == 0;
}
}
int empty( const unsigned int a[], size_t n )
{
while ( n && a[n-1] == 0 ) --n;
return n == 0;
}
int main(void)
{
unsigned int a[N] = { 0 };
do
{
for ( size_t i = 0; i < N; i++ ) printf( "%i ", a[i] );
putchar( '\n' );
next_value( a, N );
} while ( !empty( a, N ) );
return 0;
}
The program output is
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
Or you can write the function that evaluates a next value such a way that if the next value is equal to 0 then the function returns 0.
For example
#include <stdio.h>
#include <stdlib.h>
int next_value( unsigned int a[], size_t n )
{
unsigned int overflow = 1;
for ( ; n != 0 && overflow; n-- )
{
overflow = ( a[n-1] ^= overflow ) == 0;
}
return overflow == 0;
}
int main(void)
{
size_t n;
printf( "Enter the length of the binary number: " );
if ( scanf( "%zu", &n ) != 1 ) n = 0;
unsigned int *a = calloc( n, sizeof( unsigned int ) );
do
{
for ( size_t i = 0; i < n; i++ ) printf( "%i ", a[i] );
putchar( '\n' );
} while ( next_value( a, n ) );
free( a );
return 0;
}
The program output might look like
Enter the length of the binary number: 3
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
No need for an algorithm, you could build a function,
Here is a process which could be a good idea if the array is of a fixed size :
Build a function which take your array
Create a local integrer for this function
Set the bits value of the integrer to the cells value of the array
Increment the integrer
Set the array values to match each bits of the integrer
All this process can be done using shifts (>> <<) and masks (& 255 for example).
I'm working on a problem dealing with iteration. I'm supposed to pass in two ints into a function, which represent a number of N objects and M values that I must find all permutations of. I am also given a sample of what the output is supposed to look like
void perm_iter(int N, int nr_values)
and the output this is supposed to print is :
Called : perm_iter(3, 2);
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
I understand the concept of recursion by using a swap function to change the orders of strings to find all permutations of a string, but I'm unsure of how to use iteration to get the same, or similar result. Is this a case where I need to use the stack and push/pop iteratively to get my answer? I was thinking I could use something like a set of nested loops to take the place of recursion and get something like this output but I'm unsure how to set the loops up to go through every permutation and not just iterate, missing some of the possible permutations.
Any help would be appreciated, and thank you for your time.
You just need to count up each "digit" until the max is reached, then reset and increment the next.
Imagine nr_values is 10 (with n=2):
0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
Looks familiar because it's just "regular" counting in this case.
Implement this just like you count up: In each step, increment the leftmost value. If max is reached, reset and increment the next value etc.
void perm_iter(int n, int nr_values) {
int[] counter = new int[n];
int i;
// Clear all values
for (i = 0; i < n; i++) {
counter[i] = 0;
}
do {
// Print the current set of values
for (i = 0; i < n; i++) {
printf("%n ", counter[i]);
}
printf("\n");
// Keep incrementing while the values overflow,
// starting at the rightmost counter
i = n - 1;
while (i >= 0) {
counter[i]++;
if (counter[i] < nr_values) {
break;
}
counter[i] = 0;
i--;
}
// We are done when the first value overflows
} while (i >= 0);
}
We are given an array of numbers and we want to find a subsequence of size 4 that is sorted in increasing order.
for eg ARRAY : -4 2 8 3 1 5
sorted subsequence of size 4 : -4 2 3 5
PS:There is a way of finding the sorted subsequence of size 3(see this). I am trying to think along the same lines but can't seem to find a solution for 4 integers.
Here is a solution that will find a sorted subsequence of fixed size k+1 by doing k passes over the input. Each pass is done left-to-right.
Pass 1: Create an auxiliary array p1[0..n-1]. p1[i] should store the index j of a number which is smaller than arr[i] and is on the left side of arr[i] (in other words: j<i and arr[j]<arr[i]). p1[i] should contain -1 if there is no such element. (p1 is the same as the smaller array from the solution for size 3).
Pass 2: Create an auxiliary array p2[0..n-1]. p2[i] should store the index j of a number which is smaller than arr[i], is on the left side of arr[i], and such that p1[j] != -1 (in other words: j<i, arr[j]<arr[i], and p1[j]!=-1). p2[i] should contain -1 if there is no such element.
....
Pass k: Create an auxiliary array pk[0..n-1]. pk[i] should store the index j of a number which is smaller than arr[i], is on the left side of arr[i], and such that p(k-1)[j] != -1 (in other words: j<i, arr[j]<arr[i], and p(k-1)[j]!=-1). pk[i] should contain -1 if there is no such element.
After the kth pass, each element where pk[i] != -1 corresponds to the largest element in a sorted subsequence of size k+1.
Pseudocode for kth pass (k>1):
function do_kth_pass(pk[], p_k_minus_1[])
min = -1
for i in 0..n-1:
if min != -1 and arr[i] > arr[min]:
pk[i] = min
else
pk[i] = -1
if p_k_minus_1[i] != -1 and (min == -1 or arr[i] < arr[min]):
min = i
Example:
Index: 0 1 2 3 4 5
Array: -4 2 8 3 1 5
p1: -1 0 0 0 0 0
p2: -1 -1 1 1 -1 4
p3: -1 -1 -1 -1 -1 3
After 3 passes, you have p3[5] != -1, so a sorted subsequence of size 4 exists. The indices of its elements are: p1[p2[p3[5]]], p2[p3[5]], p3[5], 5 which is 0,1,3,5
Having a greater and lesser array is a good option but it increases the space complexity. Below, is a solution to find four numbers in a linear subsequence without additional array space but rather it uses constant space and does only one pass over the array.
#include <iostream>
void sortedSubseqFour(int a[], int n)
{
int small = INT_MAX;
int middle_1 = INT_MAX;
int middle_2 = INT_MAX;
int greater = 0;
int main_small = 0;
int main_middle_1 = 0;
int main_main_small = 0;
for(int i = 0; i<n; i++)
{
if (a[i] <= small)
small = a[i];
else if (a[i] <= middle_1)
{
middle_1 = a[i];
main_small = small;
}
else if (a[i] <= middle_2)
{
middle_2 = a[i];
main_middle_1 = middle_1;
main_main_small = main_small;
}
else
{
greater = a[i];
break;
}
}
//end of loop
if (greater != 0)
std::cout << main_main_small << '\t' << main_middle_1 << '\t'
<< middle_2 << '\t' << greater;
else
std::cout << "No such Quadruple";
}
int main()
{
int arr[10] = {6, 7, 5, 1, 4, 3, 0, 7, 2, 11};
int n = 10;
sortedSubseqFour(arr, n);
return 0;
}
The above approach remembers all layers of minimum's when it sets the current minimum. The same code can also be used for a sorted subsequence of size 3 in an array by removing main_main_small and middle_2 part of the code.
If, the same code is to be extended up to size k then at say minimum i, we have to remember all minimum's before i, i.e min_1, min_2,... till min_i. Only in the last minimum, i.e. the greatest value in our subsequence, we just break and there is no need to remember previous or current minimum.
Please do inform if any bugs are discovered!
You can find the longest increasing subsequence and see if its size if greater than equal to 4(or even k in case you need to find it for a more general question). If the length of the Longest Increasing Subsequence is less than 4(or k) you can report that no such subsequence exists. LIS can be found out in O(nlog(n))
Create a smaller and greater array, similarly as to what was done for a subsequence of size 3. In addition to this, also have betweenSmallerAndCurrent array which stores the index of a value that is between the smallest and the current element - both in value and in index. More explicitly:
betweenSmallerAndCurrent[i] = -1 or
input[smaller[i]] < input[betweenSmallerAndCurrent[i]] < input[value[i]] and
smaller[i] < betweenSmallerAndCurrent[i] < value[i]
Constructing this should be pretty easy.
You'd just return the index i where betweenSmallerAndCurrent[i], smaller[betweenSmallerAndCurrent[i]] and greater[i] are all initialized. Note that we can't simply check smaller[i] as we may have something like [2,3,1,4,5], in which case, when we get to 4, the second smallest value 3 is before the current smallest value 1.
Example:
Indices: 0 1 2 3 4 5 6 7
Input: 12 11 10 5 6 2 9 30
smaller: -1 -1 -1 -1 3 -1 5 5
betweenSmallerAndCurrent:
-1 -1 -1 -1 -1 -1 4 4
greater: 7 7 7 7 7 7 7 -1
The only index with all values initialized is 6 (input value 9).
Java code: (not extensively tested)
void find4Numbers(int arr[], int n)
{
int max = n-1; //Index of maximum element from right side
int min = 0, second = -1; //Index of minimum element from left side
int i;
// Create an array that will store index of a smaller
// element on left side. If there is no smaller element
// on left side, then smaller[i] will be -1.
int[] smaller = new int[n];
int[] betweenSmallerAndCurrent = new int[n];
smaller[0] = -1; // first entry will always be -1
betweenSmallerAndCurrent[0] = -1;
for (i = 1; i < n; i++)
{
if (arr[i] <= arr[min])
{
min = i;
smaller[i] = -1;
betweenSmallerAndCurrent[i] = -1;
}
else
{
smaller[i] = min;
if (second != -1 && arr[second] < arr[i])
betweenSmallerAndCurrent[i] = second;
else
betweenSmallerAndCurrent[i] = -1;
if (second == -1 || arr[i] < arr[second])
second = i;
}
}
// Create another array that will store index of a
// greater element on right side. If there is no greater
// element on right side, then greater[i] will be -1.
int[] greater = new int[n];
greater[n-1] = -1; // last entry will always be -1
for (i = n-2; i >= 0; i--)
{
if (arr[i] >= arr[max])
{
max = i;
greater[i] = -1;
}
else
greater[i] = max;
}
// Make sure they're right
System.out.println(Arrays.toString(smaller));
System.out.println(Arrays.toString(betweenSmallerAndCurrent));
System.out.println(Arrays.toString(greater));
// Now find a number which has both a greater number on
// right side and smaller number on left side
for (i = 0; i < n; i++)
{
if (betweenSmallerAndCurrent[i] != -1 && smaller[betweenSmallerAndCurrent[i]] != -1 && greater[i] != -1)
{
System.out.printf("%d %d %d %d\n",
arr[smaller[betweenSmallerAndCurrent[i]]],
arr[betweenSmallerAndCurrent[i]],
arr[i],
arr[greater[i]]);
return;
}
}
// If we reach number, then there are no such 3 numbers
System.out.println("No such triplet found");
}
You may notice that the main code changes from this, apart from the C to Java conversion and added initializations, lies in the loop that sets up smaller. The code should be pretty easy to understand - try translating it into words if you're having trouble.
Test.
For each element, find next greater element index else -1
Now think of this as a graph and find a path of length k(if it exist)
This can be done easily in linear time using hashtable and memoization.