Related
Self-Aware Arrays.
An integer array int[] A is self-aware if for each i < A.length, A[i] is the exact number of occurrences of i in A.
For example, [2, 0, 2, 0] is self-aware.
Write an algorithm accepts a positive integer n as input, when executed, prints out a list of all self-aware arrays of that length.
Here are some Self-aware arrays have been found. But I haven't found an algorithm.
N = 4
{2, 0, 2, 0}
{1, 2, 1, 0}
N = 5
{2, 1, 2, 0, 0}
N = 6
None
N = 7
{3, 2, 1, 1, 0, 0, 0}
N = 8
{4, 2, 1, 0, 1, 0, 0, 0}
N = 9
{5, 2, 1, 0, 0, 1, 0, 0, 0}
N = 10
{6, 2, 1, 0, 0, 0, 1, 0, 0, 0}
N = 11
{7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0}
N = a
{ a-4, 2, 1, <a-7 0s>, 1, 0, 0, 0 }
Seems we have the properties
sum(A[i]) = n = sum(i * A[i])
A[0] = sum( (i-1) * A[i] ) i>=2
Outer loop: Generate all candidates of length n. This can be done with any convenient set product software; you need n elements in the range 0:n-1. For each candidate, filter and check (below).
Filter:
The sum of the candidates elements must equal n. Note that if you're writing your own candidate generator, you can use this to greatly reduce the quantity of candidates.
The first element can never be 0.
Check:
Count the quantity of each number 0:n-1 in order. The resulting list is your check count. If this list is equal to the original candidate, you have a solution: print it.
Shortcuts:
Are you allowed to use known results? It's long proved that for n >= 7, the formula you give is the only solution: you can directly generate the one solution and return. For n < 7, brute force will produce all valid solutions quite quickly.
function valueCountMap(arr) {
let obj = {};
for (let i = 0; i < arr.length; i++) {
let temp = arr[i];
let val = obj[temp];
if (val) {
obj[temp] += 1;
} else {
obj[temp] = 1;
}
}
return obj;
}
function isSelfAware(arr) {
let map = valueCountMap(arr);
for (const key in map) {
if (map.hasOwnProperty(key)) {
const found = map[key];
if (arr[key] !== found) {
return false;
}
}
}
return true;
}
let arr1 = [7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0];
console.log(isSelfAware(arr1));
So given an array of:
input[3] = {0, 0, 0}
this outputs :
output[3] = {3, 0 ,0}
code:
void create_hist(double input[], int num_of_inputs, int output[])
{
int num_to_check = input[0];
int counter = 0;
for (int i = 0; i < num_of_inputs; i++)
{
int j = output[i];
if ((int)input[i] == num_to_check)
{
counter++; /* it was found */
}
output[j] = counter;
}
return;
}
but if I have a floating point array
input[5] = {0.0000, 1.0000, 2.0000, 3.0000, 4.000}
and I want to truncate the values to int, and count how many times each integer in the range 0 - 10 appears in the input array then output it to:
output[5] = {1, 1, 1, 1, 1}
output[0] = {1} //indicates how many times 0 appeared in the array
or
input[10] = {1.000, 4.000, 5.0000, 2.000, 4.000, 7.000, 9.000, 6.000, 0.000, 0.000}
and output
output[10] = {2, 1, 1, 0, 2, 1, 1, 1, 0, 1}
output[0] = {2} // this indicates how many times 0 appeared in the first array
Can anyone tell me how to do this?
You shouldn't use output[i] as an array index. It's a counter, not the value whose count you want. You should use (int)input[i] as the index.
You first need to initialize all elements of output to 0, then you increment the elements corresponding to the integer part of each input.
memset(output, 0, sizeof(output[0]) * MAX_INPUT_VALUE);
for (int i = 0; i < num_of_inputs; i++) {
output[(int)input[i]]++;
}
My programm compiles, and it is ok. When I start it and type "AB", they appear on one line, but when I type "BAAB", the "AB" goes under the "BA". I am stuck here for a long time. I will be very glas if you give a solution for this problem.
//it needs to read input from the keyboard and appear every letter constructed by astersks
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
char line[100] = { 'A', 'B' };
int i;
int row;
int col;
bool A[7][6] = { {0, 0, 1, 0, 0, 0}, //letter A
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0} };
bool B[7][6] = { {1, 1, 1, 0, 0, 0}, //letter B
{1, 0, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0},
{1, 1, 1, 1, 0, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 0} };
int main () {
//reads the input
printf ("Type a word or number, or both: ");
scanf ("%s", line);
// loop for every row of every letter
for (row = 0; row < 7; row++)
{
// loop for every inputed letter
for (i = 0; line[i]; i++)
{
// if letter is A do this...
if (line[i] == 'A')
{
// lopp for every column to read the asterisks
for (col = 0; col < 5; col++) {
if (A[row][col])
printf ("*");
else
printf (" ");
}
printf ("\n");
}
if (line[i] == 'B') {
for (col = 0; col < 5; col++) {
if (B[row][col])
printf ("*");
else
printf (" ");
}
}
}
}
return (0);
}
Trex, what you first need to understand is "What does my code do if I take NO input?". So comment out your initial printf and scanf and check:
//reads the input
// printf ("Type a word or number, or both: ");
// scanf ("%s", line);
Output:
$ ./bin/multi_array_mess
*
*** * *
* * * *
* * *****
**** * *
* ** *
* ** *
****
What values of line produce that output? {'A', 'B'} What happens if line contains anything other than AB? Try just 'A':
$ Type a word or number, or both: A
*
* *
* *
*****
* *
* *
* *
Then with 'B':
$ ./bin/multi_array_mess
Type a word or number, or both: B
*** * * * * **** * ** *****
It should be obvious that a newline is missing somewhere in the loop that prints B. Changing your logic to match the way you print 'A' similar to:
if (line[i] == 'B') {
for (col = 0; col < 5; col++) {
if (B[row][col])
printf ("*");
else
printf (" ");
}
printf ("\n");
}
Provides the desired output if you enter just 'B' in response to your prompt:
$ ./bin/multi_array_mess
Type a word or number, or both: B
***
* *
* *
****
* *
* *
****
What is printed if you enter anything other than 'A' or 'B'? NOTHING. What happens if you enter both 'A' and 'B'? (you get a mess).
So it looks just from tinkering with your program, it was designed to print either A of B using '*' as the character depending on the values of 0 or 1 in your arrays. You can either fix the logic to handle line containing both 'A' and 'B', or you can limit your input to one character at a time.
Since your intent appears to be able to handle multiple characters in line at a time, what happens if we just tweak the loop logic a bit. E.g.:
// loop for every inputed letter
for (i = 0; line[i]; i++)
{
// loop for every row of every letter
for (row = 0; row < 7; row++)
{
// if letter is A do this...
if (line[i] == 'A')
{
Give it a try...
Next, think about how you are prompting for input:
printf ("Type a word or number, or both: ");
Wouldn't it make more sense to limit your request to what your code will provide output for?
printf ("Please enter A or B, or both: ");
After receiving input, wouldn't it more sense to check what your user provided before blindly passing the input to the rest of your program? Something simple will do:
for (i = 0; i < (int)strlen (line); i++)
if (line[i] != 'A' || line[i] != 'B') {
fprintf (stderr, "error: invalid input '%c'.\n", line[i]);
return 1;
}
Now try your program again.
Printing Each Letter on One Row
OK. Now that I know what you are intending, it makes it a bit easier to help. In order to print each array as '*' or ' ' on the same row, you basically have to loop through each row, checking if a given letter is specified in line and print that row for every character you need to print. You can cut down on the code repetition by creating a function to print the row for each array (you can actually use a macro, but we'll leave that for later).
In keeping with the earlier discussion, I added a few sanity checks and created a new character array allowed that holds a list of the current characters you have created arrays for (the allowed characters). Just add to it as you add arrays. You will also note I moved all your global variables inside main. There is nothing wrong with using globals, but use them sparingly, and only when necessary.
Putting the pieces together, you could do something like:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAXL 100
#define ROWS 7
#define COLS 5
void prn_letter_row (bool a[][COLS+1], size_t row);
int main (void) {
char line[MAXL] = {0};
char allowed[] = "AB";
size_t i, row, len;
i = row = len = 0;
bool A[ROWS][COLS+1] = {{0, 0, 1, 0, 0, 0}, //letter A
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0}};
bool B[ROWS][COLS+1] = {{1, 1, 1, 0, 0, 0}, //letter B
{1, 0, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0},
{1, 1, 1, 1, 0, 0},
{1, 0, 0, 0, 1, 0},
{1, 0, 0, 0, 1, 0},
{1, 1, 1, 1, 0, 0}};
/* prompt for input */
while (!*line)
{
printf ("\nType a word or number, or both [A-B only]: ");
if (!fgets (line, MAXL, stdin))
fprintf (stderr, "error: no input provided - 'ctrl+d'.\n");
len = strlen (line); /* get length, remove trailing \n */
if (line[len-1] == '\n')
line[--len] = 0;
char *p = line;
while (*p) { /* check each character against 'allowed' */
if (!strchr (allowed, *p)) {
fprintf (stderr, "error: invalid character '%c'.\n", *p);
*line = 0;
}
p++;
}
}
printf ("valid: %s\n\n", line);
for (row = 0; row < ROWS; row++) {
for (i = 0; i < len; i++) {
switch (line[i]) {
case 'A' : prn_letter_row (A, row);
break;
case 'B' : prn_letter_row (B, row);
break;
}
}
putchar ('\n');
}
return 0;
}
/* print given row for letter */
void prn_letter_row (bool a[][COLS+1], size_t row)
{
size_t i;
putchar (' '); /* provide a space before each letter */
for (i = 0; i < COLS; i++)
if (a[row][i])
putchar ('*');
else
putchar (' ');
}
Use/Output
$ ./bin/chars_from_arrays
Type a word or number, or both [A-B only]: A
valid: A
*
* *
* *
*****
* *
* *
* *
$ ./bin/chars_from_arrays
Type a word or number, or both [A-B only]: B
valid: B
***
* *
* *
****
* *
* *
****
$ ./bin/chars_from_arrays
Type a word or number, or both [A-B only]: AB
valid: AB
* ***
* * * *
* * * *
***** ****
* * * *
* * * *
* * ****
Here is your fixed code
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
char line[100] = {'A','B'};
int i;
int row;
int col;
// Support only latin aphabet, easly expandable
bool chars[26][7][6] = {
{ {0,0,1,0,0,0 }, //letter A
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 }},
{ {1,1,1,0,0,0 }, //letter B
{1,0,0,1,0,0 },
{1,0,0,1,0,0 },
{1,1,1,1,0,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,0,0 }},
// to Z
};
int main()
{
printf ("Type a word or number, or both: ");
scanf ("%s",line);
//reads the input
for (row = 0;row<7;row++)
// loop for every row of every letter
{
for (i = 0; line[i]; i++) //loop for every inputed letter
{
for (col = 0;col < 6;col++) // lopp for every column to read the asterisks
{
if (chars[toupper(line[i]) - 'A'][row][col])
{
printf("*");
}
else
printf(" ");
}
}
printf("\n");
}
return (0);
}
You can add multiple character support by forming 3d array like
bool chars[26][7][6] = {
{ {0,0,1,0,0,0 }, //letter A
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 }},
{ {1,1,1,0,0,0 }, //letter B
{1,0,0,1,0,0 },
{1,0,0,1,0,0 },
{1,1,1,1,0,0 },
{1,0,0,0,1,0 },
{1,0,0,0,1,0 },
{1,1,1,1,0,0 }},
// to Z
};
Than access to array member
chars[toupper(line[i]) - 'A'][row][col];
in this case you may not use any character if checks only for loops
this will only works with small string sizes, because standard console support up to 80 characters in length, to deal with it you can setup console width, or perform some manipulation with console cursors to break out formed string properly (like SetConsoleCursorPosition) in Windows.
if you want to support all printable chars, your 3d array should start at whitespace char up to 128 character. For more info look to ASCII character table.
I want do to a loop with some variables on my arduino , I have 24 variables ( ConfigSonde[0][3] to ConfigSonde[24][3] ) to change, i need do to a loop:
EX :
ConfigSonde_0[] = {'xxx', 3, 'A', 1, 0, 0, 0, 0, 0, 0};
ConfigSonde_1[] = {'xxx', 1, 'A', 1, 0, 0, 0, 0, 0, 0};
for (i = 0; i < 25; i = i + 1) { ConfigSonde_[i][3]=0;}
Is it possible ?
Thank
You are mixing ints and 'xxx'? (if it's supposed to be a string it must be "xxx"), and this is not legal in C.
ConfigSonde_[i][3] where i = 0 doesn't give you a reference to the variable ConfigSonde_0[3]
Maybe you are looking for:
int ConfigSonde_0[] = {'x', 3, 'A', 1, 0, 0, 0, 0, 0, 0};
int ConfigSonde_1[] = {'x', 1, 'A', 1, 0, 0, 0, 0, 0, 0};
int *ConfigSonde [] = {ConfigSonde_0, ConfigSonde_1};
for (i = 0; i < 2; i = i + 1) {ConfigSonde[i][3] = 0;}
or
int ConfigSonde[][10] = {
{'x', 3, 'A', 1, 0, 0, 0, 0, 0, 0},
{'x', 1, 'A', 1, 0, 0, 0, 0, 0, 0}
};
for (i = 0; i < 2; i = i + 1) {ConfigSonde[i][3] = 0;}
Rewrite: Do do what you need, you're going to have to either add additional variables that point at the things you want to change in the loop, or change your 25 distinct arrays to be a single 2-dimensional array.
You cannot dynamically "compute" names of variables to access their values in C (or C++), since these languages are compiled the names of variables are no longer relevant when the program runs.
I am writing a C program to generate Keys and test them in an encryption function. However since I have NEVER written a C program before, and I'm completely unused to having manage memory manually, I have run into a problem. I have a memory leak and to be honest, I don't know how to solve it. I understand I need to release the memory at some point but can't until I've run through all keys and I run out of memory before I get through all of them. Writing the program in a different language is NOT an option so please do not suggest that. The code that is leaking is shown below, any help would be appreciated.
EDIT: I know i haven't called a free function to free the memory. I don't see where I can put it because I need the memory until i run through all keys. Putting it outside the loops doesn't solve the problem because the leak occurs inside the loops
2nd EDIT: Posted the full program. I do not have the option of using data structures (i.e. the bool arrays) other than those shown because of how the DES encrypt function(which I did not write) works
#include <stdio.h>
#include <stdlib.h>
#include "des.h"
void dec2bin(bool *testaRR, bool *to_return, int convert);
int main(int argc, const char * argv[])
{
// insert code here...
bool testKey[56] = {
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 1
};
bool testKey2[56] = {//intuitive key reversed for testing
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 1, 0
};
bool output[64];
bool input[64] = {//the reverse of below... DES bits are numbered left to right, in order of least to most significant so we must enter the bit values in reverse.
//forexample the binary vale of N is 01001110 but below is displayed as 01110010
1, 0, 0, 0, 1, 1, 0, 0,//1
0, 0, 0, 0, 1, 1, 0, 0,//0
1, 1, 0, 0, 0, 0, 1, 0,//C
1, 0, 1, 0, 0, 0, 1, 0,//E
1, 1, 0, 0, 1, 0, 1, 0,//S
0, 0, 1, 0, 1, 0, 1, 0,//T
1, 0, 1, 0, 0, 0, 1, 0,//E
0, 1, 1, 1, 0, 0, 1, 0 //N
};
int y = sizeof(input);
printf("(Input MSG: ");
for (int i = y-4; i >= 0; i-=4)
printf("%X", input[i]+2*input[i+1]+4*input[i+2]+8*input[i+3]);//this is the conversion to hex code
printf(")\n");
/*
use char[] to store the key as set of
*/
/*bool input[64] = {//this is the given plaintext message in the intuitive order (opposite of what it is)
0, 1, 0, 0, 1, 1, 1, 0,//N
0, 1, 0, 0, 0, 1, 0, 1,//E
0, 1, 0, 1, 0, 1, 0, 0,//T
0, 1, 0, 1, 0, 0, 1, 1,//S
0, 1, 0, 0, 0, 1, 0, 1,//E
0, 1, 0, 0, 0, 0, 1, 1,//C
0, 0, 1, 1, 0, 0, 0, 0,//0
0, 0, 1, 1, 0, 0, 0, 1 //1
};
int y = sizeof(input);
printf("(Input MSG: ");
for (int j = 0; j < y; j+=4)
printf("%X", input[j+3]+2*input[j+2]+4*input[j+1]+8*input[j]);//this is the conversion to hex code
printf(")\n");*/
bool test [8];
bool returned[8];
char keyphrase [8];
keyphrase[7] = 0;
for(int start = 65; start<=90; start++)
{
//dec2bin(test, returned, start);
keyphrase[0] = start;
for(int two = 65; two<=90; two++){
keyphrase[1]=two;
for(int three = 65; three<=90; three++){
keyphrase[2]=three;
for(int four = 65; four<=90; four++){
keyphrase[3]=four;
for(int five = 65;five<=90;five++){
keyphrase[4]=five;
for( int six = 65; six <=90; six++){
keyphrase[5]=six;
for(int seven = 65; seven <=90; seven++){
keyphrase[6]=seven;
printf("%s \n", keyphrase);
}
}}
}
}
}
//once i fix the memory leak I will be calling the EncryptDes Function here and checking the outputblk agains the given cipher text
}
free(keyphrase);
int k = sizeof(testKey);
printf("(Test Key: ");
for (int z = 0; z < k; z+=7)
printf("%d", testKey[z+7]+2*testKey[z+6]+4*testKey[z+5]+8*testKey[z+4]+16*testKey[z+3]+32*testKey[z+2]+64*testKey[z+1]+ 128*testKey[z]);//this is the conversion to hex code
printf(")\n");
//loop on the key (starting at
EncryptDES(testKey, output, input, 0);
int x = sizeof(output);
printf("(Output MSG: ");
for (int i = 0; i < x; i+=4)
printf("%X", output[i+3]+2*output[i+2]+4*output[i+1]+8*output[i]);//this is the conversion to hex code
printf(")\n");
return 0;
}
void dec2bin (bool *testaRR, bool *to_return, int convert)
{
printf("%d : ", convert);
printf("%c", convert);
printf("\n ");
//bool testaRR [8];
for(int st = 0; st<8; st++){
testaRR[st] = convert%2;
to_return[7-st] = testaRR[st];
//printf("%d :", 7-st);
//printf(" %d spot ", st);
convert = convert/2;
//testaRR stores the arrays in one direction
//to_return stores them in the other
//Example:
//65 = 01000001 testaRR least significant on the far right (m0st sig is in index 7)better for storage and keeping track of where the bits actually are in binary
//65 = 10000010 to_return least significant on the far left (same as DES) (most significant bit is index 0) good for printing to screen
}
You do not need dynamic memory management here.
Start with
char keyphrase[8];
keyphrase[7]=0;
instead of your malloc and you will be good to go. Your highest array index is 7 (the terminating NUL), and hence you need an array of 8 items (0..7).
If you really want to use malloc, simply a free() at the end will be fine, but you need to malloc 8 characters and set keyphrase[7] to 0 to do the terminating NUL still.
Here's a tested version that works:
#include <stdio.h>
/* compile with gcc -Wall -std=c99 keyphrase.c -o keyphrase */
int
main (int argc, char **argv)
{
char keyphrase[8];
keyphrase[7] = 0;
for (int start = 65; start <= 90; start++)
{
//dec2bin(test, returned, start);
keyphrase[0] = start;
for (int two = 65; two <= 90; two++)
{
keyphrase[1] = two;
for (int three = 65; three <= 90; three++)
{
keyphrase[2] = three;
for (int four = 65; four <= 90; four++)
{
keyphrase[3] = four;
for (int five = 65; five <= 90; five++)
{
keyphrase[4] = five;
for (int six = 65; six <= 90; six++)
{
keyphrase[5] = six;
for (int seven = 65; seven <= 90; seven++)
{
keyphrase[6] = seven;
printf ("%s \n", keyphrase);
}
}
}
}
}
}
}
}
The real problem is the use of printf. You did not NULL terminate keyphrase, so every time you printf you overflow.
Also, to avoid the memory leak, simply replace char *keyphrase = (char *)malloc(7); with char keyphrase[8];.
You're calling malloc on the first line but I don't see a single free to release what you allocated. After all the loops are completed (i.e. usage of the allocated data is complete) you must call free(keyphrase);
New answer as the program has been modified.
You say your program is using all memory 'because I'm watching the available memory go down from over 4 free GB to about 5 MB'.
I'm guessing the answer is not the loops but these lines:
//loop on the key (starting at
EncryptDES(testKey, output, input, 0);
int x = sizeof(output);
We can't see the source to or declaration of EncryptDES, but you aren't passing a length to it. If 0 is meant to be the length, this would explain it.
The next line however suggests that output is meant to be an array of 64 bytes (rather than 2 strings). But EncryptDES would have no way of knowing this.
I suggest you run the whole thing under valgrind to find out what is happening.