Problem 828

Numbers Challenge: minimum score expression from given numbers. Pure Flow port of the native C solver.

Answer148693670
Output148693670
StatusPASS
Native helperno
Runtime19120 ms
Peak memory25056 KB
Time complexityO(2^n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(2^n)O(n log n)
Space complexityO(n^2)O(n)
ApproachFlow solutionSearch with pruning or sieve
VerdictSuboptimal

Flow source

# Project Euler 828
# Numbers Challenge: minimum score expression from given numbers.
# Pure Flow port of the native C solver.

extern {
    function fopen(path: string, mode: string) -> ptr<void>
    function fgetc(f: ptr<void>) -> i32
    function fclose(f: ptr<void>) -> i32
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
    function malloc(n: i64) -> ptr<void>
    function memcpy(dst: ptr<void>, src: ptr<void>, n: i64) -> ptr<void>
    function memset(p: ptr<void>, c: i32, n: i64) -> void
}

const MOD: i64 = 1005075251
const CACHE_CAP: i32 = 1048576
const MAX_PROBS: i32 = 200
const MAX_NUMS: i32 = 6

struct CacheSlot {
    key: i64
    vals: ptr<i32>
    count: i32
    used: i32
}

# Global cache
let mut g_cache: ptr<CacheSlot> = null

# Global dynamic array state
let mut g_da_vals: ptr<i32> = null
let mut g_da_count: i32 = 0
let mut g_da_cap: i32 = 0

# Problem data
let mut g_targets: ptr<i32> = null
let mut g_counts: ptr<i32> = null
let mut g_nums: ptr<i32> = null
let mut g_num_problems: i32 = 0

function da_init() -> void {
    g_da_cap = 16
    g_da_vals = malloc((g_da_cap as i64) * 4)
    g_da_count = 0
}

function da_free() -> void {
    free(g_da_vals)
    g_da_vals = null
    g_da_count = 0
    g_da_cap = 0
}

function da_add(v: i32) -> void {
    if g_da_count >= g_da_cap {
        let new_cap: i32 = g_da_cap * 2
        let new_vals: ptr<i32> = malloc((new_cap as i64) * 4)
        memcpy(new_vals, g_da_vals, (g_da_count as i64) * 4)
        free(g_da_vals)
        g_da_vals = new_vals
        g_da_cap = new_cap
    }
    g_da_vals[g_da_count] = v
    g_da_count = g_da_count + 1
}

function cache_reset() -> void {
    g_cache = calloc(CACHE_CAP as i64, 24)
}

function cache_hash(key: i64) -> i32 {
    return ((key * 1099511628211) & ((CACHE_CAP as i64) - 1)) as i32
}

function cache_find(key: i64) -> i32 {
    let mut h: i32 = cache_hash(key)
    while g_cache[h].used != 0 {
        if g_cache[h].key == key { return h }
        h = (h + 1) & (CACHE_CAP - 1)
    }
    return -1
}

function cache_insert(key: i64) -> i32 {
    let mut h: i32 = cache_hash(key)
    while g_cache[h].used != 0 {
        if g_cache[h].key == key { return h }
        h = (h + 1) & (CACHE_CAP - 1)
    }
    g_cache[h].used = 1
    g_cache[h].key = key
    g_cache[h].vals = null
    g_cache[h].count = 0
    return h
}

function encode_key(nums: ptr<i32>, len: i32) -> i64 {
    let sorted: ptr<i32> = malloc(24)
    let mut i: i32 = 0
    while i < len {
        sorted[i] = nums[i]
        i = i + 1
    }
    let mut i2: i32 = 1
    while i2 < len {
        let key: i32 = sorted[i2]
        let mut j: i32 = i2 - 1
        while j >= 0 {
            if sorted[j] > key {
                sorted[j + 1] = sorted[j]
                j = j - 1
            } else {
                break
            }
        }
        sorted[j + 1] = key
        i2 = i2 + 1
    }
    let mut k: i64 = 0
    let mut i3: i32 = 0
    while i3 < len {
        k = k * 201 + ((sorted[i3] + 1) as i64)
        i3 = i3 + 1
    }
    free(sorted)
    return k
}

function sort_i32(arr: ptr<i32>, n: i32) -> void {
    let mut i: i32 = 1
    while i < n {
        let key: i32 = arr[i]
        let mut j: i32 = i - 1
        while j >= 0 {
            if arr[j] > key {
                arr[j + 1] = arr[j]
                j = j - 1
            } else {
                break
            }
        }
        arr[j + 1] = key
        i = i + 1
    }
}

function dedup_sorted(arr: ptr<i32>, n: i32) -> i32 {
    if n <= 1 { return n }
    let mut w: i32 = 1
    let mut r: i32 = 1
    while r < n {
        if arr[r] != arr[r - 1] {
            arr[w] = arr[r]
            w = w + 1
        }
        r = r + 1
    }
    return w
}

# Generate all achievable values from nums[0..len-1].
# Results are added to the global dynamic array g_da_vals.
function generate_values(nums: ptr<i32>, len: i32) -> void {
    let key: i64 = encode_key(nums, len)
    let slot_idx: i32 = cache_find(key)
    if slot_idx >= 0 {
        let mut i: i32 = 0
        while i < g_cache[slot_idx].count {
            da_add(g_cache[slot_idx].vals[i])
            i = i + 1
        }
        return
    }

    # Build result in a new dynamic array
    let saved_vals: ptr<i32> = g_da_vals
    let saved_count: i32 = g_da_count
    let saved_cap: i32 = g_da_cap
    da_init()

    if len == 1 {
        da_add(nums[0])
    } else {
        let total: i32 = 1 << len
        let mut mask: i32 = 1
        while mask < total - 1 {
            let complement: i32 = (~mask) & (total - 1)
            if mask > complement {
                mask = mask + 1
                continue
            }

            let left: ptr<i32> = malloc(24)
            let right: ptr<i32> = malloc(24)
            let mut nl: i32 = 0
            let mut nr: i32 = 0
            let mut i: i32 = 0
            while i < len {
                if (mask & (1 << i)) != 0 {
                    left[nl] = nums[i]
                    nl = nl + 1
                } else {
                    right[nr] = nums[i]
                    nr = nr + 1
                }
                i = i + 1
            }

            # Generate values for left group into a temp array
            let save_l_vals: ptr<i32> = g_da_vals
            let save_l_count: i32 = g_da_count
            let save_l_cap: i32 = g_da_cap
            da_init()
            generate_values(left, nl)
            let vl: ptr<i32> = g_da_vals
            let vl_count: i32 = g_da_count

            # Generate values for right group into a temp array
            g_da_vals = save_l_vals
            g_da_count = save_l_count
            g_da_cap = save_l_cap
            let save_r_vals: ptr<i32> = g_da_vals
            let save_r_count: i32 = g_da_count
            let save_r_cap: i32 = g_da_cap
            da_init()
            generate_values(right, nr)
            let vr: ptr<i32> = g_da_vals
            let vr_count: i32 = g_da_count

            # Restore to result array
            g_da_vals = save_r_vals
            g_da_count = save_r_count
            g_da_cap = save_r_cap

            # Combine
            let mut i2: i32 = 0
            while i2 < vl_count {
                let mut j: i32 = 0
                while j < vr_count {
                    let a: i32 = vl[i2]
                    let b: i32 = vr[j]
                    da_add(a + b)
                    da_add(a * b)
                    if a > b { da_add(a - b) }
                    if b > a { da_add(b - a) }
                    if b > 0 && a % b == 0 { da_add(a / b) }
                    if a > 0 && b % a == 0 { da_add(b / a) }
                    j = j + 1
                }
                i2 = i2 + 1
            }

            free(vl)
            free(vr)
            free(left)
            free(right)

            mask = mask + 1
        }
    }

    # Sort and dedup
    sort_i32(g_da_vals, g_da_count)
    g_da_count = dedup_sorted(g_da_vals, g_da_count)

    # Store in cache
    let s_idx: i32 = cache_insert(key)
    let stored_vals: ptr<i32> = malloc((g_da_count as i64) * 4)
    memcpy(stored_vals, g_da_vals, (g_da_count as i64) * 4)
    g_cache[s_idx].vals = stored_vals
    g_cache[s_idx].count = g_da_count

    # Copy results to the caller's array
    let result_vals: ptr<i32> = g_da_vals
    let result_count: i32 = g_da_count

    # Restore caller's dynamic array
    g_da_vals = saved_vals
    g_da_count = saved_count
    g_da_cap = saved_cap

    # Add results to caller's array
    let mut i3: i32 = 0
    while i3 < result_count {
        da_add(result_vals[i3])
        i3 = i3 + 1
    }

    free(result_vals)
}

function min_score(target: i32, nums_base: ptr<i32>, nums_offset: i32, count: i32) -> i32 {
    let mut best: i32 = 0
    let total: i32 = 1 << count
    let mut mask: i32 = 1
    while mask < total {
        let subset: ptr<i32> = malloc(24)
        let mut ns: i32 = 0
        let mut sum: i32 = 0
        let mut i: i32 = 0
        while i < count {
            if (mask & (1 << i)) != 0 {
                subset[ns] = nums_base[nums_offset + i]
                sum = sum + nums_base[nums_offset + i]
                ns = ns + 1
            }
            i = i + 1
        }
        if best > 0 && sum >= best {
            free(subset)
            mask = mask + 1
            continue
        }

        da_init()
        generate_values(subset, ns)

        # Binary search for target
        let mut lo: i32 = 0
        let mut hi: i32 = g_da_count - 1
        let mut found: i32 = 0
        while lo <= hi {
            let mid: i32 = (lo + hi) / 2
            if g_da_vals[mid] == target {
                found = 1
                break
            }
            if g_da_vals[mid] < target {
                lo = mid + 1
            } else {
                hi = mid - 1
            }
        }
        if found != 0 {
            if best == 0 || sum < best { best = sum }
        }
        da_free()
        free(subset)
        mask = mask + 1
    }
    return best
}

function read_data(path: string) -> void {
    g_targets = malloc((MAX_PROBS as i64) * 4)
    g_counts = malloc((MAX_PROBS as i64) * 4)
    g_nums = malloc((MAX_PROBS as i64) * (MAX_NUMS as i64) * 4)

    let f: ptr<void> = fopen(path, "r")
    if f == null { return }

    g_num_problems = 0

    let mut c: i32 = fgetc(f)
    while c >= 0 {
        # Skip whitespace
        while c >= 0 && c <= 32 { c = fgetc(f) }
        if c < 0 { break }

        # Read target
        let mut target: i32 = 0
        while c >= 48 && c <= 57 {
            target = target * 10 + (c - 48)
            c = fgetc(f)
        }
        g_targets[g_num_problems] = target

        # Skip ':'
        if c == 58 { c = fgetc(f) }

        # Read numbers
        let mut cnt: i32 = 0
        while c >= 0 && c != 10 && c != 13 {
            # Skip comma
            while c == 44 { c = fgetc(f) }
            if c < 0 || c == 10 || c == 13 { break }
            # Read number
            let mut val: i32 = 0
            while c >= 48 && c <= 57 {
                val = val * 10 + (c - 48)
                c = fgetc(f)
            }
            if val > 0 {
                g_nums[g_num_problems * MAX_NUMS + cnt] = val
                cnt = cnt + 1
            }
        }
        g_counts[g_num_problems] = cnt
        g_num_problems = g_num_problems + 1

        # Skip to next line
        while c >= 0 && c != 10 { c = fgetc(f) }
        if c == 10 { c = fgetc(f) }
    }
    fclose(f)
}

function main() -> i32 {
    cache_reset()
    read_data("data/0828_number_challenges.txt")

    let mut total: i64 = 0
    let mut pow3: i64 = 3
    let mut n: i32 = 0
    while n < g_num_problems {
        let target: i32 = g_targets[n]
        let count: i32 = g_counts[n]
        let s: i32 = min_score(target, g_nums, n * MAX_NUMS, count)
        total = (total + pow3 * (s as i64)) % MOD
        pow3 = (pow3 * 3) % MOD
        n = n + 1
    }

    free(g_targets)
    free(g_counts)
    free(g_nums)
    free(g_cache)

    printf("%lld\n", total)
    return 0
}

Generated C

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Flow runtime helpers */
typedef struct flow_temp_node { struct flow_temp_node* next; } flow_temp_node;
static flow_temp_node* flow_temp_head = NULL;
static int flow_temp_atexit_set = 0;
__attribute__((unused)) static void flow_temp_free_all(void) {
    while (flow_temp_head) {
        flow_temp_node* n = flow_temp_head;
        flow_temp_head = n->next;
        free(n);
    }
}
__attribute__((unused)) static void* flow_temp_alloc(size_t nbytes) {
    flow_temp_node* node = (flow_temp_node*)malloc(sizeof(flow_temp_node) + nbytes);
    if (!node) return NULL;
    node->next = flow_temp_head;
    flow_temp_head = node;
    if (!flow_temp_atexit_set) {
        flow_temp_atexit_set = 1;
        atexit(flow_temp_free_all);
    }
    return (void*)(node + 1);
}
#ifndef FLOW_DIAG
#define FLOW_DIAG(msg) fprintf(stderr, "%s", (msg))
#endif
#ifndef FLOW_LOG
#define FLOW_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
#ifndef FLOW_LOG_EMPTY
#define FLOW_LOG_EMPTY(fmt) printf(fmt)
#endif
static char* flow_strcat(const char* a, const char* b) {
    size_t la = strlen(a ? a : ""), lb = strlen(b ? b : "");
    char* r = (char*)flow_temp_alloc(la + lb + 1);
    if (!r) return NULL;
    if (la) memcpy(r, a, la);
    if (lb) memcpy(r + la, b, lb);
    r[la + lb] = '\0';
    return r;
}

#define __flow_in_arr(arr, val) __extension__ ({ \
    int _found = 0; \
    size_t _n = sizeof(arr)/sizeof((arr)[0]); \
    for (size_t _i = 0; _i < _n; _i++) { \
        if ((arr)[_i] == (val)) { _found = 1; break; } \
    } _found; })

/* Unified fault handler (MISRA #279) — override with -DFLOW_FAULT_HANDLER=fn */
#ifndef FLOW_FAULT_HANDLER
__attribute__((unused)) static inline void flow_fault_handler(const char* msg) {
    fprintf(stderr, "flow: %s\n", msg ? msg : "fault");
    abort();
#if defined(__GNUC__) || defined(__clang__)
    __builtin_unreachable();
#endif
}
#else
#define flow_fault_handler FLOW_FAULT_HANDLER
#endif
#define flow_div_by_zero_handler() flow_fault_handler("division by zero")
#define flow_shift_ub_handler() flow_fault_handler("invalid shift (amount out of range or left-shift of negative)")

#ifndef FLOW_CHECKED_DIV
#define FLOW_CHECKED_DIV(L, R) (((R) != 0) ? ((L) / (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_MOD
#define FLOW_CHECKED_MOD(L, R) (((R) != 0) ? ((L) % (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHL
#define FLOW_CHECKED_SHL(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull)) && ((L) >= 0)) ? ((L) << (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHR
#define FLOW_CHECKED_SHR(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull))) ? ((L) >> (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif

#include <math.h>

void* _ui_state = NULL;

static inline float i32_to_f32(int32_t v) { return (float)v; }

/* Host stub for @gpu kernels (device codegen replaces this). */
static inline int32_t gpu_thread_id(void) { return 0; }

typedef struct CacheSlot CacheSlot;

struct CacheSlot {
    int64_t key;
    int32_t* vals;
    int32_t count;
    int32_t used;
};

void da_init(void);
void da_free(void);
void da_add_i32(int32_t v);
void cache_reset(void);
int32_t cache_hash_i64(int64_t key);
int32_t cache_find_i64(int64_t key);
int32_t cache_insert_i64(int64_t key);
int64_t encode_key_ptr_i32_i32(int32_t* nums, int32_t len);
void sort_i32_ptr_i32_i32(int32_t* arr, int32_t n);
int32_t dedup_sorted_ptr_i32_i32(int32_t* arr, int32_t n);
void generate_values_ptr_i32_i32(int32_t* nums, int32_t len);
int32_t min_score_i32_ptr_i32_i32_i32(int32_t target, int32_t* nums_base, int32_t nums_offset, int32_t count);
void read_data_string(char* path);
int32_t main(void);

static const int64_t MOD = 1005075251;
static const int32_t CACHE_CAP = 1048576;
static const int32_t MAX_PROBS = 200;
static const int32_t MAX_NUMS = 6;

/* Module statics */
static CacheSlot* g_cache = NULL;
static int32_t* g_da_vals = NULL;
static int32_t g_da_count = 0;
static int32_t g_da_cap = 0;
static int32_t* g_targets = NULL;
static int32_t* g_counts = NULL;
static int32_t* g_nums = NULL;
static int32_t g_num_problems = 0;









void da_init(void) {
    g_da_cap = 16;
    g_da_vals = malloc((((int64_t)(g_da_cap)) * 4));
    g_da_count = 0;
}

void da_free(void) {
    free(g_da_vals);
    g_da_vals = NULL;
    g_da_count = 0;
    g_da_cap = 0;
}

void da_add_i32(int32_t v) {
    if (g_da_count >= g_da_cap) {
        int32_t new_cap = (g_da_cap * 2);
        int32_t* new_vals = (int32_t*)(malloc((((int64_t)(new_cap)) * 4)));
        memcpy(new_vals, g_da_vals, (((int64_t)(g_da_count)) * 4));
        free(g_da_vals);
        g_da_vals = new_vals;
        g_da_cap = new_cap;
    }
    g_da_vals[g_da_count] = v;
    g_da_count = (g_da_count + 1);
}

void cache_reset(void) {
    g_cache = calloc(((int64_t)(CACHE_CAP)), 24);
}

int32_t cache_hash_i64(int64_t key) {
    return ((int32_t)(((key * 1099511628211) & (((int64_t)(CACHE_CAP)) - 1))));
}

int32_t cache_find_i64(int64_t key) {
    int32_t h = cache_hash_i64(key);
    while (g_cache[h].used != 0) {
        if (g_cache[h].key == key) {
            return h;
        }
        h = ((h + 1) & (CACHE_CAP - 1));
    }
    return (-1);
}

int32_t cache_insert_i64(int64_t key) {
    int32_t h = cache_hash_i64(key);
    while (g_cache[h].used != 0) {
        if (g_cache[h].key == key) {
            return h;
        }
        h = ((h + 1) & (CACHE_CAP - 1));
    }
    g_cache[h].used = 1;
    g_cache[h].key = key;
    g_cache[h].vals = NULL;
    g_cache[h].count = 0;
    return h;
}

int64_t encode_key_ptr_i32_i32(int32_t* nums, int32_t len) {
    int32_t* sorted = (int32_t*)(malloc(24));
    int32_t i = 0;
    while (i < len) {
        sorted[i] = nums[i];
        i = (i + 1);
    }
    int32_t i2 = 1;
    while (i2 < len) {
        int32_t key = sorted[i2];
        int32_t j = (i2 - 1);
        while (j >= 0) {
            if (sorted[j] > key) {
                sorted[(j + 1)] = sorted[j];
                j = (j - 1);
            } else {
                break;
            }
        }
        sorted[(j + 1)] = key;
        i2 = (i2 + 1);
    }
    int64_t k = 0;
    int32_t i3 = 0;
    while (i3 < len) {
        k = ((k * 201) + ((int64_t)((sorted[i3] + 1))));
        i3 = (i3 + 1);
    }
    free(sorted);
    return k;
}

void sort_i32_ptr_i32_i32(int32_t* arr, int32_t n) {
    int32_t i = 1;
    while (i < n) {
        int32_t key = arr[i];
        int32_t j = (i - 1);
        while (j >= 0) {
            if (arr[j] > key) {
                arr[(j + 1)] = arr[j];
                j = (j - 1);
            } else {
                break;
            }
        }
        arr[(j + 1)] = key;
        i = (i + 1);
    }
}

int32_t dedup_sorted_ptr_i32_i32(int32_t* arr, int32_t n) {
    if (n <= 1) {
        return n;
    }
    int32_t w = 1;
    int32_t r = 1;
    while (r < n) {
        if (arr[r] != arr[(r - 1)]) {
            arr[w] = arr[r];
            w = (w + 1);
        }
        r = (r + 1);
    }
    return w;
}

void generate_values_ptr_i32_i32(int32_t* nums, int32_t len) {
    int64_t key = encode_key_ptr_i32_i32(nums, len);
    int32_t slot_idx = cache_find_i64(key);
    if (slot_idx >= 0) {
        int32_t i = 0;
        while (i < g_cache[slot_idx].count) {
            da_add_i32(g_cache[slot_idx].vals[i]);
            i = (i + 1);
        }
        return;
    }
    int32_t* saved_vals = (int32_t*)(g_da_vals);
    int32_t saved_count = g_da_count;
    int32_t saved_cap = g_da_cap;
    da_init();
    if (len == 1) {
        da_add_i32(nums[0]);
    } else {
        int32_t total = FLOW_CHECKED_SHL((1), (len));
        int32_t mask = 1;
        while (mask < (total - 1)) {
            int32_t complement = ((~mask) & (total - 1));
            if (mask > complement) {
                mask = (mask + 1);
                continue;
            }
            int32_t* left = (int32_t*)(malloc(24));
            int32_t* right = (int32_t*)(malloc(24));
            int32_t nl = 0;
            int32_t nr = 0;
            int32_t i = 0;
            while (i < len) {
                if ((mask & FLOW_CHECKED_SHL((1), (i))) != 0) {
                    left[nl] = nums[i];
                    nl = (nl + 1);
                } else {
                    right[nr] = nums[i];
                    nr = (nr + 1);
                }
                i = (i + 1);
            }
            int32_t* save_l_vals = (int32_t*)(g_da_vals);
            int32_t save_l_count = g_da_count;
            int32_t save_l_cap = g_da_cap;
            da_init();
            generate_values_ptr_i32_i32(left, nl);
            int32_t* vl = (int32_t*)(g_da_vals);
            int32_t vl_count = g_da_count;
            g_da_vals = save_l_vals;
            g_da_count = save_l_count;
            g_da_cap = save_l_cap;
            int32_t* save_r_vals = (int32_t*)(g_da_vals);
            int32_t save_r_count = g_da_count;
            int32_t save_r_cap = g_da_cap;
            da_init();
            generate_values_ptr_i32_i32(right, nr);
            int32_t* vr = (int32_t*)(g_da_vals);
            int32_t vr_count = g_da_count;
            g_da_vals = save_r_vals;
            g_da_count = save_r_count;
            g_da_cap = save_r_cap;
            int32_t i2 = 0;
            while (i2 < vl_count) {
                int32_t j = 0;
                while (j < vr_count) {
                    int32_t a = vl[i2];
                    int32_t b = vr[j];
                    da_add_i32((a + b));
                    da_add_i32((a * b));
                    if (a > b) {
                        da_add_i32((a - b));
                    }
                    if (b > a) {
                        da_add_i32((b - a));
                    }
                    if ((b > 0 && FLOW_CHECKED_MOD((a), (b)) == 0)) {
                        da_add_i32(FLOW_CHECKED_DIV((a), (b)));
                    }
                    if ((a > 0 && FLOW_CHECKED_MOD((b), (a)) == 0)) {
                        da_add_i32(FLOW_CHECKED_DIV((b), (a)));
                    }
                    j = (j + 1);
                }
                i2 = (i2 + 1);
            }
            free(vl);
            free(vr);
            free(left);
            free(right);
            mask = (mask + 1);
        }
    }
    sort_i32_ptr_i32_i32(g_da_vals, g_da_count);
    g_da_count = dedup_sorted_ptr_i32_i32(g_da_vals, g_da_count);
    int32_t s_idx = cache_insert_i64(key);
    int32_t* stored_vals = (int32_t*)(malloc((((int64_t)(g_da_count)) * 4)));
    memcpy(stored_vals, g_da_vals, (((int64_t)(g_da_count)) * 4));
    g_cache[s_idx].vals = stored_vals;
    g_cache[s_idx].count = g_da_count;
    int32_t* result_vals = (int32_t*)(g_da_vals);
    int32_t result_count = g_da_count;
    g_da_vals = saved_vals;
    g_da_count = saved_count;
    g_da_cap = saved_cap;
    int32_t i3 = 0;
    while (i3 < result_count) {
        da_add_i32(result_vals[i3]);
        i3 = (i3 + 1);
    }
    free(result_vals);
}

int32_t min_score_i32_ptr_i32_i32_i32(int32_t target, int32_t* nums_base, int32_t nums_offset, int32_t count) {
    int32_t best = 0;
    int32_t total = FLOW_CHECKED_SHL((1), (count));
    int32_t mask = 1;
    while (mask < total) {
        int32_t* subset = (int32_t*)(malloc(24));
        int32_t ns = 0;
        int32_t sum = 0;
        int32_t i = 0;
        while (i < count) {
            if ((mask & FLOW_CHECKED_SHL((1), (i))) != 0) {
                subset[ns] = nums_base[(nums_offset + i)];
                sum = (sum + nums_base[(nums_offset + i)]);
                ns = (ns + 1);
            }
            i = (i + 1);
        }
        if ((best > 0 && sum >= best)) {
            free(subset);
            mask = (mask + 1);
            continue;
        }
        da_init();
        generate_values_ptr_i32_i32(subset, ns);
        int32_t lo = 0;
        int32_t hi = (g_da_count - 1);
        int32_t found = 0;
        while (lo <= hi) {
            int32_t mid = FLOW_CHECKED_DIV(((lo + hi)), (2));
            if (g_da_vals[mid] == target) {
                found = 1;
                break;
            }
            if (g_da_vals[mid] < target) {
                lo = (mid + 1);
            } else {
                hi = (mid - 1);
            }
        }
        if (found != 0) {
            if ((best == 0 || sum < best)) {
                best = sum;
            }
        }
        da_free();
        free(subset);
        mask = (mask + 1);
    }
    return best;
}

void read_data_string(char* path) {
    g_targets = malloc((((int64_t)(MAX_PROBS)) * 4));
    g_counts = malloc((((int64_t)(MAX_PROBS)) * 4));
    g_nums = malloc(((((int64_t)(MAX_PROBS)) * ((int64_t)(MAX_NUMS))) * 4));
    void* f = (void*)(fopen(path, "r"));
    if (f == NULL) {
        return;
    }
    g_num_problems = 0;
    int32_t c = fgetc(f);
    while (c >= 0) {
        while ((c >= 0 && c <= 32)) {
            c = fgetc(f);
        }
        if (c < 0) {
            break;
        }
        int32_t target = 0;
        while ((c >= 48 && c <= 57)) {
            target = ((target * 10) + (c - 48));
            c = fgetc(f);
        }
        g_targets[g_num_problems] = target;
        if (c == 58) {
            c = fgetc(f);
        }
        int32_t cnt = 0;
        while (((c >= 0 && c != 10) && c != 13)) {
            while (c == 44) {
                c = fgetc(f);
            }
            if (((c < 0 || c == 10) || c == 13)) {
                break;
            }
            int32_t val = 0;
            while ((c >= 48 && c <= 57)) {
                val = ((val * 10) + (c - 48));
                c = fgetc(f);
            }
            if (val > 0) {
                g_nums[((g_num_problems * MAX_NUMS) + cnt)] = val;
                cnt = (cnt + 1);
            }
        }
        g_counts[g_num_problems] = cnt;
        g_num_problems = (g_num_problems + 1);
        while ((c >= 0 && c != 10)) {
            c = fgetc(f);
        }
        if (c == 10) {
            c = fgetc(f);
        }
    }
    fclose(f);
}

int32_t main(void) {
    cache_reset();
    read_data_string("data/0828_number_challenges.txt");
    int64_t total = 0;
    int64_t pow3 = 3;
    int32_t n = 0;
    while (n < g_num_problems) {
        int32_t target = g_targets[n];
        int32_t count = g_counts[n];
        int32_t s = min_score_i32_ptr_i32_i32_i32(target, g_nums, (n * MAX_NUMS), count);
        total = FLOW_CHECKED_MOD(((total + (pow3 * ((int64_t)(s))))), (MOD));
        pow3 = FLOW_CHECKED_MOD(((pow3 * 3)), (MOD));
        n = (n + 1);
    }
    free(g_targets);
    free(g_counts);
    free(g_nums);
    free(g_cache);
    printf("%lld\n", total);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("r\00") {addr_space = 0 : i32} : !llvm.array<2 x i8>
  llvm.mlir.global internal constant @str_1("data/0828_number_challenges.txt\00") {addr_space = 0 : i32} : !llvm.array<32 x i8>
  llvm.mlir.global internal constant @str_2("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @fopen(!llvm.ptr, !llvm.ptr) -> !llvm.ptr
  func.func private @fgetc(!llvm.ptr) -> i32
  func.func private @fclose(!llvm.ptr) -> i32
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  func.func private @malloc(i64) -> !llvm.ptr
  func.func private @memcpy(!llvm.ptr, !llvm.ptr, i64) -> !llvm.ptr
  func.func private @memset(!llvm.ptr, i32, i64) -> ()
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(1005075251 : i64) : i64
  // Constant: CACHE_CAP
  llvm.mlir.global internal constant @CACHE_CAP(1048576 : i32) : i32
  // Constant: MAX_PROBS
  llvm.mlir.global internal constant @MAX_PROBS(200 : i32) : i32
  // Constant: MAX_NUMS
  llvm.mlir.global internal constant @MAX_NUMS(6 : i32) : i32
  // Struct: CacheSlot
  // Fields:
  //   key: i64
  //   vals: !llvm.ptr
  //   count: i32
  //   used: i32
  // Module static: g_cache
  llvm.mlir.global internal @g_cache() {addr_space = 0 : i32} : !llvm.ptr {
    %0 = llvm.mlir.zero : !llvm.ptr
    llvm.return %0 : !llvm.ptr
  }
  // Module static: g_da_vals
  llvm.mlir.global internal @g_da_vals() {addr_space = 0 : i32} : !llvm.ptr {
    %1 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1 : !llvm.ptr
  }
  // Module static: g_da_count
  llvm.mlir.global internal @g_da_count(0 : i32) : i32
  // Module static: g_da_cap
  llvm.mlir.global internal @g_da_cap(0 : i32) : i32
  // Module static: g_targets
  llvm.mlir.global internal @g_targets() {addr_space = 0 : i32} : !llvm.ptr {
    %2 = llvm.mlir.zero : !llvm.ptr
    llvm.return %2 : !llvm.ptr
  }
  // Module static: g_counts
  llvm.mlir.global internal @g_counts() {addr_space = 0 : i32} : !llvm.ptr {
    %3 = llvm.mlir.zero : !llvm.ptr
    llvm.return %3 : !llvm.ptr
  }
  // Module static: g_nums
  llvm.mlir.global internal @g_nums() {addr_space = 0 : i32} : !llvm.ptr {
    %4 = llvm.mlir.zero : !llvm.ptr
    llvm.return %4 : !llvm.ptr
  }
  // Module static: g_num_problems
  llvm.mlir.global internal @g_num_problems(0 : i32) : i32
  func.func @da_init() -> () {
    %5 = arith.constant 16 : i32
    %6 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
    llvm.store %5, %6 : i32, !llvm.ptr
    %8 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
    %9 = llvm.load %8 : !llvm.ptr -> i32
    %10 = arith.extsi %9 : i32 to i64
    %11 = arith.constant 4 : i32
    %13 = arith.extsi %11 : i32 to i64
    %12 = arith.muli %10, %13 : i64
    %7 = func.call @malloc(%12) : (i64) -> !llvm.ptr
    %14 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    llvm.store %7, %14 : !llvm.ptr, !llvm.ptr
    %15 = arith.constant 0 : i32
    %16 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    llvm.store %15, %16 : i32, !llvm.ptr
    func.return
  }
  func.func @da_free() -> () {
    %18 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %19 = llvm.load %18 : !llvm.ptr -> !llvm.ptr
    func.call @free(%19) : (!llvm.ptr) -> ()
    %20 = llvm.mlir.zero : !llvm.ptr
    %21 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    llvm.store %20, %21 : !llvm.ptr, !llvm.ptr
    %22 = arith.constant 0 : i32
    %23 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    llvm.store %22, %23 : i32, !llvm.ptr
    %24 = arith.constant 0 : i32
    %25 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
    llvm.store %24, %25 : i32, !llvm.ptr
    func.return
  }
  func.func @da_add(%arg0: i32) -> () {
    %26 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %27 = llvm.load %26 : !llvm.ptr -> i32
    %28 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
    %29 = llvm.load %28 : !llvm.ptr -> i32
    %30 = arith.cmpi sge, %27, %29 : i32
    cf.cond_br %30, ^bb0, ^bb1
    ^bb0:
      %31 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
      %32 = llvm.load %31 : !llvm.ptr -> i32
      %33 = arith.constant 2 : i32
      %34 = arith.muli %32, %33 : i32
      %36 = arith.extsi %34 : i32 to i64
      %37 = arith.constant 4 : i32
      %39 = arith.extsi %37 : i32 to i64
      %38 = arith.muli %36, %39 : i64
      %35 = func.call @malloc(%38) : (i64) -> !llvm.ptr
      %41 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
      %42 = llvm.load %41 : !llvm.ptr -> !llvm.ptr
      %43 = llvm.mlir.addressof @g_da_count : !llvm.ptr
      %44 = llvm.load %43 : !llvm.ptr -> i32
      %45 = arith.extsi %44 : i32 to i64
      %46 = arith.constant 4 : i32
      %48 = arith.extsi %46 : i32 to i64
      %47 = arith.muli %45, %48 : i64
      %40 = func.call @memcpy(%35, %42, %47) : (!llvm.ptr, !llvm.ptr, i64) -> !llvm.ptr
      %50 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
      %51 = llvm.load %50 : !llvm.ptr -> !llvm.ptr
      func.call @free(%51) : (!llvm.ptr) -> ()
      %52 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
      llvm.store %35, %52 : !llvm.ptr, !llvm.ptr
      %53 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
      llvm.store %34, %53 : i32, !llvm.ptr
      cf.br ^bb2
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %54 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %55 = llvm.load %54 : !llvm.ptr -> !llvm.ptr
    %56 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %57 = llvm.load %56 : !llvm.ptr -> i32
    %58 = arith.extsi %57 : i32 to i64
    %59 = llvm.getelementptr %55[%58] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %arg0, %59 : i32, !llvm.ptr
    %60 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %61 = llvm.load %60 : !llvm.ptr -> i32
    %62 = arith.constant 1 : i32
    %63 = arith.addi %61, %62 : i32
    %64 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    llvm.store %63, %64 : i32, !llvm.ptr
    func.return
  }
  func.func @cache_reset() -> () {
    %66 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
    %67 = llvm.load %66 : !llvm.ptr -> i32
    %68 = arith.extsi %67 : i32 to i64
    %69 = arith.constant 24 : i32
    %70 = arith.extsi %69 : i32 to i64
    %65 = func.call @calloc(%68, %70) : (i64, i64) -> !llvm.ptr
    %71 = llvm.mlir.addressof @g_cache : !llvm.ptr
    llvm.store %65, %71 : !llvm.ptr, !llvm.ptr
    func.return
  }
  func.func @cache_hash(%arg0: i64) -> i32 {
    %72 = arith.constant 1095216660915 : i32
    %74 = arith.extsi %72 : i32 to i64
    %73 = arith.muli %arg0, %74 : i64
    %75 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
    %76 = llvm.load %75 : !llvm.ptr -> i32
    %77 = arith.extsi %76 : i32 to i64
    %78 = arith.constant 1 : i32
    %80 = arith.extsi %78 : i32 to i64
    %79 = arith.subi %77, %80 : i64
    %81 = arith.andi %73, %79 : i64
    %82 = arith.trunci %81 : i64 to i32
    func.return %82 : i32
  }
  func.func @cache_find(%arg0: i64) -> i32 {
    %83 = func.call @cache_hash(%arg0) : (i64) -> i32
    %84 = llvm.mlir.constant(1 : i64) : i64
    %85 = llvm.alloca %84 x i32 : (i64) -> !llvm.ptr
    llvm.store %83, %85 : i32, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %87 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %88 = llvm.load %87 : !llvm.ptr -> !llvm.ptr
    %89 = llvm.load %85 : !llvm.ptr -> i32
    %90 = arith.extsi %89 : i32 to i64
    %91 = llvm.getelementptr %88[%90] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %86 = llvm.load %91 : !llvm.ptr -> !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %92 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %93 = llvm.load %92 : !llvm.ptr -> !llvm.ptr
    %94 = llvm.load %85 : !llvm.ptr -> i32
    %95 = arith.extsi %94 : i32 to i64
    %96 = llvm.getelementptr %93[%95] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %97 = llvm.getelementptr %96[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %98 = llvm.load %97 : !llvm.ptr -> i32
    %99 = arith.constant 0 : i32
    %100 = arith.cmpi ne, %98, %99 : i32
    cf.cond_br %100, ^bb4, ^bb5
    ^bb4:
      %102 = llvm.mlir.addressof @g_cache : !llvm.ptr
      %103 = llvm.load %102 : !llvm.ptr -> !llvm.ptr
      %104 = llvm.load %85 : !llvm.ptr -> i32
      %105 = arith.extsi %104 : i32 to i64
      %106 = llvm.getelementptr %103[%105] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %101 = llvm.load %106 : !llvm.ptr -> !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %107 = llvm.mlir.addressof @g_cache : !llvm.ptr
      %108 = llvm.load %107 : !llvm.ptr -> !llvm.ptr
      %109 = llvm.load %85 : !llvm.ptr -> i32
      %110 = arith.extsi %109 : i32 to i64
      %111 = llvm.getelementptr %108[%110] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %112 = llvm.getelementptr %111[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %113 = llvm.load %112 : !llvm.ptr -> i64
      %114 = arith.cmpi eq, %113, %arg0 : i64
      cf.cond_br %114, ^bb6, ^bb7
      ^bb6:
        %115 = llvm.load %85 : !llvm.ptr -> i32
        func.return %115 : i32
      ^bb7:
        cf.br ^bb8
      ^bb8:
      %116 = llvm.load %85 : !llvm.ptr -> i32
      %117 = arith.constant 1 : i32
      %118 = arith.addi %116, %117 : i32
      %119 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
      %120 = llvm.load %119 : !llvm.ptr -> i32
      %121 = arith.constant 1 : i32
      %122 = arith.subi %120, %121 : i32
      %123 = arith.andi %118, %122 : i32
      llvm.store %123, %85 : i32, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %124 = arith.constant 1 : i32
    %126 = arith.constant 0 : i32
    %125 = arith.subi %126, %124 : i32
    func.return %125 : i32
  }
  func.func @cache_insert(%arg0: i64) -> i32 {
    %127 = func.call @cache_hash(%arg0) : (i64) -> i32
    %128 = llvm.mlir.constant(1 : i64) : i64
    %129 = llvm.alloca %128 x i32 : (i64) -> !llvm.ptr
    llvm.store %127, %129 : i32, !llvm.ptr
    cf.br ^bb9
    ^bb9:
    %131 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %132 = llvm.load %131 : !llvm.ptr -> !llvm.ptr
    %133 = llvm.load %129 : !llvm.ptr -> i32
    %134 = arith.extsi %133 : i32 to i64
    %135 = llvm.getelementptr %132[%134] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %130 = llvm.load %135 : !llvm.ptr -> !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %136 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %137 = llvm.load %136 : !llvm.ptr -> !llvm.ptr
    %138 = llvm.load %129 : !llvm.ptr -> i32
    %139 = arith.extsi %138 : i32 to i64
    %140 = llvm.getelementptr %137[%139] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %141 = llvm.getelementptr %140[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %142 = llvm.load %141 : !llvm.ptr -> i32
    %143 = arith.constant 0 : i32
    %144 = arith.cmpi ne, %142, %143 : i32
    cf.cond_br %144, ^bb10, ^bb11
    ^bb10:
      %146 = llvm.mlir.addressof @g_cache : !llvm.ptr
      %147 = llvm.load %146 : !llvm.ptr -> !llvm.ptr
      %148 = llvm.load %129 : !llvm.ptr -> i32
      %149 = arith.extsi %148 : i32 to i64
      %150 = llvm.getelementptr %147[%149] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %145 = llvm.load %150 : !llvm.ptr -> !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %151 = llvm.mlir.addressof @g_cache : !llvm.ptr
      %152 = llvm.load %151 : !llvm.ptr -> !llvm.ptr
      %153 = llvm.load %129 : !llvm.ptr -> i32
      %154 = arith.extsi %153 : i32 to i64
      %155 = llvm.getelementptr %152[%154] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %156 = llvm.getelementptr %155[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %157 = llvm.load %156 : !llvm.ptr -> i64
      %158 = arith.cmpi eq, %157, %arg0 : i64
      cf.cond_br %158, ^bb12, ^bb13
      ^bb12:
        %159 = llvm.load %129 : !llvm.ptr -> i32
        func.return %159 : i32
      ^bb13:
        cf.br ^bb14
      ^bb14:
      %160 = llvm.load %129 : !llvm.ptr -> i32
      %161 = arith.constant 1 : i32
      %162 = arith.addi %160, %161 : i32
      %163 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
      %164 = llvm.load %163 : !llvm.ptr -> i32
      %165 = arith.constant 1 : i32
      %166 = arith.subi %164, %165 : i32
      %167 = arith.andi %162, %166 : i32
      llvm.store %167, %129 : i32, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %168 = arith.constant 1 : i32
    %169 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %170 = llvm.load %169 : !llvm.ptr -> !llvm.ptr
    %171 = llvm.load %129 : !llvm.ptr -> i32
    %172 = arith.extsi %171 : i32 to i64
    %173 = llvm.getelementptr %170[%172] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %174 = llvm.getelementptr %173[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    llvm.store %168, %174 : i32, !llvm.ptr
    %175 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %176 = llvm.load %175 : !llvm.ptr -> !llvm.ptr
    %177 = llvm.load %129 : !llvm.ptr -> i32
    %178 = arith.extsi %177 : i32 to i64
    %179 = llvm.getelementptr %176[%178] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %180 = llvm.getelementptr %179[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    llvm.store %arg0, %180 : i64, !llvm.ptr
    %181 = llvm.mlir.zero : !llvm.ptr
    %182 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %183 = llvm.load %182 : !llvm.ptr -> !llvm.ptr
    %184 = llvm.load %129 : !llvm.ptr -> i32
    %185 = arith.extsi %184 : i32 to i64
    %186 = llvm.getelementptr %183[%185] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %187 = llvm.getelementptr %186[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    llvm.store %181, %187 : !llvm.ptr, !llvm.ptr
    %188 = arith.constant 0 : i32
    %189 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %190 = llvm.load %189 : !llvm.ptr -> !llvm.ptr
    %191 = llvm.load %129 : !llvm.ptr -> i32
    %192 = arith.extsi %191 : i32 to i64
    %193 = llvm.getelementptr %190[%192] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %194 = llvm.getelementptr %193[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    llvm.store %188, %194 : i32, !llvm.ptr
    %195 = llvm.load %129 : !llvm.ptr -> i32
    func.return %195 : i32
  }
  func.func @encode_key(%arg0: !llvm.ptr, %arg1: i32) -> i64 {
    %197 = arith.constant 24 : i32
    %198 = arith.extsi %197 : i32 to i64
    %196 = func.call @malloc(%198) : (i64) -> !llvm.ptr
    %199 = arith.constant 0 : i32
    %200 = llvm.mlir.constant(1 : i64) : i64
    %201 = llvm.alloca %200 x i32 : (i64) -> !llvm.ptr
    llvm.store %199, %201 : i32, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %202 = llvm.load %201 : !llvm.ptr -> i32
    %203 = arith.cmpi slt, %202, %arg1 : i32
    cf.cond_br %203, ^bb16, ^bb17
    ^bb16:
      %205 = llvm.load %201 : !llvm.ptr -> i32
      %206 = arith.extsi %205 : i32 to i64
      %207 = llvm.getelementptr %arg0[%206] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %204 = llvm.load %207 : !llvm.ptr -> i32
      %208 = llvm.load %201 : !llvm.ptr -> i32
      %209 = arith.extsi %208 : i32 to i64
      %210 = llvm.getelementptr %196[%209] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %204, %210 : i32, !llvm.ptr
      %211 = llvm.load %201 : !llvm.ptr -> i32
      %212 = arith.constant 1 : i32
      %213 = arith.addi %211, %212 : i32
      llvm.store %213, %201 : i32, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    %214 = arith.constant 1 : i32
    %215 = llvm.mlir.constant(1 : i64) : i64
    %216 = llvm.alloca %215 x i32 : (i64) -> !llvm.ptr
    llvm.store %214, %216 : i32, !llvm.ptr
    cf.br ^bb18
    ^bb18:
    %217 = llvm.load %216 : !llvm.ptr -> i32
    %218 = arith.cmpi slt, %217, %arg1 : i32
    cf.cond_br %218, ^bb19, ^bb20
    ^bb19:
      %220 = llvm.load %216 : !llvm.ptr -> i32
      %221 = arith.extsi %220 : i32 to i64
      %222 = llvm.getelementptr %196[%221] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %219 = llvm.load %222 : !llvm.ptr -> i32
      %223 = llvm.load %216 : !llvm.ptr -> i32
      %224 = arith.constant 1 : i32
      %225 = arith.subi %223, %224 : i32
      %226 = llvm.mlir.constant(1 : i64) : i64
      %227 = llvm.alloca %226 x i32 : (i64) -> !llvm.ptr
      llvm.store %225, %227 : i32, !llvm.ptr
      cf.br ^bb21
      ^bb21:
      %228 = llvm.load %227 : !llvm.ptr -> i32
      %229 = arith.constant 0 : i32
      %230 = arith.cmpi sge, %228, %229 : i32
      cf.cond_br %230, ^bb22, ^bb23
      ^bb22:
        %232 = llvm.load %227 : !llvm.ptr -> i32
        %233 = arith.extsi %232 : i32 to i64
        %234 = llvm.getelementptr %196[%233] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %231 = llvm.load %234 : !llvm.ptr -> i32
        %235 = arith.cmpi sgt, %231, %219 : i32
        cf.cond_br %235, ^bb24, ^bb25
        ^bb24:
          %237 = llvm.load %227 : !llvm.ptr -> i32
          %238 = arith.extsi %237 : i32 to i64
          %239 = llvm.getelementptr %196[%238] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %236 = llvm.load %239 : !llvm.ptr -> i32
          %240 = llvm.load %227 : !llvm.ptr -> i32
          %241 = arith.constant 1 : i32
          %242 = arith.addi %240, %241 : i32
          %243 = arith.extsi %242 : i32 to i64
          %244 = llvm.getelementptr %196[%243] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %236, %244 : i32, !llvm.ptr
          %245 = llvm.load %227 : !llvm.ptr -> i32
          %246 = arith.constant 1 : i32
          %247 = arith.subi %245, %246 : i32
          llvm.store %247, %227 : i32, !llvm.ptr
          cf.br ^bb26
        ^bb25:
          cf.br ^bb23
        ^bb26:
        cf.br ^bb21
      ^bb23:
      %248 = llvm.load %227 : !llvm.ptr -> i32
      %249 = arith.constant 1 : i32
      %250 = arith.addi %248, %249 : i32
      %251 = arith.extsi %250 : i32 to i64
      %252 = llvm.getelementptr %196[%251] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %219, %252 : i32, !llvm.ptr
      %253 = llvm.load %216 : !llvm.ptr -> i32
      %254 = arith.constant 1 : i32
      %255 = arith.addi %253, %254 : i32
      llvm.store %255, %216 : i32, !llvm.ptr
      cf.br ^bb18
    ^bb20:
    %256 = arith.constant 0 : i32
    %257 = arith.extsi %256 : i32 to i64
    %258 = llvm.mlir.constant(1 : i64) : i64
    %259 = llvm.alloca %258 x i64 : (i64) -> !llvm.ptr
    llvm.store %257, %259 : i64, !llvm.ptr
    %260 = arith.constant 0 : i32
    %261 = llvm.mlir.constant(1 : i64) : i64
    %262 = llvm.alloca %261 x i32 : (i64) -> !llvm.ptr
    llvm.store %260, %262 : i32, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %263 = llvm.load %262 : !llvm.ptr -> i32
    %264 = arith.cmpi slt, %263, %arg1 : i32
    cf.cond_br %264, ^bb28, ^bb29
    ^bb28:
      %265 = llvm.load %259 : !llvm.ptr -> i64
      %266 = arith.constant 201 : i32
      %268 = arith.extsi %266 : i32 to i64
      %267 = arith.muli %265, %268 : i64
      %270 = llvm.load %262 : !llvm.ptr -> i32
      %271 = arith.extsi %270 : i32 to i64
      %272 = llvm.getelementptr %196[%271] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %269 = llvm.load %272 : !llvm.ptr -> i32
      %273 = arith.constant 1 : i32
      %274 = arith.addi %269, %273 : i32
      %275 = arith.extsi %274 : i32 to i64
      %276 = arith.addi %267, %275 : i64
      llvm.store %276, %259 : i64, !llvm.ptr
      %277 = llvm.load %262 : !llvm.ptr -> i32
      %278 = arith.constant 1 : i32
      %279 = arith.addi %277, %278 : i32
      llvm.store %279, %262 : i32, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    func.call @free(%196) : (!llvm.ptr) -> ()
    %281 = llvm.load %259 : !llvm.ptr -> i64
    func.return %281 : i64
  }
  func.func @sort_i32(%arg0: !llvm.ptr, %arg1: i32) -> () {
    %282 = arith.constant 1 : i32
    %283 = llvm.mlir.constant(1 : i64) : i64
    %284 = llvm.alloca %283 x i32 : (i64) -> !llvm.ptr
    llvm.store %282, %284 : i32, !llvm.ptr
    cf.br ^bb30
    ^bb30:
    %285 = llvm.load %284 : !llvm.ptr -> i32
    %286 = arith.cmpi slt, %285, %arg1 : i32
    cf.cond_br %286, ^bb31, ^bb32
    ^bb31:
      %288 = llvm.load %284 : !llvm.ptr -> i32
      %289 = arith.extsi %288 : i32 to i64
      %290 = llvm.getelementptr %arg0[%289] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %287 = llvm.load %290 : !llvm.ptr -> i32
      %291 = llvm.load %284 : !llvm.ptr -> i32
      %292 = arith.constant 1 : i32
      %293 = arith.subi %291, %292 : i32
      %294 = llvm.mlir.constant(1 : i64) : i64
      %295 = llvm.alloca %294 x i32 : (i64) -> !llvm.ptr
      llvm.store %293, %295 : i32, !llvm.ptr
      cf.br ^bb33
      ^bb33:
      %296 = llvm.load %295 : !llvm.ptr -> i32
      %297 = arith.constant 0 : i32
      %298 = arith.cmpi sge, %296, %297 : i32
      cf.cond_br %298, ^bb34, ^bb35
      ^bb34:
        %300 = llvm.load %295 : !llvm.ptr -> i32
        %301 = arith.extsi %300 : i32 to i64
        %302 = llvm.getelementptr %arg0[%301] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %299 = llvm.load %302 : !llvm.ptr -> i32
        %303 = arith.cmpi sgt, %299, %287 : i32
        cf.cond_br %303, ^bb36, ^bb37
        ^bb36:
          %305 = llvm.load %295 : !llvm.ptr -> i32
          %306 = arith.extsi %305 : i32 to i64
          %307 = llvm.getelementptr %arg0[%306] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %304 = llvm.load %307 : !llvm.ptr -> i32
          %308 = llvm.load %295 : !llvm.ptr -> i32
          %309 = arith.constant 1 : i32
          %310 = arith.addi %308, %309 : i32
          %311 = arith.extsi %310 : i32 to i64
          %312 = llvm.getelementptr %arg0[%311] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %304, %312 : i32, !llvm.ptr
          %313 = llvm.load %295 : !llvm.ptr -> i32
          %314 = arith.constant 1 : i32
          %315 = arith.subi %313, %314 : i32
          llvm.store %315, %295 : i32, !llvm.ptr
          cf.br ^bb38
        ^bb37:
          cf.br ^bb35
        ^bb38:
        cf.br ^bb33
      ^bb35:
      %316 = llvm.load %295 : !llvm.ptr -> i32
      %317 = arith.constant 1 : i32
      %318 = arith.addi %316, %317 : i32
      %319 = arith.extsi %318 : i32 to i64
      %320 = llvm.getelementptr %arg0[%319] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %287, %320 : i32, !llvm.ptr
      %321 = llvm.load %284 : !llvm.ptr -> i32
      %322 = arith.constant 1 : i32
      %323 = arith.addi %321, %322 : i32
      llvm.store %323, %284 : i32, !llvm.ptr
      cf.br ^bb30
    ^bb32:
    func.return
  }
  func.func @dedup_sorted(%arg0: !llvm.ptr, %arg1: i32) -> i32 {
    %324 = arith.constant 1 : i32
    %325 = arith.cmpi sle, %arg1, %324 : i32
    cf.cond_br %325, ^bb39, ^bb40
    ^bb39:
      func.return %arg1 : i32
    ^bb40:
      cf.br ^bb41
    ^bb41:
    %326 = arith.constant 1 : i32
    %327 = llvm.mlir.constant(1 : i64) : i64
    %328 = llvm.alloca %327 x i32 : (i64) -> !llvm.ptr
    llvm.store %326, %328 : i32, !llvm.ptr
    %329 = arith.constant 1 : i32
    %330 = llvm.mlir.constant(1 : i64) : i64
    %331 = llvm.alloca %330 x i32 : (i64) -> !llvm.ptr
    llvm.store %329, %331 : i32, !llvm.ptr
    cf.br ^bb42
    ^bb42:
    %332 = llvm.load %331 : !llvm.ptr -> i32
    %333 = arith.cmpi slt, %332, %arg1 : i32
    cf.cond_br %333, ^bb43, ^bb44
    ^bb43:
      %335 = llvm.load %331 : !llvm.ptr -> i32
      %336 = arith.extsi %335 : i32 to i64
      %337 = llvm.getelementptr %arg0[%336] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %334 = llvm.load %337 : !llvm.ptr -> i32
      %339 = llvm.load %331 : !llvm.ptr -> i32
      %340 = arith.constant 1 : i32
      %341 = arith.subi %339, %340 : i32
      %342 = arith.extsi %341 : i32 to i64
      %343 = llvm.getelementptr %arg0[%342] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %338 = llvm.load %343 : !llvm.ptr -> i32
      %344 = arith.cmpi ne, %334, %338 : i32
      cf.cond_br %344, ^bb45, ^bb46
      ^bb45:
        %346 = llvm.load %331 : !llvm.ptr -> i32
        %347 = arith.extsi %346 : i32 to i64
        %348 = llvm.getelementptr %arg0[%347] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %345 = llvm.load %348 : !llvm.ptr -> i32
        %349 = llvm.load %328 : !llvm.ptr -> i32
        %350 = arith.extsi %349 : i32 to i64
        %351 = llvm.getelementptr %arg0[%350] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %345, %351 : i32, !llvm.ptr
        %352 = llvm.load %328 : !llvm.ptr -> i32
        %353 = arith.constant 1 : i32
        %354 = arith.addi %352, %353 : i32
        llvm.store %354, %328 : i32, !llvm.ptr
        cf.br ^bb47
      ^bb46:
        cf.br ^bb47
      ^bb47:
      %355 = llvm.load %331 : !llvm.ptr -> i32
      %356 = arith.constant 1 : i32
      %357 = arith.addi %355, %356 : i32
      llvm.store %357, %331 : i32, !llvm.ptr
      cf.br ^bb42
    ^bb44:
    %358 = llvm.load %328 : !llvm.ptr -> i32
    func.return %358 : i32
  }
  func.func @generate_values(%arg0: !llvm.ptr, %arg1: i32) -> () {
    %359 = func.call @encode_key(%arg0, %arg1) : (!llvm.ptr, i32) -> i64
    %360 = func.call @cache_find(%359) : (i64) -> i32
    %361 = arith.constant 0 : i32
    %362 = arith.cmpi sge, %360, %361 : i32
    cf.cond_br %362, ^bb48, ^bb49
    ^bb48:
      %363 = arith.constant 0 : i32
      %364 = llvm.mlir.constant(1 : i64) : i64
      %365 = llvm.alloca %364 x i32 : (i64) -> !llvm.ptr
      llvm.store %363, %365 : i32, !llvm.ptr
      cf.br ^bb51
      ^bb51:
      %366 = llvm.load %365 : !llvm.ptr -> i32
      %368 = llvm.mlir.addressof @g_cache : !llvm.ptr
      %369 = llvm.load %368 : !llvm.ptr -> !llvm.ptr
      %370 = arith.extsi %360 : i32 to i64
      %371 = llvm.getelementptr %369[%370] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %367 = llvm.load %371 : !llvm.ptr -> !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %372 = llvm.mlir.addressof @g_cache : !llvm.ptr
      %373 = llvm.load %372 : !llvm.ptr -> !llvm.ptr
      %374 = arith.extsi %360 : i32 to i64
      %375 = llvm.getelementptr %373[%374] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %376 = llvm.getelementptr %375[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
      %377 = llvm.load %376 : !llvm.ptr -> i32
      %378 = arith.cmpi slt, %366, %377 : i32
      cf.cond_br %378, ^bb52, ^bb53
      ^bb52:
        %382 = llvm.mlir.addressof @g_cache : !llvm.ptr
        %383 = llvm.load %382 : !llvm.ptr -> !llvm.ptr
        %384 = arith.extsi %360 : i32 to i64
        %385 = llvm.getelementptr %383[%384] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
        %381 = llvm.load %385 : !llvm.ptr -> !llvm.struct<(i64, !llvm.ptr, i32, i32)>
        %386 = llvm.mlir.addressof @g_cache : !llvm.ptr
        %387 = llvm.load %386 : !llvm.ptr -> !llvm.ptr
        %388 = arith.extsi %360 : i32 to i64
        %389 = llvm.getelementptr %387[%388] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
        %390 = llvm.getelementptr %389[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
        %391 = llvm.load %390 : !llvm.ptr -> !llvm.ptr
        %392 = llvm.load %365 : !llvm.ptr -> i32
        %393 = arith.extsi %392 : i32 to i64
        %394 = llvm.getelementptr %391[%393] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %380 = llvm.load %394 : !llvm.ptr -> i32
        func.call @da_add(%380) : (i32) -> ()
        %395 = llvm.load %365 : !llvm.ptr -> i32
        %396 = arith.constant 1 : i32
        %397 = arith.addi %395, %396 : i32
        llvm.store %397, %365 : i32, !llvm.ptr
        cf.br ^bb51
      ^bb53:
      func.return
    ^bb49:
      cf.br ^bb50
    ^bb50:
    %398 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %399 = llvm.load %398 : !llvm.ptr -> !llvm.ptr
    %400 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %401 = llvm.load %400 : !llvm.ptr -> i32
    %402 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
    %403 = llvm.load %402 : !llvm.ptr -> i32
    func.call @da_init() : () -> ()
    %405 = arith.constant 1 : i32
    %406 = arith.cmpi eq, %arg1, %405 : i32
    cf.cond_br %406, ^bb54, ^bb55
    ^bb54:
      %409 = arith.constant 0 : i32
      %410 = arith.extsi %409 : i32 to i64
      %411 = llvm.getelementptr %arg0[%410] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %408 = llvm.load %411 : !llvm.ptr -> i32
      func.call @da_add(%408) : (i32) -> ()
      cf.br ^bb56
    ^bb55:
      %412 = arith.constant 1 : i32
      %413 = arith.shli %412, %arg1 : i32
      %414 = arith.constant 1 : i32
      %415 = llvm.mlir.constant(1 : i64) : i64
      %416 = llvm.alloca %415 x i32 : (i64) -> !llvm.ptr
      llvm.store %414, %416 : i32, !llvm.ptr
      cf.br ^bb57
      ^bb57:
      %417 = llvm.load %416 : !llvm.ptr -> i32
      %418 = arith.constant 1 : i32
      %419 = arith.subi %413, %418 : i32
      %420 = arith.cmpi slt, %417, %419 : i32
      cf.cond_br %420, ^bb58, ^bb59
      ^bb58:
        %421 = llvm.load %416 : !llvm.ptr -> i32
        %423 = arith.constant -1 : i32
        %422 = arith.xori %421, %423 : i32
        %424 = arith.constant 1 : i32
        %425 = arith.subi %413, %424 : i32
        %426 = arith.andi %422, %425 : i32
        %427 = llvm.load %416 : !llvm.ptr -> i32
        %428 = arith.cmpi sgt, %427, %426 : i32
        cf.cond_br %428, ^bb60, ^bb61
        ^bb60:
          %429 = llvm.load %416 : !llvm.ptr -> i32
          %430 = arith.constant 1 : i32
          %431 = arith.addi %429, %430 : i32
          llvm.store %431, %416 : i32, !llvm.ptr
          cf.br ^bb57
        ^bb61:
          cf.br ^bb62
        ^bb62:
        %433 = arith.constant 24 : i32
        %434 = arith.extsi %433 : i32 to i64
        %432 = func.call @malloc(%434) : (i64) -> !llvm.ptr
        %436 = arith.constant 24 : i32
        %437 = arith.extsi %436 : i32 to i64
        %435 = func.call @malloc(%437) : (i64) -> !llvm.ptr
        %438 = arith.constant 0 : i32
        %439 = llvm.mlir.constant(1 : i64) : i64
        %440 = llvm.alloca %439 x i32 : (i64) -> !llvm.ptr
        llvm.store %438, %440 : i32, !llvm.ptr
        %441 = arith.constant 0 : i32
        %442 = llvm.mlir.constant(1 : i64) : i64
        %443 = llvm.alloca %442 x i32 : (i64) -> !llvm.ptr
        llvm.store %441, %443 : i32, !llvm.ptr
        %444 = arith.constant 0 : i32
        %445 = llvm.mlir.constant(1 : i64) : i64
        %446 = llvm.alloca %445 x i32 : (i64) -> !llvm.ptr
        llvm.store %444, %446 : i32, !llvm.ptr
        cf.br ^bb63
        ^bb63:
        %447 = llvm.load %446 : !llvm.ptr -> i32
        %448 = arith.cmpi slt, %447, %arg1 : i32
        cf.cond_br %448, ^bb64, ^bb65
        ^bb64:
          %449 = llvm.load %416 : !llvm.ptr -> i32
          %450 = arith.constant 1 : i32
          %451 = llvm.load %446 : !llvm.ptr -> i32
          %452 = arith.shli %450, %451 : i32
          %453 = arith.andi %449, %452 : i32
          %454 = arith.constant 0 : i32
          %455 = arith.cmpi ne, %453, %454 : i32
          cf.cond_br %455, ^bb66, ^bb67
          ^bb66:
            %457 = llvm.load %446 : !llvm.ptr -> i32
            %458 = arith.extsi %457 : i32 to i64
            %459 = llvm.getelementptr %arg0[%458] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %456 = llvm.load %459 : !llvm.ptr -> i32
            %460 = llvm.load %440 : !llvm.ptr -> i32
            %461 = arith.extsi %460 : i32 to i64
            %462 = llvm.getelementptr %432[%461] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            llvm.store %456, %462 : i32, !llvm.ptr
            %463 = llvm.load %440 : !llvm.ptr -> i32
            %464 = arith.constant 1 : i32
            %465 = arith.addi %463, %464 : i32
            llvm.store %465, %440 : i32, !llvm.ptr
            cf.br ^bb68
          ^bb67:
            %467 = llvm.load %446 : !llvm.ptr -> i32
            %468 = arith.extsi %467 : i32 to i64
            %469 = llvm.getelementptr %arg0[%468] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %466 = llvm.load %469 : !llvm.ptr -> i32
            %470 = llvm.load %443 : !llvm.ptr -> i32
            %471 = arith.extsi %470 : i32 to i64
            %472 = llvm.getelementptr %435[%471] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            llvm.store %466, %472 : i32, !llvm.ptr
            %473 = llvm.load %443 : !llvm.ptr -> i32
            %474 = arith.constant 1 : i32
            %475 = arith.addi %473, %474 : i32
            llvm.store %475, %443 : i32, !llvm.ptr
            cf.br ^bb68
          ^bb68:
          %476 = llvm.load %446 : !llvm.ptr -> i32
          %477 = arith.constant 1 : i32
          %478 = arith.addi %476, %477 : i32
          llvm.store %478, %446 : i32, !llvm.ptr
          cf.br ^bb63
        ^bb65:
        %479 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        %480 = llvm.load %479 : !llvm.ptr -> !llvm.ptr
        %481 = llvm.mlir.addressof @g_da_count : !llvm.ptr
        %482 = llvm.load %481 : !llvm.ptr -> i32
        %483 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
        %484 = llvm.load %483 : !llvm.ptr -> i32
        func.call @da_init() : () -> ()
        %487 = llvm.load %440 : !llvm.ptr -> i32
        func.call @generate_values(%432, %487) : (!llvm.ptr, i32) -> ()
        %488 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        %489 = llvm.load %488 : !llvm.ptr -> !llvm.ptr
        %490 = llvm.mlir.addressof @g_da_count : !llvm.ptr
        %491 = llvm.load %490 : !llvm.ptr -> i32
        %492 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        llvm.store %480, %492 : !llvm.ptr, !llvm.ptr
        %493 = llvm.mlir.addressof @g_da_count : !llvm.ptr
        llvm.store %482, %493 : i32, !llvm.ptr
        %494 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
        llvm.store %484, %494 : i32, !llvm.ptr
        %495 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        %496 = llvm.load %495 : !llvm.ptr -> !llvm.ptr
        %497 = llvm.mlir.addressof @g_da_count : !llvm.ptr
        %498 = llvm.load %497 : !llvm.ptr -> i32
        %499 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
        %500 = llvm.load %499 : !llvm.ptr -> i32
        func.call @da_init() : () -> ()
        %503 = llvm.load %443 : !llvm.ptr -> i32
        func.call @generate_values(%435, %503) : (!llvm.ptr, i32) -> ()
        %504 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        %505 = llvm.load %504 : !llvm.ptr -> !llvm.ptr
        %506 = llvm.mlir.addressof @g_da_count : !llvm.ptr
        %507 = llvm.load %506 : !llvm.ptr -> i32
        %508 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        llvm.store %496, %508 : !llvm.ptr, !llvm.ptr
        %509 = llvm.mlir.addressof @g_da_count : !llvm.ptr
        llvm.store %498, %509 : i32, !llvm.ptr
        %510 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
        llvm.store %500, %510 : i32, !llvm.ptr
        %511 = arith.constant 0 : i32
        %512 = llvm.mlir.constant(1 : i64) : i64
        %513 = llvm.alloca %512 x i32 : (i64) -> !llvm.ptr
        llvm.store %511, %513 : i32, !llvm.ptr
        cf.br ^bb69
        ^bb69:
        %514 = llvm.load %513 : !llvm.ptr -> i32
        %515 = arith.cmpi slt, %514, %491 : i32
        cf.cond_br %515, ^bb70, ^bb71
        ^bb70:
          %516 = arith.constant 0 : i32
          %517 = llvm.mlir.constant(1 : i64) : i64
          %518 = llvm.alloca %517 x i32 : (i64) -> !llvm.ptr
          llvm.store %516, %518 : i32, !llvm.ptr
          cf.br ^bb72
          ^bb72:
          %519 = llvm.load %518 : !llvm.ptr -> i32
          %520 = arith.cmpi slt, %519, %507 : i32
          cf.cond_br %520, ^bb73, ^bb74
          ^bb73:
            %522 = llvm.load %513 : !llvm.ptr -> i32
            %523 = arith.extsi %522 : i32 to i64
            %524 = llvm.getelementptr %489[%523] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %521 = llvm.load %524 : !llvm.ptr -> i32
            %526 = llvm.load %518 : !llvm.ptr -> i32
            %527 = arith.extsi %526 : i32 to i64
            %528 = llvm.getelementptr %505[%527] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %525 = llvm.load %528 : !llvm.ptr -> i32
            %530 = arith.addi %521, %525 : i32
            func.call @da_add(%530) : (i32) -> ()
            %532 = arith.muli %521, %525 : i32
            func.call @da_add(%532) : (i32) -> ()
            %533 = arith.cmpi sgt, %521, %525 : i32
            cf.cond_br %533, ^bb75, ^bb76
            ^bb75:
              %535 = arith.subi %521, %525 : i32
              func.call @da_add(%535) : (i32) -> ()
              cf.br ^bb77
            ^bb76:
              cf.br ^bb77
            ^bb77:
            %536 = arith.cmpi sgt, %525, %521 : i32
            cf.cond_br %536, ^bb78, ^bb79
            ^bb78:
              %538 = arith.subi %525, %521 : i32
              func.call @da_add(%538) : (i32) -> ()
              cf.br ^bb80
            ^bb79:
              cf.br ^bb80
            ^bb80:
            %539 = arith.constant 0 : i32
            %540 = arith.cmpi sgt, %525, %539 : i32
            %541 = scf.if %540 -> (i1) {
              %542 = arith.remsi %521, %525 : i32
              %543 = arith.constant 0 : i32
              %544 = arith.cmpi eq, %542, %543 : i32
              scf.yield %544 : i1
            } else {
              %545 = arith.constant false
              scf.yield %545 : i1
            }
            cf.cond_br %541, ^bb81, ^bb82
            ^bb81:
              %547 = arith.divsi %521, %525 : i32
              func.call @da_add(%547) : (i32) -> ()
              cf.br ^bb83
            ^bb82:
              cf.br ^bb83
            ^bb83:
            %548 = arith.constant 0 : i32
            %549 = arith.cmpi sgt, %521, %548 : i32
            %550 = scf.if %549 -> (i1) {
              %551 = arith.remsi %525, %521 : i32
              %552 = arith.constant 0 : i32
              %553 = arith.cmpi eq, %551, %552 : i32
              scf.yield %553 : i1
            } else {
              %554 = arith.constant false
              scf.yield %554 : i1
            }
            cf.cond_br %550, ^bb84, ^bb85
            ^bb84:
              %556 = arith.divsi %525, %521 : i32
              func.call @da_add(%556) : (i32) -> ()
              cf.br ^bb86
            ^bb85:
              cf.br ^bb86
            ^bb86:
            %557 = llvm.load %518 : !llvm.ptr -> i32
            %558 = arith.constant 1 : i32
            %559 = arith.addi %557, %558 : i32
            llvm.store %559, %518 : i32, !llvm.ptr
            cf.br ^bb72
          ^bb74:
          %560 = llvm.load %513 : !llvm.ptr -> i32
          %561 = arith.constant 1 : i32
          %562 = arith.addi %560, %561 : i32
          llvm.store %562, %513 : i32, !llvm.ptr
          cf.br ^bb69
        ^bb71:
        func.call @free(%489) : (!llvm.ptr) -> ()
        func.call @free(%505) : (!llvm.ptr) -> ()
        func.call @free(%432) : (!llvm.ptr) -> ()
        func.call @free(%435) : (!llvm.ptr) -> ()
        %567 = llvm.load %416 : !llvm.ptr -> i32
        %568 = arith.constant 1 : i32
        %569 = arith.addi %567, %568 : i32
        llvm.store %569, %416 : i32, !llvm.ptr
        cf.br ^bb57
      ^bb59:
      cf.br ^bb56
    ^bb56:
    %571 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %572 = llvm.load %571 : !llvm.ptr -> !llvm.ptr
    %573 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %574 = llvm.load %573 : !llvm.ptr -> i32
    func.call @sort_i32(%572, %574) : (!llvm.ptr, i32) -> ()
    %576 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %577 = llvm.load %576 : !llvm.ptr -> !llvm.ptr
    %578 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %579 = llvm.load %578 : !llvm.ptr -> i32
    %575 = func.call @dedup_sorted(%577, %579) : (!llvm.ptr, i32) -> i32
    %580 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    llvm.store %575, %580 : i32, !llvm.ptr
    %581 = func.call @cache_insert(%359) : (i64) -> i32
    %583 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %584 = llvm.load %583 : !llvm.ptr -> i32
    %585 = arith.extsi %584 : i32 to i64
    %586 = arith.constant 4 : i32
    %588 = arith.extsi %586 : i32 to i64
    %587 = arith.muli %585, %588 : i64
    %582 = func.call @malloc(%587) : (i64) -> !llvm.ptr
    %590 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %591 = llvm.load %590 : !llvm.ptr -> !llvm.ptr
    %592 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %593 = llvm.load %592 : !llvm.ptr -> i32
    %594 = arith.extsi %593 : i32 to i64
    %595 = arith.constant 4 : i32
    %597 = arith.extsi %595 : i32 to i64
    %596 = arith.muli %594, %597 : i64
    %589 = func.call @memcpy(%582, %591, %596) : (!llvm.ptr, !llvm.ptr, i64) -> !llvm.ptr
    %598 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %599 = llvm.load %598 : !llvm.ptr -> !llvm.ptr
    %600 = arith.extsi %581 : i32 to i64
    %601 = llvm.getelementptr %599[%600] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %602 = llvm.getelementptr %601[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    llvm.store %582, %602 : !llvm.ptr, !llvm.ptr
    %603 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %604 = llvm.load %603 : !llvm.ptr -> i32
    %605 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %606 = llvm.load %605 : !llvm.ptr -> !llvm.ptr
    %607 = arith.extsi %581 : i32 to i64
    %608 = llvm.getelementptr %606[%607] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    %609 = llvm.getelementptr %608[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, !llvm.ptr, i32, i32)>
    llvm.store %604, %609 : i32, !llvm.ptr
    %610 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    %611 = llvm.load %610 : !llvm.ptr -> !llvm.ptr
    %612 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    %613 = llvm.load %612 : !llvm.ptr -> i32
    %614 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
    llvm.store %399, %614 : !llvm.ptr, !llvm.ptr
    %615 = llvm.mlir.addressof @g_da_count : !llvm.ptr
    llvm.store %401, %615 : i32, !llvm.ptr
    %616 = llvm.mlir.addressof @g_da_cap : !llvm.ptr
    llvm.store %403, %616 : i32, !llvm.ptr
    %617 = arith.constant 0 : i32
    %618 = llvm.mlir.constant(1 : i64) : i64
    %619 = llvm.alloca %618 x i32 : (i64) -> !llvm.ptr
    llvm.store %617, %619 : i32, !llvm.ptr
    cf.br ^bb87
    ^bb87:
    %620 = llvm.load %619 : !llvm.ptr -> i32
    %621 = arith.cmpi slt, %620, %613 : i32
    cf.cond_br %621, ^bb88, ^bb89
    ^bb88:
      %624 = llvm.load %619 : !llvm.ptr -> i32
      %625 = arith.extsi %624 : i32 to i64
      %626 = llvm.getelementptr %611[%625] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %623 = llvm.load %626 : !llvm.ptr -> i32
      func.call @da_add(%623) : (i32) -> ()
      %627 = llvm.load %619 : !llvm.ptr -> i32
      %628 = arith.constant 1 : i32
      %629 = arith.addi %627, %628 : i32
      llvm.store %629, %619 : i32, !llvm.ptr
      cf.br ^bb87
    ^bb89:
    func.call @free(%611) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @min_score(%arg0: i32, %arg1: !llvm.ptr, %arg2: i32, %arg3: i32) -> i32 {
    %631 = arith.constant 0 : i32
    %632 = llvm.mlir.constant(1 : i64) : i64
    %633 = llvm.alloca %632 x i32 : (i64) -> !llvm.ptr
    llvm.store %631, %633 : i32, !llvm.ptr
    %634 = arith.constant 1 : i32
    %635 = arith.shli %634, %arg3 : i32
    %636 = arith.constant 1 : i32
    %637 = llvm.mlir.constant(1 : i64) : i64
    %638 = llvm.alloca %637 x i32 : (i64) -> !llvm.ptr
    llvm.store %636, %638 : i32, !llvm.ptr
    cf.br ^bb90
    ^bb90:
    %639 = llvm.load %638 : !llvm.ptr -> i32
    %640 = arith.cmpi slt, %639, %635 : i32
    cf.cond_br %640, ^bb91, ^bb92
    ^bb91:
      %642 = arith.constant 24 : i32
      %643 = arith.extsi %642 : i32 to i64
      %641 = func.call @malloc(%643) : (i64) -> !llvm.ptr
      %644 = arith.constant 0 : i32
      %645 = llvm.mlir.constant(1 : i64) : i64
      %646 = llvm.alloca %645 x i32 : (i64) -> !llvm.ptr
      llvm.store %644, %646 : i32, !llvm.ptr
      %647 = arith.constant 0 : i32
      %648 = llvm.mlir.constant(1 : i64) : i64
      %649 = llvm.alloca %648 x i32 : (i64) -> !llvm.ptr
      llvm.store %647, %649 : i32, !llvm.ptr
      %650 = arith.constant 0 : i32
      %651 = llvm.mlir.constant(1 : i64) : i64
      %652 = llvm.alloca %651 x i32 : (i64) -> !llvm.ptr
      llvm.store %650, %652 : i32, !llvm.ptr
      cf.br ^bb93
      ^bb93:
      %653 = llvm.load %652 : !llvm.ptr -> i32
      %654 = arith.cmpi slt, %653, %arg3 : i32
      cf.cond_br %654, ^bb94, ^bb95
      ^bb94:
        %655 = llvm.load %638 : !llvm.ptr -> i32
        %656 = arith.constant 1 : i32
        %657 = llvm.load %652 : !llvm.ptr -> i32
        %658 = arith.shli %656, %657 : i32
        %659 = arith.andi %655, %658 : i32
        %660 = arith.constant 0 : i32
        %661 = arith.cmpi ne, %659, %660 : i32
        cf.cond_br %661, ^bb96, ^bb97
        ^bb96:
          %663 = llvm.load %652 : !llvm.ptr -> i32
          %664 = arith.addi %arg2, %663 : i32
          %665 = arith.extsi %664 : i32 to i64
          %666 = llvm.getelementptr %arg1[%665] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %662 = llvm.load %666 : !llvm.ptr -> i32
          %667 = llvm.load %646 : !llvm.ptr -> i32
          %668 = arith.extsi %667 : i32 to i64
          %669 = llvm.getelementptr %641[%668] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %662, %669 : i32, !llvm.ptr
          %670 = llvm.load %649 : !llvm.ptr -> i32
          %672 = llvm.load %652 : !llvm.ptr -> i32
          %673 = arith.addi %arg2, %672 : i32
          %674 = arith.extsi %673 : i32 to i64
          %675 = llvm.getelementptr %arg1[%674] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %671 = llvm.load %675 : !llvm.ptr -> i32
          %676 = arith.addi %670, %671 : i32
          llvm.store %676, %649 : i32, !llvm.ptr
          %677 = llvm.load %646 : !llvm.ptr -> i32
          %678 = arith.constant 1 : i32
          %679 = arith.addi %677, %678 : i32
          llvm.store %679, %646 : i32, !llvm.ptr
          cf.br ^bb98
        ^bb97:
          cf.br ^bb98
        ^bb98:
        %680 = llvm.load %652 : !llvm.ptr -> i32
        %681 = arith.constant 1 : i32
        %682 = arith.addi %680, %681 : i32
        llvm.store %682, %652 : i32, !llvm.ptr
        cf.br ^bb93
      ^bb95:
      %683 = llvm.load %633 : !llvm.ptr -> i32
      %684 = arith.constant 0 : i32
      %685 = arith.cmpi sgt, %683, %684 : i32
      %686 = scf.if %685 -> (i1) {
        %687 = llvm.load %649 : !llvm.ptr -> i32
        %688 = llvm.load %633 : !llvm.ptr -> i32
        %689 = arith.cmpi sge, %687, %688 : i32
        scf.yield %689 : i1
      } else {
        %690 = arith.constant false
        scf.yield %690 : i1
      }
      cf.cond_br %686, ^bb99, ^bb100
      ^bb99:
        func.call @free(%641) : (!llvm.ptr) -> ()
        %692 = llvm.load %638 : !llvm.ptr -> i32
        %693 = arith.constant 1 : i32
        %694 = arith.addi %692, %693 : i32
        llvm.store %694, %638 : i32, !llvm.ptr
        cf.br ^bb90
      ^bb100:
        cf.br ^bb101
      ^bb101:
      func.call @da_init() : () -> ()
      %697 = llvm.load %646 : !llvm.ptr -> i32
      func.call @generate_values(%641, %697) : (!llvm.ptr, i32) -> ()
      %698 = arith.constant 0 : i32
      %699 = llvm.mlir.constant(1 : i64) : i64
      %700 = llvm.alloca %699 x i32 : (i64) -> !llvm.ptr
      llvm.store %698, %700 : i32, !llvm.ptr
      %701 = llvm.mlir.addressof @g_da_count : !llvm.ptr
      %702 = llvm.load %701 : !llvm.ptr -> i32
      %703 = arith.constant 1 : i32
      %704 = arith.subi %702, %703 : i32
      %705 = llvm.mlir.constant(1 : i64) : i64
      %706 = llvm.alloca %705 x i32 : (i64) -> !llvm.ptr
      llvm.store %704, %706 : i32, !llvm.ptr
      %707 = arith.constant 0 : i32
      %708 = llvm.mlir.constant(1 : i64) : i64
      %709 = llvm.alloca %708 x i32 : (i64) -> !llvm.ptr
      llvm.store %707, %709 : i32, !llvm.ptr
      cf.br ^bb102
      ^bb102:
      %710 = llvm.load %700 : !llvm.ptr -> i32
      %711 = llvm.load %706 : !llvm.ptr -> i32
      %712 = arith.cmpi sle, %710, %711 : i32
      cf.cond_br %712, ^bb103, ^bb104
      ^bb103:
        %713 = llvm.load %700 : !llvm.ptr -> i32
        %714 = llvm.load %706 : !llvm.ptr -> i32
        %715 = arith.addi %713, %714 : i32
        %716 = arith.constant 2 : i32
        %717 = arith.divsi %715, %716 : i32
        %719 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        %720 = llvm.load %719 : !llvm.ptr -> !llvm.ptr
        %721 = arith.extsi %717 : i32 to i64
        %722 = llvm.getelementptr %720[%721] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %718 = llvm.load %722 : !llvm.ptr -> i32
        %723 = arith.cmpi eq, %718, %arg0 : i32
        cf.cond_br %723, ^bb105, ^bb106
        ^bb105:
          %724 = arith.constant 1 : i32
          llvm.store %724, %709 : i32, !llvm.ptr
          cf.br ^bb104
        ^bb106:
          cf.br ^bb107
        ^bb107:
        %726 = llvm.mlir.addressof @g_da_vals : !llvm.ptr
        %727 = llvm.load %726 : !llvm.ptr -> !llvm.ptr
        %728 = arith.extsi %717 : i32 to i64
        %729 = llvm.getelementptr %727[%728] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %725 = llvm.load %729 : !llvm.ptr -> i32
        %730 = arith.cmpi slt, %725, %arg0 : i32
        cf.cond_br %730, ^bb108, ^bb109
        ^bb108:
          %731 = arith.constant 1 : i32
          %732 = arith.addi %717, %731 : i32
          llvm.store %732, %700 : i32, !llvm.ptr
          cf.br ^bb110
        ^bb109:
          %733 = arith.constant 1 : i32
          %734 = arith.subi %717, %733 : i32
          llvm.store %734, %706 : i32, !llvm.ptr
          cf.br ^bb110
        ^bb110:
        cf.br ^bb102
      ^bb104:
      %735 = llvm.load %709 : !llvm.ptr -> i32
      %736 = arith.constant 0 : i32
      %737 = arith.cmpi ne, %735, %736 : i32
      cf.cond_br %737, ^bb111, ^bb112
      ^bb111:
        %738 = llvm.load %633 : !llvm.ptr -> i32
        %739 = arith.constant 0 : i32
        %740 = arith.cmpi eq, %738, %739 : i32
        %741 = scf.if %740 -> (i1) {
          %742 = arith.constant true
          scf.yield %742 : i1
        } else {
          %743 = llvm.load %649 : !llvm.ptr -> i32
          %744 = llvm.load %633 : !llvm.ptr -> i32
          %745 = arith.cmpi slt, %743, %744 : i32
          scf.yield %745 : i1
        }
        cf.cond_br %741, ^bb114, ^bb115
        ^bb114:
          %746 = llvm.load %649 : !llvm.ptr -> i32
          llvm.store %746, %633 : i32, !llvm.ptr
          cf.br ^bb116
        ^bb115:
          cf.br ^bb116
        ^bb116:
        cf.br ^bb113
      ^bb112:
        cf.br ^bb113
      ^bb113:
      func.call @da_free() : () -> ()
      func.call @free(%641) : (!llvm.ptr) -> ()
      %749 = llvm.load %638 : !llvm.ptr -> i32
      %750 = arith.constant 1 : i32
      %751 = arith.addi %749, %750 : i32
      llvm.store %751, %638 : i32, !llvm.ptr
      cf.br ^bb90
    ^bb92:
    %752 = llvm.load %633 : !llvm.ptr -> i32
    func.return %752 : i32
  }
  func.func @read_data(%arg0: !llvm.ptr) -> () {
    %754 = llvm.mlir.addressof @MAX_PROBS : !llvm.ptr
    %755 = llvm.load %754 : !llvm.ptr -> i32
    %756 = arith.extsi %755 : i32 to i64
    %757 = arith.constant 4 : i32
    %759 = arith.extsi %757 : i32 to i64
    %758 = arith.muli %756, %759 : i64
    %753 = func.call @malloc(%758) : (i64) -> !llvm.ptr
    %760 = llvm.mlir.addressof @g_targets : !llvm.ptr
    llvm.store %753, %760 : !llvm.ptr, !llvm.ptr
    %762 = llvm.mlir.addressof @MAX_PROBS : !llvm.ptr
    %763 = llvm.load %762 : !llvm.ptr -> i32
    %764 = arith.extsi %763 : i32 to i64
    %765 = arith.constant 4 : i32
    %767 = arith.extsi %765 : i32 to i64
    %766 = arith.muli %764, %767 : i64
    %761 = func.call @malloc(%766) : (i64) -> !llvm.ptr
    %768 = llvm.mlir.addressof @g_counts : !llvm.ptr
    llvm.store %761, %768 : !llvm.ptr, !llvm.ptr
    %770 = llvm.mlir.addressof @MAX_PROBS : !llvm.ptr
    %771 = llvm.load %770 : !llvm.ptr -> i32
    %772 = arith.extsi %771 : i32 to i64
    %773 = llvm.mlir.addressof @MAX_NUMS : !llvm.ptr
    %774 = llvm.load %773 : !llvm.ptr -> i32
    %775 = arith.extsi %774 : i32 to i64
    %776 = arith.muli %772, %775 : i64
    %777 = arith.constant 4 : i32
    %779 = arith.extsi %777 : i32 to i64
    %778 = arith.muli %776, %779 : i64
    %769 = func.call @malloc(%778) : (i64) -> !llvm.ptr
    %780 = llvm.mlir.addressof @g_nums : !llvm.ptr
    llvm.store %769, %780 : !llvm.ptr, !llvm.ptr
    %782 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %781 = func.call @fopen(%arg0, %782) : (!llvm.ptr, !llvm.ptr) -> !llvm.ptr
    %783 = llvm.mlir.zero : !llvm.ptr
    %784 = llvm.icmp "eq" %781, %783 : !llvm.ptr
    cf.cond_br %784, ^bb117, ^bb118
    ^bb117:
      func.return
    ^bb118:
      cf.br ^bb119
    ^bb119:
    %785 = arith.constant 0 : i32
    %786 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
    llvm.store %785, %786 : i32, !llvm.ptr
    %787 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
    %788 = llvm.mlir.constant(1 : i64) : i64
    %789 = llvm.alloca %788 x i32 : (i64) -> !llvm.ptr
    llvm.store %787, %789 : i32, !llvm.ptr
    cf.br ^bb120
    ^bb120:
    %790 = llvm.load %789 : !llvm.ptr -> i32
    %791 = arith.constant 0 : i32
    %792 = arith.cmpi sge, %790, %791 : i32
    cf.cond_br %792, ^bb121, ^bb122
    ^bb121:
      cf.br ^bb123
      ^bb123:
      %793 = llvm.load %789 : !llvm.ptr -> i32
      %794 = arith.constant 0 : i32
      %795 = arith.cmpi sge, %793, %794 : i32
      %796 = scf.if %795 -> (i1) {
        %797 = llvm.load %789 : !llvm.ptr -> i32
        %798 = arith.constant 32 : i32
        %799 = arith.cmpi sle, %797, %798 : i32
        scf.yield %799 : i1
      } else {
        %800 = arith.constant false
        scf.yield %800 : i1
      }
      cf.cond_br %796, ^bb124, ^bb125
      ^bb124:
        %801 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
        llvm.store %801, %789 : i32, !llvm.ptr
        cf.br ^bb123
      ^bb125:
      %802 = llvm.load %789 : !llvm.ptr -> i32
      %803 = arith.constant 0 : i32
      %804 = arith.cmpi slt, %802, %803 : i32
      cf.cond_br %804, ^bb126, ^bb127
      ^bb126:
        cf.br ^bb122
      ^bb127:
        cf.br ^bb128
      ^bb128:
      %805 = arith.constant 0 : i32
      %806 = llvm.mlir.constant(1 : i64) : i64
      %807 = llvm.alloca %806 x i32 : (i64) -> !llvm.ptr
      llvm.store %805, %807 : i32, !llvm.ptr
      cf.br ^bb129
      ^bb129:
      %808 = llvm.load %789 : !llvm.ptr -> i32
      %809 = arith.constant 48 : i32
      %810 = arith.cmpi sge, %808, %809 : i32
      %811 = scf.if %810 -> (i1) {
        %812 = llvm.load %789 : !llvm.ptr -> i32
        %813 = arith.constant 57 : i32
        %814 = arith.cmpi sle, %812, %813 : i32
        scf.yield %814 : i1
      } else {
        %815 = arith.constant false
        scf.yield %815 : i1
      }
      cf.cond_br %811, ^bb130, ^bb131
      ^bb130:
        %816 = llvm.load %807 : !llvm.ptr -> i32
        %817 = arith.constant 10 : i32
        %818 = arith.muli %816, %817 : i32
        %819 = llvm.load %789 : !llvm.ptr -> i32
        %820 = arith.constant 48 : i32
        %821 = arith.subi %819, %820 : i32
        %822 = arith.addi %818, %821 : i32
        llvm.store %822, %807 : i32, !llvm.ptr
        %823 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
        llvm.store %823, %789 : i32, !llvm.ptr
        cf.br ^bb129
      ^bb131:
      %824 = llvm.load %807 : !llvm.ptr -> i32
      %825 = llvm.mlir.addressof @g_targets : !llvm.ptr
      %826 = llvm.load %825 : !llvm.ptr -> !llvm.ptr
      %827 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
      %828 = llvm.load %827 : !llvm.ptr -> i32
      %829 = arith.extsi %828 : i32 to i64
      %830 = llvm.getelementptr %826[%829] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %824, %830 : i32, !llvm.ptr
      %831 = llvm.load %789 : !llvm.ptr -> i32
      %832 = arith.constant 58 : i32
      %833 = arith.cmpi eq, %831, %832 : i32
      cf.cond_br %833, ^bb132, ^bb133
      ^bb132:
        %834 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
        llvm.store %834, %789 : i32, !llvm.ptr
        cf.br ^bb134
      ^bb133:
        cf.br ^bb134
      ^bb134:
      %835 = arith.constant 0 : i32
      %836 = llvm.mlir.constant(1 : i64) : i64
      %837 = llvm.alloca %836 x i32 : (i64) -> !llvm.ptr
      llvm.store %835, %837 : i32, !llvm.ptr
      cf.br ^bb135
      ^bb135:
      %838 = llvm.load %789 : !llvm.ptr -> i32
      %839 = arith.constant 0 : i32
      %840 = arith.cmpi sge, %838, %839 : i32
      %841 = scf.if %840 -> (i1) {
        %842 = llvm.load %789 : !llvm.ptr -> i32
        %843 = arith.constant 10 : i32
        %844 = arith.cmpi ne, %842, %843 : i32
        scf.yield %844 : i1
      } else {
        %845 = arith.constant false
        scf.yield %845 : i1
      }
      %846 = scf.if %841 -> (i1) {
        %847 = llvm.load %789 : !llvm.ptr -> i32
        %848 = arith.constant 13 : i32
        %849 = arith.cmpi ne, %847, %848 : i32
        scf.yield %849 : i1
      } else {
        %850 = arith.constant false
        scf.yield %850 : i1
      }
      cf.cond_br %846, ^bb136, ^bb137
      ^bb136:
        cf.br ^bb138
        ^bb138:
        %851 = llvm.load %789 : !llvm.ptr -> i32
        %852 = arith.constant 44 : i32
        %853 = arith.cmpi eq, %851, %852 : i32
        cf.cond_br %853, ^bb139, ^bb140
        ^bb139:
          %854 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
          llvm.store %854, %789 : i32, !llvm.ptr
          cf.br ^bb138
        ^bb140:
        %855 = llvm.load %789 : !llvm.ptr -> i32
        %856 = arith.constant 0 : i32
        %857 = arith.cmpi slt, %855, %856 : i32
        %858 = scf.if %857 -> (i1) {
          %859 = arith.constant true
          scf.yield %859 : i1
        } else {
          %860 = llvm.load %789 : !llvm.ptr -> i32
          %861 = arith.constant 10 : i32
          %862 = arith.cmpi eq, %860, %861 : i32
          scf.yield %862 : i1
        }
        %863 = scf.if %858 -> (i1) {
          %864 = arith.constant true
          scf.yield %864 : i1
        } else {
          %865 = llvm.load %789 : !llvm.ptr -> i32
          %866 = arith.constant 13 : i32
          %867 = arith.cmpi eq, %865, %866 : i32
          scf.yield %867 : i1
        }
        cf.cond_br %863, ^bb141, ^bb142
        ^bb141:
          cf.br ^bb137
        ^bb142:
          cf.br ^bb143
        ^bb143:
        %868 = arith.constant 0 : i32
        %869 = llvm.mlir.constant(1 : i64) : i64
        %870 = llvm.alloca %869 x i32 : (i64) -> !llvm.ptr
        llvm.store %868, %870 : i32, !llvm.ptr
        cf.br ^bb144
        ^bb144:
        %871 = llvm.load %789 : !llvm.ptr -> i32
        %872 = arith.constant 48 : i32
        %873 = arith.cmpi sge, %871, %872 : i32
        %874 = scf.if %873 -> (i1) {
          %875 = llvm.load %789 : !llvm.ptr -> i32
          %876 = arith.constant 57 : i32
          %877 = arith.cmpi sle, %875, %876 : i32
          scf.yield %877 : i1
        } else {
          %878 = arith.constant false
          scf.yield %878 : i1
        }
        cf.cond_br %874, ^bb145, ^bb146
        ^bb145:
          %879 = llvm.load %870 : !llvm.ptr -> i32
          %880 = arith.constant 10 : i32
          %881 = arith.muli %879, %880 : i32
          %882 = llvm.load %789 : !llvm.ptr -> i32
          %883 = arith.constant 48 : i32
          %884 = arith.subi %882, %883 : i32
          %885 = arith.addi %881, %884 : i32
          llvm.store %885, %870 : i32, !llvm.ptr
          %886 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
          llvm.store %886, %789 : i32, !llvm.ptr
          cf.br ^bb144
        ^bb146:
        %887 = llvm.load %870 : !llvm.ptr -> i32
        %888 = arith.constant 0 : i32
        %889 = arith.cmpi sgt, %887, %888 : i32
        cf.cond_br %889, ^bb147, ^bb148
        ^bb147:
          %890 = llvm.load %870 : !llvm.ptr -> i32
          %891 = llvm.mlir.addressof @g_nums : !llvm.ptr
          %892 = llvm.load %891 : !llvm.ptr -> !llvm.ptr
          %893 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
          %894 = llvm.load %893 : !llvm.ptr -> i32
          %895 = llvm.mlir.addressof @MAX_NUMS : !llvm.ptr
          %896 = llvm.load %895 : !llvm.ptr -> i32
          %897 = arith.muli %894, %896 : i32
          %898 = llvm.load %837 : !llvm.ptr -> i32
          %899 = arith.addi %897, %898 : i32
          %900 = arith.extsi %899 : i32 to i64
          %901 = llvm.getelementptr %892[%900] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %890, %901 : i32, !llvm.ptr
          %902 = llvm.load %837 : !llvm.ptr -> i32
          %903 = arith.constant 1 : i32
          %904 = arith.addi %902, %903 : i32
          llvm.store %904, %837 : i32, !llvm.ptr
          cf.br ^bb149
        ^bb148:
          cf.br ^bb149
        ^bb149:
        cf.br ^bb135
      ^bb137:
      %905 = llvm.load %837 : !llvm.ptr -> i32
      %906 = llvm.mlir.addressof @g_counts : !llvm.ptr
      %907 = llvm.load %906 : !llvm.ptr -> !llvm.ptr
      %908 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
      %909 = llvm.load %908 : !llvm.ptr -> i32
      %910 = arith.extsi %909 : i32 to i64
      %911 = llvm.getelementptr %907[%910] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %905, %911 : i32, !llvm.ptr
      %912 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
      %913 = llvm.load %912 : !llvm.ptr -> i32
      %914 = arith.constant 1 : i32
      %915 = arith.addi %913, %914 : i32
      %916 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
      llvm.store %915, %916 : i32, !llvm.ptr
      cf.br ^bb150
      ^bb150:
      %917 = llvm.load %789 : !llvm.ptr -> i32
      %918 = arith.constant 0 : i32
      %919 = arith.cmpi sge, %917, %918 : i32
      %920 = scf.if %919 -> (i1) {
        %921 = llvm.load %789 : !llvm.ptr -> i32
        %922 = arith.constant 10 : i32
        %923 = arith.cmpi ne, %921, %922 : i32
        scf.yield %923 : i1
      } else {
        %924 = arith.constant false
        scf.yield %924 : i1
      }
      cf.cond_br %920, ^bb151, ^bb152
      ^bb151:
        %925 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
        llvm.store %925, %789 : i32, !llvm.ptr
        cf.br ^bb150
      ^bb152:
      %926 = llvm.load %789 : !llvm.ptr -> i32
      %927 = arith.constant 10 : i32
      %928 = arith.cmpi eq, %926, %927 : i32
      cf.cond_br %928, ^bb153, ^bb154
      ^bb153:
        %929 = func.call @fgetc(%781) : (!llvm.ptr) -> i32
        llvm.store %929, %789 : i32, !llvm.ptr
        cf.br ^bb155
      ^bb154:
        cf.br ^bb155
      ^bb155:
      cf.br ^bb120
    ^bb122:
    %930 = func.call @fclose(%781) : (!llvm.ptr) -> i32
    func.return
  }
  func.func @main() -> i32 {
    func.call @cache_reset() : () -> ()
    %933 = llvm.mlir.addressof @str_1 : !llvm.ptr
    func.call @read_data(%933) : (!llvm.ptr) -> ()
    %934 = arith.constant 0 : i32
    %935 = arith.extsi %934 : i32 to i64
    %936 = llvm.mlir.constant(1 : i64) : i64
    %937 = llvm.alloca %936 x i64 : (i64) -> !llvm.ptr
    llvm.store %935, %937 : i64, !llvm.ptr
    %938 = arith.constant 3 : i32
    %939 = arith.extsi %938 : i32 to i64
    %940 = llvm.mlir.constant(1 : i64) : i64
    %941 = llvm.alloca %940 x i64 : (i64) -> !llvm.ptr
    llvm.store %939, %941 : i64, !llvm.ptr
    %942 = arith.constant 0 : i32
    %943 = llvm.mlir.constant(1 : i64) : i64
    %944 = llvm.alloca %943 x i32 : (i64) -> !llvm.ptr
    llvm.store %942, %944 : i32, !llvm.ptr
    cf.br ^bb156
    ^bb156:
    %945 = llvm.load %944 : !llvm.ptr -> i32
    %946 = llvm.mlir.addressof @g_num_problems : !llvm.ptr
    %947 = llvm.load %946 : !llvm.ptr -> i32
    %948 = arith.cmpi slt, %945, %947 : i32
    cf.cond_br %948, ^bb157, ^bb158
    ^bb157:
      %950 = llvm.mlir.addressof @g_targets : !llvm.ptr
      %951 = llvm.load %950 : !llvm.ptr -> !llvm.ptr
      %952 = llvm.load %944 : !llvm.ptr -> i32
      %953 = arith.extsi %952 : i32 to i64
      %954 = llvm.getelementptr %951[%953] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %949 = llvm.load %954 : !llvm.ptr -> i32
      %956 = llvm.mlir.addressof @g_counts : !llvm.ptr
      %957 = llvm.load %956 : !llvm.ptr -> !llvm.ptr
      %958 = llvm.load %944 : !llvm.ptr -> i32
      %959 = arith.extsi %958 : i32 to i64
      %960 = llvm.getelementptr %957[%959] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %955 = llvm.load %960 : !llvm.ptr -> i32
      %962 = llvm.mlir.addressof @g_nums : !llvm.ptr
      %963 = llvm.load %962 : !llvm.ptr -> !llvm.ptr
      %964 = llvm.load %944 : !llvm.ptr -> i32
      %965 = llvm.mlir.addressof @MAX_NUMS : !llvm.ptr
      %966 = llvm.load %965 : !llvm.ptr -> i32
      %967 = arith.muli %964, %966 : i32
      %961 = func.call @min_score(%949, %963, %967, %955) : (i32, !llvm.ptr, i32, i32) -> i32
      %968 = llvm.load %937 : !llvm.ptr -> i64
      %969 = llvm.load %941 : !llvm.ptr -> i64
      %970 = arith.extsi %961 : i32 to i64
      %971 = arith.muli %969, %970 : i64
      %972 = arith.addi %968, %971 : i64
      %973 = llvm.mlir.addressof @MOD : !llvm.ptr
      %974 = llvm.load %973 : !llvm.ptr -> i64
      %975 = arith.remsi %972, %974 : i64
      llvm.store %975, %937 : i64, !llvm.ptr
      %976 = llvm.load %941 : !llvm.ptr -> i64
      %977 = arith.constant 3 : i32
      %979 = arith.extsi %977 : i32 to i64
      %978 = arith.muli %976, %979 : i64
      %980 = llvm.mlir.addressof @MOD : !llvm.ptr
      %981 = llvm.load %980 : !llvm.ptr -> i64
      %982 = arith.remsi %978, %981 : i64
      llvm.store %982, %941 : i64, !llvm.ptr
      %983 = llvm.load %944 : !llvm.ptr -> i32
      %984 = arith.constant 1 : i32
      %985 = arith.addi %983, %984 : i32
      llvm.store %985, %944 : i32, !llvm.ptr
      cf.br ^bb156
    ^bb158:
    %987 = llvm.mlir.addressof @g_targets : !llvm.ptr
    %988 = llvm.load %987 : !llvm.ptr -> !llvm.ptr
    func.call @free(%988) : (!llvm.ptr) -> ()
    %990 = llvm.mlir.addressof @g_counts : !llvm.ptr
    %991 = llvm.load %990 : !llvm.ptr -> !llvm.ptr
    func.call @free(%991) : (!llvm.ptr) -> ()
    %993 = llvm.mlir.addressof @g_nums : !llvm.ptr
    %994 = llvm.load %993 : !llvm.ptr -> !llvm.ptr
    func.call @free(%994) : (!llvm.ptr) -> ()
    %996 = llvm.mlir.addressof @g_cache : !llvm.ptr
    %997 = llvm.load %996 : !llvm.ptr -> !llvm.ptr
    func.call @free(%997) : (!llvm.ptr) -> ()
    %998 = llvm.mlir.addressof @str_2 : !llvm.ptr
    %999 = llvm.load %937 : !llvm.ptr -> i64
    %1000 = llvm.call @printf(%998, %999) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %1001 = arith.constant 0 : i32
    func.return %1001 : i32
  }
}