#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef unsigned long long type_key;
typedef struct value {
unsigned int values[10];
} type_value;
typedef struct entry {
type_key key;
type_value value;
} type_entry;
typedef unsigned int type_index;
typedef struct table {
type_index bin_power, entry_power, n_entries, *bins;
type_entry *entries;
} type_table;
static inline type_index value_cap(type_value *value) {
return sizeof value->values / sizeof *value->values;
}
static inline type_index value_size(type_value *value) {
type_index i, size = value_cap(value);
for (i = 0; i < size && value->values[i]; i++);
return i;
}
void value_inspect_values(type_value *value) {
type_index i, cap = value_cap(value);
for (i = 0; i < cap; i += 2) {
printf("[%u, %u]", value
->values
[i
], value
->values
[i
+ 1]); }
}
void value_inspect(type_value *value) {
printf("value {cap: %u, size: %u, values: ", value_cap
(value
), value_size
(value
)); value_inspect_values(value);
}
static inline void value_append(type_value *value, unsigned int a, unsigned int b) {
type_index i, cap = value_cap(value), size = value_size(value);
if (size < cap)
value->values[size] = a, value->values[size + 1] = b;
else
fprintf(stderr
, "value cap: %u, required: %u\n", cap
, cap
+ 2), exit(EXIT_FAILURE
); }
static inline type_index bins_cap(type_table *table) {
return (type_index)1 << table->bin_power;
}
static inline type_index entries_cap(type_table *table) {
return (type_index)1 << table->entry_power;
}
static inline size_t bins_n_bytes(type_table *table) {
return sizeof *table->bins * bins_cap(table);
}
static inline size_t entries_n_bytes(type_table *table) {
return sizeof *table->entries * entries_cap(table);
}
void inspect_bins(type_table *table) {
for (size_t i = 0; i < bins_cap(table); i++)
printf("bs[%d]: %u\n", i
, table
->bins
[i
]); }
void table_inspect(type_table *table) {
printf("bin_power: %u\n", table
->bin_power
); printf("entry_power: %u\n", table
->entry_power
); printf("n_entries: %u\n", table
->n_entries
); printf("bins: %p\n", table
->bins
); printf("entries: %p\n", table
->entries
); printf("bins_cap: %p %d\n", bins_cap
(table
), bins_cap
(table
)); printf("entries_cap: %p %d\n", entries_cap
(table
), entries_cap
(table
)); }
type_table *table_new(type_index bin_power, type_index entry_power) {
type_table
*table
= malloc(sizeof (type_table
)); table->bin_power = bin_power;
table->entry_power = entry_power;
table->n_entries = 0;
table
->bins
= malloc(bins_n_bytes
(table
)); table
->entries
= malloc(entries_n_bytes
(table
)); memset(table
->bins
, 0, bins_n_bytes
(table
)); if (!table || !table->bins || !table->entries)
fprintf(stderr
, "table_new: out of memory\n"), exit(EXIT_FAILURE
); return table;
}
void table_free(type_table *table) {
}
static inline type_index calc_bin_index(type_table *table, type_key key) {
return (bins_cap(table) - 1) & key;
}
static inline type_index find_bin_index(type_table *table, type_key key) {
type_index found = calc_bin_index(table, key);
type_index collision = 0;
type_index borderline = bins_cap(table) - 1;
type_index *bins = table->bins;
type_entry *entries = table->entries;
while (bins[found] && entries[bins[found]].key != key) {
collision++;
if (borderline < collision)
fprintf(stderr
, "borderline: %u, collision: %u\n", borderline
, collision
), exit(EXIT_FAILURE
); else
found = calc_bin_index(table, found + 1);
}
return found;
}
static inline void table_put_at(type_table *table, type_key key, type_value value, type_index bin_index) {
type_index borderline = entries_cap(table) - 1;
type_index *bins = table->bins;
type_entry *entries = table->entries;
if (!bins[bin_index]) {
// bins[x] == 0はビンが未使用という表現。そのため entries[0] は欠番。最初のデータは entries[1] に入る。
if (borderline < table->n_entries + 1)
fprintf(stderr
, "borderline: %u, (table->n_entries + 1): %u\n", borderline
, table
->n_entries
+ 1), exit(EXIT_FAILURE
); table->n_entries++;
bins[bin_index] = table->n_entries;
entries[bins[bin_index]].key = key;
entries[bins[bin_index]].value = value;
} else {
// 既存のエントリに上書き。
entries[bins[bin_index]].key = key;
entries[bins[bin_index]].value = value;
}
}
void table_put(type_table *table, type_key key, type_value value) {
return table_put_at(table, key, value, find_bin_index(table, key));
}
static inline type_value *table_get_at(type_table *table, type_index bin_index) {
type_index *bins = table->bins;
type_entry *entries = table->entries;
return !bins[bin_index] ? 0 : &entries[bins[bin_index]].value;
}
type_value *table_get(type_table *table, type_key key) {
return table_get_at(table, find_bin_index(table, key));
}
int table_contains_key(type_table *table, type_key key) {
return !!table_get(table, key);
}
type_index table_size(type_table *table) {
return table->n_entries;
}
type_value f(unsigned m) {
type_table *table = table_new(27, 24);
type_value *value = 0, found;
type_index index;
type_key a, b, c;
for (a = 1; ; a++) {
for (b = 1; b < a; b++) {
c = a * a * a - b * b * b;
index = find_bin_index(table, c);
value = table_get_at(table, index);
if (value)
value_append(value, a, b);
else
table_put_at(table, c, (type_value){a, b}, index);
if (value && value_size(value) == m * 2)
goto finally;
}
}
finally:
found = *value;
table_free(table);
return found;
}
int main() {
type_value value = f(5);
value_inspect_values(&value);
return 0;
}
I2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxzdGRpby5oPgp0eXBlZGVmIHVuc2lnbmVkIGxvbmcgbG9uZyB0eXBlX2tleTsKdHlwZWRlZiBzdHJ1Y3QgdmFsdWUgewogIHVuc2lnbmVkIGludCB2YWx1ZXNbMTBdOwp9IHR5cGVfdmFsdWU7CnR5cGVkZWYgc3RydWN0IGVudHJ5IHsKICB0eXBlX2tleSBrZXk7CiAgdHlwZV92YWx1ZSB2YWx1ZTsKfSB0eXBlX2VudHJ5Owp0eXBlZGVmIHVuc2lnbmVkIGludCB0eXBlX2luZGV4Owp0eXBlZGVmIHN0cnVjdCB0YWJsZSB7CiAgdHlwZV9pbmRleCBiaW5fcG93ZXIsIGVudHJ5X3Bvd2VyLCBuX2VudHJpZXMsICpiaW5zOwogIHR5cGVfZW50cnkgKmVudHJpZXM7Cn0gdHlwZV90YWJsZTsKc3RhdGljIGlubGluZSB0eXBlX2luZGV4IHZhbHVlX2NhcCh0eXBlX3ZhbHVlICp2YWx1ZSkgewogIHJldHVybiBzaXplb2YgdmFsdWUtPnZhbHVlcyAvIHNpemVvZiAqdmFsdWUtPnZhbHVlczsKfQpzdGF0aWMgaW5saW5lIHR5cGVfaW5kZXggdmFsdWVfc2l6ZSh0eXBlX3ZhbHVlICp2YWx1ZSkgewogIHR5cGVfaW5kZXggaSwgc2l6ZSA9IHZhbHVlX2NhcCh2YWx1ZSk7CiAgZm9yIChpID0gMDsgaSA8IHNpemUgJiYgdmFsdWUtPnZhbHVlc1tpXTsgaSsrKTsKICByZXR1cm4gaTsKfQp2b2lkIHZhbHVlX2luc3BlY3RfdmFsdWVzKHR5cGVfdmFsdWUgKnZhbHVlKSB7CiAgdHlwZV9pbmRleCBpLCBjYXAgPSB2YWx1ZV9jYXAodmFsdWUpOwogIHB1dGNoYXIoJ1snKTsKICBmb3IgKGkgPSAwOyBpIDwgY2FwOyBpICs9IDIpIHsKICAgIGlmICgwIDwgaSkgcHJpbnRmKCIsICIpOwogICAgcHJpbnRmKCJbJXUsICV1XSIsIHZhbHVlLT52YWx1ZXNbaV0sIHZhbHVlLT52YWx1ZXNbaSArIDFdKTsKICB9CiAgcHV0Y2hhcignXScpOwp9CnZvaWQgdmFsdWVfaW5zcGVjdCh0eXBlX3ZhbHVlICp2YWx1ZSkgewogIHByaW50ZigidmFsdWUge2NhcDogJXUsIHNpemU6ICV1LCB2YWx1ZXM6ICIsIHZhbHVlX2NhcCh2YWx1ZSksIHZhbHVlX3NpemUodmFsdWUpKTsKICB2YWx1ZV9pbnNwZWN0X3ZhbHVlcyh2YWx1ZSk7CiAgcHV0cygifSIpOwp9CnN0YXRpYyBpbmxpbmUgdm9pZCB2YWx1ZV9hcHBlbmQodHlwZV92YWx1ZSAqdmFsdWUsIHVuc2lnbmVkIGludCBhLCB1bnNpZ25lZCBpbnQgYikgewogIHR5cGVfaW5kZXggaSwgY2FwID0gdmFsdWVfY2FwKHZhbHVlKSwgc2l6ZSA9IHZhbHVlX3NpemUodmFsdWUpOwogIGlmIChzaXplIDwgY2FwKQogICAgdmFsdWUtPnZhbHVlc1tzaXplXSA9IGEsIHZhbHVlLT52YWx1ZXNbc2l6ZSArIDFdID0gYjsKICBlbHNlCiAgICBmcHJpbnRmKHN0ZGVyciwgInZhbHVlIGNhcDogJXUsIHJlcXVpcmVkOiAldVxuIiwgY2FwLCBjYXAgKyAyKSwgZXhpdChFWElUX0ZBSUxVUkUpOwp9CnN0YXRpYyBpbmxpbmUgdHlwZV9pbmRleCBiaW5zX2NhcCh0eXBlX3RhYmxlICp0YWJsZSkgewogIHJldHVybiAodHlwZV9pbmRleCkxIDw8IHRhYmxlLT5iaW5fcG93ZXI7Cn0Kc3RhdGljIGlubGluZSB0eXBlX2luZGV4IGVudHJpZXNfY2FwKHR5cGVfdGFibGUgKnRhYmxlKSB7CiAgcmV0dXJuICh0eXBlX2luZGV4KTEgPDwgdGFibGUtPmVudHJ5X3Bvd2VyOwp9CnN0YXRpYyBpbmxpbmUgc2l6ZV90IGJpbnNfbl9ieXRlcyh0eXBlX3RhYmxlICp0YWJsZSkgewogIHJldHVybiBzaXplb2YgKnRhYmxlLT5iaW5zICogYmluc19jYXAodGFibGUpOwp9CnN0YXRpYyBpbmxpbmUgc2l6ZV90IGVudHJpZXNfbl9ieXRlcyh0eXBlX3RhYmxlICp0YWJsZSkgewogIHJldHVybiBzaXplb2YgKnRhYmxlLT5lbnRyaWVzICogZW50cmllc19jYXAodGFibGUpOwp9CnZvaWQgaW5zcGVjdF9iaW5zKHR5cGVfdGFibGUgKnRhYmxlKSB7CiAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBiaW5zX2NhcCh0YWJsZSk7IGkrKykKICAgIHByaW50ZigiYnNbJWRdOiAldVxuIiwgaSwgdGFibGUtPmJpbnNbaV0pOwp9CnZvaWQgdGFibGVfaW5zcGVjdCh0eXBlX3RhYmxlICp0YWJsZSkgewogIHByaW50ZigidGFibGU6ICVwXG4iLCB0YWJsZSk7CiAgcHJpbnRmKCJiaW5fcG93ZXI6ICV1XG4iLCB0YWJsZS0+YmluX3Bvd2VyKTsKICBwcmludGYoImVudHJ5X3Bvd2VyOiAldVxuIiwgdGFibGUtPmVudHJ5X3Bvd2VyKTsKICBwcmludGYoIm5fZW50cmllczogJXVcbiIsIHRhYmxlLT5uX2VudHJpZXMpOwogIHByaW50ZigiYmluczogJXBcbiIsIHRhYmxlLT5iaW5zKTsKICBwcmludGYoImVudHJpZXM6ICVwXG4iLCB0YWJsZS0+ZW50cmllcyk7CiAgcHJpbnRmKCJiaW5zX2NhcDogJXAgJWRcbiIsIGJpbnNfY2FwKHRhYmxlKSwgYmluc19jYXAodGFibGUpKTsKICBwcmludGYoImVudHJpZXNfY2FwOiAlcCAlZFxuIiwgZW50cmllc19jYXAodGFibGUpLCBlbnRyaWVzX2NhcCh0YWJsZSkpOwp9CnR5cGVfdGFibGUgKnRhYmxlX25ldyh0eXBlX2luZGV4IGJpbl9wb3dlciwgdHlwZV9pbmRleCBlbnRyeV9wb3dlcikgewogIHR5cGVfdGFibGUgKnRhYmxlID0gbWFsbG9jKHNpemVvZiAodHlwZV90YWJsZSkpOwogIHRhYmxlLT5iaW5fcG93ZXIgPSBiaW5fcG93ZXI7CiAgdGFibGUtPmVudHJ5X3Bvd2VyID0gZW50cnlfcG93ZXI7CiAgdGFibGUtPm5fZW50cmllcyA9IDA7CiAgdGFibGUtPmJpbnMgPSBtYWxsb2MoYmluc19uX2J5dGVzKHRhYmxlKSk7CiAgdGFibGUtPmVudHJpZXMgPSBtYWxsb2MoZW50cmllc19uX2J5dGVzKHRhYmxlKSk7CiAgbWVtc2V0KHRhYmxlLT5iaW5zLCAwLCBiaW5zX25fYnl0ZXModGFibGUpKTsKICBpZiAoIXRhYmxlIHx8ICF0YWJsZS0+YmlucyB8fCAhdGFibGUtPmVudHJpZXMpCiAgICBmcHJpbnRmKHN0ZGVyciwgInRhYmxlX25ldzogb3V0IG9mIG1lbW9yeVxuIiksIGV4aXQoRVhJVF9GQUlMVVJFKTsKICByZXR1cm4gdGFibGU7Cn0Kdm9pZCB0YWJsZV9mcmVlKHR5cGVfdGFibGUgKnRhYmxlKSB7CiAgZnJlZSh0YWJsZS0+YmlucyksIGZyZWUodGFibGUtPmVudHJpZXMpLCBmcmVlKHRhYmxlKTsKfQpzdGF0aWMgaW5saW5lIHR5cGVfaW5kZXggY2FsY19iaW5faW5kZXgodHlwZV90YWJsZSAqdGFibGUsIHR5cGVfa2V5IGtleSkgewogIHJldHVybiAoYmluc19jYXAodGFibGUpIC0gMSkgJiBrZXk7Cn0Kc3RhdGljIGlubGluZSB0eXBlX2luZGV4IGZpbmRfYmluX2luZGV4KHR5cGVfdGFibGUgKnRhYmxlLCB0eXBlX2tleSBrZXkpIHsKICB0eXBlX2luZGV4IGZvdW5kID0gY2FsY19iaW5faW5kZXgodGFibGUsIGtleSk7CiAgdHlwZV9pbmRleCBjb2xsaXNpb24gPSAwOwogIHR5cGVfaW5kZXggYm9yZGVybGluZSA9IGJpbnNfY2FwKHRhYmxlKSAtIDE7CiAgdHlwZV9pbmRleCAqYmlucyA9IHRhYmxlLT5iaW5zOwogIHR5cGVfZW50cnkgKmVudHJpZXMgPSB0YWJsZS0+ZW50cmllczsKICB3aGlsZSAoYmluc1tmb3VuZF0gJiYgZW50cmllc1tiaW5zW2ZvdW5kXV0ua2V5ICE9IGtleSkgewogICAgY29sbGlzaW9uKys7CiAgICBpZiAoYm9yZGVybGluZSA8IGNvbGxpc2lvbikKICAgICAgZnByaW50ZihzdGRlcnIsICJib3JkZXJsaW5lOiAldSwgY29sbGlzaW9uOiAldVxuIiwgYm9yZGVybGluZSwgY29sbGlzaW9uKSwgZXhpdChFWElUX0ZBSUxVUkUpOwogICAgZWxzZQogICAgICBmb3VuZCA9IGNhbGNfYmluX2luZGV4KHRhYmxlLCBmb3VuZCArIDEpOwogIH0KICByZXR1cm4gZm91bmQ7Cn0Kc3RhdGljIGlubGluZSB2b2lkIHRhYmxlX3B1dF9hdCh0eXBlX3RhYmxlICp0YWJsZSwgdHlwZV9rZXkga2V5LCB0eXBlX3ZhbHVlIHZhbHVlLCB0eXBlX2luZGV4IGJpbl9pbmRleCkgewogIHR5cGVfaW5kZXggYm9yZGVybGluZSA9IGVudHJpZXNfY2FwKHRhYmxlKSAtIDE7CiAgdHlwZV9pbmRleCAqYmlucyA9IHRhYmxlLT5iaW5zOwogIHR5cGVfZW50cnkgKmVudHJpZXMgPSB0YWJsZS0+ZW50cmllczsKICBpZiAoIWJpbnNbYmluX2luZGV4XSkgewogICAgLy8gYmluc1t4XSA9PSAw44Gv44OT44Oz44GM5pyq5L2/55So44Go44GE44GG6KGo54++44CC44Gd44Gu44Gf44KBIGVudHJpZXNbMF0g44Gv5qyg55Wq44CC5pyA5Yid44Gu44OH44O844K/44GvIGVudHJpZXNbMV0g44Gr5YWl44KL44CCCiAgICBpZiAoYm9yZGVybGluZSA8IHRhYmxlLT5uX2VudHJpZXMgKyAxKQogICAgICBmcHJpbnRmKHN0ZGVyciwgImJvcmRlcmxpbmU6ICV1LCAodGFibGUtPm5fZW50cmllcyArIDEpOiAldVxuIiwgYm9yZGVybGluZSwgdGFibGUtPm5fZW50cmllcyArIDEpLCBleGl0KEVYSVRfRkFJTFVSRSk7CiAgICB0YWJsZS0+bl9lbnRyaWVzKys7CiAgICBiaW5zW2Jpbl9pbmRleF0gPSB0YWJsZS0+bl9lbnRyaWVzOwogICAgZW50cmllc1tiaW5zW2Jpbl9pbmRleF1dLmtleSA9IGtleTsKICAgIGVudHJpZXNbYmluc1tiaW5faW5kZXhdXS52YWx1ZSA9IHZhbHVlOwogIH0gZWxzZSB7CiAgICAvLyDml6LlrZjjga7jgqjjg7Pjg4jjg6rjgavkuIrmm7jjgY3jgIIKICAgIGVudHJpZXNbYmluc1tiaW5faW5kZXhdXS5rZXkgPSBrZXk7CiAgICBlbnRyaWVzW2JpbnNbYmluX2luZGV4XV0udmFsdWUgPSB2YWx1ZTsKICB9Cn0Kdm9pZCB0YWJsZV9wdXQodHlwZV90YWJsZSAqdGFibGUsIHR5cGVfa2V5IGtleSwgdHlwZV92YWx1ZSB2YWx1ZSkgewogIHJldHVybiB0YWJsZV9wdXRfYXQodGFibGUsIGtleSwgdmFsdWUsIGZpbmRfYmluX2luZGV4KHRhYmxlLCBrZXkpKTsKfQpzdGF0aWMgaW5saW5lIHR5cGVfdmFsdWUgKnRhYmxlX2dldF9hdCh0eXBlX3RhYmxlICp0YWJsZSwgdHlwZV9pbmRleCBiaW5faW5kZXgpIHsKICB0eXBlX2luZGV4ICpiaW5zID0gdGFibGUtPmJpbnM7CiAgdHlwZV9lbnRyeSAqZW50cmllcyA9IHRhYmxlLT5lbnRyaWVzOwogIHJldHVybiAhYmluc1tiaW5faW5kZXhdID8gMCA6ICZlbnRyaWVzW2JpbnNbYmluX2luZGV4XV0udmFsdWU7Cn0KdHlwZV92YWx1ZSAqdGFibGVfZ2V0KHR5cGVfdGFibGUgKnRhYmxlLCB0eXBlX2tleSBrZXkpIHsKICByZXR1cm4gdGFibGVfZ2V0X2F0KHRhYmxlLCBmaW5kX2Jpbl9pbmRleCh0YWJsZSwga2V5KSk7Cn0KaW50IHRhYmxlX2NvbnRhaW5zX2tleSh0eXBlX3RhYmxlICp0YWJsZSwgdHlwZV9rZXkga2V5KSB7CiAgcmV0dXJuICEhdGFibGVfZ2V0KHRhYmxlLCBrZXkpOwp9CnR5cGVfaW5kZXggdGFibGVfc2l6ZSh0eXBlX3RhYmxlICp0YWJsZSkgewogIHJldHVybiB0YWJsZS0+bl9lbnRyaWVzOwp9CnR5cGVfdmFsdWUgZih1bnNpZ25lZCBtKSB7CiAgdHlwZV90YWJsZSAqdGFibGUgPSB0YWJsZV9uZXcoMjcsIDI0KTsKICB0eXBlX3ZhbHVlICp2YWx1ZSA9IDAsIGZvdW5kOwogIHR5cGVfaW5kZXggaW5kZXg7CiAgdHlwZV9rZXkgYSwgYiwgYzsKICBmb3IgKGEgPSAxOyA7IGErKykgewogICAgZm9yIChiID0gMTsgYiA8IGE7IGIrKykgewogICAgICBjID0gYSAqIGEgKiBhIC0gYiAqIGIgKiBiOwogICAgICBpbmRleCA9IGZpbmRfYmluX2luZGV4KHRhYmxlLCBjKTsKICAgICAgdmFsdWUgPSB0YWJsZV9nZXRfYXQodGFibGUsIGluZGV4KTsKICAgICAgaWYgKHZhbHVlKSAKICAgICAgICB2YWx1ZV9hcHBlbmQodmFsdWUsIGEsIGIpOwogICAgICBlbHNlIAogICAgICAgIHRhYmxlX3B1dF9hdCh0YWJsZSwgYywgKHR5cGVfdmFsdWUpe2EsIGJ9LCBpbmRleCk7CiAgICAgIAogICAgICBpZiAodmFsdWUgJiYgdmFsdWVfc2l6ZSh2YWx1ZSkgPT0gbSAqIDIpIAogICAgICAgIGdvdG8gZmluYWxseTsKICAgIH0KICB9CiBmaW5hbGx5OgogIGZvdW5kID0gKnZhbHVlOwogIHRhYmxlX2ZyZWUodGFibGUpOwogIHJldHVybiBmb3VuZDsKfQppbnQgbWFpbigpIHsKICB0eXBlX3ZhbHVlIHZhbHVlID0gZig1KTsKICB2YWx1ZV9pbnNwZWN0X3ZhbHVlcygmdmFsdWUpOwogIHJldHVybiAwOwp9Cg==