Funny tests (might remove later)

This commit is contained in:
Андреев Григорий 2025-10-20 14:54:20 +03:00
parent d2cad703b1
commit 6527ee98e0
14 changed files with 947 additions and 55 deletions

View File

@ -38,11 +38,11 @@ add_compile_options(-fno-trapping-math)
#add_executable(codegen_l1_5 src/l1_5/anne/codegen.c)
add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c)
target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng)
#add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c)
#target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -lpng)
add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
target_link_libraries(0r_tex_init_prep -lm -lpng)
#add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
#target_link_libraries(0r_tex_init_prep -lm -lpng)
#add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c)
#target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon)
@ -57,4 +57,11 @@ target_link_libraries(0r_tex_init_prep -lm -lpng)
#target_link_libraries(0_play_test -lncurses)
#
#add_executable(l2t0 src/l2/tests/data_structures/t0.c)
add_compile_definitions(RUNNING_HERE)
add_executable(l2t0 src/l2/tests/data_structures/t0.c)
add_executable(l2t1 src/l2/tests/data_structures/t1.c)
add_executable(H src/l2/tests/r_alg/H.c)
add_executable(I src/l2/tests/r_alg/I.c)
add_executable(J src/l2/tests/r_alg/J.c)

View File

@ -10,7 +10,7 @@ HEADERS_src_l2 := $(HEADERS_gen_l1_5) $(call find_headers,l2)
HEADERS_gen_l2 := $(HEADERS_src_l2) gen/l2/dorothy.txt
cflags := -Wall -Wextra -Werror=implicit-function-declaration -Werror=return-type -Wno-unused-parameter \
--std=c99 -g -ggdb -O3 \
--std=c99 -g -ggdb -O0 \
-fno-trapping-math -D_POSIX_C_SOURCE=200112L -D_GNU_SOURCE
cc := gcc
@ -106,7 +106,16 @@ out/l2/r3: src/l2/tests/r3/r3.c $(HEADERS_src_l2) $(l_wl_protocols)
run_r3: out/l2/r3
./out/l2/r3
out/SICK_JOKE_H.c: src/l2/tests/r_alg/H.c $(HEADERS_gen_l1_5)
python src/l1/sobiralka.py $< $@
out/SICK_JOKE_I.c: src/l2/tests/r_alg/I.c $(HEADERS_gen_l1_5)
python src/l1/sobiralka.py $< $@
out/SICK_JOKE_J.c: src/l2/tests/r_alg/J.c $(HEADERS_gen_l1_5)
python src/l1/sobiralka.py $< $@
.PHONY: clean
clean:
rm -rf gen out
rm -rf gen out

View File

@ -32,6 +32,12 @@ void generate_headers_for_r0_r1_r2_r3() {
.T = cstr("PlayingSound"), .vec_extended = true
});
}
mkdir_nofail("l1/eve/r_alg");
{ /* r_alg. Wow! Even these freaks are here! */
SpanU8 ns = cstr("r_alg");
generate_eve_span_company_for_primitive(l, ns, cstr("I_FishNode"), true, false);
generate_eve_span_company_for_primitive(l, ns, cstr("J_AlphaVertex"), true, false);
}
}
#endif

View File

@ -6,7 +6,7 @@
/* These headers are guarded */
void generate_util_temp_very_base_headers() {
SpanU8 l = cstr("l1"), ns = cstr("");
SpanU8 T_codegen_VecAndSpan[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64")};
SpanU8 T_codegen_VecAndSpan[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64")};
SpanU8 T_codegen_Option[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64")};
SpanU8 T_codegen_VecAndSpan_of_Vec[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")};
SpanU8 T_codegen_VecAndSpan_of_Span[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")};

View File

@ -30,20 +30,20 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_reserved(size_t n) {\n"
SPACE "return (%s){ .buf = safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n"
"}\n\n", VecT, VecT, VecT, T));
SPACE "return (%s){ .buf = (%s*)safe_calloc(n, sizeof(%s)), .len = 0, .capacity = n };\n"
"}\n\n", VecT, VecT, VecT, T, T));
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append(%s* self, %s el) {\n"
"void %s_append(%s* self, %s el) {\n" /* VecT, VecT, T */
SPACE "size_t new_length = self->len + 1;\n"
SPACE "if (new_length > self->capacity) {\n"
SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n"
SPACE SPACE "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n"
SPACE SPACE "self->buf = (%s*)safe_realloc(self->buf, new_capacity * sizeof(%s));\n" /* T, T */
SPACE SPACE "self->capacity = new_capacity;\n"
SPACE "}\n"
SPACE "self->buf[self->len] = el;\n"
SPACE "self->len = new_length;\n"
"}\n\n", VecT, VecT, T, T));
"}\n\n", VecT, VecT, T, T, T));
VecU8_append_vec(&res, VecU8_fmt(
"%s* %s_mat(%s* self, size_t i) {\n"
@ -59,9 +59,9 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
if (clonable) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_clone(const %s* self) {\n"
SPACE "%s res = (%s){.buf = safe_calloc(self->len, sizeof(%s)), .len = self->len, .capacity = self->len};\n",
VecT, VecT, VecT, VecT, VecT, T));
"NODISCARD %s %s_clone(const %s* self) {\n" /* VecT, VecT, VecT */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(self->len, sizeof(%s)), .len = self->len, .capacity = self->len};\n",
VecT, VecT, VecT, VecT, VecT, T, T));
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(SPACE "memcpy(res.buf, self->buf, self->len * sizeof(%s));\n", T));
} else {
@ -73,11 +73,11 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
}
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append_vec(%s* self, %s b) {\n"
"void %s_append_vec(%s* self, %s b) {\n" /* VecT, VecT, VecT */
SPACE "size_t new_length = self->len + b.len;\n"
SPACE "if (new_length > self->capacity) {\n"
SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n"
SPACE SPACE "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n"
SPACE SPACE "self->buf = (%s*)safe_realloc(self->buf, new_capacity * sizeof(%s));\n" /* T, T */
SPACE SPACE "self->capacity = new_capacity;\n"
SPACE "}\n"
SPACE "for (size_t i = 0; i < b.len; i++){\n"
@ -85,13 +85,14 @@ NODISCARD VecU8 generate_VecT_struct_and_base_methods(SpanU8 T, bool primitive,
SPACE "}\n"
SPACE "self->len = new_length;\n"
SPACE "free(b.buf);\n"
"}\n\n", VecT, VecT, VecT, T));
"}\n\n", VecT, VecT, VecT, T, T));
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_zeroinit(size_t len) {\n"
SPACE "return (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n"
"}\n\n", VecT, VecT, VecT, T));
"NODISCARD %s %s_new_zeroinit(size_t len) {\n" /* VecT, VecT*/
SPACE "return (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, T, T */
"}\n\n",
VecT, VecT, VecT, T, T));
}
VecU8_drop(g_VecT); // VecT invalidated too
@ -148,20 +149,20 @@ NODISCARD VecU8 generate_VecT_trivmove_extended_methods(SpanU8 T, bool primitive
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_filled(size_t len, %s el) {\n"
SPACE "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n"
"NODISCARD %s %s_new_filled(size_t len, %s el) {\n" /* VecT, VecT, T */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = el;\n"
SPACE "return res;\n"
"}\n\n", VecT, VecT, T, VecT, VecT, T));
"}\n\n", VecT, VecT, T, VecT, VecT, T, T));
} else if (clonable) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_new_filled(size_t len, const %s* el) {\n"
SPACE "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n"
"NODISCARD %s %s_new_filled(size_t len, const %s* el) {\n" /* VecT, VecT, T */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = %s_clone(el);\n"
SPACE SPACE "res.buf[i] = %s_clone(el);\n" /* T */
SPACE "return res;\n"
"}\n\n", VecT, VecT, T, VecT, VecT, T, T));
"}\n\n", VecT, VecT, T, VecT, VecT, T, T, T));
}
VecU8_drop(g_VecT); // VecT invalidated
@ -198,12 +199,12 @@ NODISCARD VecU8 generate_VecT_new_of_size_method(SpanU8 T) {
VecU8 g_VecT = VecU8_fmt("Vec%s", T);
SpanU8 VecT = VecU8_to_span(&g_VecT);
VecU8 res = VecU8_fmt(
"NODISCARD %s %s_new_of_size(size_t len) {\n"
SPACE "%s res = (%s){.buf = safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n"
"NODISCARD %s %s_new_of_size(size_t len) {\n" /* VecT, VecT */
SPACE "%s res = (%s){.buf = (%s*)safe_calloc(len, sizeof(%s)), .len = len, .capacity = len};\n" /* VecT, VecT, T, T */
SPACE "for (size_t i = 0; i < len; i++)\n"
SPACE SPACE "res.buf[i] = %s_new();\n"
SPACE SPACE "res.buf[i] = %s_new();\n" /* T */
SPACE "return res;\n"
"}\n", VecT, VecT, VecT, VecT, T, T);
"}\n", VecT, VecT, VecT, VecT, T, T, T);
VecU8_drop(g_VecT);
return res;
@ -319,9 +320,9 @@ NODISCARD VecU8 generate_SpanT_VecT_trivmove_collab(SpanU8 T, bool primitive, bo
if (clonable) {
VecU8_append_vec(&res, VecU8_fmt(
"NODISCARD %s %s_from_span(%s src){\n"
SPACE "%s res = (%s){ .buf = safe_calloc(src.len, sizeof(%s)), .len = src.len, .capacity = src.len };\n",
VecT, VecT, SpanT, VecT, VecT, T));
"NODISCARD %s %s_from_span(%s src){\n" /* VecT, VecT, SpanT */
SPACE "%s res = (%s){ .buf = (%s*)safe_calloc(src.len, sizeof(%s)), .len = src.len, .capacity = src.len };\n", /* VecT, VecT, T, T */
VecT, VecT, SpanT, VecT, VecT, T, T));
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(
SPACE "memcpy(res.buf, src.data, src.len * sizeof(%s));\n", T));
@ -346,13 +347,13 @@ NODISCARD VecU8 generate_SpanT_VecT_trivmove_collab(SpanU8 T, bool primitive, bo
if (clonable) {
VecU8_append_vec(&res, VecU8_fmt(
"void %s_append_span(%s* self, %s b) {\n"
"void %s_append_span(%s* self, %s b) {\n" /* VecT, VecT, SpanT */
SPACE "size_t new_length = self->len + b.len;\n"
SPACE "if (new_length > self->capacity) {\n"
SPACE SPACE "size_t new_capacity = Vec_get_new_capacity(self->capacity, new_length);\n"
SPACE SPACE "self->buf = safe_realloc(self->buf, new_capacity * sizeof(%s));\n"
SPACE SPACE "self->buf = (%s*)safe_realloc(self->buf, new_capacity * sizeof(%s));\n" /* T, T */
SPACE SPACE "self->capacity = new_capacity;\n"
SPACE "}\n", VecT, VecT, SpanT, T));
SPACE "}\n", VecT, VecT, SpanT, T, T));
if (primitive) {
VecU8_append_vec(&res, VecU8_fmt(
SPACE "memcpy(self->buf + self->len, b.data, b.len * sizeof(%s));\n", T));

View File

@ -10,9 +10,9 @@
#include <inttypes.h>
#include "int_primitives.h"
// Gonna change it when I face pedantic compilers
#define NORETURN [[noreturn]]
#define NODISCARD [[nodiscard]]
// Gonna change it
#define NORETURN __attribute((noreturn))
#define NODISCARD __attribute((warn_unused_result))
typedef const char* CSTR;
@ -54,16 +54,6 @@ void* safe_realloc(void* ptr, size_t n) {
return res;
}
// todo: rewrite it to make it faster
#define unsigned_safe_mul_Definition(TSZ) \
U##TSZ safe_mul_U##TSZ(U##TSZ a, U##TSZ b) { \
if (b > 0 && a > UINT##TSZ##_MAX / b) \
abortf("Overflow in multiplication: %" PRIu##TSZ " * %" PRIu##TSZ "\n", a, b); \
return a * b; \
}
unsigned_safe_mul_Definition(64)
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/* I assume that new_length > old_capacity */

View File

@ -0,0 +1,85 @@
#ifndef prototype1_src_l1_5_core_input_olproga_h
#define prototype1_src_l1_5_core_input_olproga_h
#include "../../../gen/l1/OptionU64.h"
#include "../../../gen/l1/VecAndSpan_U8.h"
void stdin_skip_whitespaces(){
while (true) {
int ch = fgetc(stdin);
if (ch == EOF)
return;
if (ch < 0) {
perror("fgetc(stdin)");
abort();
}
if (ch != ' ' && ch != '\t' && ch != '\n') {
ungetc(ch, stdin);
break;
}
}
}
// Aborts on error
OptionU64 stdin_read_U64(){
stdin_skip_whitespaces();
U64 x = 0;
int i = 0;
for (;; i++) {
int ch = fgetc(stdin);
if (ch == EOF)
break;
if (ch < 0) {
perror("fgetc(stdin)");
abort();
}
if (!('0' <= ch && ch <= '9')) {
ungetc(ch, stdin);
break;
}
U64 d = (U64)(ch - '0');
if (x == 0 && i > 0)
abortf("Bad integer input\n");
if (x > UINT64_MAX / 10)
abortf("Integer input exceeds UINT64_MAX\n");
x *= 10;
if (x > UINT64_MAX - d)
abortf("Integer input exceeds UINT64_MAX\n");
x += d;
}
if (i > 0)
return Some_U64(x);
return None_U64();
}
/* If empty string is returned it means EOF was reached */
NODISCARD VecU8 stdin_read_VecU8_nospace(){
stdin_skip_whitespaces();
VecU8 str = VecU8_new();
while (true) {
int ch = fgetc(stdin);
if (ch == EOF)
break;
if (ch < 0) {
perror("fgetc(stdin)");
abort();
}
if (ch == ' ' || ch == '\t' || ch == '\n') {
ungetc(ch, stdin);
break;
}
VecU8_append(&str, ch);
}
return str;
}
// Aborts if non-integer input or EOF was encountered before my integer
U64 stdin_read_U64_nofail(){
OptionU64 x = stdin_read_U64();
if (x.variant == Option_None)
abortf("No number found\n");
return x.some;
}
#endif

View File

@ -0,0 +1,42 @@
#ifndef prototype1_src_l1_5_core_stringsearch_h
#define prototype1_src_l1_5_core_stringsearch_h
#include "../../l1/core/VecU8_as_str.h"
#include "../../../gen/l1/VecAndSpan_U64.h"
NODISCARD VecU64 prefix_function(SpanU8 s){
VecU64 prefix = VecU64_new_zeroinit(s.len + 1);
for (size_t i = 1; i < s.len; i++) {
size_t k = prefix.buf[i];
while (k > 0 && s.data[k] != s.data[i])
k = prefix.buf[k];
if (s.data[k] == s.data[i])
k++;
prefix.buf[i + 1] = k;
}
return prefix;
}
NODISCARD VecU64 z_function(SpanU8 s){
VecU64 Z = VecU64_new_zeroinit(s.len + 1);
Z.buf[0] = s.len;
size_t l = 0, r = 0;
for (size_t i = 1; i <= s.len; i++) {
if (i + 1 < r) {
Z.buf[i] = MIN_U64(r - i, Z.buf[i - l]);
}
while (i + Z.buf[i] < s.len && s.data[Z.buf[i]] == s.data[i + Z.buf[i]]) {
Z.buf[i]++;
}
if (i + Z.buf[i] >= r) {
l = i;
r = i + Z.buf[i];
}
}
return Z;
}
#endif

View File

@ -1007,7 +1007,7 @@ VkDeviceMemory margaret_initialize_buffers_and_images(
#define margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(TV) \
MargaretBufferInMemoryInfo TV##_buffer_crinfo_of_gpu_vbo(size_t n) { \
return (MargaretBufferInMemoryInfo){ \
.sz = safe_mul_U64(sizeof(TV), n), \
.sz = sizeof(TV) * n, \
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT \
}; \
}

View File

@ -0,0 +1,93 @@
#include "../../../l1_5/core/stringsearch.h"
void VecU64_fprint_debug_vivod(FILE* file, const VecU64* vec){
for (size_t i = 0; i < vec->len; i++) {
fprintf(file, "%lu ", vec->buf[i]);
}
fprintf(file, "\n");
}
VecU64 trivial_prefix_function(SpanU8 s){
VecU64 prefix = VecU64_new_zeroinit(s.len + 1);
for (size_t i = 0; i <= s.len; i++) {
for (size_t k = 0; k < i; k++) {
for (size_t j = 0; j < k; j++) {
if (s.data[j] != s.data[i - k + j])
goto cnt;
}
prefix.buf[i] = k;
cnt:
continue;
}
}
return prefix;
}
VecU64 trivial_z_function(SpanU8 s){
VecU64 z = VecU64_new_zeroinit(s.len + 1);
for (size_t i = 0; i <= s.len; i++) {
for (size_t j = 0; i + j < s.len; j++) {
if (s.data[j] != s.data[i + j])
break;
z.buf[i]++;
}
}
return z;
}
void test_prefix_function(SpanU8 str){
VecU64 correct = trivial_prefix_function(str);
VecU64 my = prefix_function(str);
if (!VecU64_equal_VecU64(&correct, &my)) {
fprintf(stderr, "Test Pi ");
SpanU8_fprint(str, stderr);
fprintf(stderr, "\n");
fprintf(stderr, "Correct: ");
VecU64_fprint_debug_vivod(stderr, &correct);
fprintf(stderr, "My: ");
VecU64_fprint_debug_vivod(stderr, &my);
abort();
}
VecU64_drop(correct);
VecU64_drop(my);
}
void test_z_function(SpanU8 str){
VecU64 correct = trivial_z_function(str);
VecU64 my = z_function(str);
if (!VecU64_equal_VecU64(&correct, &my)) {
fprintf(stderr, "Test Z ");
SpanU8_fprint(str, stderr);
fprintf(stderr, "\n");
fprintf(stderr, "Correct: ");
VecU64_fprint_debug_vivod(stderr, &correct);
fprintf(stderr, "My: ");
VecU64_fprint_debug_vivod(stderr, &my);
abort();
}
VecU64_drop(correct);
VecU64_drop(my);
}
int main(){
test_prefix_function(cstr(""));
test_prefix_function(cstr("a"));
test_prefix_function(cstr("ab"));
test_prefix_function(cstr("aaaa"));
test_prefix_function(cstr("aabbaabxxxaabbaab"));
test_z_function(cstr(""));
test_z_function(cstr("a"));
test_z_function(cstr("aa"));
test_z_function(cstr("aaa"));
test_z_function(cstr("aaaa"));
test_z_function(cstr("ab"));
test_z_function(cstr("aba"));
test_z_function(cstr("bbaa"));
test_z_function(cstr("abacad"));
test_prefix_function(cstr("hsooihoioifodoiwoihoiodisifoioihhhshshsshsoodfojoioow"));
test_z_function(cstr("kdfkjpkjpksdpsdkpfpkspksfpksdpjpsdpdfjpospsdjpsdpfpspsf"));
test_prefix_function(cstr("alkalaalkalakalkalakklakalalkalaakllaklakka"));
test_z_function(cstr("alkalaalkalakalkalakklakalalkalaakllaklakka"));
}

View File

@ -98,11 +98,11 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat colorbuffer_
}
MargaretBufferInMemoryInfo GenericMeshVertex_buffer_crinfo_of_gpu_vbo(size_t n) {
return (MargaretBufferInMemoryInfo){ .sz = safe_mul_U64(sizeof(GenericMeshVertex), n),
return (MargaretBufferInMemoryInfo){ .sz = sizeof(GenericMeshVertex) * n,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT };
}
MargaretBufferInMemoryInfo ShinyMeshVertex_buffer_crinfo_of_gpu_vbo(size_t n) {
return (MargaretBufferInMemoryInfo){ .sz = safe_mul_U64(sizeof(ShinyMeshVertex), n),
return (MargaretBufferInMemoryInfo){ .sz = sizeof(ShinyMeshVertex) * n,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT };
}

68
src/l2/tests/r_alg/H.c Normal file
View File

@ -0,0 +1,68 @@
/* We switch on the light */
#include "../../../l1_5/core/stringsearch.h"
#include "../../../l1_5/core/input_olproga.h"
#include "../../../../gen/l1/VecAndSpan_VecU64.h"
#include "../../../../gen/l1/VecAndSpan_U64.h"
// Aborts on errors
U64 fast_solution(U64 n, U64 a, U64 b, const VecU8* S){
VecVecU64 Z = VecVecU64_new();
for (size_t i = 0; i < n; i++) {
VecU64 z = z_function(VecU8_span(S, i, n - i));
VecVecU64_append(&Z, z);
}
VecU64 dp = VecU64_new_filled(n + 1, UINT64_MAX);
dp.buf[0] = 0;
for (size_t k = 0; k < n; k++) {
size_t score_here = dp.buf[k];
dp.buf[k + 1] = MIN_U64(dp.buf[k + 1], score_here + a);
size_t lets = 0;
for (size_t sss = 0; sss <= k; sss++) {
size_t before = k - sss;
size_t reach = Z.buf[sss].buf[before];
lets = MAX_U64(lets, MIN_U64(reach, before));
}
for (size_t after = 1; after <= lets; after++) {
dp.buf[k + after] = MIN_U64(dp.buf[k + after], score_here + b);
}
}
return dp.buf[n];
}
U64 correct_solution(U64 n, U64 a, U64 b, const VecU8* S){
VecU64 dp = VecU64_new_filled(n + 1, UINT64_MAX);
dp.buf[0] = 0;
for (size_t i = 1; i <= n; i++) {
dp.buf[i] = dp.buf[i - 1] + a;
for (size_t gb = 1; gb <= i; gb++) {
for (size_t start = 0; start + gb * 2 <= i; gb++) {
for (size_t j = 0; j < gb; j++) {
if (S->buf[start + j] != S->buf[i - gb + j])
goto incorrect;
}
/* It was correct */
dp.buf[i] = MIN_U64(dp.buf[i], dp.buf[i - gb] + b);
incorrect:
continue;
}
}
}
return dp.buf[n];
}
int main(){
U64 n = stdin_read_U64_nofail();
U64 a = stdin_read_U64_nofail();
U64 b = stdin_read_U64_nofail();
VecU8 S = stdin_read_VecU8_nospace();
assert(n != 0 && S.len == n);
assert(n <= 5000);
assert(a <= 5000 && b <= 5000);
printf("%lu\n", fast_solution(n, a, b, &S));
return 0;
}

304
src/l2/tests/r_alg/I.c Normal file
View File

@ -0,0 +1,304 @@
/* Your death is near */
#include "../../../../gen/l1/VecAndSpan_U8.h"
#include "../../../../gen/l1/VecAndSpan_VecU8.h"
#include "../../../../gen/l1/VecAndSpan_VecU32.h"
#include "../../../../gen/l1/VecAndSpan_S64.h"
#include "../../../../gen/l1/VecAndSpan_U64.h"
// #include "../../../l1_5/core/input_olproga.h"
#include "../../../../gen/l1/OptionU64.h"
#define BUF_SIZE 4096
static unsigned char buf[BUF_SIZE];
static size_t pos = 0, sz = 0;
static int pushback = EOF;
int fast_getc() {
if (pushback != EOF) {
int c = pushback;
pushback = EOF;
return c;
}
if (pos == sz) {
sz = fread(buf, 1, BUF_SIZE, stdin);
pos = 0;
if (sz == 0) return EOF;
}
return (int)buf[pos++];
}
void fast_ungetc(int c) {
if (pushback != EOF) {
abort(); // Multiple pushbacks not supported (not needed in your functions)
}
pushback = c;
}
void stdin_skip_whitespaces() {
while (true) {
int ch = fast_getc();
if (ch == EOF)
return;
if (ch != ' ' && ch != '\t' && ch != '\n') {
fast_ungetc(ch);
break;
}
}
}
// Aborts on error
OptionU64 stdin_read_U64() {
stdin_skip_whitespaces();
U64 x = 0;
int i = 0;
for (;; i++) {
int ch = fast_getc();
if (ch == EOF)
break;
if (!('0' <= ch && ch <= '9')) {
fast_ungetc(ch);
break;
}
U64 d = (U64)(ch - '0');
if (x == 0 && i > 0)
abortf("Bad integer input\n");
if (x > UINT64_MAX / 10)
abortf("Integer input exceeds UINT64_MAX\n");
x *= 10;
if (x > UINT64_MAX - d)
abortf("Integer input exceeds UINT64_MAX\n");
x += d;
}
if (i > 0)
return Some_U64(x);
return None_U64();
}
/* If empty string is returned it means EOF was reached */
NODISCARD VecU8 stdin_read_VecU8_nospace() {
stdin_skip_whitespaces();
VecU8 str = VecU8_new();
while (true) {
int ch = fast_getc();
if (ch == EOF)
break;
if (ch == ' ' || ch == '\t' || ch == '\n') {
fast_ungetc(ch);
break;
}
VecU8_append(&str, ch);
}
return str;
}
// Aborts if non-integer input or EOF was encountered before my integer
U64 stdin_read_U64_nofail() {
OptionU64 x = stdin_read_U64();
if (x.variant == Option_None)
abortf("No number found\n");
return x.some;
}
typedef struct {
U64 suf_link;
U64 ans_up_link;
U64 transition[26];
S64 class_ref;
} I_FishNode;
I_FishNode I_FishNode_new(){
/* C++ is fucking lame*/
return (I_FishNode){.suf_link = 0, .ans_up_link = 0, .transition = {0}, .class_ref = -1};
// return (I_FishNode){.class_ref = -1};
}
#include "../../../../gen/l1/eve/r_alg/VecI_FishNode.h"
typedef struct {
VecS64 next_same_ref_on_strings;
VecI_FishNode nodes;
} Fish;
Fish incomplete_Fish_from_VecU8(SpanVecU8 S){
VecS64 next_same_ref_on_strings = VecS64_new_filled(S.len, -1);
VecI_FishNode nodes = VecI_FishNode_new_reserved(1000001);
VecI_FishNode_append(&nodes, I_FishNode_new());
assert(nodes.buf[0].suf_link == 0 && nodes.buf[0].ans_up_link == 0 && nodes.buf[0].transition[0] == 0);
for (size_t j = 0; j < S.len; j++) {
SpanU8 str = VecU8_to_span(&S.data[j]);
U64 cur = 0; /* cur trie node */
for (size_t i = 0; i < str.len; i++) {
U8 ch = str.data[i];
assert('a' <= ch && ch <= 'z');
U8 d = ch - 'a';
assert(d < 26);
assert(cur < nodes.len);
if (nodes.buf[cur].transition[d] == 0) {
U64 nid = nodes.len;
VecI_FishNode_append(&nodes, I_FishNode_new());
nodes.buf[cur].transition[d] = nid;
}
assert(nodes.buf[cur].transition[d] < nodes.len);
assert(nodes.buf[cur].transition[d] != 0);
cur = nodes.buf[cur].transition[d];
}
if (nodes.buf[cur].class_ref != -1) {
assert(next_same_ref_on_strings.buf[j] == -1);
next_same_ref_on_strings.buf[j] = nodes.buf[cur].class_ref;
}
nodes.buf[cur].class_ref = (S64)j;
}
return (Fish){.next_same_ref_on_strings=next_same_ref_on_strings, .nodes=nodes};
}
/* Debug function */
void Fish_debug_print(const Fish* self){
printf("next_same_ref_on_strings:\n");
for (size_t i = 0; i < self->next_same_ref_on_strings.len; i++)
printf("%3ld ", self->next_same_ref_on_strings.buf[i]);
printf("\n");
size_t nc = self->nodes.len;
for (size_t i = 0; i < nc; i++)
printf("=== ");
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("%3ld ", self->nodes.buf[i].class_ref);
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("--- ");
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("%3lu ", self->nodes.buf[i].suf_link);
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("--- ");
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("%3lu ", self->nodes.buf[i].ans_up_link);
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("--- ");
printf("\n");
for (U8 d = 0; d < 26; d++) {
for (size_t i = 0; i < nc; i++) {
printf("%3lu ", self->nodes.buf[i].transition[d]);
}
printf("\n");
}
}
void complete_Fish(Fish* fish){
/* trie unpacked */
size_t nc = fish->nodes.len;
assert(nc >= 1);
/* We first, fields suf_link, ans_up_link are filled with garbage */
// Except for root. Root is already almost initialized
assert(fish->nodes.buf[0].suf_link == 0 && fish->nodes.buf[0].ans_up_link == 0);
// Some transitions are already complete. Those that contain 0 are yet to be filled
// transitions to 0 can't occur naturally in Trie. (Incomplete Fish = Trie)
VecU64 bfs_cur = VecU64_new_zeroinit(1); /* Initialize with one node pointing to the */
VecU64 bfs_next = VecU64_new();
while (bfs_cur.len > 0) {
do {
U64 pu = VecU64_pop(&bfs_cur);
for (U8 d = 0; d < 26; d++) {
if (fish->nodes.buf[pu].transition[d] != 0) {
U64 u = fish->nodes.buf[pu].transition[d];
U64 u_suf_link = pu == 0 ? 0 : fish->nodes.buf[fish->nodes.buf[pu].suf_link].transition[d];
fish->nodes.buf[u].suf_link = u_suf_link;
if (fish->nodes.buf[u_suf_link].class_ref != -1) {
fish->nodes.buf[u].ans_up_link = u_suf_link;
} else {
fish->nodes.buf[u].ans_up_link = fish->nodes.buf[u_suf_link].ans_up_link;
}
// fish->nodes.buf[pu].transition[d] = u;
VecU64_append(&bfs_next, u);
} else if (pu == 0) {
fish->nodes.buf[pu].transition[d] = 0;
} else {
fish->nodes.buf[pu].transition[d] = fish->nodes.buf[fish->nodes.buf[pu].suf_link].transition[d];
}
}
} while (bfs_cur.len > 0);
VecU64 t = bfs_cur;
bfs_cur = bfs_next;
bfs_next = t;
}
VecU64_drop(bfs_cur);
VecU64_drop(bfs_next);
}
void Fish_drop(Fish self){
VecS64_drop(self.next_same_ref_on_strings);
VecI_FishNode_drop(self.nodes);
}
int main() {
// #ifndef RUNNING_HERE
freopen("inputik.txt", "r", stdin);
freopen("outputik.txt", "w", stdout);
// #endif
VecU8 T = stdin_read_VecU8_nospace();
U64 N = stdin_read_U64_nofail();
VecVecU8 S = VecVecU8_new_of_size(N);
for (size_t i = 0; i < N; i++) {
VecU8 s = stdin_read_VecU8_nospace();
assert(S.buf[i].buf == NULL);
S.buf[i] = s;
}
Fish fish = incomplete_Fish_from_VecU8(VecVecU8_to_span(&S));
// Fish_debug_print(&fish);
complete_Fish(&fish);
VecVecU32 answer = VecVecU32_new_of_size(N);
/* going through T to fill answer */
U64 fish_v = 0;
for (size_t i = 0;; i++) {
int VIBE_CHECK = 0; // Can be safely removed
U64 CUR = fish_v;
while (true) {
S64 j_in_class = fish.nodes.buf[CUR].class_ref;
if (j_in_class == -1) // Can be safely removed
VIBE_CHECK++; // Can be safely removed
while (j_in_class != -1) {
assert(j_in_class < (S64)N);
size_t slen = S.buf[j_in_class].len;
assert(slen <= i);
VecU32_append(&answer.buf[j_in_class], (U32)(i - slen));
j_in_class = fish.next_same_ref_on_strings.buf[j_in_class];
}
/* We give a root a chance to execute, yet this is where we stop */
if (CUR == 0)
break;
CUR = fish.nodes.buf[CUR].ans_up_link;
}
if (VIBE_CHECK > 2) // Can be safely removed
abort(); // Can be safely removed
if (i == T.len)
break;
U8 ch = T.buf[i];
assert('a' <= ch && ch <= 'z');
U8 d = ch - 'a';
assert(d < 26);
fish_v = fish.nodes.buf[fish_v].transition[d];
}
for (size_t i = 0; i < N; i++) {
printf("%lu", answer.buf[i].len);
for (size_t e = 0; e < answer.buf[i].len; e++) {
printf(" %u", answer.buf[i].buf[e] + 1);
}
printf("\n");
}
VecVecU8_drop(S);
VecVecU32_drop(answer);
Fish_drop(fish);
VecU8_drop(T);
return 0;
}

287
src/l2/tests/r_alg/J.c Normal file
View File

@ -0,0 +1,287 @@
/* __You get millions of volts__ */
#include "../../../../gen/l1/VecAndSpan_U8.h"
#include "../../../../gen/l1/VecAndSpan_VecU8.h"
#include "../../../../gen/l1/VecAndSpan_S64.h"
#include "../../../../gen/l1/VecAndSpan_U64.h"
#include "../../../l1_5/core/input_olproga.h"
typedef struct {
U64 suf_link;
U64 ans_up_link;
U64 transition[26];
S64 class_ref;
} I_FishNode;
I_FishNode I_FishNode_new(){
/* C++ is fucking lame*/
return (I_FishNode){.suf_link = 0, .ans_up_link = 0, .transition = {0}, .class_ref = -1};
// return (I_FishNode){.class_ref = -1};
}
#include "../../../../gen/l1/eve/r_alg/VecI_FishNode.h"
typedef struct {
VecS64 next_same_ref_on_strings;
VecI_FishNode nodes;
} Fish;
Fish incomplete_Fish_from_VecU8(SpanVecU8 S){
VecS64 next_same_ref_on_strings = VecS64_new_filled(S.len, -1);
VecI_FishNode nodes = VecI_FishNode_new_reserved(1000001);
VecI_FishNode_append(&nodes, I_FishNode_new());
assert(nodes.buf[0].suf_link == 0 && nodes.buf[0].ans_up_link == 0 && nodes.buf[0].transition[0] == 0);
for (size_t j = 0; j < S.len; j++) {
SpanU8 str = VecU8_to_span(&S.data[j]);
U64 cur = 0; /* cur trie node */
for (size_t i = 0; i < str.len; i++) {
U8 ch = str.data[i];
assert('a' <= ch && ch <= 'z');
U8 d = ch - 'a';
assert(d < 26);
assert(cur < nodes.len);
if (nodes.buf[cur].transition[d] == 0) {
U64 nid = nodes.len;
VecI_FishNode_append(&nodes, I_FishNode_new());
nodes.buf[cur].transition[d] = nid;
}
assert(nodes.buf[cur].transition[d] < nodes.len);
assert(nodes.buf[cur].transition[d] != 0);
cur = nodes.buf[cur].transition[d];
}
if (nodes.buf[cur].class_ref != -1) {
assert(next_same_ref_on_strings.buf[j] == -1);
next_same_ref_on_strings.buf[j] = nodes.buf[cur].class_ref;
}
nodes.buf[cur].class_ref = (S64)j;
}
return (Fish){.next_same_ref_on_strings=next_same_ref_on_strings, .nodes=nodes};
}
/* Debug function */
void Fish_debug_print(const Fish* self){
printf("next_same_ref_on_strings:\n");
for (size_t i = 0; i < self->next_same_ref_on_strings.len; i++)
printf("%3ld ", self->next_same_ref_on_strings.buf[i]);
printf("\n");
size_t nc = self->nodes.len;
for (size_t i = 0; i < nc; i++)
printf("=== ");
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("%3ld ", self->nodes.buf[i].class_ref);
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("--- ");
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("%3lu ", self->nodes.buf[i].suf_link);
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("--- ");
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("%3lu ", self->nodes.buf[i].ans_up_link);
printf("\n");
for (size_t i = 0; i < nc; i++)
printf("--- ");
printf("\n");
for (U8 d = 0; d < 26; d++) {
for (size_t i = 0; i < nc; i++) {
printf("%3lu ", self->nodes.buf[i].transition[d]);
}
printf("\n");
}
}
void complete_Fish(Fish* fish){
/* trie unpacked */
size_t nc = fish->nodes.len;
assert(nc >= 1);
/* We first, fields suf_link, ans_up_link are filled with garbage */
// Except for root. Root is already almost initialized
assert(fish->nodes.buf[0].suf_link == 0 && fish->nodes.buf[0].ans_up_link == 0);
// Some transitions are already complete. Those that contain 0 are yet to be filled
// transitions to 0 can't occur naturally in Trie. (Incomplete Fish = Trie)
VecU64 bfs_cur = VecU64_new_zeroinit(1); /* Initialize with one node pointing to the */
VecU64 bfs_next = VecU64_new();
while (bfs_cur.len > 0) {
do {
U64 pu = VecU64_pop(&bfs_cur);
for (U8 d = 0; d < 26; d++) {
if (fish->nodes.buf[pu].transition[d] != 0) {
U64 u = fish->nodes.buf[pu].transition[d];
U64 u_suf_link = pu == 0 ? 0 : fish->nodes.buf[fish->nodes.buf[pu].suf_link].transition[d];
fish->nodes.buf[u].suf_link = u_suf_link;
if (fish->nodes.buf[u_suf_link].class_ref != -1) {
fish->nodes.buf[u].ans_up_link = u_suf_link;
} else {
fish->nodes.buf[u].ans_up_link = fish->nodes.buf[u_suf_link].ans_up_link;
}
// fish->nodes.buf[pu].transition[d] = u;
VecU64_append(&bfs_next, u);
} else if (pu == 0) {
fish->nodes.buf[pu].transition[d] = 0;
} else {
fish->nodes.buf[pu].transition[d] = fish->nodes.buf[fish->nodes.buf[pu].suf_link].transition[d];
}
}
} while (bfs_cur.len > 0);
VecU64 t = bfs_cur;
bfs_cur = bfs_next;
bfs_next = t;
}
VecU64_drop(bfs_cur);
VecU64_drop(bfs_next);
}
void Fish_drop(Fish self){
VecS64_drop(self.next_same_ref_on_strings);
VecI_FishNode_drop(self.nodes);
}
typedef struct {
U64 trans[26];
} J_AlphaVertex;
#include "../../../../gen/l1/eve/r_alg/VecJ_AlphaVertex.h"
typedef struct{
size_t only_trash_state;
size_t start;
VecJ_AlphaVertex states;
} AntiGraph;
void AntiGraph_drop(AntiGraph self){
VecJ_AlphaVertex_drop(self.states);
}
U64 Fish_anti_automaton_dfs(U64 fv, VecS64* map, VecJ_AlphaVertex* graph, const VecI_FishNode* fish){
assert(fv < map->len);
assert(fv < fish->len);
/* Priority number 1: check if it is terminal */
if (fish->buf[fv].class_ref != -1 || fish->buf[fish->buf[fv].ans_up_link].class_ref != -1)
return 0; // Trash vertex
if (map->buf[fv] == -1) {
size_t mid = graph->len;
map->buf[fv] = (S64)mid;
/* Right now it is filled with trash. The important point is that it marked as visited */
VecJ_AlphaVertex_append(graph, (J_AlphaVertex){0});
for (U8 d = 0; d < 26; d++) {
U64 nnon = Fish_anti_automaton_dfs(fish->buf[fv].transition[d], map, graph, fish);
graph->buf[mid].trans[d] = nnon;
}
}
return map->buf[fv];
}
AntiGraph Fish_anti_automaton(Fish fish){
size_t nc = fish.nodes.len;
assert(nc > 0);
/* starting with just trash vertex, it ppints to inself, zalooping on itself */
VecJ_AlphaVertex graph = VecJ_AlphaVertex_new_zeroinit(1);
VecS64 map = VecS64_new_filled(nc, -1);
U64 start = Fish_anti_automaton_dfs(0, &map, &graph, &fish.nodes);
Fish_drop(fish);
VecS64_drop(map);
return (AntiGraph){.only_trash_state = 0, .start = start, .states = graph};
}
#define MOD (1000000007)
NODISCARD VecU64 mat_mul(uint32_t N, const VecU64* A, const VecU64* B){
assert(A->len == N * N && B->len == N * N);
VecU64 C = VecU64_new_zeroinit(N * N);
for (size_t y = 0; y < N; y++) {
for (size_t x = 0; x < N; x++) {
size_t s = 0;
for (size_t k = 0; k < N; k++) {
s = (s + (A->buf[y * N + k] * B->buf[k * N + x]) % MOD) % MOD;
}
C.buf[y * N + x] = s;
}
}
return C;
}
NODISCARD VecU64 pow_matrix(uint32_t N, const VecU64* A, uint64_t B){
if (B == 0) {
VecU64 E = VecU64_new_zeroinit(N * N);
for (size_t k = 0; k < N; k++)
E.buf[N * k + k] = 1;
return E;
}
if (B == 1)
return VecU64_clone(A);
uint64_t b = B / 2;
VecU64 e = pow_matrix(N, A, b);
assert(e.len == N * N);
VecU64 E = mat_mul(N, &e, &e);
VecU64_drop(e); // e is no more
if (B % 2 == 0)
return E;
VecU64 F = mat_mul(N, &E, A);
VecU64_drop(E);
return F;
}
void VecU64_debug_print_cool_matrix(size_t N, const VecU64* matrix){
assert(matrix->len == N * N);
for (size_t y = 0; y < N; y++) {
for (size_t x = 0; x < N; x++)
printf(" %2lu", matrix->buf[y * N + x]);
printf("\n");
}
}
int main(){
U64 K = stdin_read_U64_nofail();
U64 m = stdin_read_U64_nofail();
VecVecU8 S = VecVecU8_new_of_size(m);
for (size_t i = 0; i < m; i++) {
U64 sn = stdin_read_U64_nofail();
if (sn == 0)
abort();
assert(S.buf[i].buf == NULL);
S.buf[i] = stdin_read_VecU8_nospace();
// assert(S.buf[i].len == sn);
}
// I_Trie_debug_print(&trie);
Fish fish = incomplete_Fish_from_VecU8(VecVecU8_to_span(&S));
complete_Fish(&fish);
// Fish_debug_print(&fish);
AntiGraph antigraph = Fish_anti_automaton(fish);
size_t N = antigraph.states.len;
assert(1 < N);
assert(0 == antigraph.only_trash_state);
VecU64 graph_matrix = VecU64_new_zeroinit(N * N);
for (size_t v = 0; v < N; v++) {
for (U8 d = 0; d < 26; d++) {
size_t t = antigraph.states.buf[v].trans[d];
assert(t < N);
graph_matrix.buf[t * N + v]++;
}
}
// VecU64_debug_print_cool_matrix(N, &graph_matrix);
VecU64 K_graph_matrix = pow_matrix(N, &graph_matrix, K);
U64 K_paths = 0;
for (size_t endpoint = 1; endpoint < N; endpoint++) {
K_paths = (K_paths + K_graph_matrix.buf[endpoint * N + antigraph.start]) % MOD;
}
printf("%lu\n", K_paths);
VecU64_drop(graph_matrix);
VecU64_drop(K_graph_matrix);
AntiGraph_drop(antigraph);
VecVecU8_drop(S);
}