#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//HASHITEM
/*Holds the word and the number of times it has appeared in the document */
typedef struct {
char *word;
int occurences;
} HashItem;
/* Creates and returns a new HashItem struct */
HashItem *item_new(char *word){
HashItem
*item
= (HashItem
*)malloc(sizeof(HashItem
)); item->occurences = 1;
item
->word
= (char*)malloc(sizeof(char) * (chars
+1)); return item;
}
/* Get the word containted within the passed HashItem */
char *item_get_word(HashItem *item){
return item->word;
}
/* Get the occurences of the passed HashItem */
int item_get_occurences(HashItem *item){
return item->occurences;
}
/* Increment the occurences of the passed HashItem, used when there is a verified collision */
void item_increment_occurences(HashItem *item){
item->occurences++;
}
//HASHTABLE
/* Hashtable struct holds all the HashItems and a null if there is no HashItem in the position */
typedef struct {
int size;
HashItem **items;
} Hash;
/* Create and return a new Hash struct */
Hash *hash_new (int size) {
Hash
*hash
= (Hash
*)calloc(1, sizeof (Hash
)); hash->size = size;
hash
->items
= (HashItem
**)calloc(size
, sizeof (HashItem
*)); return hash;
}
/* Hash function used to assign a integer value to a word */
int hash_func(char *word, int mod){
int i = 0;
int value = 0;
while(word[i] != '\0'){
value = ((word[i] * i) + value) % mod;
i++;
}
return value;
}
/* Get the index to place a given word within the passed hash table */
int hash_index (Hash *hash, char *word) {
int index = hash_func(word, hash->size);
HashItem *item = (hash->items)[index];
while (item){
if(!strcmp(item
->word
, word
)){ printf("word %s is equal to %s \n", item
->word
, word
); return index;
}
index = (index + 1) % hash->size;
item = hash->items[index];
}
return index;
}
/* Returns the Hashitem that corresponds to the word given, null is returned if it is not found */
HashItem *hash_get (Hash *hash, char *word) {
int index = hash_index(hash, word);
return hash->items[index];
}
/* Update the passed HashTable with a given word, adds the word if it is not in the table, increments the
corresponding Hashitem's occurence value if it is. */
HashItem *hash_update (Hash *hash, char *word) {
HashItem *item = hash_get(hash, word);
int index = hash_index(hash, word);
if(item){
item->occurences++;
return NULL;
}else{
int index = hash_index(hash, word);
item = item_new(word);
hash->items[index] = item;
return item;
}
}
//Dynamic Array
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
/*Method to create a new dynamic array and return it */
DynArray* array_new(int file_size){
DynArray
*array
= (DynArray
*)malloc(sizeof(DynArray
)); array->number_of_values = 0;
array->capacity = file_size / 10;
printf("capacity is %d " , array
->capacity
); array
->items
= (HashItem
**)malloc(sizeof(HashItem
*)* array
->capacity
); return array;
}
/*Method used to increase the size of the array and reallocate memory*/
void array_increase_if_full(DynArray *array){
if (array->number_of_values >= array->capacity){
array->capacity *= 1.25;
array
->items
= (HashItem
**)realloc(array
->items
, sizeof(HashItem
)*array
->capacity
); }
}
/*Method to add a string to the dynamic array specified */
void array_append(DynArray *array, HashItem *item){
array_increase_if_full(array);
array->items[array->number_of_values] = item;
//printf("item %s added \n at position %d ", array->items[array->number_of_values]->word, array->number_of_values);
array->number_of_values++;
}
/*Method used to get value at specified position for given array*/
HashItem *array_get(DynArray *array, int position){
if(position >= array->number_of_values || position <0){
printf("Index specified out of range"); }
//printf("item %s at position %d retrieved", array->items[position]->word, position);
return array->items[position];
}
HashItem **array_getarray(DynArray *array){
HashItem
**toreturn
= (HashItem
**)malloc(sizeof(HashItem
*) * (array
->number_of_values
)); int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
DynArray *readFile(char* file_path){
FILE *file;
file
= fopen(file_path
, "r"); if(file == NULL){
printf("Error opening file %s", file_path
); }
//Work out size of file and create hash table and array accordingly
fseek(file
, 0, SEEK_END
); int file_size
= ftell(file
); fseek(file
, 0, SEEK_SET
); //Create hash table assuming average word length is 3 (somewhat worst case) and
//add extra spaces to reduce collisions. Ensures hash table will not overflow at cost
//of some extra memory. More spaces also means less collisions so increases performance.
Hash* hash = hash_new((file_size/3)*1.25);
DynArray *array = array_new(file_size);
//String with memory allocation related to the longest word in english dictionary
int c;
int characters = 0;
int n = 0;
char *str
= (char*)malloc(45); while((c
= fgetc(file
)) != EOF
){ //Check if character is a ' or an alphabetic character
if ((c > 64 && c < 91) || (c > 96 && c < 123) || c == 39){
if(c > 64 && c < 91){
c += 32; //If character is upper case convert to lower
}
str[n] = c;
n++;
}else{
str[n] = '\0';
printf("String is : %s \n", str
); HashItem *temp_item = hash_update(hash, str);
//If update returns a HashItem it already exists therefore add HashItem to array
if(temp_item != NULL){
array_append(array, temp_item);
printf("String %s added! \n ", str
); //printf("Item : %s added \n", temp_item->word);
}else{
printf("String %s already exists, current count is %d \n", hash_get
(hash
, str
)->word
, hash_get
(hash
, str
)->occurences
); }
n = 0;
//allocate new memory for string
}
}
}
printf("\n \n HERE: %s SIZE : %d \n",array_get
(array
, 1)->word
, array
->number_of_values
); return array;
}
int compare_func(const void *a, const void *b)
{
HashItem
*aItem
= (HashItem
*)malloc (sizeof (HashItem
)); HashItem
*bItem
= (HashItem
*)malloc (sizeof (HashItem
));
memcpy (aItem
, a
, sizeof (HashItem
)); memcpy (bItem
, b
, sizeof (HashItem
));
int aCount = aItem->occurences;
int bCount = bItem->occurences;
printf("comparing %d to %d \n", aCount
, bCount
); return (aCount-bCount);
}
int main (int argc, char *argv[]) {
DynArray *array = readFile(argv[1]);
int n = array->number_of_values;
int i;
HashItem **standard_array = array_getarray(array);
for(i = 0; i < n; i++){
printf("%s : %d \n" , array_get
(array
, i
)->word
, array_get
(array
, i
)->occurences
); }
qsort(standard_array
, n
, sizeof(HashItem
*), compare_func
); for(n; n > 0; n--){
printf("Word : %s , occurences : %d \n", item_get_word
(standard_array
[n
]),item_get_occurences
(standard_array
[n
])); }
return 0;
}
I2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxzdGRpby5oPgoKLy9IQVNISVRFTQoKLypIb2xkcyB0aGUgd29yZCBhbmQgdGhlIG51bWJlciBvZiB0aW1lcyBpdCBoYXMgYXBwZWFyZWQgaW4gdGhlIGRvY3VtZW50ICovCnR5cGVkZWYgc3RydWN0IHsKCWNoYXIgKndvcmQ7CglpbnQgb2NjdXJlbmNlczsKfSBIYXNoSXRlbTsKCi8qIENyZWF0ZXMgYW5kIHJldHVybnMgYSBuZXcgSGFzaEl0ZW0gc3RydWN0ICovCkhhc2hJdGVtICppdGVtX25ldyhjaGFyICp3b3JkKXsKCUhhc2hJdGVtICppdGVtID0gKEhhc2hJdGVtKiltYWxsb2Moc2l6ZW9mKEhhc2hJdGVtKSk7CglpdGVtLT5vY2N1cmVuY2VzID0gMTsKCWludCBjaGFycyA9IHN0cmxlbih3b3JkKTsKCWl0ZW0tPndvcmQgPSAoY2hhciopbWFsbG9jKHNpemVvZihjaGFyKSAqIChjaGFycysxKSk7CglzdHJjcHkoaXRlbS0+d29yZCwgd29yZCk7CglyZXR1cm4gaXRlbTsKfQoKLyogR2V0IHRoZSB3b3JkIGNvbnRhaW50ZWQgd2l0aGluIHRoZSBwYXNzZWQgSGFzaEl0ZW0gKi8KY2hhciAqaXRlbV9nZXRfd29yZChIYXNoSXRlbSAqaXRlbSl7CglyZXR1cm4gaXRlbS0+d29yZDsKfQoKLyogR2V0IHRoZSBvY2N1cmVuY2VzIG9mIHRoZSBwYXNzZWQgSGFzaEl0ZW0gKi8KaW50IGl0ZW1fZ2V0X29jY3VyZW5jZXMoSGFzaEl0ZW0gKml0ZW0pewoJcmV0dXJuIGl0ZW0tPm9jY3VyZW5jZXM7Cn0KCi8qIEluY3JlbWVudCB0aGUgb2NjdXJlbmNlcyBvZiB0aGUgcGFzc2VkIEhhc2hJdGVtLCB1c2VkIHdoZW4gdGhlcmUgaXMgYSB2ZXJpZmllZCBjb2xsaXNpb24gKi8Kdm9pZCBpdGVtX2luY3JlbWVudF9vY2N1cmVuY2VzKEhhc2hJdGVtICppdGVtKXsKCWl0ZW0tPm9jY3VyZW5jZXMrKzsKfQoKCi8vSEFTSFRBQkxFCgovKiBIYXNodGFibGUgc3RydWN0IGhvbGRzIGFsbCB0aGUgSGFzaEl0ZW1zIGFuZCBhIG51bGwgaWYgdGhlcmUgaXMgbm8gSGFzaEl0ZW0gaW4gdGhlIHBvc2l0aW9uICovCnR5cGVkZWYgc3RydWN0IHsKCWludCBzaXplOwoJSGFzaEl0ZW0gKippdGVtczsKfSBIYXNoOwoKLyogQ3JlYXRlIGFuZCByZXR1cm4gYSBuZXcgSGFzaCBzdHJ1Y3QgKi8KSGFzaCAqaGFzaF9uZXcgKGludCBzaXplKSB7CglIYXNoICpoYXNoID0gKEhhc2gqKWNhbGxvYygxLCBzaXplb2YgKEhhc2gpKTsKCWhhc2gtPnNpemUgPSBzaXplOwoJaGFzaC0+aXRlbXMgPSAoSGFzaEl0ZW0qKiljYWxsb2Moc2l6ZSwgc2l6ZW9mIChIYXNoSXRlbSopKTsKCXJldHVybiBoYXNoOwp9CgovKiBIYXNoIGZ1bmN0aW9uIHVzZWQgdG8gYXNzaWduIGEgaW50ZWdlciB2YWx1ZSB0byBhIHdvcmQgKi8KaW50IGhhc2hfZnVuYyhjaGFyICp3b3JkLCBpbnQgbW9kKXsKCWludCBpID0gMDsgICAgIAoJaW50IHZhbHVlID0gMDsKCXdoaWxlKHdvcmRbaV0gIT0gJ1wwJyl7CgkJdmFsdWUgPSAoKHdvcmRbaV0gKiBpKSArIHZhbHVlKSAlIG1vZDsKCQlpKys7Cgl9CglyZXR1cm4gdmFsdWU7Cn0KCi8qIEdldCB0aGUgaW5kZXggdG8gcGxhY2UgYSBnaXZlbiB3b3JkIHdpdGhpbiB0aGUgcGFzc2VkIGhhc2ggdGFibGUgKi8KaW50IGhhc2hfaW5kZXggKEhhc2ggKmhhc2gsIGNoYXIgKndvcmQpIHsKCWludCBpbmRleCA9IGhhc2hfZnVuYyh3b3JkLCBoYXNoLT5zaXplKTsKCUhhc2hJdGVtICppdGVtID0gKGhhc2gtPml0ZW1zKVtpbmRleF07Cgl3aGlsZSAoaXRlbSl7CgkJaWYoIXN0cmNtcChpdGVtLT53b3JkLCB3b3JkKSl7CgkJCXByaW50Zigid29yZCAlcyBpcyBlcXVhbCB0byAlcyBcbiIsIGl0ZW0tPndvcmQsIHdvcmQgKTsKCQkJcmV0dXJuIGluZGV4OyAgICAgICAgICAgICAgICAgICAgICAgICAgCgkJfQoJCWluZGV4ID0gKGluZGV4ICsgMSkgJSBoYXNoLT5zaXplOwoJCWl0ZW0gPSBoYXNoLT5pdGVtc1tpbmRleF07Cgl9CglyZXR1cm4gaW5kZXg7Cn0KCi8qIFJldHVybnMgdGhlIEhhc2hpdGVtIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIHdvcmQgZ2l2ZW4sIG51bGwgaXMgcmV0dXJuZWQgaWYgaXQgaXMgbm90IGZvdW5kICovCkhhc2hJdGVtICpoYXNoX2dldCAoSGFzaCAqaGFzaCwgY2hhciAqd29yZCkgewoJaW50IGluZGV4ID0gaGFzaF9pbmRleChoYXNoLCB3b3JkKTsKCXJldHVybiBoYXNoLT5pdGVtc1tpbmRleF07Cn0KCi8qIFVwZGF0ZSB0aGUgcGFzc2VkIEhhc2hUYWJsZSB3aXRoIGEgZ2l2ZW4gd29yZCwgYWRkcyB0aGUgd29yZCBpZiBpdCBpcyBub3QgaW4gdGhlIHRhYmxlLCBpbmNyZW1lbnRzIHRoZQpjb3JyZXNwb25kaW5nIEhhc2hpdGVtJ3Mgb2NjdXJlbmNlIHZhbHVlIGlmIGl0IGlzLiAqLwpIYXNoSXRlbSAqaGFzaF91cGRhdGUgKEhhc2ggKmhhc2gsIGNoYXIgKndvcmQpIHsKCUhhc2hJdGVtICppdGVtID0gaGFzaF9nZXQoaGFzaCwgd29yZCk7CglpbnQgaW5kZXggPSBoYXNoX2luZGV4KGhhc2gsIHdvcmQpOwoJaWYoaXRlbSl7CgkJaXRlbS0+b2NjdXJlbmNlcysrOyAgICAKCQlyZXR1cm4gTlVMTDsKCX1lbHNlewoJCWludCBpbmRleCA9IGhhc2hfaW5kZXgoaGFzaCwgd29yZCk7CgkJaXRlbSA9IGl0ZW1fbmV3KHdvcmQpOwoJCWhhc2gtPml0ZW1zW2luZGV4XSA9IGl0ZW07CgkJcmV0dXJuIGl0ZW07Cgl9Cn0KCi8vRHluYW1pYyBBcnJheQoKLypEeW5BcnJheSBpcyBhIGR5bmFtaWNhbGx5IHJlc2l6aW5nIGFycmF5IHRoYXQgaXMgdXNlZCB0byBob2xkIHZhbHVlcyBhbmQgcmV0YWluIHNpemUgZGF0YSB0aHJvdWdob3V0Ki8KdHlwZWRlZiBzdHJ1Y3R7CglpbnQgbnVtYmVyX29mX3ZhbHVlczsKCWludCBjYXBhY2l0eTsKCUhhc2hJdGVtICoqaXRlbXM7Cn1EeW5BcnJheTsKCi8qTWV0aG9kIHRvIGNyZWF0ZSBhIG5ldyBkeW5hbWljIGFycmF5IGFuZCByZXR1cm4gaXQgKi8KRHluQXJyYXkqIGFycmF5X25ldyhpbnQgZmlsZV9zaXplKXsKCUR5bkFycmF5ICphcnJheSA9IChEeW5BcnJheSopbWFsbG9jKHNpemVvZihEeW5BcnJheSkpOwoJYXJyYXktPm51bWJlcl9vZl92YWx1ZXMgPSAwOwoJYXJyYXktPmNhcGFjaXR5ID0gZmlsZV9zaXplIC8gMTA7CglwcmludGYoImNhcGFjaXR5IGlzICVkICIgLCBhcnJheS0+Y2FwYWNpdHkpOwoJYXJyYXktPml0ZW1zID0gKEhhc2hJdGVtKiopbWFsbG9jKHNpemVvZihIYXNoSXRlbSopKiBhcnJheS0+Y2FwYWNpdHkpOwoJcmV0dXJuIGFycmF5Owp9CgovKk1ldGhvZCB1c2VkIHRvIGluY3JlYXNlIHRoZSBzaXplIG9mIHRoZSBhcnJheSBhbmQgcmVhbGxvY2F0ZSBtZW1vcnkqLwp2b2lkIGFycmF5X2luY3JlYXNlX2lmX2Z1bGwoRHluQXJyYXkgKmFycmF5KXsKCWlmIChhcnJheS0+bnVtYmVyX29mX3ZhbHVlcyA+PSBhcnJheS0+Y2FwYWNpdHkpewoJCWFycmF5LT5jYXBhY2l0eSAqPSAxLjI1OwoJCWFycmF5LT5pdGVtcyA9IChIYXNoSXRlbSoqKXJlYWxsb2MoYXJyYXktPml0ZW1zLCBzaXplb2YoSGFzaEl0ZW0pKmFycmF5LT5jYXBhY2l0eSk7Cgl9Cn0KCi8qTWV0aG9kIHRvIGFkZCBhIHN0cmluZyB0byB0aGUgZHluYW1pYyBhcnJheSBzcGVjaWZpZWQgKi8Kdm9pZCBhcnJheV9hcHBlbmQoRHluQXJyYXkgKmFycmF5LCBIYXNoSXRlbSAqaXRlbSl7CglhcnJheV9pbmNyZWFzZV9pZl9mdWxsKGFycmF5KTsKCWFycmF5LT5pdGVtc1thcnJheS0+bnVtYmVyX29mX3ZhbHVlc10gPSBpdGVtOwoJLy9wcmludGYoIml0ZW0gJXMgYWRkZWQgXG4gYXQgcG9zaXRpb24gJWQgIiwgYXJyYXktPml0ZW1zW2FycmF5LT5udW1iZXJfb2ZfdmFsdWVzXS0+d29yZCwgYXJyYXktPm51bWJlcl9vZl92YWx1ZXMpOwoJYXJyYXktPm51bWJlcl9vZl92YWx1ZXMrKzsKfQoKLypNZXRob2QgdXNlZCB0byBnZXQgdmFsdWUgYXQgc3BlY2lmaWVkIHBvc2l0aW9uIGZvciBnaXZlbiBhcnJheSovCkhhc2hJdGVtICphcnJheV9nZXQoRHluQXJyYXkgKmFycmF5LCBpbnQgcG9zaXRpb24pewoJaWYocG9zaXRpb24gPj0gYXJyYXktPm51bWJlcl9vZl92YWx1ZXMgfHwgcG9zaXRpb24gPDApewoJCXByaW50ZigiSW5kZXggc3BlY2lmaWVkIG91dCBvZiByYW5nZSIpOwoJCWV4aXQoMSk7Cgl9CgkvL3ByaW50ZigiaXRlbSAlcyBhdCBwb3NpdGlvbiAlZCByZXRyaWV2ZWQiLCBhcnJheS0+aXRlbXNbcG9zaXRpb25dLT53b3JkLCBwb3NpdGlvbik7CglyZXR1cm4gYXJyYXktPml0ZW1zW3Bvc2l0aW9uXTsKfQoKSGFzaEl0ZW0gKiphcnJheV9nZXRhcnJheShEeW5BcnJheSAqYXJyYXkpewoJSGFzaEl0ZW0gKip0b3JldHVybiA9IChIYXNoSXRlbSoqKW1hbGxvYyhzaXplb2YoSGFzaEl0ZW0qKSAqIChhcnJheS0+bnVtYmVyX29mX3ZhbHVlcykpOwoJaW50IGk7Cglmb3IoaSA9IDA7IGkgPCBhcnJheS0+bnVtYmVyX29mX3ZhbHVlczsgaSsrKXsKCQl0b3JldHVybltpXSA9IGFycmF5X2dldChhcnJheSwgaSk7Cgl9CglyZXR1cm4gdG9yZXR1cm47Cn0KCgpEeW5BcnJheSAqcmVhZEZpbGUoY2hhciogZmlsZV9wYXRoKXsKCUZJTEUgKmZpbGU7CglmaWxlID0gZm9wZW4oZmlsZV9wYXRoLCAiciIpOwoJaWYoZmlsZSA9PSBOVUxMKXsKCQlwcmludGYoIkVycm9yIG9wZW5pbmcgZmlsZSAlcyIsIGZpbGVfcGF0aCk7CgkJZXhpdCgxKTsgICAgICAgCgl9CgkvL1dvcmsgb3V0IHNpemUgb2YgZmlsZSBhbmQgY3JlYXRlIGhhc2ggdGFibGUgYW5kIGFycmF5IGFjY29yZGluZ2x5Cglmc2VlayhmaWxlLCAwLCBTRUVLX0VORCk7CglpbnQgZmlsZV9zaXplID0gZnRlbGwoZmlsZSk7Cglmc2VlayhmaWxlLCAwLCBTRUVLX1NFVCk7CgkvL0NyZWF0ZSBoYXNoIHRhYmxlIGFzc3VtaW5nIGF2ZXJhZ2Ugd29yZCBsZW5ndGggaXMgMyAoc29tZXdoYXQgd29yc3QgY2FzZSkgYW5kCgkvL2FkZCBleHRyYSBzcGFjZXMgdG8gcmVkdWNlIGNvbGxpc2lvbnMuIEVuc3VyZXMgaGFzaCB0YWJsZSB3aWxsIG5vdCBvdmVyZmxvdyBhdCBjb3N0CgkvL29mIHNvbWUgZXh0cmEgbWVtb3J5LiBNb3JlIHNwYWNlcyBhbHNvIG1lYW5zIGxlc3MgY29sbGlzaW9ucyBzbyBpbmNyZWFzZXMgcGVyZm9ybWFuY2UuCglIYXNoKiBoYXNoID0gaGFzaF9uZXcoKGZpbGVfc2l6ZS8zKSoxLjI1KTsKCUR5bkFycmF5ICphcnJheSA9IGFycmF5X25ldyhmaWxlX3NpemUpOwoKCS8vU3RyaW5nIHdpdGggbWVtb3J5IGFsbG9jYXRpb24gcmVsYXRlZCB0byB0aGUgbG9uZ2VzdCB3b3JkIGluIGVuZ2xpc2ggZGljdGlvbmFyeQoJaW50IGM7CglpbnQgY2hhcmFjdGVycyA9IDA7CglpbnQgbiA9IDA7CgljaGFyICpzdHIgPSAoY2hhciopbWFsbG9jKDQ1KTsKCXdoaWxlKChjID0gZmdldGMoZmlsZSkpICE9IEVPRil7CgkJLy9DaGVjayBpZiBjaGFyYWN0ZXIgaXMgYSAnIG9yIGFuIGFscGhhYmV0aWMgY2hhcmFjdGVyCgkJaWYgKChjID4gNjQgJiYgYyA8IDkxKSB8fCAoYyA+IDk2ICYmIGMgPCAxMjMpIHx8IGMgPT0gMzkpewoJCQlpZihjID4gNjQgJiYgYyA8IDkxKXsKCQkJCWMgKz0gMzI7IC8vSWYgY2hhcmFjdGVyIGlzIHVwcGVyIGNhc2UgY29udmVydCB0byBsb3dlcgoJCQl9CgkJCXN0cltuXSA9IGM7CgkJCW4rKzsKCQl9ZWxzZXsKCQkJc3RyW25dID0gJ1wwJzsKCQkJaWYoc3RyY21wKHN0ciwgIiIpKXsKCQkJCXByaW50ZigiU3RyaW5nIGlzIDogJXMgXG4iLCBzdHIpOyAgICAgICAgICAgCgkJCQlIYXNoSXRlbSAqdGVtcF9pdGVtID0gaGFzaF91cGRhdGUoaGFzaCwgc3RyKTsKCQkJCS8vSWYgdXBkYXRlIHJldHVybnMgYSBIYXNoSXRlbSBpdCBhbHJlYWR5IGV4aXN0cyB0aGVyZWZvcmUgYWRkIEhhc2hJdGVtIHRvIGFycmF5CgkJCQlpZih0ZW1wX2l0ZW0gIT0gTlVMTCl7CgkJCQkJYXJyYXlfYXBwZW5kKGFycmF5LCB0ZW1wX2l0ZW0pOwoJCQkJCXByaW50ZigiU3RyaW5nICVzIGFkZGVkISBcbiAiLCBzdHIpOwoJCQkJCS8vcHJpbnRmKCJJdGVtIDogJXMgYWRkZWQgXG4iLCB0ZW1wX2l0ZW0tPndvcmQpOwoJCQkJfWVsc2V7CgkJCQkJcHJpbnRmKCJTdHJpbmcgJXMgYWxyZWFkeSBleGlzdHMsIGN1cnJlbnQgY291bnQgaXMgJWQgXG4iLCBoYXNoX2dldChoYXNoLCBzdHIpLT53b3JkLCBoYXNoX2dldChoYXNoLCBzdHIpLT5vY2N1cmVuY2VzKTsKCQkJCX0KCQkJCW4gPSAwOwoJCQkJLy9hbGxvY2F0ZSBuZXcgbWVtb3J5IGZvciBzdHJpbmcKCQkJCXN0ciA9IChjaGFyKiltYWxsb2MoNDUpOwoJCQl9CgkJfQoJfQoJZmNsb3NlKGZpbGUpOwoJZnJlZShoYXNoKTsgICAgCglwcmludGYoIlxuIFxuIEhFUkU6ICVzICBTSVpFIDogJWQgXG4iLGFycmF5X2dldChhcnJheSwgMSktPndvcmQsIGFycmF5LT5udW1iZXJfb2ZfdmFsdWVzKTsKCXJldHVybiBhcnJheTsgICAgICAgICAgICAgICAgICAKfQoKaW50IGNvbXBhcmVfZnVuYyhjb25zdCB2b2lkICphLCBjb25zdCB2b2lkICpiKQp7CglIYXNoSXRlbSAqYUl0ZW0gPSAoSGFzaEl0ZW0qKW1hbGxvYyAoc2l6ZW9mIChIYXNoSXRlbSkpOwoJSGFzaEl0ZW0gKmJJdGVtID0gKEhhc2hJdGVtKiltYWxsb2MgKHNpemVvZiAoSGFzaEl0ZW0pKTsKCgltZW1jcHkgKGFJdGVtLCBhLCBzaXplb2YgKEhhc2hJdGVtKSk7CgltZW1jcHkgKGJJdGVtLCBiLCBzaXplb2YgKEhhc2hJdGVtKSk7CgoJaW50IGFDb3VudCA9IGFJdGVtLT5vY2N1cmVuY2VzOwoJaW50IGJDb3VudCA9IGJJdGVtLT5vY2N1cmVuY2VzOwoKCWZyZWUoYUl0ZW0pOwoJZnJlZShiSXRlbSk7CgoJcHJpbnRmKCJjb21wYXJpbmcgJWQgdG8gJWQgXG4iLCBhQ291bnQsIGJDb3VudCk7CglyZXR1cm4gKGFDb3VudC1iQ291bnQpOwp9CgppbnQgbWFpbiAoaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkgewoJRHluQXJyYXkgKmFycmF5ID0gcmVhZEZpbGUoYXJndlsxXSk7CglpbnQgbiA9IGFycmF5LT5udW1iZXJfb2ZfdmFsdWVzOwoJaW50IGk7CglIYXNoSXRlbSAqKnN0YW5kYXJkX2FycmF5ID0gYXJyYXlfZ2V0YXJyYXkoYXJyYXkpOwoJZm9yKGkgPSAwOyBpIDwgbjsgaSsrKXsKCQlwcmludGYoIiVzIDogJWQgXG4iICwgYXJyYXlfZ2V0KGFycmF5LCBpKS0+d29yZCwgYXJyYXlfZ2V0KGFycmF5LCBpKS0+b2NjdXJlbmNlcyk7Cgl9CglwcmludGYoInRyeWluZyB0byBzb3J0Iik7Cglxc29ydChzdGFuZGFyZF9hcnJheSwgbiwgc2l6ZW9mKEhhc2hJdGVtKiksIGNvbXBhcmVfZnVuYyk7CglwcmludGYoInNvcnRlZCIpOwoJZm9yKG47IG4gPiAwOyBuLS0pewoJCXByaW50ZigiV29yZCA6ICVzICwgb2NjdXJlbmNlcyA6ICVkIFxuIiwgaXRlbV9nZXRfd29yZChzdGFuZGFyZF9hcnJheVtuXSksaXRlbV9nZXRfb2NjdXJlbmNlcyhzdGFuZGFyZF9hcnJheVtuXSkpOwoJfQoJcmV0dXJuIDA7Cn0=