#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
/* ==================== Input Data ==================== */
#define TOTAL_ITEMS 20
#define TOTAL_MODULES 5
#define MH_ITER 1000
#define MH_ALPHA 1.0
// Table 1: Mean Information for Items Across Modules (H22)
double mean_info[TOTAL_ITEMS][TOTAL_MODULES] = {
{0.0551342205, 1.1229549861, 1.0746550402, 0.273644702, 0.3789612651}, // Item_1
{1.5159051325, 0.9547912017, 0.6838172809, 0.729615083, 1.3183586369}, // Item_2
{0.4263425097, 0.4009858961, 0.1942834514, 1.9686943023, 1.9678124012}, // Item_3
{1.3914179336, 1.9653292177, 1.6987745520, 1.276778025, 0.0037878142}, // Item_4
{0.3729225141, 1.4446974322, 1.1962628849, 0.2984828125, 0.8939753608}, // Item_5
{0.0912230066, 1.3080023215, 1.4472607197, 0.0348708527, 0.6183642983}, // Item_6
{0.7302597184, 1.1067225309, 1.7269795015, 1.3609462492, 0.8742362978}, // Item_7
{0.7628315771, 0.90299008, 0.5567556787, 0.0081749232, 0.6736855884}, // Item_8
{0.5476417858, 0.7755998513, 1.3814817402, 1.5209261049, 1.1303703147}, // Item_9
{0.9169885837, 1.430428321, 0.8864384596, 0.9514936865, 1.6372995656}, // Item_10
{0.7191456454, 1.2072812952, 0.4427503883, 0.2653594026, 0.7121747779}, // Item_11
{1.8255623579, 1.5235340218, 0.2311946922, 1.7890632707, 1.3132771454}, // Item_12
{0.0592750302, 0.4910661918, 1.5775046116, 1.8711764617, 0.5687820357}, // Item_13
{1.7727101115, 1.9907456539, 0.5861100047, 0.75383928, 0.597872715}, // Item_14
{1.5786721054, 0.7445353908, 1.2787411003, 0.8351749131, 1.8470229823}, // Item_15
{1.0837545246, 0.6862612348, 1.2791052731, 0.8805288146, 0.3869853732}, // Item_16
{1.565522531, 0.2279829192, 0.5790772517, 1.1613239124, 1.9721290898}, // Item_17
{1.4484547731, 1.7876939061, 1.5256539653, 0.7668565032, 0.2002832731}, // Item_18
{0.4790251292, 1.33859911, 1.5265114061, 1.3049658258, 1.4785322957}, // Item_19
{0.8885746957, 1.21464705, 0.9087569579, 1.9485661844, 0.267142314} // Item_20
};
// Table 2: Item Attributes (F23)
int item_attr[TOTAL_ITEMS] = {
2, 2, 2, 1, 1, 4, 3, 3, 1, 5,
3, 1, 4, 5, 4, 5, 4, 2, 1, 3
};
// Array to mark whether an item has been used (0: available, 1: used)
int used[TOTAL_ITEMS] = {0};
/* Blueprint from Table 3: Module-Item Assignments (C19)
Each module’s required attribute IDs are listed in blueprint order.
*/
typedef struct {
char name[3];
int stage;
int num_req;
int req[10]; // required attribute IDs (in blueprint order)
int assign[10]; // assigned item IDs (1-indexed; 0 if not filled)
} Module;
Module modules[TOTAL_MODULES] = {
{"M1", 1, 3, {1, 3, 4}, {0,0,0}},
{"M2", 2, 4, {2, 3, 1, 4}, {0,0,0,0}},
{"M3", 2, 3, {3, 5, 2}, {0,0,0}},
{"M4", 3, 3, {2, 4, 3}, {0,0,0}},
{"M5", 3, 2, {1, 5}, {0,0}}
};
/* ==================== MH Black-Box Code ====================
(Do NOT change any line of logic in this block.)
Global variables used:
g_nitems: number of candidate items (for current attribute)
g_nmod: number of modules (for current attribute)
g_info[][]: candidate matrix (rows: candidate items, columns: modules)
*/
int g_nitems; // candidate items count
int g_nmod; // number of modules for current attribute
double g_info[100][100];
double runifC() {
return (double)rand() / (double)RAND_MAX
; }
double sampleGumbel() {
double u = runifC();
if(u <= 0.0) u = 1e-10;
if(u >= 1.0) u = 1 - 1e-10;
}
/* GsampleEq: Samples x integers (1-indexed) from numbrs[1..len] using Gumbel perturbation */
void GsampleEq(const int *numbrs, int len, int x, int *out) {
typedef struct {
int val;
double g;
} Gpair;
Gpair arr[100];
double constant
= log(1.0 / len
); for (int i = 1; i <= len; i++) {
double gumb = sampleGumbel() + constant;
arr[i].val = numbrs[i];
arr[i].g = gumb;
}
// Bubble sort in descending order of g
for (int i = 1; i < len; i++) {
for (int j = i + 1; j <= len; j++) {
if (arr[j].g > arr[i].g) {
Gpair tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
for (int i = 1; i <= x; i++) {
out[i] = arr[i].val;
}
}
double pop_sd(const double *vals, int n) {
if(n <= 1) return 0.0;
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += vals[i];
}
double mean = sum / n;
double sse = 0.0;
for (int i = 1; i <= n; i++) {
double diff = vals[i] - mean;
sse += diff * diff;
}
}
/* MH optimizer function.
It uses global variables g_nitems, g_nmod, and matrix g_info.
The output bestSelect[1..g_nmod] gives the (1-indexed) candidate chosen for each module.
*/
void mh(int iter, double alpha, int *bestSelect, double *bestObjValue, double *objTrace) {
int itemsArray[100], modsArray[100];
for (int i = 1; i <= g_nitems; i++) {
itemsArray[i] = i;
}
for (int j = 1; j <= g_nmod; j++) {
modsArray[j] = j;
}
int citems[100];
GsampleEq(itemsArray, g_nitems, g_nmod, citems);
double cvals[100];
double sumVals = 0.0;
for (int j = 1; j <= g_nmod; j++) {
int itemIndex = citems[j];
double val = g_info[itemIndex - 1][j - 1];
cvals[j] = val;
sumVals += val;
}
double cSD = pop_sd(cvals, g_nmod);
double cObj = sumVals - cSD;
for (int j = 1; j <= g_nmod; j++) {
bestSelect[j] = citems[j];
}
double bestObj = cObj;
for (int i = 1; i <= iter; i++) {
int nselect[100];
for (int j = 1; j <= g_nmod; j++) {
nselect[j] = citems[j];
}
int chosen[10];
GsampleEq(modsArray, g_nmod, 1, chosen);
int changemod = chosen[1];
int notChosen[100];
int ncCount = 0;
for (int k = 1; k <= g_nitems; k++) {
int inSel = 0;
for (int jj = 1; jj <= g_nmod; jj++) {
if(nselect[jj] == k) { inSel = 1; break; }
}
if(!inSel) { ncCount++; notChosen[ncCount] = k; }
}
int newOne[10];
if(ncCount > 0) {
GsampleEq(notChosen, ncCount, 1, newOne);
int newItem = newOne[1];
nselect[changemod] = newItem;
}
double nvals[100];
double newSum = 0.0;
for (int j = 1; j <= g_nmod; j++) {
int it = nselect[j];
double val = g_info[it - 1][j - 1];
nvals[j] = val;
newSum += val;
}
double newSD = pop_sd(nvals, g_nmod);
double newObj = newSum - newSD;
if(newObj > cObj) {
for (int j = 1; j <= g_nmod; j++) {
citems[j] = nselect[j];
}
cObj = newObj;
} else {
double aprob
= exp(alpha
* (newObj
- cObj
)); if(aprob > 1.0) aprob = 1.0;
double u = runifC();
if(u < aprob) {
for (int j = 1; j <= g_nmod; j++) {
citems[j] = nselect[j];
}
cObj = newObj;
}
}
if(cObj > bestObj) {
bestObj = cObj;
for (int j = 1; j <= g_nmod; j++) {
bestSelect[j] = citems[j];
}
}
objTrace[i] = bestObj;
}
*bestObjValue = bestObj;
}
/* ==================== Extended MST Logic ==================== */
/*
For a given attribute (attr), gather candidate items (from Table 2) that have that attribute and are not used.
Returns candidate count and fills array cand[] (with 1-indexed candidate positions).
*/
int get_candidates(int attr, int cand[]) {
int count = 0;
for (int i = 0; i < TOTAL_ITEMS; i++) {
if(!used[i] && item_attr[i] == attr) {
cand[++count] = i; // store candidate item (0-indexed) at position count
}
}
return count;
}
/*
For a single module (mod, 0-indexed) and attribute, select the candidate with highest mean information.
*/
int select_best_for_module(int mod, int attr, int cand[], int candCount) {
int best = -1;
double bestVal = -1e9;
for (int i = 1; i <= candCount; i++) {
int itemIndex = cand[i];
double val = mean_info[itemIndex][mod];
if(val > bestVal) {
bestVal = val;
best = itemIndex;
}
}
return best;
}
/*
Process a given attribute for a set of modules (modList[]) in the same stage that require it.
If only one module requires the attribute, assign directly.
If more than one require it, then (to mimic the single–attribute MH call)
we sort the list of modules in natural (ascending) order before building the candidate matrix.
*/
void process_attribute(int attr, int modList[], int count) {
int cand[100];
int candCount = get_candidates(attr, cand);
if(candCount == 0) {
printf("No available items for attribute %d\n", attr
); return;
}
if(count == 1) {
int mod = modList[0];
int bestItem = select_best_for_module(mod, attr, cand, candCount);
for (int i = 0; i < modules[mod].num_req; i++) {
if(modules[mod].req[i] == attr && modules[mod].assign[i] == 0) {
modules[mod].assign[i] = bestItem + 1; // store 1-indexed
used[bestItem] = 1;
printf("Module %s: Assigned Item_%d for attribute %d (direct selection)\n", modules[mod].name, bestItem+1, attr);
break;
}
}
} else {
// Build a copy of modList and sort it in ascending order (natural order).
int orderedMods[10];
for (int i = 0; i < count; i++) {
orderedMods[i] = modList[i];
}
for (int i = 0; i < count - 1; i++) {
for (int j = i+1; j < count; j++) {
if(orderedMods[i] > orderedMods[j]) {
int temp = orderedMods[i];
orderedMods[i] = orderedMods[j];
orderedMods[j] = temp;
}
}
}
// Use the orderedMods for the MH candidate matrix.
g_nitems = candCount;
g_nmod = count;
for (int i = 1; i <= g_nitems; i++) {
for (int j = 0; j < g_nmod; j++) {
int mod = orderedMods[j]; // natural order (e.g., for stage 2: M2 then M3)
g_info[i-1][j] = mean_info[cand[i]][mod];
}
}
int bestSelect[100];
double bestObj;
double objTrace[MH_ITER+1];
mh(MH_ITER, MH_ALPHA, bestSelect, &bestObj, objTrace);
// Assign the chosen candidate for each module using the same orderedMods.
for (int j = 0; j < g_nmod; j++) {
int selCandIndex = bestSelect[j+1]; // 1-indexed into cand[]
int bestItem = cand[selCandIndex];
int mod = orderedMods[j];
for (int k = 0; k < modules[mod].num_req; k++) {
if(modules[mod].req[k] == attr && modules[mod].assign[k] == 0) {
modules[mod].assign[k] = bestItem + 1;
used[bestItem] = 1;
printf("Module %s: Assigned Item_%d for attribute %d (via MH)\n", modules[mod].name, bestItem+1, attr);
break;
}
}
}
}
}
/*
Process a given stage.
Collect all modules in that stage (using the stage field), sort them in descending order
(so that direct selections obey the “last module first” rule), then for each attribute (1 to 5)
required by at least one module, call process_attribute.
*/
void process_stage(int stage) {
int modList[10];
int modCount = 0;
for (int i = 0; i < TOTAL_MODULES; i++) {
if(modules[i].stage == stage) {
modList[modCount++] = i;
}
}
// Sort modList in descending order for direct selection.
for (int i = 0; i < modCount - 1; i++) {
for (int j = i+1; j < modCount; j++) {
if(modList[i] < modList[j]) {
int temp = modList[i];
modList[i] = modList[j];
modList[j] = temp;
}
}
}
// For each attribute (1 to 5), find modules (from modList) that still need that attribute.
for (int attr = 1; attr <= 5; attr++) {
int reqMods[10];
int count = 0;
for (int i = 0; i < modCount; i++) {
int mod = modList[i];
for (int j = 0; j < modules[mod].num_req; j++) {
if(modules[mod].req[j] == attr && modules[mod].assign[j] == 0) {
reqMods[count++] = mod;
break;
}
}
}
if(count > 0) {
process_attribute(attr, reqMods, count);
}
}
}
/* ==================== Main ==================== */
int main() {
// Use a fixed seed for reproducibility.
printf("Starting MST Item Assignment...\n\n");
// Process stages from last to first.
// Stage 3 (modules M4 and M5)
process_stage(3);
// Stage 2 (modules M2 and M3)
process_stage(2);
// Stage 1 (module M1)
process_stage(1);
// Print final assignments.
printf("\nFinal Module Assignments:\n"); for (int i = 0; i < TOTAL_MODULES; i++) {
printf("%s (Stage %d): ", modules
[i
].
name, modules
[i
].
stage); for (int j = 0; j < modules[i].num_req; j++) {
if(modules[i].assign[j] != 0)
printf("Item_%d ", modules
[i
].
assign[j
]); else
}
}
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPHRpbWUuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKLyogPT09PT09PT09PT09PT09PT09PT0gSW5wdXQgRGF0YSA9PT09PT09PT09PT09PT09PT09PSAqLwoKI2RlZmluZSBUT1RBTF9JVEVNUyAyMAojZGVmaW5lIFRPVEFMX01PRFVMRVMgNQojZGVmaW5lIE1IX0lURVIgMTAwMAojZGVmaW5lIE1IX0FMUEhBIDEuMAoKLy8gVGFibGUgMTogTWVhbiBJbmZvcm1hdGlvbiBmb3IgSXRlbXMgQWNyb3NzIE1vZHVsZXMgKEgyMikKZG91YmxlIG1lYW5faW5mb1tUT1RBTF9JVEVNU11bVE9UQUxfTU9EVUxFU10gPSB7CiAgICB7MC4wNTUxMzQyMjA1LCAxLjEyMjk1NDk4NjEsIDEuMDc0NjU1MDQwMiwgMC4yNzM2NDQ3MDIsICAwLjM3ODk2MTI2NTF9LCAvLyBJdGVtXzEKICAgIHsxLjUxNTkwNTEzMjUsIDAuOTU0NzkxMjAxNywgMC42ODM4MTcyODA5LCAwLjcyOTYxNTA4MywgIDEuMzE4MzU4NjM2OX0sIC8vIEl0ZW1fMgogICAgezAuNDI2MzQyNTA5NywgMC40MDA5ODU4OTYxLCAwLjE5NDI4MzQ1MTQsIDEuOTY4Njk0MzAyMywgIDEuOTY3ODEyNDAxMn0sIC8vIEl0ZW1fMwogICAgezEuMzkxNDE3OTMzNiwgMS45NjUzMjkyMTc3LCAxLjY5ODc3NDU1MjAsIDEuMjc2Nzc4MDI1LCAgIDAuMDAzNzg3ODE0Mn0sIC8vIEl0ZW1fNAogICAgezAuMzcyOTIyNTE0MSwgMS40NDQ2OTc0MzIyLCAxLjE5NjI2Mjg4NDksIDAuMjk4NDgyODEyNSwgIDAuODkzOTc1MzYwOH0sIC8vIEl0ZW1fNQogICAgezAuMDkxMjIzMDA2NiwgMS4zMDgwMDIzMjE1LCAxLjQ0NzI2MDcxOTcsIDAuMDM0ODcwODUyNywgIDAuNjE4MzY0Mjk4M30sIC8vIEl0ZW1fNgogICAgezAuNzMwMjU5NzE4NCwgMS4xMDY3MjI1MzA5LCAxLjcyNjk3OTUwMTUsIDEuMzYwOTQ2MjQ5MiwgIDAuODc0MjM2Mjk3OH0sIC8vIEl0ZW1fNwogICAgezAuNzYyODMxNTc3MSwgMC45MDI5OTAwOCwgICAwLjU1Njc1NTY3ODcsIDAuMDA4MTc0OTIzMiwgIDAuNjczNjg1NTg4NH0sIC8vIEl0ZW1fOAogICAgezAuNTQ3NjQxNzg1OCwgMC43NzU1OTk4NTEzLCAxLjM4MTQ4MTc0MDIsIDEuNTIwOTI2MTA0OSwgIDEuMTMwMzcwMzE0N30sIC8vIEl0ZW1fOQogICAgezAuOTE2OTg4NTgzNywgMS40MzA0MjgzMjEsICAwLjg4NjQzODQ1OTYsIDAuOTUxNDkzNjg2NSwgIDEuNjM3Mjk5NTY1Nn0sIC8vIEl0ZW1fMTAKICAgIHswLjcxOTE0NTY0NTQsIDEuMjA3MjgxMjk1MiwgMC40NDI3NTAzODgzLCAwLjI2NTM1OTQwMjYsICAwLjcxMjE3NDc3Nzl9LCAvLyBJdGVtXzExCiAgICB7MS44MjU1NjIzNTc5LCAxLjUyMzUzNDAyMTgsIDAuMjMxMTk0NjkyMiwgMS43ODkwNjMyNzA3LCAgMS4zMTMyNzcxNDU0fSwgLy8gSXRlbV8xMgogICAgezAuMDU5Mjc1MDMwMiwgMC40OTEwNjYxOTE4LCAxLjU3NzUwNDYxMTYsIDEuODcxMTc2NDYxNywgIDAuNTY4NzgyMDM1N30sIC8vIEl0ZW1fMTMKICAgIHsxLjc3MjcxMDExMTUsIDEuOTkwNzQ1NjUzOSwgMC41ODYxMTAwMDQ3LCAwLjc1MzgzOTI4LCAgICAwLjU5Nzg3MjcxNX0sICAvLyBJdGVtXzE0CiAgICB7MS41Nzg2NzIxMDU0LCAwLjc0NDUzNTM5MDgsIDEuMjc4NzQxMTAwMywgMC44MzUxNzQ5MTMxLCAgMS44NDcwMjI5ODIzfSwgLy8gSXRlbV8xNQogICAgezEuMDgzNzU0NTI0NiwgMC42ODYyNjEyMzQ4LCAxLjI3OTEwNTI3MzEsIDAuODgwNTI4ODE0NiwgIDAuMzg2OTg1MzczMn0sIC8vIEl0ZW1fMTYKICAgIHsxLjU2NTUyMjUzMSwgIDAuMjI3OTgyOTE5MiwgMC41NzkwNzcyNTE3LCAxLjE2MTMyMzkxMjQsICAxLjk3MjEyOTA4OTh9LCAvLyBJdGVtXzE3CiAgICB7MS40NDg0NTQ3NzMxLCAxLjc4NzY5MzkwNjEsIDEuNTI1NjUzOTY1MywgMC43NjY4NTY1MDMyLCAgMC4yMDAyODMyNzMxfSwgLy8gSXRlbV8xOAogICAgezAuNDc5MDI1MTI5MiwgMS4zMzg1OTkxMSwgICAxLjUyNjUxMTQwNjEsIDEuMzA0OTY1ODI1OCwgIDEuNDc4NTMyMjk1N30sIC8vIEl0ZW1fMTkKICAgIHswLjg4ODU3NDY5NTcsIDEuMjE0NjQ3MDUsICAgMC45MDg3NTY5NTc5LCAxLjk0ODU2NjE4NDQsICAwLjI2NzE0MjMxNH0gICAvLyBJdGVtXzIwCn07CgovLyBUYWJsZSAyOiBJdGVtIEF0dHJpYnV0ZXMgKEYyMykKaW50IGl0ZW1fYXR0cltUT1RBTF9JVEVNU10gPSB7CiAgICAyLCAyLCAyLCAxLCAxLCA0LCAzLCAzLCAxLCA1LAogICAgMywgMSwgNCwgNSwgNCwgNSwgNCwgMiwgMSwgMwp9OwoKLy8gQXJyYXkgdG8gbWFyayB3aGV0aGVyIGFuIGl0ZW0gaGFzIGJlZW4gdXNlZCAoMDogYXZhaWxhYmxlLCAxOiB1c2VkKQppbnQgdXNlZFtUT1RBTF9JVEVNU10gPSB7MH07CgovKiBCbHVlcHJpbnQgZnJvbSBUYWJsZSAzOiBNb2R1bGUtSXRlbSBBc3NpZ25tZW50cyAoQzE5KQogICBFYWNoIG1vZHVsZeKAmXMgcmVxdWlyZWQgYXR0cmlidXRlIElEcyBhcmUgbGlzdGVkIGluIGJsdWVwcmludCBvcmRlci4KKi8KdHlwZWRlZiBzdHJ1Y3QgewogICAgY2hhciBuYW1lWzNdOwogICAgaW50IHN0YWdlOwogICAgaW50IG51bV9yZXE7CiAgICBpbnQgcmVxWzEwXTsgICAgICAvLyByZXF1aXJlZCBhdHRyaWJ1dGUgSURzIChpbiBibHVlcHJpbnQgb3JkZXIpCiAgICBpbnQgYXNzaWduWzEwXTsgICAvLyBhc3NpZ25lZCBpdGVtIElEcyAoMS1pbmRleGVkOyAwIGlmIG5vdCBmaWxsZWQpCn0gTW9kdWxlOwoKTW9kdWxlIG1vZHVsZXNbVE9UQUxfTU9EVUxFU10gPSB7CiAgICB7Ik0xIiwgMSwgMywgezEsIDMsIDR9LCB7MCwwLDB9fSwKICAgIHsiTTIiLCAyLCA0LCB7MiwgMywgMSwgNH0sIHswLDAsMCwwfX0sCiAgICB7Ik0zIiwgMiwgMywgezMsIDUsIDJ9LCB7MCwwLDB9fSwKICAgIHsiTTQiLCAzLCAzLCB7MiwgNCwgM30sIHswLDAsMH19LAogICAgeyJNNSIsIDMsIDIsIHsxLCA1fSwgezAsMH19Cn07CgovKiA9PT09PT09PT09PT09PT09PT09PSBNSCBCbGFjay1Cb3ggQ29kZSA9PT09PT09PT09PT09PT09PT09PQogICAoRG8gTk9UIGNoYW5nZSBhbnkgbGluZSBvZiBsb2dpYyBpbiB0aGlzIGJsb2NrLikKICAgR2xvYmFsIHZhcmlhYmxlcyB1c2VkOgogICAgIGdfbml0ZW1zOiBudW1iZXIgb2YgY2FuZGlkYXRlIGl0ZW1zIChmb3IgY3VycmVudCBhdHRyaWJ1dGUpCiAgICAgZ19ubW9kOiBudW1iZXIgb2YgbW9kdWxlcyAoZm9yIGN1cnJlbnQgYXR0cmlidXRlKQogICAgIGdfaW5mb1tdW106IGNhbmRpZGF0ZSBtYXRyaXggKHJvd3M6IGNhbmRpZGF0ZSBpdGVtcywgY29sdW1uczogbW9kdWxlcykKKi8KaW50IGdfbml0ZW1zOyAgIC8vIGNhbmRpZGF0ZSBpdGVtcyBjb3VudAppbnQgZ19ubW9kOyAgICAgLy8gbnVtYmVyIG9mIG1vZHVsZXMgZm9yIGN1cnJlbnQgYXR0cmlidXRlCmRvdWJsZSBnX2luZm9bMTAwXVsxMDBdOwoKZG91YmxlIHJ1bmlmQygpIHsKICAgIHJldHVybiAoZG91YmxlKXJhbmQoKSAvIChkb3VibGUpUkFORF9NQVg7Cn0KCmRvdWJsZSBzYW1wbGVHdW1iZWwoKSB7CiAgICBkb3VibGUgdSA9IHJ1bmlmQygpOwogICAgaWYodSA8PSAwLjApIHUgPSAxZS0xMDsKICAgIGlmKHUgPj0gMS4wKSB1ID0gMSAtIDFlLTEwOwogICAgcmV0dXJuIC1sb2coLWxvZyh1KSk7Cn0KCi8qIEdzYW1wbGVFcTogU2FtcGxlcyB4IGludGVnZXJzICgxLWluZGV4ZWQpIGZyb20gbnVtYnJzWzEuLmxlbl0gdXNpbmcgR3VtYmVsIHBlcnR1cmJhdGlvbiAqLwp2b2lkIEdzYW1wbGVFcShjb25zdCBpbnQgKm51bWJycywgaW50IGxlbiwgaW50IHgsIGludCAqb3V0KSB7CiAgICB0eXBlZGVmIHN0cnVjdCB7CiAgICAgICAgaW50IHZhbDsKICAgICAgICBkb3VibGUgZzsKICAgIH0gR3BhaXI7CiAgICBHcGFpciBhcnJbMTAwXTsKICAgIGRvdWJsZSBjb25zdGFudCA9IGxvZygxLjAgLyBsZW4pOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbGVuOyBpKyspIHsKICAgICAgICBkb3VibGUgZ3VtYiA9IHNhbXBsZUd1bWJlbCgpICsgY29uc3RhbnQ7CiAgICAgICAgYXJyW2ldLnZhbCA9IG51bWJyc1tpXTsKICAgICAgICBhcnJbaV0uZyAgID0gZ3VtYjsKICAgIH0KICAgIC8vIEJ1YmJsZSBzb3J0IGluIGRlc2NlbmRpbmcgb3JkZXIgb2YgZwogICAgZm9yIChpbnQgaSA9IDE7IGkgPCBsZW47IGkrKykgewogICAgICAgIGZvciAoaW50IGogPSBpICsgMTsgaiA8PSBsZW47IGorKykgewogICAgICAgICAgICBpZiAoYXJyW2pdLmcgPiBhcnJbaV0uZykgewogICAgICAgICAgICAgICAgR3BhaXIgdG1wID0gYXJyW2ldOwogICAgICAgICAgICAgICAgYXJyW2ldID0gYXJyW2pdOwogICAgICAgICAgICAgICAgYXJyW2pdID0gdG1wOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0geDsgaSsrKSB7CiAgICAgICAgb3V0W2ldID0gYXJyW2ldLnZhbDsKICAgIH0KfQoKZG91YmxlIHBvcF9zZChjb25zdCBkb3VibGUgKnZhbHMsIGludCBuKSB7CiAgICBpZihuIDw9IDEpIHJldHVybiAwLjA7CiAgICBkb3VibGUgc3VtID0gMC4wOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSB7CiAgICAgICAgc3VtICs9IHZhbHNbaV07CiAgICB9CiAgICBkb3VibGUgbWVhbiA9IHN1bSAvIG47CiAgICBkb3VibGUgc3NlID0gMC4wOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSB7CiAgICAgICAgZG91YmxlIGRpZmYgPSB2YWxzW2ldIC0gbWVhbjsKICAgICAgICBzc2UgKz0gZGlmZiAqIGRpZmY7CiAgICB9CiAgICByZXR1cm4gc3FydChzc2UgLyBuKTsKfQoKLyogTUggb3B0aW1pemVyIGZ1bmN0aW9uLgogICBJdCB1c2VzIGdsb2JhbCB2YXJpYWJsZXMgZ19uaXRlbXMsIGdfbm1vZCwgYW5kIG1hdHJpeCBnX2luZm8uCiAgIFRoZSBvdXRwdXQgYmVzdFNlbGVjdFsxLi5nX25tb2RdIGdpdmVzIHRoZSAoMS1pbmRleGVkKSBjYW5kaWRhdGUgY2hvc2VuIGZvciBlYWNoIG1vZHVsZS4KKi8Kdm9pZCBtaChpbnQgaXRlciwgZG91YmxlIGFscGhhLCBpbnQgKmJlc3RTZWxlY3QsIGRvdWJsZSAqYmVzdE9ialZhbHVlLCBkb3VibGUgKm9ialRyYWNlKSB7CiAgICBpbnQgaXRlbXNBcnJheVsxMDBdLCBtb2RzQXJyYXlbMTAwXTsKICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IGdfbml0ZW1zOyBpKyspIHsKICAgICAgICBpdGVtc0FycmF5W2ldID0gaTsKICAgIH0KICAgIGZvciAoaW50IGogPSAxOyBqIDw9IGdfbm1vZDsgaisrKSB7CiAgICAgICAgbW9kc0FycmF5W2pdID0gajsKICAgIH0KICAgIGludCBjaXRlbXNbMTAwXTsKICAgIEdzYW1wbGVFcShpdGVtc0FycmF5LCBnX25pdGVtcywgZ19ubW9kLCBjaXRlbXMpOwogICAgZG91YmxlIGN2YWxzWzEwMF07CiAgICBkb3VibGUgc3VtVmFscyA9IDAuMDsKICAgIGZvciAoaW50IGogPSAxOyBqIDw9IGdfbm1vZDsgaisrKSB7CiAgICAgICAgaW50IGl0ZW1JbmRleCA9IGNpdGVtc1tqXTsKICAgICAgICBkb3VibGUgdmFsID0gZ19pbmZvW2l0ZW1JbmRleCAtIDFdW2ogLSAxXTsKICAgICAgICBjdmFsc1tqXSA9IHZhbDsKICAgICAgICBzdW1WYWxzICs9IHZhbDsKICAgIH0KICAgIGRvdWJsZSBjU0QgPSBwb3Bfc2QoY3ZhbHMsIGdfbm1vZCk7CiAgICBkb3VibGUgY09iaiA9IHN1bVZhbHMgLSBjU0Q7CiAgICBmb3IgKGludCBqID0gMTsgaiA8PSBnX25tb2Q7IGorKykgewogICAgICAgIGJlc3RTZWxlY3Rbal0gPSBjaXRlbXNbal07CiAgICB9CiAgICBkb3VibGUgYmVzdE9iaiA9IGNPYmo7CiAgICBmb3IgKGludCBpID0gMTsgaSA8PSBpdGVyOyBpKyspIHsKICAgICAgICBpbnQgbnNlbGVjdFsxMDBdOwogICAgICAgIGZvciAoaW50IGogPSAxOyBqIDw9IGdfbm1vZDsgaisrKSB7CiAgICAgICAgICAgIG5zZWxlY3Rbal0gPSBjaXRlbXNbal07CiAgICAgICAgfQogICAgICAgIGludCBjaG9zZW5bMTBdOwogICAgICAgIEdzYW1wbGVFcShtb2RzQXJyYXksIGdfbm1vZCwgMSwgY2hvc2VuKTsKICAgICAgICBpbnQgY2hhbmdlbW9kID0gY2hvc2VuWzFdOwogICAgICAgIGludCBub3RDaG9zZW5bMTAwXTsKICAgICAgICBpbnQgbmNDb3VudCA9IDA7CiAgICAgICAgZm9yIChpbnQgayA9IDE7IGsgPD0gZ19uaXRlbXM7IGsrKykgewogICAgICAgICAgICBpbnQgaW5TZWwgPSAwOwogICAgICAgICAgICBmb3IgKGludCBqaiA9IDE7IGpqIDw9IGdfbm1vZDsgamorKykgewogICAgICAgICAgICAgICAgaWYobnNlbGVjdFtqal0gPT0gaykgeyBpblNlbCA9IDE7IGJyZWFrOyB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYoIWluU2VsKSB7IG5jQ291bnQrKzsgbm90Q2hvc2VuW25jQ291bnRdID0gazsgfQogICAgICAgIH0KICAgICAgICBpbnQgbmV3T25lWzEwXTsKICAgICAgICBpZihuY0NvdW50ID4gMCkgewogICAgICAgICAgICBHc2FtcGxlRXEobm90Q2hvc2VuLCBuY0NvdW50LCAxLCBuZXdPbmUpOwogICAgICAgICAgICBpbnQgbmV3SXRlbSA9IG5ld09uZVsxXTsKICAgICAgICAgICAgbnNlbGVjdFtjaGFuZ2Vtb2RdID0gbmV3SXRlbTsKICAgICAgICB9CiAgICAgICAgZG91YmxlIG52YWxzWzEwMF07CiAgICAgICAgZG91YmxlIG5ld1N1bSA9IDAuMDsKICAgICAgICBmb3IgKGludCBqID0gMTsgaiA8PSBnX25tb2Q7IGorKykgewogICAgICAgICAgICBpbnQgaXQgPSBuc2VsZWN0W2pdOwogICAgICAgICAgICBkb3VibGUgdmFsID0gZ19pbmZvW2l0IC0gMV1baiAtIDFdOwogICAgICAgICAgICBudmFsc1tqXSA9IHZhbDsKICAgICAgICAgICAgbmV3U3VtICs9IHZhbDsKICAgICAgICB9CiAgICAgICAgZG91YmxlIG5ld1NEID0gcG9wX3NkKG52YWxzLCBnX25tb2QpOwogICAgICAgIGRvdWJsZSBuZXdPYmogPSBuZXdTdW0gLSBuZXdTRDsKICAgICAgICBpZihuZXdPYmogPiBjT2JqKSB7CiAgICAgICAgICAgIGZvciAoaW50IGogPSAxOyBqIDw9IGdfbm1vZDsgaisrKSB7CiAgICAgICAgICAgICAgICBjaXRlbXNbal0gPSBuc2VsZWN0W2pdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNPYmogPSBuZXdPYmo7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZG91YmxlIGFwcm9iID0gZXhwKGFscGhhICogKG5ld09iaiAtIGNPYmopKTsKICAgICAgICAgICAgaWYoYXByb2IgPiAxLjApIGFwcm9iID0gMS4wOwogICAgICAgICAgICBkb3VibGUgdSA9IHJ1bmlmQygpOwogICAgICAgICAgICBpZih1IDwgYXByb2IpIHsKICAgICAgICAgICAgICAgIGZvciAoaW50IGogPSAxOyBqIDw9IGdfbm1vZDsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgY2l0ZW1zW2pdID0gbnNlbGVjdFtqXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNPYmogPSBuZXdPYmo7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYoY09iaiA+IGJlc3RPYmopIHsKICAgICAgICAgICAgYmVzdE9iaiA9IGNPYmo7CiAgICAgICAgICAgIGZvciAoaW50IGogPSAxOyBqIDw9IGdfbm1vZDsgaisrKSB7CiAgICAgICAgICAgICAgICBiZXN0U2VsZWN0W2pdID0gY2l0ZW1zW2pdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG9ialRyYWNlW2ldID0gYmVzdE9iajsKICAgIH0KICAgICpiZXN0T2JqVmFsdWUgPSBiZXN0T2JqOwp9CgovKiA9PT09PT09PT09PT09PT09PT09PSBFeHRlbmRlZCBNU1QgTG9naWMgPT09PT09PT09PT09PT09PT09PT0gKi8KCi8qCiAgIEZvciBhIGdpdmVuIGF0dHJpYnV0ZSAoYXR0ciksIGdhdGhlciBjYW5kaWRhdGUgaXRlbXMgKGZyb20gVGFibGUgMikgdGhhdCBoYXZlIHRoYXQgYXR0cmlidXRlIGFuZCBhcmUgbm90IHVzZWQuCiAgIFJldHVybnMgY2FuZGlkYXRlIGNvdW50IGFuZCBmaWxscyBhcnJheSBjYW5kW10gKHdpdGggMS1pbmRleGVkIGNhbmRpZGF0ZSBwb3NpdGlvbnMpLgoqLwppbnQgZ2V0X2NhbmRpZGF0ZXMoaW50IGF0dHIsIGludCBjYW5kW10pIHsKICAgIGludCBjb3VudCA9IDA7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IFRPVEFMX0lURU1TOyBpKyspIHsKICAgICAgICBpZighdXNlZFtpXSAmJiBpdGVtX2F0dHJbaV0gPT0gYXR0cikgewogICAgICAgICAgICBjYW5kWysrY291bnRdID0gaTsgIC8vIHN0b3JlIGNhbmRpZGF0ZSBpdGVtICgwLWluZGV4ZWQpIGF0IHBvc2l0aW9uIGNvdW50CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGNvdW50Owp9CgovKgogICBGb3IgYSBzaW5nbGUgbW9kdWxlIChtb2QsIDAtaW5kZXhlZCkgYW5kIGF0dHJpYnV0ZSwgc2VsZWN0IHRoZSBjYW5kaWRhdGUgd2l0aCBoaWdoZXN0IG1lYW4gaW5mb3JtYXRpb24uCiovCmludCBzZWxlY3RfYmVzdF9mb3JfbW9kdWxlKGludCBtb2QsIGludCBhdHRyLCBpbnQgY2FuZFtdLCBpbnQgY2FuZENvdW50KSB7CiAgICBpbnQgYmVzdCA9IC0xOwogICAgZG91YmxlIGJlc3RWYWwgPSAtMWU5OwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gY2FuZENvdW50OyBpKyspIHsKICAgICAgICBpbnQgaXRlbUluZGV4ID0gY2FuZFtpXTsKICAgICAgICBkb3VibGUgdmFsID0gbWVhbl9pbmZvW2l0ZW1JbmRleF1bbW9kXTsKICAgICAgICBpZih2YWwgPiBiZXN0VmFsKSB7CiAgICAgICAgICAgIGJlc3RWYWwgPSB2YWw7CiAgICAgICAgICAgIGJlc3QgPSBpdGVtSW5kZXg7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIGJlc3Q7Cn0KCi8qCiAgIFByb2Nlc3MgYSBnaXZlbiBhdHRyaWJ1dGUgZm9yIGEgc2V0IG9mIG1vZHVsZXMgKG1vZExpc3RbXSkgaW4gdGhlIHNhbWUgc3RhZ2UgdGhhdCByZXF1aXJlIGl0LgogICBJZiBvbmx5IG9uZSBtb2R1bGUgcmVxdWlyZXMgdGhlIGF0dHJpYnV0ZSwgYXNzaWduIGRpcmVjdGx5LgogICBJZiBtb3JlIHRoYW4gb25lIHJlcXVpcmUgaXQsIHRoZW4gKHRvIG1pbWljIHRoZSBzaW5nbGXigJNhdHRyaWJ1dGUgTUggY2FsbCkKICAgd2Ugc29ydCB0aGUgbGlzdCBvZiBtb2R1bGVzIGluIG5hdHVyYWwgKGFzY2VuZGluZykgb3JkZXIgYmVmb3JlIGJ1aWxkaW5nIHRoZSBjYW5kaWRhdGUgbWF0cml4LgoqLwp2b2lkIHByb2Nlc3NfYXR0cmlidXRlKGludCBhdHRyLCBpbnQgbW9kTGlzdFtdLCBpbnQgY291bnQpIHsKICAgIGludCBjYW5kWzEwMF07CiAgICBpbnQgY2FuZENvdW50ID0gZ2V0X2NhbmRpZGF0ZXMoYXR0ciwgY2FuZCk7CiAgICBpZihjYW5kQ291bnQgPT0gMCkgewogICAgICAgIHByaW50ZigiTm8gYXZhaWxhYmxlIGl0ZW1zIGZvciBhdHRyaWJ1dGUgJWRcbiIsIGF0dHIpOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGlmKGNvdW50ID09IDEpIHsKICAgICAgICBpbnQgbW9kID0gbW9kTGlzdFswXTsKICAgICAgICBpbnQgYmVzdEl0ZW0gPSBzZWxlY3RfYmVzdF9mb3JfbW9kdWxlKG1vZCwgYXR0ciwgY2FuZCwgY2FuZENvdW50KTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IG1vZHVsZXNbbW9kXS5udW1fcmVxOyBpKyspIHsKICAgICAgICAgICAgaWYobW9kdWxlc1ttb2RdLnJlcVtpXSA9PSBhdHRyICYmIG1vZHVsZXNbbW9kXS5hc3NpZ25baV0gPT0gMCkgewogICAgICAgICAgICAgICAgbW9kdWxlc1ttb2RdLmFzc2lnbltpXSA9IGJlc3RJdGVtICsgMTsgLy8gc3RvcmUgMS1pbmRleGVkCiAgICAgICAgICAgICAgICB1c2VkW2Jlc3RJdGVtXSA9IDE7CiAgICAgICAgICAgICAgICBwcmludGYoIk1vZHVsZSAlczogQXNzaWduZWQgSXRlbV8lZCBmb3IgYXR0cmlidXRlICVkIChkaXJlY3Qgc2VsZWN0aW9uKVxuIiwKICAgICAgICAgICAgICAgICAgICAgICBtb2R1bGVzW21vZF0ubmFtZSwgYmVzdEl0ZW0rMSwgYXR0cik7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgICAgLy8gQnVpbGQgYSBjb3B5IG9mIG1vZExpc3QgYW5kIHNvcnQgaXQgaW4gYXNjZW5kaW5nIG9yZGVyIChuYXR1cmFsIG9yZGVyKS4KICAgICAgICBpbnQgb3JkZXJlZE1vZHNbMTBdOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICAgICAgICBvcmRlcmVkTW9kc1tpXSA9IG1vZExpc3RbaV07CiAgICAgICAgfQogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgY291bnQgLSAxOyBpKyspIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IGkrMTsgaiA8IGNvdW50OyBqKyspIHsKICAgICAgICAgICAgICAgIGlmKG9yZGVyZWRNb2RzW2ldID4gb3JkZXJlZE1vZHNbal0pIHsKICAgICAgICAgICAgICAgICAgICBpbnQgdGVtcCA9IG9yZGVyZWRNb2RzW2ldOwogICAgICAgICAgICAgICAgICAgIG9yZGVyZWRNb2RzW2ldID0gb3JkZXJlZE1vZHNbal07CiAgICAgICAgICAgICAgICAgICAgb3JkZXJlZE1vZHNbal0gPSB0ZW1wOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIC8vIFVzZSB0aGUgb3JkZXJlZE1vZHMgZm9yIHRoZSBNSCBjYW5kaWRhdGUgbWF0cml4LgogICAgICAgIGdfbml0ZW1zID0gY2FuZENvdW50OwogICAgICAgIGdfbm1vZCA9IGNvdW50OwogICAgICAgIGZvciAoaW50IGkgPSAxOyBpIDw9IGdfbml0ZW1zOyBpKyspIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBnX25tb2Q7IGorKykgewogICAgICAgICAgICAgICAgaW50IG1vZCA9IG9yZGVyZWRNb2RzW2pdOyAgLy8gbmF0dXJhbCBvcmRlciAoZS5nLiwgZm9yIHN0YWdlIDI6IE0yIHRoZW4gTTMpCiAgICAgICAgICAgICAgICBnX2luZm9baS0xXVtqXSA9IG1lYW5faW5mb1tjYW5kW2ldXVttb2RdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGludCBiZXN0U2VsZWN0WzEwMF07CiAgICAgICAgZG91YmxlIGJlc3RPYmo7CiAgICAgICAgZG91YmxlIG9ialRyYWNlW01IX0lURVIrMV07CiAgICAgICAgbWgoTUhfSVRFUiwgTUhfQUxQSEEsIGJlc3RTZWxlY3QsICZiZXN0T2JqLCBvYmpUcmFjZSk7CiAgICAgICAgLy8gQXNzaWduIHRoZSBjaG9zZW4gY2FuZGlkYXRlIGZvciBlYWNoIG1vZHVsZSB1c2luZyB0aGUgc2FtZSBvcmRlcmVkTW9kcy4KICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IGdfbm1vZDsgaisrKSB7CiAgICAgICAgICAgIGludCBzZWxDYW5kSW5kZXggPSBiZXN0U2VsZWN0W2orMV07ICAvLyAxLWluZGV4ZWQgaW50byBjYW5kW10KICAgICAgICAgICAgaW50IGJlc3RJdGVtID0gY2FuZFtzZWxDYW5kSW5kZXhdOwogICAgICAgICAgICBpbnQgbW9kID0gb3JkZXJlZE1vZHNbal07CiAgICAgICAgICAgIGZvciAoaW50IGsgPSAwOyBrIDwgbW9kdWxlc1ttb2RdLm51bV9yZXE7IGsrKykgewogICAgICAgICAgICAgICAgaWYobW9kdWxlc1ttb2RdLnJlcVtrXSA9PSBhdHRyICYmIG1vZHVsZXNbbW9kXS5hc3NpZ25ba10gPT0gMCkgewogICAgICAgICAgICAgICAgICAgIG1vZHVsZXNbbW9kXS5hc3NpZ25ba10gPSBiZXN0SXRlbSArIDE7CiAgICAgICAgICAgICAgICAgICAgdXNlZFtiZXN0SXRlbV0gPSAxOwogICAgICAgICAgICAgICAgICAgIHByaW50ZigiTW9kdWxlICVzOiBBc3NpZ25lZCBJdGVtXyVkIGZvciBhdHRyaWJ1dGUgJWQgKHZpYSBNSClcbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZHVsZXNbbW9kXS5uYW1lLCBiZXN0SXRlbSsxLCBhdHRyKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfQoKLyoKICAgUHJvY2VzcyBhIGdpdmVuIHN0YWdlLgogICBDb2xsZWN0IGFsbCBtb2R1bGVzIGluIHRoYXQgc3RhZ2UgKHVzaW5nIHRoZSBzdGFnZSBmaWVsZCksIHNvcnQgdGhlbSBpbiBkZXNjZW5kaW5nIG9yZGVyCiAgIChzbyB0aGF0IGRpcmVjdCBzZWxlY3Rpb25zIG9iZXkgdGhlIOKAnGxhc3QgbW9kdWxlIGZpcnN04oCdIHJ1bGUpLCB0aGVuIGZvciBlYWNoIGF0dHJpYnV0ZSAoMSB0byA1KQogICByZXF1aXJlZCBieSBhdCBsZWFzdCBvbmUgbW9kdWxlLCBjYWxsIHByb2Nlc3NfYXR0cmlidXRlLgoqLwp2b2lkIHByb2Nlc3Nfc3RhZ2UoaW50IHN0YWdlKSB7CiAgICBpbnQgbW9kTGlzdFsxMF07CiAgICBpbnQgbW9kQ291bnQgPSAwOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBUT1RBTF9NT0RVTEVTOyBpKyspIHsKICAgICAgICBpZihtb2R1bGVzW2ldLnN0YWdlID09IHN0YWdlKSB7CiAgICAgICAgICAgIG1vZExpc3RbbW9kQ291bnQrK10gPSBpOwogICAgICAgIH0KICAgIH0KICAgIC8vIFNvcnQgbW9kTGlzdCBpbiBkZXNjZW5kaW5nIG9yZGVyIGZvciBkaXJlY3Qgc2VsZWN0aW9uLgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBtb2RDb3VudCAtIDE7IGkrKykgewogICAgICAgIGZvciAoaW50IGogPSBpKzE7IGogPCBtb2RDb3VudDsgaisrKSB7CiAgICAgICAgICAgIGlmKG1vZExpc3RbaV0gPCBtb2RMaXN0W2pdKSB7CiAgICAgICAgICAgICAgICBpbnQgdGVtcCA9IG1vZExpc3RbaV07CiAgICAgICAgICAgICAgICBtb2RMaXN0W2ldID0gbW9kTGlzdFtqXTsKICAgICAgICAgICAgICAgIG1vZExpc3Rbal0gPSB0ZW1wOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgLy8gRm9yIGVhY2ggYXR0cmlidXRlICgxIHRvIDUpLCBmaW5kIG1vZHVsZXMgKGZyb20gbW9kTGlzdCkgdGhhdCBzdGlsbCBuZWVkIHRoYXQgYXR0cmlidXRlLgogICAgZm9yIChpbnQgYXR0ciA9IDE7IGF0dHIgPD0gNTsgYXR0cisrKSB7CiAgICAgICAgaW50IHJlcU1vZHNbMTBdOwogICAgICAgIGludCBjb3VudCA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBtb2RDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGludCBtb2QgPSBtb2RMaXN0W2ldOwogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IG1vZHVsZXNbbW9kXS5udW1fcmVxOyBqKyspIHsKICAgICAgICAgICAgICAgIGlmKG1vZHVsZXNbbW9kXS5yZXFbal0gPT0gYXR0ciAmJiBtb2R1bGVzW21vZF0uYXNzaWduW2pdID09IDApIHsKICAgICAgICAgICAgICAgICAgICByZXFNb2RzW2NvdW50KytdID0gbW9kOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmKGNvdW50ID4gMCkgewogICAgICAgICAgICBwcm9jZXNzX2F0dHJpYnV0ZShhdHRyLCByZXFNb2RzLCBjb3VudCk7CiAgICAgICAgfQogICAgfQp9CgovKiA9PT09PT09PT09PT09PT09PT09PSBNYWluID09PT09PT09PT09PT09PT09PT09ICovCmludCBtYWluKCkgewogICAgLy8gVXNlIGEgZml4ZWQgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5LgogICAgc3JhbmQoMTIzNDUpOwogICAgCiAgICBwcmludGYoIlN0YXJ0aW5nIE1TVCBJdGVtIEFzc2lnbm1lbnQuLi5cblxuIik7CiAgICAKICAgIC8vIFByb2Nlc3Mgc3RhZ2VzIGZyb20gbGFzdCB0byBmaXJzdC4KICAgIC8vIFN0YWdlIDMgKG1vZHVsZXMgTTQgYW5kIE01KQogICAgcHJvY2Vzc19zdGFnZSgzKTsKICAgIC8vIFN0YWdlIDIgKG1vZHVsZXMgTTIgYW5kIE0zKQogICAgcHJvY2Vzc19zdGFnZSgyKTsKICAgIC8vIFN0YWdlIDEgKG1vZHVsZSBNMSkKICAgIHByb2Nlc3Nfc3RhZ2UoMSk7CiAgICAKICAgIC8vIFByaW50IGZpbmFsIGFzc2lnbm1lbnRzLgogICAgcHJpbnRmKCJcbkZpbmFsIE1vZHVsZSBBc3NpZ25tZW50czpcbiIpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBUT1RBTF9NT0RVTEVTOyBpKyspIHsKICAgICAgICBwcmludGYoIiVzIChTdGFnZSAlZCk6ICIsIG1vZHVsZXNbaV0ubmFtZSwgbW9kdWxlc1tpXS5zdGFnZSk7CiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBtb2R1bGVzW2ldLm51bV9yZXE7IGorKykgewogICAgICAgICAgICBpZihtb2R1bGVzW2ldLmFzc2lnbltqXSAhPSAwKQogICAgICAgICAgICAgICAgcHJpbnRmKCJJdGVtXyVkICIsIG1vZHVsZXNbaV0uYXNzaWduW2pdKTsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgcHJpbnRmKCJOb25lICIpOwogICAgICAgIH0KICAgICAgICBwcmludGYoIlxuIik7CiAgICB9CiAgICAKICAgIHJldHVybiAwOwp9