#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct DOCUMENT {
int id;
char* body;
struct DOCUMENT* next;
} DOCUMENT;
typedef struct ArrayList {
int count;
int size;
int* data;
} ArrayList;
typedef struct WordList {
char* word;
ArrayList* list;
struct WordList* next;
} WordList;
typedef struct Hashtable {
int size;
int count;
WordList** table;
} Hashtable;
void String_destroy(char* s) {
}
char* String_new(char* cs) {
char* s
= malloc(sizeof(char) * len
); if (s != NULL) {
}
return s;
}
void DOCUMENT_destroy(DOCUMENT* s) {
if (s->body != NULL) {
String_destroy(s->body);
}
if (s->next != NULL) {
DOCUMENT_destroy(s->next);
}
}
DOCUMENT* DOCUMENT_new(int id, char* body) {
DOCUMENT
* s
= malloc(sizeof(DOCUMENT
)); if (s != NULL) {
s->body = NULL;
s->next = NULL;
s->body = String_new(body);
if (s->body != NULL) {
s->id = id;
return s;
}
DOCUMENT_destroy(s);
}
return NULL;
}
int DOCUMENT_add(DOCUMENT** s, int id, char* body) {
DOCUMENT* n = DOCUMENT_new(id, body);
DOCUMENT* a = *s;
if (n != NULL) {
if (a == NULL) {
*s = n;
} else {
while (a->next != NULL) {
a = a->next;
}
a->next = n;
}
return 1;
}
return 0;
}
char* DOCUMENT_find(DOCUMENT* s, int id) {
while (s != NULL) {
if (s->id == id) {
return s->body;
}
s = s->next;
}
return NULL;
}
void ArrayList_destroy(ArrayList* s) {
}
ArrayList* ArrayList_new(void) {
ArrayList
* s
= malloc(sizeof(ArrayList
)); s
= malloc(sizeof(ArrayList
)); if (s != NULL) {
s->data = NULL;
s->count = 0;
s->size = 4;
s
->data
= malloc(sizeof(int) * s
->size
); if (s->data != NULL) {
return s;
}
}
ArrayList_destroy(s);
return NULL;
}
int ArrayList_add(ArrayList* s, int value) {
int* data;
if (s->count >= s->size) {
s->size = s->size * 2;
data
= realloc(s
->data
, sizeof(int) * s
->size
); if (data == NULL) {
return 0;
}
s->data = data;
}
s->data[s->count] = value;
s->count = s->count + 1;
return 1;
}
void ArrayList_print(ArrayList* s) {
int i;
for (i = 0; i < s->count; i++) {
}
}
void ArrayList_clear(ArrayList* s) {
s->count = 0;
}
void ArrayList_intersect(ArrayList* s, ArrayList* m) {
int i = 0;
int j = 0;
int n = 0;
while (i < s->count) {
if (j >= m->count) {
break;
}
if (s->data[i] < m->data[j]) {
i++;
} else if (s->data[i] > m->data[j]) {
j++;
} else {
s->data[n] = s->data[i];
i++;
j++;
n++;
}
}
s->count = n;
}
void ArrayList_distinct(ArrayList* s) {
int i;
int j;
int c = s->count;
int* data = s->data;
for (i = 1; i < c; i++) {
if (data[i - 1] == data[i]) {
for (j = i + 1; j < c; j++) {
if (data[j - 1] != data[j]) {
data[i] = data[j];
i = i + 1;
}
}
s->count = i;
return;
}
}
}
void WordList_destroy(WordList* s) {
if (s->word != NULL) {
String_destroy(s->word);
}
if (s->list != NULL) {
ArrayList_destroy(s->list);
}
if (s->next != NULL) {
WordList_destroy(s->next);
}
}
WordList* WordList_new(char* word, int id, WordList* next) {
WordList
* s
= malloc(sizeof(WordList
)); if (s != NULL) {
s->word = NULL;
s->list = NULL;
s->next = next;
s->word = String_new(word);
if (s->word != NULL) {
s->list = ArrayList_new();
if (s->list != NULL) {
if (ArrayList_add(s->list, id)) {
return s;
}
}
}
}
WordList_destroy(s);
return NULL;
}
void Hashtable_destroy(Hashtable* s) {
}
Hashtable* Hashtable_new(void) {
int i;
Hashtable
* s
= malloc(sizeof(Hashtable
)); if (s != NULL) {
s->table = NULL;
s->count = 0;
s->size = 65521;
s
->table
= malloc(sizeof(WordList
*) * s
->size
); if (s->table != NULL) {
for (i = 0; i < s->size; i++) {
s->table[i] = NULL;
}
return s;
}
}
Hashtable_destroy(s);
return NULL;
}
unsigned int Hashtable_hash(Hashtable* s, char* c)
{
unsigned int hashval;
for (hashval = 0; *c != '\0'; c++)
hashval = *c + (31 * hashval);
return hashval % s->size;
}
ArrayList* Hashtable_find(Hashtable* s, char* word) {
unsigned int hash = Hashtable_hash(s, word);
WordList* a = s->table[hash];
while (a != NULL) {
if (strcmp(a
->word
, word
) == 0) { return a->list;
}
a = a->next;
}
return NULL;
}
int Hashtable_insert(Hashtable* s, char* word, int id) {
unsigned int hash = Hashtable_hash(s, word);
WordList* n = WordList_new(word, id, s->table[hash]);
if (n != NULL) {
s->table[hash] = n;
return 1;
}
return 0;
}
int Hashtable_add(Hashtable* s, char* word, int id) {
ArrayList* a = Hashtable_find(s, word);
if (a != NULL) {
if (ArrayList_add(a, id)) {
return 1;
}
} else {
if (Hashtable_insert(s, word, id)) {
s->count = s->count + 1;
return 1;
}
}
return 0;
}
DOCUMENT* use_file(FILE* f) {
char row[65536];
DOCUMENT* d = NULL;
int i = 0;
while (fgets(row
, 65536, f
) != NULL
) { if (!DOCUMENT_add(&d, i, row)) {
if (d != NULL) {
DOCUMENT_destroy(d);
}
return NULL;
}
i = i + 1;
}
return d;
}
DOCUMENT* create_document(char* filename) {
DOCUMENT* d = NULL;
FILE
* f
= fopen(filename
, "r"); if (f != NULL) {
d = use_file(f);
}
return d;
}
int add_words(int id, char* words, Hashtable* hash) {
char ws[65536];
char* w;
while (w != NULL) {
if (!Hashtable_add(hash, w, id)) {
return 0;
}
}
return 1;
}
Hashtable* create_hashtable(DOCUMENT* docs) {
Hashtable* h = Hashtable_new();
if (h != NULL) {
while (docs != NULL) {
if (!add_words(docs->id, docs->body, h)) {
Hashtable_destroy(h);
return NULL;
}
docs = docs->next;
}
}
return h;
}
ArrayList* execute_query(Hashtable* h) {
char row[65536];
char* w;
int i;
ArrayList* a = ArrayList_new();
ArrayList* b;
if (a != NULL) {
fgets(row
, 65536, stdin
); if (w != NULL) {
b = Hashtable_find(h, w);
if (b != NULL) {
for (i = 0; i < b->count; i++) {
if (!ArrayList_add(a, b->data[i])) {
ArrayList_destroy(a);
return NULL;
}
}
while (1) {
if (w == NULL) {
break;
}
b = Hashtable_find(h, w);
if (b == NULL) {
ArrayList_clear(a);
break;
}
ArrayList_intersect(a, b);
}
ArrayList_distinct(a);
}
}
}
return a;
}
int main(int argc, char* argv[]) {
int i;
ArrayList* list = NULL;
Hashtable* hash = NULL;
DOCUMENT* doc = NULL;
char* filename;
if (argc < 3) {
return 1;
}
if (strcmp(argv
[1], "-f") != 0) { return 1;
}
filename = argv[2];
doc = create_document(filename);
if (doc != NULL) {
hash = create_hashtable(doc);
if (hash != NULL) {
printf("Total number of words in the index = %d\n", hash
->count
); printf("john = %d\n", Hashtable_find
(hash
, "john")->count
); printf("and = %d\n", Hashtable_find
(hash
, "and")->count
); printf("said = %d\n", Hashtable_find
(hash
, "said")->count
); list = execute_query(hash);
if (list != NULL) {
if (list->count < 1) {
} else {
for (i = 0; i < list->count; i++) {
printf("%d\n", list
->data
[i
]); printf("%s\n", DOCUMENT_find
(doc
, list
->data
[i
])); }
}
}
}
}
if (list != NULL) {
ArrayList_destroy(list);
}
if (hash != NULL) {
Hashtable_destroy(hash);
}
if (doc != NULL) {
DOCUMENT_destroy(doc);
}
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgoKdHlwZWRlZiBzdHJ1Y3QgRE9DVU1FTlQgewogICBpbnQgaWQ7CiAgIGNoYXIqIGJvZHk7CiAgIHN0cnVjdCBET0NVTUVOVCogbmV4dDsKfSBET0NVTUVOVDsKCnR5cGVkZWYgc3RydWN0IEFycmF5TGlzdCB7CiAgIGludCBjb3VudDsKICAgaW50IHNpemU7CiAgIGludCogZGF0YTsKfSBBcnJheUxpc3Q7Cgp0eXBlZGVmIHN0cnVjdCBXb3JkTGlzdCB7CiAgIGNoYXIqIHdvcmQ7CiAgIEFycmF5TGlzdCogbGlzdDsKICAgc3RydWN0IFdvcmRMaXN0KiBuZXh0Owp9IFdvcmRMaXN0OwoKdHlwZWRlZiBzdHJ1Y3QgSGFzaHRhYmxlIHsKICAgaW50IHNpemU7CiAgIGludCBjb3VudDsKICAgV29yZExpc3QqKiB0YWJsZTsKfSBIYXNodGFibGU7Cgp2b2lkIFN0cmluZ19kZXN0cm95KGNoYXIqIHMpIHsKICAgZnJlZShzKTsKfQoKY2hhciogU3RyaW5nX25ldyhjaGFyKiBjcykgewogICBpbnQgbGVuID0gc3RybGVuKGNzKSArIDE7CiAgIGNoYXIqIHMgPSBtYWxsb2Moc2l6ZW9mKGNoYXIpICogbGVuKTsKICAgaWYgKHMgIT0gTlVMTCkgewogICAgICBtZW1jcHkocywgY3MsIGxlbik7CiAgIH0KICAgcmV0dXJuIHM7Cn0KCnZvaWQgRE9DVU1FTlRfZGVzdHJveShET0NVTUVOVCogcykgewogICBpZiAocy0+Ym9keSAhPSBOVUxMKSB7CiAgICAgIFN0cmluZ19kZXN0cm95KHMtPmJvZHkpOwogICB9CiAgIGlmIChzLT5uZXh0ICE9IE5VTEwpIHsKICAgICAgRE9DVU1FTlRfZGVzdHJveShzLT5uZXh0KTsKICAgfQogICBmcmVlKHMpOwp9CgpET0NVTUVOVCogRE9DVU1FTlRfbmV3KGludCBpZCwgY2hhciogYm9keSkgewogICBET0NVTUVOVCogcyA9IG1hbGxvYyhzaXplb2YoRE9DVU1FTlQpKTsKICAgaWYgKHMgIT0gTlVMTCkgewogICAgICBzLT5ib2R5ID0gTlVMTDsKICAgICAgcy0+bmV4dCA9IE5VTEw7CiAgICAgIAogICAgICBzLT5ib2R5ID0gU3RyaW5nX25ldyhib2R5KTsKICAgICAgaWYgKHMtPmJvZHkgIT0gTlVMTCkgewogICAgICAgICBzLT5pZCA9IGlkOwogICAgICAgICByZXR1cm4gczsKICAgICAgfQogICAgICBET0NVTUVOVF9kZXN0cm95KHMpOwogICB9CiAgIHJldHVybiBOVUxMOwp9CgppbnQgRE9DVU1FTlRfYWRkKERPQ1VNRU5UKiogcywgaW50IGlkLCBjaGFyKiBib2R5KSB7CiAgIERPQ1VNRU5UKiBuID0gRE9DVU1FTlRfbmV3KGlkLCBib2R5KTsKICAgRE9DVU1FTlQqIGEgPSAqczsKICAgaWYgKG4gIT0gTlVMTCkgewogICAgICBpZiAoYSA9PSBOVUxMKSB7CiAgICAgICAgICpzID0gbjsKICAgICAgfSBlbHNlIHsKICAgICAgICAgd2hpbGUgKGEtPm5leHQgIT0gTlVMTCkgewogICAgICAgICAgICBhID0gYS0+bmV4dDsKICAgICAgICAgfQogICAgICAgICBhLT5uZXh0ID0gbjsKICAgICAgfQogICAgICByZXR1cm4gMTsKICAgfQogICByZXR1cm4gMDsKfQoKY2hhciogRE9DVU1FTlRfZmluZChET0NVTUVOVCogcywgaW50IGlkKSB7CiAgIHdoaWxlIChzICE9IE5VTEwpIHsKICAgICAgaWYgKHMtPmlkID09IGlkKSB7CiAgICAgICAgIHJldHVybiBzLT5ib2R5OwogICAgICB9CiAgICAgIHMgPSBzLT5uZXh0OwogICB9CiAgIHJldHVybiBOVUxMOwp9Cgp2b2lkIEFycmF5TGlzdF9kZXN0cm95KEFycmF5TGlzdCogcykgewogICBmcmVlKHMtPmRhdGEpOwogICBmcmVlKHMpOwp9CgpBcnJheUxpc3QqIEFycmF5TGlzdF9uZXcodm9pZCkgewogICBBcnJheUxpc3QqIHMgPSBtYWxsb2Moc2l6ZW9mKEFycmF5TGlzdCkpOwogICBzID0gbWFsbG9jKHNpemVvZihBcnJheUxpc3QpKTsKICAgaWYgKHMgIT0gTlVMTCkgewogICAgICBzLT5kYXRhID0gTlVMTDsKICAgICAgCiAgICAgIHMtPmNvdW50ID0gMDsKICAgICAgcy0+c2l6ZSA9IDQ7CiAgICAgIHMtPmRhdGEgPSBtYWxsb2Moc2l6ZW9mKGludCkgKiBzLT5zaXplKTsKICAgICAgaWYgKHMtPmRhdGEgIT0gTlVMTCkgewogICAgICAgICByZXR1cm4gczsKICAgICAgfQogICB9CiAgIEFycmF5TGlzdF9kZXN0cm95KHMpOwogICByZXR1cm4gTlVMTDsKfQoKaW50IEFycmF5TGlzdF9hZGQoQXJyYXlMaXN0KiBzLCBpbnQgdmFsdWUpIHsKICAgaW50KiBkYXRhOwogICBpZiAocy0+Y291bnQgPj0gcy0+c2l6ZSkgewogICAgICBzLT5zaXplID0gcy0+c2l6ZSAqIDI7CiAgICAgIGRhdGEgPSByZWFsbG9jKHMtPmRhdGEsIHNpemVvZihpbnQpICogcy0+c2l6ZSk7CiAgICAgIGlmIChkYXRhID09IE5VTEwpIHsKICAgICAgICAgcmV0dXJuIDA7CiAgICAgIH0KICAgICAgcy0+ZGF0YSA9IGRhdGE7CiAgIH0KICAgcy0+ZGF0YVtzLT5jb3VudF0gPSB2YWx1ZTsKICAgcy0+Y291bnQgPSBzLT5jb3VudCArIDE7CiAgIHJldHVybiAxOwp9Cgp2b2lkIEFycmF5TGlzdF9wcmludChBcnJheUxpc3QqIHMpIHsKICAgaW50IGk7CiAgIGZvciAoaSA9IDA7IGkgPCBzLT5jb3VudDsgaSsrKSB7CiAgICAgIHByaW50ZigiJWRcbiIsIHMtPmRhdGFbaV0pOwogICB9Cn0KCnZvaWQgQXJyYXlMaXN0X2NsZWFyKEFycmF5TGlzdCogcykgewogICBzLT5jb3VudCA9IDA7Cn0KCnZvaWQgQXJyYXlMaXN0X2ludGVyc2VjdChBcnJheUxpc3QqIHMsIEFycmF5TGlzdCogbSkgewogICBpbnQgaSA9IDA7CiAgIGludCBqID0gMDsKICAgaW50IG4gPSAwOwogICB3aGlsZSAoaSA8IHMtPmNvdW50KSB7CiAgICAgIGlmIChqID49IG0tPmNvdW50KSB7CiAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChzLT5kYXRhW2ldIDwgbS0+ZGF0YVtqXSkgewogICAgICAgICBpKys7CiAgICAgIH0gZWxzZSBpZiAocy0+ZGF0YVtpXSA+IG0tPmRhdGFbal0pIHsKICAgICAgICAgaisrOwogICAgICB9IGVsc2UgewogICAgICAgICBzLT5kYXRhW25dID0gcy0+ZGF0YVtpXTsKICAgICAgICAgaSsrOwogICAgICAgICBqKys7CiAgICAgICAgIG4rKzsKICAgICAgfQogICB9CiAgIHMtPmNvdW50ID0gbjsKfQoKdm9pZCBBcnJheUxpc3RfZGlzdGluY3QoQXJyYXlMaXN0KiBzKSB7CiAgIGludCBpOwogICBpbnQgajsKICAgaW50IGMgPSBzLT5jb3VudDsKICAgaW50KiBkYXRhID0gcy0+ZGF0YTsKICAgZm9yIChpID0gMTsgaSA8IGM7IGkrKykgewogICAgICBpZiAoZGF0YVtpIC0gMV0gPT0gZGF0YVtpXSkgewogICAgICAgICBmb3IgKGogPSBpICsgMTsgaiA8IGM7IGorKykgewogICAgICAgICAgICBpZiAoZGF0YVtqIC0gMV0gIT0gZGF0YVtqXSkgewogICAgICAgICAgICAgICBkYXRhW2ldID0gZGF0YVtqXTsKICAgICAgICAgICAgICAgaSA9IGkgKyAxOwogICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgICAgcy0+Y291bnQgPSBpOwogICAgICAgICByZXR1cm47CiAgICAgIH0KICAgfQp9Cgp2b2lkIFdvcmRMaXN0X2Rlc3Ryb3koV29yZExpc3QqIHMpIHsKICAgaWYgKHMtPndvcmQgIT0gTlVMTCkgewogICAgICBTdHJpbmdfZGVzdHJveShzLT53b3JkKTsKICAgfQogICBpZiAocy0+bGlzdCAhPSBOVUxMKSB7CiAgICAgIEFycmF5TGlzdF9kZXN0cm95KHMtPmxpc3QpOwogICB9CiAgIGlmIChzLT5uZXh0ICE9IE5VTEwpIHsKICAgICAgV29yZExpc3RfZGVzdHJveShzLT5uZXh0KTsKICAgfQogICBmcmVlKHMpOwp9CgpXb3JkTGlzdCogV29yZExpc3RfbmV3KGNoYXIqIHdvcmQsIGludCBpZCwgV29yZExpc3QqIG5leHQpIHsKICAgV29yZExpc3QqIHMgPSBtYWxsb2Moc2l6ZW9mKFdvcmRMaXN0KSk7CiAgIGlmIChzICE9IE5VTEwpIHsKICAgICAgcy0+d29yZCA9IE5VTEw7CiAgICAgIHMtPmxpc3QgPSBOVUxMOwogICAgICBzLT5uZXh0ID0gbmV4dDsKICAgICAgCiAgICAgIHMtPndvcmQgPSBTdHJpbmdfbmV3KHdvcmQpOwogICAgICBpZiAocy0+d29yZCAhPSBOVUxMKSB7CiAgICAgICAgIHMtPmxpc3QgPSBBcnJheUxpc3RfbmV3KCk7CiAgICAgICAgIGlmIChzLT5saXN0ICE9IE5VTEwpIHsKICAgICAgICAgICAgaWYgKEFycmF5TGlzdF9hZGQocy0+bGlzdCwgaWQpKSB7CiAgICAgICAgICAgICAgIHJldHVybiBzOwogICAgICAgICAgICB9CiAgICAgICAgIH0KICAgICAgfQogICB9CiAgIFdvcmRMaXN0X2Rlc3Ryb3kocyk7CiAgIHJldHVybiBOVUxMOwp9Cgp2b2lkIEhhc2h0YWJsZV9kZXN0cm95KEhhc2h0YWJsZSogcykgewogICBmcmVlKHMtPnRhYmxlKTsKICAgZnJlZShzKTsKfQoKSGFzaHRhYmxlKiBIYXNodGFibGVfbmV3KHZvaWQpIHsKICAgaW50IGk7CiAgIEhhc2h0YWJsZSogcyA9IG1hbGxvYyhzaXplb2YoSGFzaHRhYmxlKSk7CiAgIGlmIChzICE9IE5VTEwpIHsKICAgICAgcy0+dGFibGUgPSBOVUxMOwogICAgICAKICAgICAgcy0+Y291bnQgPSAwOwogICAgICBzLT5zaXplID0gNjU1MjE7CiAgICAgIHMtPnRhYmxlID0gbWFsbG9jKHNpemVvZihXb3JkTGlzdCopICogcy0+c2l6ZSk7CiAgICAgIGlmIChzLT50YWJsZSAhPSBOVUxMKSB7CiAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzLT5zaXplOyBpKyspIHsKICAgICAgICAgICAgcy0+dGFibGVbaV0gPSBOVUxMOwogICAgICAgICB9CiAgICAgICAgIHJldHVybiBzOwogICAgICB9CiAgIH0KICAgSGFzaHRhYmxlX2Rlc3Ryb3kocyk7CiAgIHJldHVybiBOVUxMOwp9Cgp1bnNpZ25lZCBpbnQgSGFzaHRhYmxlX2hhc2goSGFzaHRhYmxlKiBzLCBjaGFyKiBjKQp7CiAgIHVuc2lnbmVkIGludCBoYXNodmFsOwogICBmb3IgKGhhc2h2YWwgPSAwOyAqYyAhPSAnXDAnOyBjKyspCiAgICAgIGhhc2h2YWwgPSAqYyArICgzMSAqIGhhc2h2YWwpOwogICByZXR1cm4gaGFzaHZhbCAlIHMtPnNpemU7Cn0KCkFycmF5TGlzdCogSGFzaHRhYmxlX2ZpbmQoSGFzaHRhYmxlKiBzLCBjaGFyKiB3b3JkKSB7CiAgIHVuc2lnbmVkIGludCBoYXNoID0gSGFzaHRhYmxlX2hhc2gocywgd29yZCk7CiAgIFdvcmRMaXN0KiBhID0gcy0+dGFibGVbaGFzaF07CiAgIHdoaWxlIChhICE9IE5VTEwpIHsKICAgICAgaWYgKHN0cmNtcChhLT53b3JkLCB3b3JkKSA9PSAwKSB7CiAgICAgICAgIHJldHVybiBhLT5saXN0OwogICAgICB9CiAgICAgIGEgPSBhLT5uZXh0OwogICB9CiAgIHJldHVybiBOVUxMOwp9CgppbnQgSGFzaHRhYmxlX2luc2VydChIYXNodGFibGUqIHMsIGNoYXIqIHdvcmQsIGludCBpZCkgewogICB1bnNpZ25lZCBpbnQgaGFzaCA9IEhhc2h0YWJsZV9oYXNoKHMsIHdvcmQpOwogICBXb3JkTGlzdCogbiA9IFdvcmRMaXN0X25ldyh3b3JkLCBpZCwgcy0+dGFibGVbaGFzaF0pOwogICBpZiAobiAhPSBOVUxMKSB7CiAgICAgIHMtPnRhYmxlW2hhc2hdID0gbjsKICAgICAgcmV0dXJuIDE7CiAgIH0KICAgcmV0dXJuIDA7Cn0KCmludCBIYXNodGFibGVfYWRkKEhhc2h0YWJsZSogcywgY2hhciogd29yZCwgaW50IGlkKSB7CiAgIEFycmF5TGlzdCogYSA9IEhhc2h0YWJsZV9maW5kKHMsIHdvcmQpOwogICBpZiAoYSAhPSBOVUxMKSB7CiAgICAgIGlmIChBcnJheUxpc3RfYWRkKGEsIGlkKSkgewogICAgICAgICByZXR1cm4gMTsKICAgICAgfQogICB9IGVsc2UgewogICAgICBpZiAoSGFzaHRhYmxlX2luc2VydChzLCB3b3JkLCBpZCkpIHsKICAgICAgICAgcy0+Y291bnQgPSBzLT5jb3VudCArIDE7CiAgICAgICAgIHJldHVybiAxOwogICAgICB9CiAgIH0KICAgcmV0dXJuIDA7Cn0KCkRPQ1VNRU5UKiB1c2VfZmlsZShGSUxFKiBmKSB7CiAgIGNoYXIgcm93WzY1NTM2XTsKICAgRE9DVU1FTlQqIGQgPSBOVUxMOwogICBpbnQgaSA9IDA7CiAgIHdoaWxlIChmZ2V0cyhyb3csIDY1NTM2LCBmKSAhPSBOVUxMKSB7CiAgICAgIHJvd1tzdHJsZW4ocm93KSAtIDFdID0gJ1wwJzsKICAgICAgaWYgKCFET0NVTUVOVF9hZGQoJmQsIGksIHJvdykpIHsKICAgICAgICAgaWYgKGQgIT0gTlVMTCkgewogICAgICAgICAgICBET0NVTUVOVF9kZXN0cm95KGQpOwogICAgICAgICB9CiAgICAgICAgIHJldHVybiBOVUxMOwogICAgICB9CiAgICAgIGkgPSBpICsgMTsKICAgfQogICByZXR1cm4gZDsKfQoKRE9DVU1FTlQqIGNyZWF0ZV9kb2N1bWVudChjaGFyKiBmaWxlbmFtZSkgewogICBET0NVTUVOVCogZCA9IE5VTEw7CiAgIEZJTEUqIGYgPSBmb3BlbihmaWxlbmFtZSwgInIiKTsKICAgaWYgKGYgIT0gTlVMTCkgewogICAgICBkID0gdXNlX2ZpbGUoZik7CiAgICAgIGZjbG9zZShmKTsKICAgfQogICByZXR1cm4gZDsKfQoKaW50IGFkZF93b3JkcyhpbnQgaWQsIGNoYXIqIHdvcmRzLCBIYXNodGFibGUqIGhhc2gpIHsKICAgY2hhciB3c1s2NTUzNl07CiAgIGNoYXIqIHc7CiAgIHN0cmNweSh3cywgd29yZHMpOwogICB3ID0gc3RydG9rKHdzLCAiIFx0XG4iKTsKICAgd2hpbGUgKHcgIT0gTlVMTCkgewogICAgICBpZiAoIUhhc2h0YWJsZV9hZGQoaGFzaCwgdywgaWQpKSB7CiAgICAgICAgIHJldHVybiAwOwogICAgICB9CiAgICAgIHcgPSBzdHJ0b2soTlVMTCwgIiBcdFxuIik7CiAgIH0KICAgcmV0dXJuIDE7Cn0KCkhhc2h0YWJsZSogY3JlYXRlX2hhc2h0YWJsZShET0NVTUVOVCogZG9jcykgewogICBIYXNodGFibGUqIGggPSBIYXNodGFibGVfbmV3KCk7CiAgIGlmIChoICE9IE5VTEwpIHsKICAgICAgd2hpbGUgKGRvY3MgIT0gTlVMTCkgewogICAgICAgICBpZiAoIWFkZF93b3Jkcyhkb2NzLT5pZCwgZG9jcy0+Ym9keSwgaCkpIHsKICAgICAgICAgICAgSGFzaHRhYmxlX2Rlc3Ryb3koaCk7CiAgICAgICAgICAgIHJldHVybiBOVUxMOwogICAgICAgICB9CiAgICAgICAgIGRvY3MgPSBkb2NzLT5uZXh0OwogICAgICB9CiAgIH0KICAgcmV0dXJuIGg7Cn0KCkFycmF5TGlzdCogZXhlY3V0ZV9xdWVyeShIYXNodGFibGUqIGgpIHsKICAgY2hhciByb3dbNjU1MzZdOwogICBjaGFyKiB3OwogICBpbnQgaTsKICAgQXJyYXlMaXN0KiBhID0gQXJyYXlMaXN0X25ldygpOwogICBBcnJheUxpc3QqIGI7CiAgIGlmIChhICE9IE5VTEwpIHsKICAgICAgcHJpbnRmKCJFbnRlciBRdWVyeToiKTsKICAgICAgZmdldHMocm93LCA2NTUzNiwgc3RkaW4pOwogICAgICB3ID0gc3RydG9rKHJvdywgIiBcdFxuIik7CiAgICAgIGlmICh3ICE9IE5VTEwpIHsKICAgICAgICAgYiA9IEhhc2h0YWJsZV9maW5kKGgsIHcpOwogICAgICAgICBpZiAoYiAhPSBOVUxMKSB7CiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBiLT5jb3VudDsgaSsrKSB7CiAgICAgICAgICAgICAgIGlmICghQXJyYXlMaXN0X2FkZChhLCBiLT5kYXRhW2ldKSkgewogICAgICAgICAgICAgICAgICBBcnJheUxpc3RfZGVzdHJveShhKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuIE5VTEw7CiAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICB3aGlsZSAoMSkgewogICAgICAgICAgICAgICB3ID0gc3RydG9rKE5VTEwsICIgXHRcbiIpOwogICAgICAgICAgICAgICBpZiAodyA9PSBOVUxMKSB7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgIGIgPSBIYXNodGFibGVfZmluZChoLCB3KTsKICAgICAgICAgICAgICAgaWYgKGIgPT0gTlVMTCkgewogICAgICAgICAgICAgICAgICBBcnJheUxpc3RfY2xlYXIoYSk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgIEFycmF5TGlzdF9pbnRlcnNlY3QoYSwgYik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgQXJyYXlMaXN0X2Rpc3RpbmN0KGEpOwogICAgICAgICB9CiAgICAgIH0KICAgfQogICByZXR1cm4gYTsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqIGFyZ3ZbXSkgewogICBpbnQgaTsKICAgQXJyYXlMaXN0KiBsaXN0ID0gTlVMTDsKICAgSGFzaHRhYmxlKiBoYXNoID0gTlVMTDsKICAgRE9DVU1FTlQqIGRvYyA9IE5VTEw7CiAgIGNoYXIqIGZpbGVuYW1lOwogICAKICAgaWYgKGFyZ2MgPCAzKSB7CiAgICAgIHJldHVybiAxOwogICB9CiAgIGlmIChzdHJjbXAoYXJndlsxXSwgIi1mIikgIT0gMCkgewogICAgICByZXR1cm4gMTsKICAgfQogICAKICAgZmlsZW5hbWUgPSBhcmd2WzJdOwogICAKICAgZG9jID0gY3JlYXRlX2RvY3VtZW50KGZpbGVuYW1lKTsKICAgaWYgKGRvYyAhPSBOVUxMKSB7CiAgICAgIGhhc2ggPSBjcmVhdGVfaGFzaHRhYmxlKGRvYyk7CiAgICAgIGlmIChoYXNoICE9IE5VTEwpIHsKICAgICAgICAgcHJpbnRmKCJUb3RhbCBudW1iZXIgb2Ygd29yZHMgaW4gdGhlIGluZGV4ID0gJWRcbiIsIGhhc2gtPmNvdW50KTsKICAgICAgICAgcHJpbnRmKCJqb2huID0gJWRcbiIsIEhhc2h0YWJsZV9maW5kKGhhc2gsICJqb2huIiktPmNvdW50KTsKICAgICAgICAgcHJpbnRmKCJhbmQgPSAlZFxuIiwgSGFzaHRhYmxlX2ZpbmQoaGFzaCwgImFuZCIpLT5jb3VudCk7CiAgICAgICAgIHByaW50Zigic2FpZCA9ICVkXG4iLCBIYXNodGFibGVfZmluZChoYXNoLCAic2FpZCIpLT5jb3VudCk7CiAgICAgICAgIGxpc3QgPSBleGVjdXRlX3F1ZXJ5KGhhc2gpOwogICAgICAgICBpZiAobGlzdCAhPSBOVUxMKSB7CiAgICAgICAgICAgIGlmIChsaXN0LT5jb3VudCA8IDEpIHsKICAgICAgICAgICAgICAgcHJpbnRmKCJ3b3JkcyBub3QgZm91bmRcbiIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC0+Y291bnQ7IGkrKykgewogICAgICAgICAgICAgICAgICBwcmludGYoIiVkXG4iLCBsaXN0LT5kYXRhW2ldKTsKICAgICAgICAgICAgICAgICAgcHJpbnRmKCIlc1xuIiwgRE9DVU1FTlRfZmluZChkb2MsIGxpc3QtPmRhdGFbaV0pKTsKICAgICAgICAgICAgICAgICAgcHJpbnRmKCJcbiIpOwogICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgfQogICAgICB9CiAgIH0KICAgCiAgIGlmIChsaXN0ICE9IE5VTEwpIHsKICAgICAgQXJyYXlMaXN0X2Rlc3Ryb3kobGlzdCk7CiAgIH0KICAgaWYgKGhhc2ggIT0gTlVMTCkgewogICAgICBIYXNodGFibGVfZGVzdHJveShoYXNoKTsKICAgfQogICBpZiAoZG9jICE9IE5VTEwpIHsKICAgICAgRE9DVU1FTlRfZGVzdHJveShkb2MpOwogICB9CiAgIAogICByZXR1cm4gMDsKfQo=