#include <iostream>
#include <cstring>
using namespace std;
void reverseString(char s[])
{
int length = strlen(s);
for (int i = 0; s[i] != '\0'; i++) {
char temp = s[i];
s[i] = s[length - i - 1];
s[length - i - 1] = temp;
cout << s[i]; //this ends up printing "eooe" instead of reversing the whole string
}
}
int main()
{
char a[] = "Shoe";
reverseString(a);
return 1;
}
I'm wondering where the algorithm messes up and what I can do to fix it, maybe I overlooked something because when I try to solve it on a piece of paper it appears to work correctly.
Your algo is right but need a little modification, you have to run algorithm for length/2 times. It prevents your string to again swap the contents i.e At i = 2 your s = eohs but it again swaps h with o. Try to insert the break point to understand it further. I modify your function little bit.
char* reverseString(char s[])
{
int length = strlen(s);
for (int i = 0; i<length/2; i++)
{
char temp = s[i];
s[i] = s[length - i - 1];
s[length - i - 1] = temp;
//cout << s[i]; //this ends up printing "eooe" instead of reversing the whole string
}
return s;
}
int main()
{
char a[] = "Shoe";
cout<<reverseString(a);
system("pause");
return 1;
}
Use the code below:
#include <stdio.h>
void strrev(char *p)
{
char *q = p;
while(q && *q) ++q;
for(--q; p < q; ++p, --q)
*p = *p ^ *q,
*q = *p ^ *q,
*p = *p ^ *q;
}
int main(int argc, char **argv)
{
do {
printf("%s ", argv[argc-1]);
strrev(argv[argc-1]);
printf("%s\n", argv[argc-1]);
} while(--argc);
return 0;
}
Related
I have written a multithreaded program in C using pthreads to solve the N-queens problem. It uses the producer consumer programming model. One producer who creates all possible combinations and consumers who evaluate if the combination is valid. I use a shared buffer that can hold one combination at a time.
Once I have 2+ consumers the program starts to behave strange. I get more consumptions than productions. 1.5:1 ratio approx (should be 1:1). The interesting part is that this only happens on my MacBook and is nowhere to be seen when I run it on the Linux machine (Red Hat Enterprise Linux Workstation release 6.10 (Santiago)) I have access to over SSH.
I'm quite sure that my implementation is correct with locks and conditional variables too, the program runs for 10+ seconds which should reveal if there are any mistakes with the synchronization.
I compile with GCC (Apple clang version 12.0.5) via xcode developer tools on my MacBook Pro (2020, x86_64) and GCC on Linux too, but version 4.4.7 20120313 (Red Hat 4.4.7-23).
compile: gcc -o 8q 8q.c
run: ./8q <producers> <N>, NxN chess board, N queens to place
parameters: ./8q 2 4 Enough to highlight the problem (should yield 2 solutions, but every other run yields 3+ solutions, i.e duplicate solutions exist
note: print(printouts) Visualizes the valid solutions (duplicates shown)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
typedef struct stack_buf {
int positions[8];
int top;
} stack_buf;
typedef struct global_buf {
int positions[8];
volatile int buf_empty;
volatile long done;
} global_buf;
typedef struct print_buf {
int qpositions[100][8];
int top;
} print_buf;
stack_buf queen_comb = { {0}, 0 };
global_buf global = { {0}, 1, 0 };
print_buf printouts = { {{0}}, -1 };
int N; //NxN board and N queens to place
clock_t start, stop, diff;
pthread_mutex_t buffer_mutex, print_mutex;
pthread_cond_t empty, filled;
/* ##########################################################################################
################################## VALIDATION FUNCTIONS ##################################
########################################################################################## */
/* Validate that no queens are placed on the same row */
int valid_rows(int qpositions[]) {
int rows[N];
memset(rows, 0, N * sizeof(int));
int row;
for (int i = 0; i < N; i++) {
row = qpositions[i] / N;
if (rows[row] == 0) rows[row] = 1;
else return 0;
}
return 1;
}
/* Validate that no queens are placed in the same column */
int valid_columns(int qpositions[]) {
int columns[N];
memset(columns, 0, N*sizeof(int));
int column;
for (int i = 0; i < N; i++) {
column = qpositions[i] % N;
if (columns[column] == 0) columns[column] = 1;
else return 0;
}
return 1;
}
/* Validate that left and right diagonals aren't used by another queen */
int valid_diagonals(int qpositions[]) {
int left_bottom_diagonals[N];
int right_bottom_diagonals[N];
int row, col, temp_col, temp_row, fill_value, index;
for (int queen = 0; queen < N; queen++) {
row = qpositions[queen] / N;
col = qpositions[queen] % N;
/* position --> left down diagonal endpoint (index) */
fill_value = col < row ? col : row; //min of col and row
temp_row = row - fill_value;
temp_col = col - fill_value;
index = temp_row * N + temp_col; // position
for (int i = 0; i < queen; i++) { // check if interference occurs
if (left_bottom_diagonals[i] == index) return 0;
}
left_bottom_diagonals[queen] = index; // no interference
/* position --> right down diagonal endpoint (index) */
fill_value = (N-1) - col < row ? N - col - 1 : row; // closest to bottom or right wall
temp_row = row - fill_value;
temp_col = col + fill_value;
index = temp_row * N + temp_col; // position
for (int i = 0; i < queen; i++) { // check if interference occurs
if (right_bottom_diagonals[i] == index) return 0;
}
right_bottom_diagonals[queen] = index; // no interference
};
return 1;
}
/* ##########################################################################################
#################################### HELPER FUNCTIONS ####################################
########################################################################################## */
/* print the collected solutions */
void print(print_buf printouts) {
static int solution_number = 1;
int placement;
for (int sol = 0; sol <= printouts.top; sol++) { // number of solutions
printf("Solution %d: [ ", solution_number++);
for (int pos = 0; pos < N; pos++) {
printf("%d ", printouts.qpositions[sol][pos]+1);
}
printf("]\n");
printf("Placement:\n");
for (int i = 1; i <= N; i++) { // rows
printf("[ ");
placement = printouts.qpositions[sol][N-i];
for (int j = (N-i)*N; j < (N-i)*N+N; j++) { // physical position
if (j == placement) {
printf(" Q ");
} else printf("%2d ", j+1);
}
printf("]\n");
}
printf("\n");
}
}
/* push value to top of list instance */
void push(stack_buf *instance, int value) {
assert(instance->top <= 8 || instance->top >= 0);
instance->positions[instance->top++] = value;
}
/* pop top element of list instance */
void pop(stack_buf *instance) {
assert(instance->top > 0);
instance->positions[--instance->top] = -1;
}
/* ##########################################################################################
#################################### THREAD FUNCTIONS ####################################
########################################################################################## */
static int consumptions = 0;
/* entry point for each worker (consumer)
workers will check each queen's row, column and
diagonal to evaluate satisfactory placements */
void *eval_positioning(void *id) {
long thr_id = (long)id;
int qpositions[N];
while (!global.done) {
pthread_mutex_lock(&buffer_mutex);
while (global.buf_empty == 1) {
if (global.done) break; // consumers who didn't get last production
pthread_cond_wait(&filled, &buffer_mutex);
}
if (global.done) break;
consumptions++;
memcpy(qpositions, global.positions, N * sizeof(int)); // retrieve queen combination
global.buf_empty = 1;
pthread_cond_signal(&empty);
pthread_mutex_unlock(&buffer_mutex);
if (valid_rows(qpositions) && valid_columns(qpositions) && valid_diagonals(qpositions)) {
/* save for printing later */
pthread_mutex_lock(&print_mutex);
memcpy(printouts.qpositions[++printouts.top], qpositions, N * sizeof(int));
pthread_mutex_unlock(&print_mutex);
}
}
return NULL;
}
static int productions = 0;
/* recursively generate all possible queen_combs */
void rec_positions(int pos, int queens) {
if (queens == 0) { // base case
pthread_mutex_lock(&buffer_mutex);
while (global.buf_empty == 0) {
pthread_cond_wait(&empty, &buffer_mutex);
}
productions++;
memcpy(global.positions, queen_comb.positions, N * sizeof(int));
global.buf_empty = 0;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_broadcast(&filled); // wake one worker
return;
}
for (int i = pos; i <= N*N - queens; i++) {
push(&queen_comb, i); // physical chess box
rec_positions(i+1, queens-1);
pop(&queen_comb);
}
}
/* binomial coefficient | without order, without replacement
8 queens on 8x8 board: 4'426'165'368 queen combinations */
void *generate_positions(void *arg) {
rec_positions(0, N);
return (void*)1;
}
/* ##########################################################################################
########################################## MAIN ##########################################
########################################################################################## */
/* main procedure of the program */
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./8q <workers> <board width/height>\n");
exit(1);
}
int workers = atoi(argv[1]);
N = atoi(argv[2]);
pthread_t thr[workers];
pthread_t producer;
// int sol1[] = {5,8,20,25,39,42,54,59};
// int sol2[] = {2,12,17,31,32,46,51,61};
printf("\n");
start = (float)clock()/CLOCKS_PER_SEC;
pthread_create(&producer, NULL, generate_positions, NULL);
for (long i = 0; i < workers; i++) {
pthread_create(&thr[i], NULL, eval_positioning, (void*)i+1);
}
pthread_join(producer, (void*)&global.done);
pthread_cond_broadcast(&filled);
for (int i = 0; i < workers; i++) {
pthread_join(thr[i], NULL);
}
stop = clock();
diff = (double)(stop - start) / CLOCKS_PER_SEC;
/* go through all valid solutions and print */
print(printouts);
printf("board: %dx%d, workers: %d (+1), exec time: %ld, solutions: %d\n", N, N, workers, diff, printouts.top+1);
printf("productions: %d\nconsumptions: %d\n", productions, consumptions);
return 0;
}
EDIT: I have reworked sync around prod_done and made a new shared variable last_done. When producer is done, it will set prod_done and the thread currently active will either return (last element already validated) or capture the last element at set last_done to inform the other consumers.
Despite the fact that I solved the data race in my book, I still have problems with the shared combination. I have really put time looking into the synchronization but I always get back to the feeling that it should work, but it clearly doesn't when I run it.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
typedef struct stack_buf {
int positions[8];
int top;
} stack_buf;
typedef struct global_buf {
int positions[8];
volatile int buf_empty;
volatile long prod_done;
volatile int last_done;
} global_buf;
typedef struct print_buf {
int qpositions[100][8];
int top;
} print_buf;
stack_buf queen_comb = { {0}, 0 };
global_buf global = { {0}, 1, 0, 0 };
print_buf printouts = { {{0}}, -1 };
int N; //NxN board and N queens to place
long productions, consumptions = 0;
clock_t start, stop, diff;
pthread_mutex_t buffer_mutex, print_mutex;
pthread_cond_t empty, filled;
/* ##########################################################################################
################################## VALIDATION FUNCTIONS ##################################
########################################################################################## */
/* Validate that no queens are placed on the same row */
int valid_rows(int qpositions[]) {
int rows[N];
memset(rows, 0, N*sizeof(int));
int row;
for (int i = 0; i < N; i++) {
row = qpositions[i] / N;
if (rows[row] == 0) rows[row] = 1;
else return 0;
}
return 1;
}
/* Validate that no queens are placed in the same column */
int valid_columns(int qpositions[]) {
int columns[N];
memset(columns, 0, N*sizeof(int));
int column;
for (int i = 0; i < N; i++) {
column = qpositions[i] % N;
if (columns[column] == 0) columns[column] = 1;
else return 0;
}
return 1;
}
/* Validate that left and right diagonals aren't used by another queen */
int valid_diagonals(int qpositions[]) {
int left_bottom_diagonals[N];
int right_bottom_diagonals[N];
int row, col, temp_col, temp_row, fill_value, index;
for (int queen = 0; queen < N; queen++) {
row = qpositions[queen] / N;
col = qpositions[queen] % N;
/* position --> left down diagonal endpoint (index) */
fill_value = col < row ? col : row; // closest to bottom or left wall
temp_row = row - fill_value;
temp_col = col - fill_value;
index = temp_row * N + temp_col; // board position
for (int i = 0; i < queen; i++) { // check if interference occurs
if (left_bottom_diagonals[i] == index) return 0;
}
left_bottom_diagonals[queen] = index; // no interference
/* position --> right down diagonal endpoint (index) */
fill_value = (N-1) - col < row ? N - col - 1 : row; // closest to bottom or right wall
temp_row = row - fill_value;
temp_col = col + fill_value;
index = temp_row * N + temp_col; // board position
for (int i = 0; i < queen; i++) { // check if interference occurs
if (right_bottom_diagonals[i] == index) return 0;
}
right_bottom_diagonals[queen] = index; // no interference
}
return 1;
}
/* ##########################################################################################
#################################### HELPER FUNCTIONS ####################################
########################################################################################## */
/* print the collected solutions */
void print(print_buf printouts) {
static int solution_number = 1;
int placement;
for (int sol = 0; sol <= printouts.top; sol++) { // number of solutions
printf("Solution %d: [ ", solution_number++);
for (int pos = 0; pos < N; pos++) {
printf("%d ", printouts.qpositions[sol][pos]+1);
}
printf("]\n");
printf("Placement:\n");
for (int i = 1; i <= N; i++) { // rows
printf("[ ");
placement = printouts.qpositions[sol][N-i];
for (int j = (N-i)*N; j < (N-i)*N+N; j++) { // physical position
if (j == placement) {
printf(" Q ");
} else printf("%2d ", j+1);
}
printf("]\n");
}
printf("\n");
}
}
/* ##########################################################################################
#################################### THREAD FUNCTIONS ####################################
########################################################################################## */
/* entry point for each worker (consumer)
workers will check each queen's row, column and
diagonal to evaluate satisfactory placements */
void *eval_positioning(void *id) {
long thr_id = (long)id;
int qpositions[N];
pthread_mutex_lock(&buffer_mutex);
while (!global.last_done) {
while (global.buf_empty == 1) {
pthread_cond_wait(&filled, &buffer_mutex);
if (global.last_done) { // last_done ==> prod_done, so thread returns
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
if (global.prod_done) { // prod done, current thread takes last elem produced
global.last_done = 1;
break;
}
}
if (!global.last_done) consumptions++;
memcpy(qpositions, global.positions, N*sizeof(int)); // retrieve queen combination
global.buf_empty = 1;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_signal(&empty);
if (valid_rows(qpositions) && valid_columns(qpositions) && valid_diagonals(qpositions)) {
/* save for printing later */
pthread_mutex_lock(&print_mutex);
memcpy(printouts.qpositions[++printouts.top], qpositions, N*sizeof(int));
pthread_mutex_unlock(&print_mutex);
}
pthread_mutex_lock(&buffer_mutex);
}
pthread_mutex_unlock(&buffer_mutex);
return NULL;
}
/* recursively generate all possible queen_combs */
void rec_positions(int pos, int queens) {
if (queens == 0) { // base case
pthread_mutex_lock(&buffer_mutex);
while (global.buf_empty == 0) {
pthread_cond_wait(&empty, &buffer_mutex);
}
productions++;
memcpy(global.positions, queen_comb.positions, N*sizeof(int));
global.buf_empty = 0;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_signal(&filled);
return;
}
for (int i = pos; i <= N*N - queens; i++) {
queen_comb.positions[queen_comb.top++] = i;
rec_positions(i+1, queens-1);
queen_comb.top--;
}
}
/* binomial coefficient | without order, without replacement
8 queens on 8x8 board: 4'426'165'368 queen combinations */
void *generate_positions(void *arg) {
rec_positions(0, N);
return (void*)1;
}
/* ##########################################################################################
########################################## MAIN ##########################################
########################################################################################## */
/* main procedure of the program */
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./8q <workers> <board width/height>\n");
exit(1);
}
int workers = atoi(argv[1]);
N = atoi(argv[2]);
pthread_t thr[workers];
pthread_t producer;
printf("\n");
start = (float)clock()/CLOCKS_PER_SEC;
pthread_create(&producer, NULL, generate_positions, NULL);
for (long i = 0; i < workers; i++) {
pthread_create(&thr[i], NULL, eval_positioning, (void*)i+1);
}
pthread_join(producer, (void*)&global.prod_done);
pthread_cond_broadcast(&filled);
for (int i = 0; i < workers; i++) {
printf("thread #%d done\n", i+1);
pthread_join(thr[i], NULL);
pthread_cond_broadcast(&filled);
}
stop = clock();
diff = (double)(stop - start) / CLOCKS_PER_SEC;
/* go through all valid solutions and print */
print(printouts);
printf("board: %dx%d, workers: %d (+1), exec time: %ld, solutions: %d\n", N, N, workers, diff, printouts.top+1);
printf("productions: %ld\nconsumptions: %ld\n", productions, consumptions);
return 0;
}
I'm quite sure that my implementation is correct with locks and conditional variables
That is a bold statement, and it's provably false. Your program hangs on Linux when run with clang -g q.c -o 8q && ./8q 2 4.
When I look at the state of the program, I see one thread here:
#4 __pthread_cond_wait (cond=0x404da8 <filled>, mutex=0x404d80 <buffer_mutex>) at pthread_cond_wait.c:619
#5 0x000000000040196b in eval_positioning (id=0x1) at q.c:163
#6 0x00007ffff7f8cd80 in start_thread (arg=0x7ffff75b6640) at pthread_create.c:481
#7 0x00007ffff7eb7b6f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
and the main thread trying to join the above thread. All other threads have exited, so there is nothing to signal the condition.
One immediate problem I see is this:
void *eval_positioning(void *id) {
long thr_id = (long)id;
int qpositions[N];
while (!global.done) {
...
int main(int argc, char *argv[]) {
...
pthread_join(producer, (void*)&global.done);
If the producer thread finishes before the eval_positioning starts, then eval_positioning will do nothing at all.
You should set global.done when all positions have been evaluated, not when the producer thread is done.
Another obvious problem is that global.done is accessed without any mutexes held, yielding a data race (undefined behavior -- anything can happen).
Apologies if the answer to this is incredibly simple. I just can't work it out.
I've been working on the CS50 Vigenere problem and I think I'm almost there. However the program loops in a way that I don't expect and I'm not sure why. Once it has printed the first ciphered character of the plaintext, it loops back to move to the next character in the key but misses out the part where it needs to move to the next character of the plain text. At least I think that is what is happening.
Here is my code. Any help would be greatly appreciated.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv [])
{
int a;
int ciphertext;
int k;
string plain;
int cipher;
// check user has input a valid number of arguments
if (argc < 2 || argc > 2)
{
printf("please input a valid number of arguments\n");
return 1;
}
// check user has input a valid key and prompt for plaintext
char * key = argv [1];
for (a = 0; a < strlen(key); a++)
if (!isalpha(key[a]))
{
printf("Please input a valid key. Key must be alphabetical");
return 1;
}
{
if (a == strlen(key))
{
plain = get_string("Plaintext: ");
}
{
printf("ciphertext: ");
}
}
//read plaintext and keep track
{
for (int i = 0, n = strlen(plain); i < n; i++)
{
//read key and keep track
if (isalpha(plain[i]))
{
for (int j = 0, p = strlen(key); j < p; j++)
//convert key to numerical
{
if (isupper(key[j]) > 'A')
{
k = (key[j] - 65);
//calculate ciphertext and print (upper case)
{
printf("%c", (plain[i] + (k % p) %26) +65);
}
}
else if (islower(key[j]) > 'a')
{
k = (key[j] - 97);
{
printf("%c", (plain[i] + (k % p) %26) +97);
}
}
else printf("%c", plain[i]);
}
}
}
{
printf("\n");
}
}
}
We are given a pattern string: 'foo' and a source string: 'foobaroofzaqofom' and we need to find all occurrences of word pattern string in any order of letters. So for a given example solution will looks like: ['foo', 'oof', 'ofo'].
I have a solution, but i'm not sure that it is the most efficient one:
Create hash_map of chars of pattern string where each char is a key and each value is a counter of chars in pattern. For a given example it would be {{f: 1}, {o: 2}}
Look through the source string and if found one of the elements from hash_map, than try to find all the rest elements of pattern
If all elements are found than it is our solution, if not going forward
Here is an implementation in c++:
set<string> FindSubstringPermutations(string& s, string& p)
{
set<string> result;
unordered_map<char, int> um;
for (auto ch : p)
{
auto it = um.find(ch);
if (it == um.end())
um.insert({ ch, 1 });
else
um[ch] += 1;
}
for (int i = 0; i < (s.size() - p.size() + 1); ++i)
{
auto it = um.find(s[i]);
if (it != um.end())
{
decltype (um) um_c = um;
um_c[s[i]] -= 1;
for (int t = (i + 1); t < i + p.size(); ++t)
{
auto it = um_c.find(s[t]);
if (it == um_c.end())
break;
else if (it->second == 0)
break;
else
it->second -= 1;
}
int sum = 0;
for (auto c : um_c)
sum += c.second;
if (sum == 0)
result.insert(s.substr(i, p.size()));
}
}
return result;
}
Complexity is near O(n), i don't know how to calculate more precisely.
So the question: is there any efficient solution, because using hash_map is a bit of hacks and i think there may be more efficient solution using simple arrays and flags of found elements.
You could use a order-invariant hash-algorithm that works with a sliding window to optimize things a bit.
An example for such a hash-algorithm could be
int hash(string s){
int result = 0;
for(int i = 0; i < s.length(); i++)
result += s[i];
return result;
}
This algorithm is a bit over-simplistic and is rather horrible in all points except performance (i.e. distribution and number of possible hash-values), but that isn't too hard to change.
The advantage with such a hash-algorithm would be:
hash("abc") == hash("acb") == hash("bac") == ...
and using a sliding-window with this algorithm is pretty simple:
string s = "abcd";
hash(s.substring(0, 3)) + 'd' - 'a' == hash(s.substring(1, 3));
These two properties of such hashing approaches allow us to do something like this:
int hash(string s){
return sum(s.chars);
}
int slideHash(int oldHash, char slideOut, char slideIn){
return oldHash - slideOut + slideIn;
}
int findPermuted(string s, string pattern){
int patternHash = hash(pattern);
int slidingHash = hash(s.substring(0, pattern.length()));
if(patternHash == slidingHash && isPermutation(pattern, s.substring(0, pattern.length())
return 0;
for(int i = 0; i < s.length() - pattern.length(); i++){
slidingHash = slideHash(slidingHash, s[i], s[i + pattern.length()]);
if(patternHash == slidingHash)
if(isPermutation(pattern, s.substring(i + 1, pattern.length())
return i + 1;
}
return -1;
}
This is basically an altered version of the Rabin-Karp-algorithm that works for permuted strings. The main-advantage of this approach is that less strings actually have to be compared, which brings quite a bit of an advantage. This especially applies here, since the comparison (checking if a string is a permutation of another string) is quite expensive itself already.
NOTE:
The above code is only supposed as a demonstration of an idea. It's aimed at being easy to understand rather than performance and shouldn't be directly used.
EDIT:
The above "implementation" of an order-invariant rolling hash algorithm shouldn't be used, since it performs extremely poor in terms of data-distribution. Of course there are obviously a few problems with this kind of hash: the only thing from which the hash can be generated is the actual value of the characters (no indices!), which need to be accumulated using a reversible operation.
A better approach would be to map each character to a prime (don't use 2!!!). Since all operations are modulo 2^(8 * sizeof(hashtype)) (integer overflow), we need to generate a table of the multiplicative inverses modulo 2^(8 * sizeof(hashtype)) for all used primes. I won't cover generating these tables, as there's plenty of resources available on that topic here already.
The final hash would then look like this:
map<char, int> primes = generatePrimTable();
map<int, int> inverse = generateMultiplicativeInverses(primes);
unsigned int hash(string s){
unsigned int hash = 1;
for(int i = 0; i < s.length(); i++)
hash *= primes[s[i]];
return hash;
}
unsigned int slideHash(unsigned int oldHash, char slideOut, char slideIn){
return oldHash * inverse[primes[slideOut]] * primes[slideIn];
}
Keep in mind that this solution works with unsigned integers.
Typical rolling hashfunction for anagrams
using product of primes
This will only work for relatively short patterns
The hashvalues for allmost all normal words will fit into a 64 bit value without overflow.
Based on this anagram matcher
/* braek; */
/* 'foobaroofzaqofom' */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned long long HashVal;
static HashVal hashchar (unsigned char ch);
static HashVal hashmem (void *ptr, size_t len);
unsigned char primes26[] =
{ 5,71,79,19,2,83,31,43,11,53,37,23,41,3,13,73,101,17,29,7,59,47,61,97,89,67, };
/*********************************************/
static HashVal hashchar (unsigned char ch)
{
HashVal val=1;
if (ch >= 'A' && ch <= 'Z' ) val = primes26[ ch - 'A'];
else if (ch >= 'a' && ch <= 'z' ) val = primes26[ ch - 'a'];
return val;
}
static HashVal hashmem (void *ptr, size_t len)
{
size_t idx;
unsigned char *str = ptr;
HashVal val=1;
if (!len) return 0;
for (idx = 0; idx < len; idx++) {
val *= hashchar ( str[idx] );
}
return val;
}
/*********************************************/
unsigned char buff [4096];
int main (int argc, char **argv)
{
size_t patlen,len,pos,rotor;
int ch;
HashVal patval;
HashVal rothash=1;
patlen = strlen(argv[1]);
patval = hashmem( argv[1], patlen);
// fprintf(stderr, "Pat=%s, len=%zu, Hash=%llx\n", argv[1], patlen, patval);
for (rotor=pos=len =0; ; len++) {
ch=getc(stdin);
if (ch == EOF) break;
if (ch < 'A' || ch > 'z') { pos = 0; rothash = 1; continue; }
if (ch > 'Z' && ch < 'a') { pos = 0; rothash = 1; continue; }
/* remove old char from rolling hash */
if (pos >= patlen) { rothash /= hashchar(buff[rotor]); }
/* add new char to rolling hash */
buff[rotor] = ch;
rothash *= hashchar(buff[rotor]);
// fprintf(stderr, "%zu: [rot=%zu]pos=%zu, Hash=%llx\n", len, rotor, pos, rothash);
rotor = (rotor+1) % patlen;
/* matched enough characters ? */
if (++pos < patlen) continue;
/* correct hash value ? */
if (rothash != patval) continue;
fprintf(stdout, "Pos=%zu\n", len);
}
return 0;
}
Output/result:
$ ./a.out foo < anascan.c
Pos=21
Pos=27
Pos=33
Update. For people who don't like product of primes, here is a taxinumber sum of cubes (+ additional histogram check) implementation. This is also supposed to be 8-bit clean. Note the cubes are not necessary; it wotks equally well with squares. Or just the sum. (the final histogram check will have some more work todo)
/* braek; */
/* 'foobaroofzaqofom' */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned long long HashVal;
static HashVal hashchar (unsigned char ch);
static HashVal hashmem (void *ptr, size_t len);
/*********************************************/
static HashVal hashchar (unsigned char ch)
{
HashVal val=1+ch;
return val*val*val;
}
static HashVal hashmem (void *ptr, size_t len)
{
size_t idx;
unsigned char *str = ptr;
HashVal val=1;
if (!len) return 0;
for (idx = 0; idx < len; idx++) {
val += hashchar ( str[idx] );
}
return val;
}
/*********************************************/
int main (int argc, char **argv)
{
size_t patlen,len,rotor;
int ch;
HashVal patval;
HashVal rothash=1;
unsigned char *patstr;
unsigned pathist[256] = {0};
unsigned rothist[256] = {0};
unsigned char cycbuff[1024];
patstr = (unsigned char*) argv[1];
patlen = strlen((const char*) patstr);
patval = hashmem( patstr, patlen);
for(rotor=0; rotor < patlen; rotor++) {
pathist [ patstr[rotor] ] += 1;
}
fprintf(stderr, "Pat=%s, len=%zu, Hash=%llx\n", argv[1], patlen, patval);
for (rotor=len =0; ; len++) {
ch=getc(stdin);
if (ch == EOF) break;
/* remove old char from rolling hash */
if (len >= patlen) {
rothash -= hashchar(cycbuff[rotor]);
rothist [ cycbuff[rotor] ] -= 1;
}
/* add new char to rolling hash */
cycbuff[rotor] = ch;
rothash += hashchar(cycbuff[rotor]);
rothist [ cycbuff[rotor] ] += 1;
// fprintf(stderr, "%zu: [rot=%zu], Hash=%llx\n", len, rotor, rothash);
rotor = (rotor+1) % patlen;
/* matched enough characters ? */
if (len < patlen) continue;
/* correct hash value ? */
if (rothash != patval) continue;
/* correct histogram? */
if (memcmp(rothist,pathist, sizeof pathist)) continue;
fprintf(stdout, "Pos=%zu\n", len-patlen);
}
return 0;
}
Im not sure what to do i want it to print 0000 to ending in BBBB i was trying to use the printf statement anyways, if anyone can help me figure this out that would be great. Thanks
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
char digits[] = "0123456789AB";
for (int column1=0; column1<=12; column1++) {
for (int column2=0; column2<=12; column2++) {
for (int column3=0; column3<=12; column3++) {
for (int column4=0; column4<=12; column4++) {
std::cout<< digits[column2]<<endl;
}
}}}
return(0);
}
The 4 for loops are not the prettiest thing ever, but they should work and I'm not sure it's worth the complications to do it differently. So keep what you have, just print all digits:
std::cout<< digits[column1]<< digits[column2] << digits[column3] << digits[column4]<<endl;
It's better to parametrize the base and the column count to avoid many nested for's.
#include <iostream>
const int columnCount = 4, base = 12;
char digitToChar(int digit) {
if(digit >= 0 && digit <= 9) {
return '0' + digit;
} else {
return 'A' + digit - 10;
}
}
bool increment(int* number) {
int currentColumn = columnCount - 1;
++number[currentColumn];
while(number[currentColumn] == base) {
number[currentColumn] = 0;
--currentColumn;
if(currentColumn < 0) {
return false;
}
++number[currentColumn];
}
return true;
}
void outputNumber(int* number) {
for(int i = 0; i < columnCount; ++i) {
std::cout << digitToChar(number[i]);
}
std::cout << std::endl;
}
int main() {
int number[columnCount] = {0, 0, 0, 0};
bool overflow = false;
do {
outputNumber(number);
overflow = !increment(number);
} while(!overflow);
return 0;
}
After the enter the first answer the code crashes.
Also it states that the memory is unsuccessful allocated. How can i fix this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(void)
{
int i;
srand(time(NULL));
int *num1;
int *num2;
int response;
int *answer;
char *result;
printf("\nMath Quiz\n");
printf("Enter # of problems: ");
scanf("%d", &response);
based on the number of questions the user wishes to take, allocate enough memory to hold question data
num1 = (int *)calloc(response, sizeof(int));
num2 = (int *)calloc(response, sizeof(int));
answer = (int *)calloc(response, sizeof(int));
result - (char *)calloc(response, sizeof(char));
if(num1 == NULL || num2 == NULL || answer == NULL || result == NULL)
{
printf("memory allocation unsucessful\n");
} //end if
for(i=0; i<response; i++)
{
num1[i] = (rand() % 12)+1;
num2[i] = (rand() % 12)+1;
printf("%d * %d = ", num1[i], num2[i]); //somewhere at this point the program messes up
scanf("%d", &answer[i]);
if(answer[i]= num1[i] * num2[i])
{
result[i] = 'c';
}
else
{
result[i] = 'i';
}
} //end for loop
printf("Quiz Results\n");
printf("Question\tYour Answer\tCorrect");
for(i=0; i<response; i++);
{
if(result[i] == 'c')
{
printf("%d * %d\t\t%d\t\tYES",num1[i],num2[i],answer[i]);
}
else
{
printf("%d * %d\t\t%d\t\tNo",num1[i],num2[i],answer[i]);
}
} //end for loop
free(num1);
free(num2);
free(answer);
free(result);
system("pause");
return 0;
} //end main
answer[i]= num1[i] * num2[i]
should read
answer[i] == num1[i] * num2[i]
= is for assignments, == is for comparisons.
and result - (char *)calloc(response, sizeof(char));
should read
result = (char *)calloc(response, sizeof(char));
If there are other problems, you need to be more specific than "the program messes up".
Also, don't cast the return value of malloc or calloc. Read Do I cast the result of malloc? .
Might this be the answer:
result - (char *)calloc(response, sizeof(char));
The '-' should be an '='.