Problem 369

Badugi: count n-card hands (4≤n≤13) containing a 4-suit matching.

Answer862400558448
Output862400558448
StatusPASS
Native helperno
Runtime0 ms
Peak memory1376 KB
Time complexityO(n^3) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)O(n)
Space complexityO(n^2)O(1)
ApproachFlow solutionDirect hand evaluation or enumeration
VerdictSuboptimal

Flow source

# Project Euler 369
# Badugi: count n-card hands (4≤n≤13) containing a 4-suit matching.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
}

function popcount4(x: i32) -> i32 {
    return (x & 1) + ((x >> 1) & 1) + ((x >> 2) & 1) + ((x >> 3) & 1)
}

function update_reachable(reach: i32, suits_present: i32) -> i32 {
    let mut new_reach: i32 = reach
    let mut m: i32 = 0
    while m < 16 {
        if ((reach >> m) & 1) == 1 {
            let mut b: i32 = suits_present & (0xF ^ m)
            while b != 0 {
                let lsb: i32 = b & (0 - b)
                new_reach = new_reach | (1 << (m | lsb))
                b = b - lsb
            }
        }
        m = m + 1
    }
    return new_reach & 65535
}

function main() -> i32 {
    let max_n: i32 = 13
    # BFS reachable reach-bitsets
    let states: ptr<i32> = calloc(128, 4)
    let index_of: ptr<i32> = calloc(65536, 4)
    if states == null || index_of == null { return 1 }
    let mut i: i32 = 0
    while i < 65536 {
        index_of[i] = -1
        i = i + 1
    }
    let start: i32 = 1
    states[0] = start
    index_of[start] = 0
    let mut nstates: i32 = 1
    let mut qi: i32 = 0
    while qi < nstates {
        let reach: i32 = states[qi]
        let mut suits: i32 = 0
        while suits < 16 {
            let nxt: i32 = update_reachable(reach, suits)
            if index_of[nxt] < 0 {
                index_of[nxt] = nstates
                states[nstates] = nxt
                nstates = nstates + 1
            }
            suits = suits + 1
        }
        qi = qi + 1
    }

    let trans: ptr<i32> = calloc((nstates * 16) as i64, 4)
    if trans == null { return 1 }
    i = 0
    while i < nstates {
        let mut suits2: i32 = 0
        while suits2 < 16 {
            trans[i * 16 + suits2] = index_of[update_reachable(states[i], suits2)]
            suits2 = suits2 + 1
        }
        i = i + 1
    }

    let dp: ptr<i64> = calloc((nstates * (max_n + 1)) as i64, 8)
    let ndp: ptr<i64> = calloc((nstates * (max_n + 1)) as i64, 8)
    if dp == null || ndp == null { return 1 }
    dp[0 * (max_n + 1) + 0] = 1  # start_idx is 0

    let mut rank: i32 = 0
    while rank < 13 {
        let mut z: i64 = 0
        while z < (nstates * (max_n + 1)) as i64 {
            ndp[z] = 0
            z = z + 1
        }
        i = 0
        while i < nstates {
            let mut k: i32 = 0
            let base: i32 = i * (max_n + 1)
            let mut any: i32 = 0
            while k <= max_n {
                if dp[base + k] != 0 { any = 1; break }
                k = k + 1
            }
            if any == 1 {
                let mut suits3: i32 = 0
                while suits3 < 16 {
                    let j: i32 = trans[i * 16 + suits3]
                    let add: i32 = popcount4(suits3)
                    k = 0
                    while k <= max_n {
                        let v: i64 = dp[base + k]
                        let nk: i32 = k + add
                        if v != 0 && nk <= max_n {
                            ndp[j * (max_n + 1) + nk] = ndp[j * (max_n + 1) + nk] + v
                        }
                        k = k + 1
                    }
                    suits3 = suits3 + 1
                }
            }
            i = i + 1
        }
        z = 0
        while z < (nstates * (max_n + 1)) as i64 {
            dp[z] = ndp[z]
            z = z + 1
        }
        rank = rank + 1
    }

    let full_bit: i32 = 1 << 15
    let mut ans: i64 = 0
    i = 0
    while i < nstates {
        if (states[i] & full_bit) != 0 {
            let mut n: i32 = 4
            while n <= max_n {
                ans = ans + dp[i * (max_n + 1) + n]
                n = n + 1
            }
        }
        i = i + 1
    }
    printf("%lld\n", ans)
    free(ndp)
    free(dp)
    free(trans)
    free(index_of)
    free(states)
    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; }

int32_t popcount4_i32(int32_t x);
int32_t update_reachable_i32_i32(int32_t reach, int32_t suits_present);
int32_t main(void);



int32_t popcount4_i32(int32_t x) {
    return ((((x & 1) + (FLOW_CHECKED_SHR((x), (1)) & 1)) + (FLOW_CHECKED_SHR((x), (2)) & 1)) + (FLOW_CHECKED_SHR((x), (3)) & 1));
}

int32_t update_reachable_i32_i32(int32_t reach, int32_t suits_present) {
    int32_t new_reach = reach;
    int32_t m = 0;
    while (m < 16) {
        if ((FLOW_CHECKED_SHR((reach), (m)) & 1) == 1) {
            int32_t b = (suits_present & (15 ^ m));
            while (b != 0) {
                int32_t lsb = (b & (0 - b));
                new_reach = (new_reach | FLOW_CHECKED_SHL((1), ((m | lsb))));
                b = (b - lsb);
            }
        }
        m = (m + 1);
    }
    return (new_reach & 65535);
}

int32_t main(void) {
    int32_t max_n = 13;
    int32_t* states = (int32_t*)(calloc(128, 4));
    int32_t* index_of = (int32_t*)(calloc(65536, 4));
    if ((states == NULL || index_of == NULL)) {
        return 1;
    }
    int32_t i = 0;
    while (i < 65536) {
        index_of[i] = (-1);
        i = (i + 1);
    }
    int32_t start = 1;
    states[0] = start;
    index_of[start] = 0;
    int32_t nstates = 1;
    int32_t qi = 0;
    while (qi < nstates) {
        int32_t reach = states[qi];
        int32_t suits = 0;
        while (suits < 16) {
            int32_t nxt = update_reachable_i32_i32(reach, suits);
            if (index_of[nxt] < 0) {
                index_of[nxt] = nstates;
                states[nstates] = nxt;
                nstates = (nstates + 1);
            }
            suits = (suits + 1);
        }
        qi = (qi + 1);
    }
    int32_t* trans = (int32_t*)(calloc(((int64_t)((nstates * 16))), 4));
    if (trans == NULL) {
        return 1;
    }
    i = 0;
    while (i < nstates) {
        int32_t suits2 = 0;
        while (suits2 < 16) {
            trans[((i * 16) + suits2)] = index_of[update_reachable_i32_i32(states[i], suits2)];
            suits2 = (suits2 + 1);
        }
        i = (i + 1);
    }
    int64_t* dp = (int64_t*)(calloc(((int64_t)((nstates * (max_n + 1)))), 8));
    int64_t* ndp = (int64_t*)(calloc(((int64_t)((nstates * (max_n + 1)))), 8));
    if ((dp == NULL || ndp == NULL)) {
        return 1;
    }
    dp[((0 * (max_n + 1)) + 0)] = 1;
    int32_t rank = 0;
    while (rank < 13) {
        int64_t z = 0;
        while (z < ((int64_t)((nstates * (max_n + 1))))) {
            ndp[z] = 0;
            z = (z + 1);
        }
        i = 0;
        while (i < nstates) {
            int32_t k = 0;
            int32_t base = (i * (max_n + 1));
            int32_t any = 0;
            while (k <= max_n) {
                if (dp[(base + k)] != 0) {
                    any = 1;
                    break;
                }
                k = (k + 1);
            }
            if (any == 1) {
                int32_t suits3 = 0;
                while (suits3 < 16) {
                    int32_t j = trans[((i * 16) + suits3)];
                    int32_t add = popcount4_i32(suits3);
                    k = 0;
                    while (k <= max_n) {
                        int64_t v = dp[(base + k)];
                        int32_t nk = (k + add);
                        if ((v != 0 && nk <= max_n)) {
                            ndp[((j * (max_n + 1)) + nk)] = (ndp[((j * (max_n + 1)) + nk)] + v);
                        }
                        k = (k + 1);
                    }
                    suits3 = (suits3 + 1);
                }
            }
            i = (i + 1);
        }
        z = 0;
        while (z < ((int64_t)((nstates * (max_n + 1))))) {
            dp[z] = ndp[z];
            z = (z + 1);
        }
        rank = (rank + 1);
    }
    int32_t full_bit = FLOW_CHECKED_SHL((1), (15));
    int64_t ans = 0;
    i = 0;
    while (i < nstates) {
        if ((states[i] & full_bit) != 0) {
            int32_t n = 4;
            while (n <= max_n) {
                ans = (ans + dp[((i * (max_n + 1)) + n)]);
                n = (n + 1);
            }
        }
        i = (i + 1);
    }
    printf("%lld\n", ans);
    free(ndp);
    free(dp);
    free(trans);
    free(index_of);
    free(states);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  func.func @popcount4(%arg0: i32) -> i32 {
    %0 = arith.constant 1 : i32
    %1 = arith.andi %arg0, %0 : i32
    %2 = arith.constant 1 : i32
    %3 = arith.shrsi %arg0, %2 : i32
    %4 = arith.constant 1 : i32
    %5 = arith.andi %3, %4 : i32
    %6 = arith.addi %1, %5 : i32
    %7 = arith.constant 2 : i32
    %8 = arith.shrsi %arg0, %7 : i32
    %9 = arith.constant 1 : i32
    %10 = arith.andi %8, %9 : i32
    %11 = arith.addi %6, %10 : i32
    %12 = arith.constant 3 : i32
    %13 = arith.shrsi %arg0, %12 : i32
    %14 = arith.constant 1 : i32
    %15 = arith.andi %13, %14 : i32
    %16 = arith.addi %11, %15 : i32
    func.return %16 : i32
  }
  func.func @update_reachable(%arg0: i32, %arg1: i32) -> i32 {
    %17 = llvm.mlir.constant(1 : i64) : i64
    %18 = llvm.alloca %17 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg0, %18 : i32, !llvm.ptr
    %19 = arith.constant 0 : i32
    %20 = llvm.mlir.constant(1 : i64) : i64
    %21 = llvm.alloca %20 x i32 : (i64) -> !llvm.ptr
    llvm.store %19, %21 : i32, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %22 = llvm.load %21 : !llvm.ptr -> i32
    %23 = arith.constant 16 : i32
    %24 = arith.cmpi slt, %22, %23 : i32
    cf.cond_br %24, ^bb1, ^bb2
    ^bb1:
      %25 = llvm.load %21 : !llvm.ptr -> i32
      %26 = arith.shrsi %arg0, %25 : i32
      %27 = arith.constant 1 : i32
      %28 = arith.andi %26, %27 : i32
      %29 = arith.constant 1 : i32
      %30 = arith.cmpi eq, %28, %29 : i32
      cf.cond_br %30, ^bb3, ^bb4
      ^bb3:
        %31 = arith.constant 15 : i32
        %32 = llvm.load %21 : !llvm.ptr -> i32
        %33 = arith.xori %31, %32 : i32
        %34 = arith.andi %arg1, %33 : i32
        %35 = llvm.mlir.constant(1 : i64) : i64
        %36 = llvm.alloca %35 x i32 : (i64) -> !llvm.ptr
        llvm.store %34, %36 : i32, !llvm.ptr
        cf.br ^bb6
        ^bb6:
        %37 = llvm.load %36 : !llvm.ptr -> i32
        %38 = arith.constant 0 : i32
        %39 = arith.cmpi ne, %37, %38 : i32
        cf.cond_br %39, ^bb7, ^bb8
        ^bb7:
          %40 = llvm.load %36 : !llvm.ptr -> i32
          %41 = arith.constant 0 : i32
          %42 = llvm.load %36 : !llvm.ptr -> i32
          %43 = arith.subi %41, %42 : i32
          %44 = arith.andi %40, %43 : i32
          %45 = llvm.load %18 : !llvm.ptr -> i32
          %46 = arith.constant 1 : i32
          %47 = llvm.load %21 : !llvm.ptr -> i32
          %48 = arith.ori %47, %44 : i32
          %49 = arith.shli %46, %48 : i32
          %50 = arith.ori %45, %49 : i32
          llvm.store %50, %18 : i32, !llvm.ptr
          %51 = llvm.load %36 : !llvm.ptr -> i32
          %52 = arith.subi %51, %44 : i32
          llvm.store %52, %36 : i32, !llvm.ptr
          cf.br ^bb6
        ^bb8:
        cf.br ^bb5
      ^bb4:
        cf.br ^bb5
      ^bb5:
      %53 = llvm.load %21 : !llvm.ptr -> i32
      %54 = arith.constant 1 : i32
      %55 = arith.addi %53, %54 : i32
      llvm.store %55, %21 : i32, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %56 = llvm.load %18 : !llvm.ptr -> i32
    %57 = arith.constant 65535 : i32
    %58 = arith.andi %56, %57 : i32
    func.return %58 : i32
  }
  func.func @main() -> i32 {
    %59 = arith.constant 13 : i32
    %61 = arith.constant 128 : i32
    %62 = arith.constant 4 : i32
    %63 = arith.extsi %61 : i32 to i64
    %64 = arith.extsi %62 : i32 to i64
    %60 = func.call @calloc(%63, %64) : (i64, i64) -> !llvm.ptr
    %66 = arith.constant 65536 : i32
    %67 = arith.constant 4 : i32
    %68 = arith.extsi %66 : i32 to i64
    %69 = arith.extsi %67 : i32 to i64
    %65 = func.call @calloc(%68, %69) : (i64, i64) -> !llvm.ptr
    %70 = llvm.mlir.zero : !llvm.ptr
    %71 = llvm.icmp "eq" %60, %70 : !llvm.ptr
    %72 = scf.if %71 -> (i1) {
      %73 = arith.constant true
      scf.yield %73 : i1
    } else {
      %74 = llvm.mlir.zero : !llvm.ptr
      %75 = llvm.icmp "eq" %65, %74 : !llvm.ptr
      scf.yield %75 : i1
    }
    cf.cond_br %72, ^bb9, ^bb10
    ^bb9:
      %76 = arith.constant 1 : i32
      func.return %76 : i32
    ^bb10:
      cf.br ^bb11
    ^bb11:
    %77 = arith.constant 0 : i32
    %78 = llvm.mlir.constant(1 : i64) : i64
    %79 = llvm.alloca %78 x i32 : (i64) -> !llvm.ptr
    llvm.store %77, %79 : i32, !llvm.ptr
    cf.br ^bb12
    ^bb12:
    %80 = llvm.load %79 : !llvm.ptr -> i32
    %81 = arith.constant 65536 : i32
    %82 = arith.cmpi slt, %80, %81 : i32
    cf.cond_br %82, ^bb13, ^bb14
    ^bb13:
      %83 = arith.constant 1 : i32
      %85 = arith.constant 0 : i32
      %84 = arith.subi %85, %83 : i32
      %86 = llvm.load %79 : !llvm.ptr -> i32
      %87 = arith.extsi %86 : i32 to i64
      %88 = llvm.getelementptr %65[%87] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %84, %88 : i32, !llvm.ptr
      %89 = llvm.load %79 : !llvm.ptr -> i32
      %90 = arith.constant 1 : i32
      %91 = arith.addi %89, %90 : i32
      llvm.store %91, %79 : i32, !llvm.ptr
      cf.br ^bb12
    ^bb14:
    %92 = arith.constant 1 : i32
    %93 = arith.constant 0 : i32
    %94 = arith.extsi %93 : i32 to i64
    %95 = llvm.getelementptr %60[%94] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %92, %95 : i32, !llvm.ptr
    %96 = arith.constant 0 : i32
    %97 = arith.extsi %92 : i32 to i64
    %98 = llvm.getelementptr %65[%97] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %96, %98 : i32, !llvm.ptr
    %99 = arith.constant 1 : i32
    %100 = llvm.mlir.constant(1 : i64) : i64
    %101 = llvm.alloca %100 x i32 : (i64) -> !llvm.ptr
    llvm.store %99, %101 : i32, !llvm.ptr
    %102 = arith.constant 0 : i32
    %103 = llvm.mlir.constant(1 : i64) : i64
    %104 = llvm.alloca %103 x i32 : (i64) -> !llvm.ptr
    llvm.store %102, %104 : i32, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %105 = llvm.load %104 : !llvm.ptr -> i32
    %106 = llvm.load %101 : !llvm.ptr -> i32
    %107 = arith.cmpi slt, %105, %106 : i32
    cf.cond_br %107, ^bb16, ^bb17
    ^bb16:
      %109 = llvm.load %104 : !llvm.ptr -> i32
      %110 = arith.extsi %109 : i32 to i64
      %111 = llvm.getelementptr %60[%110] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %108 = llvm.load %111 : !llvm.ptr -> i32
      %112 = arith.constant 0 : i32
      %113 = llvm.mlir.constant(1 : i64) : i64
      %114 = llvm.alloca %113 x i32 : (i64) -> !llvm.ptr
      llvm.store %112, %114 : i32, !llvm.ptr
      cf.br ^bb18
      ^bb18:
      %115 = llvm.load %114 : !llvm.ptr -> i32
      %116 = arith.constant 16 : i32
      %117 = arith.cmpi slt, %115, %116 : i32
      cf.cond_br %117, ^bb19, ^bb20
      ^bb19:
        %119 = llvm.load %114 : !llvm.ptr -> i32
        %118 = func.call @update_reachable(%108, %119) : (i32, i32) -> i32
        %121 = arith.extsi %118 : i32 to i64
        %122 = llvm.getelementptr %65[%121] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %120 = llvm.load %122 : !llvm.ptr -> i32
        %123 = arith.constant 0 : i32
        %124 = arith.cmpi slt, %120, %123 : i32
        cf.cond_br %124, ^bb21, ^bb22
        ^bb21:
          %125 = llvm.load %101 : !llvm.ptr -> i32
          %126 = arith.extsi %118 : i32 to i64
          %127 = llvm.getelementptr %65[%126] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %125, %127 : i32, !llvm.ptr
          %128 = llvm.load %101 : !llvm.ptr -> i32
          %129 = arith.extsi %128 : i32 to i64
          %130 = llvm.getelementptr %60[%129] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %118, %130 : i32, !llvm.ptr
          %131 = llvm.load %101 : !llvm.ptr -> i32
          %132 = arith.constant 1 : i32
          %133 = arith.addi %131, %132 : i32
          llvm.store %133, %101 : i32, !llvm.ptr
          cf.br ^bb23
        ^bb22:
          cf.br ^bb23
        ^bb23:
        %134 = llvm.load %114 : !llvm.ptr -> i32
        %135 = arith.constant 1 : i32
        %136 = arith.addi %134, %135 : i32
        llvm.store %136, %114 : i32, !llvm.ptr
        cf.br ^bb18
      ^bb20:
      %137 = llvm.load %104 : !llvm.ptr -> i32
      %138 = arith.constant 1 : i32
      %139 = arith.addi %137, %138 : i32
      llvm.store %139, %104 : i32, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    %141 = llvm.load %101 : !llvm.ptr -> i32
    %142 = arith.constant 16 : i32
    %143 = arith.muli %141, %142 : i32
    %144 = arith.extsi %143 : i32 to i64
    %145 = arith.constant 4 : i32
    %146 = arith.extsi %145 : i32 to i64
    %140 = func.call @calloc(%144, %146) : (i64, i64) -> !llvm.ptr
    %147 = llvm.mlir.zero : !llvm.ptr
    %148 = llvm.icmp "eq" %140, %147 : !llvm.ptr
    cf.cond_br %148, ^bb24, ^bb25
    ^bb24:
      %149 = arith.constant 1 : i32
      func.return %149 : i32
    ^bb25:
      cf.br ^bb26
    ^bb26:
    %150 = arith.constant 0 : i32
    llvm.store %150, %79 : i32, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %151 = llvm.load %79 : !llvm.ptr -> i32
    %152 = llvm.load %101 : !llvm.ptr -> i32
    %153 = arith.cmpi slt, %151, %152 : i32
    cf.cond_br %153, ^bb28, ^bb29
    ^bb28:
      %154 = arith.constant 0 : i32
      %155 = llvm.mlir.constant(1 : i64) : i64
      %156 = llvm.alloca %155 x i32 : (i64) -> !llvm.ptr
      llvm.store %154, %156 : i32, !llvm.ptr
      cf.br ^bb30
      ^bb30:
      %157 = llvm.load %156 : !llvm.ptr -> i32
      %158 = arith.constant 16 : i32
      %159 = arith.cmpi slt, %157, %158 : i32
      cf.cond_br %159, ^bb31, ^bb32
      ^bb31:
        %163 = llvm.load %79 : !llvm.ptr -> i32
        %164 = arith.extsi %163 : i32 to i64
        %165 = llvm.getelementptr %60[%164] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %162 = llvm.load %165 : !llvm.ptr -> i32
        %166 = llvm.load %156 : !llvm.ptr -> i32
        %161 = func.call @update_reachable(%162, %166) : (i32, i32) -> i32
        %167 = arith.extsi %161 : i32 to i64
        %168 = llvm.getelementptr %65[%167] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %160 = llvm.load %168 : !llvm.ptr -> i32
        %169 = llvm.load %79 : !llvm.ptr -> i32
        %170 = arith.constant 16 : i32
        %171 = arith.muli %169, %170 : i32
        %172 = llvm.load %156 : !llvm.ptr -> i32
        %173 = arith.addi %171, %172 : i32
        %174 = arith.extsi %173 : i32 to i64
        %175 = llvm.getelementptr %140[%174] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %160, %175 : i32, !llvm.ptr
        %176 = llvm.load %156 : !llvm.ptr -> i32
        %177 = arith.constant 1 : i32
        %178 = arith.addi %176, %177 : i32
        llvm.store %178, %156 : i32, !llvm.ptr
        cf.br ^bb30
      ^bb32:
      %179 = llvm.load %79 : !llvm.ptr -> i32
      %180 = arith.constant 1 : i32
      %181 = arith.addi %179, %180 : i32
      llvm.store %181, %79 : i32, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    %183 = llvm.load %101 : !llvm.ptr -> i32
    %184 = arith.constant 1 : i32
    %185 = arith.addi %59, %184 : i32
    %186 = arith.muli %183, %185 : i32
    %187 = arith.extsi %186 : i32 to i64
    %188 = arith.constant 8 : i32
    %189 = arith.extsi %188 : i32 to i64
    %182 = func.call @calloc(%187, %189) : (i64, i64) -> !llvm.ptr
    %191 = llvm.load %101 : !llvm.ptr -> i32
    %192 = arith.constant 1 : i32
    %193 = arith.addi %59, %192 : i32
    %194 = arith.muli %191, %193 : i32
    %195 = arith.extsi %194 : i32 to i64
    %196 = arith.constant 8 : i32
    %197 = arith.extsi %196 : i32 to i64
    %190 = func.call @calloc(%195, %197) : (i64, i64) -> !llvm.ptr
    %198 = llvm.mlir.zero : !llvm.ptr
    %199 = llvm.icmp "eq" %182, %198 : !llvm.ptr
    %200 = scf.if %199 -> (i1) {
      %201 = arith.constant true
      scf.yield %201 : i1
    } else {
      %202 = llvm.mlir.zero : !llvm.ptr
      %203 = llvm.icmp "eq" %190, %202 : !llvm.ptr
      scf.yield %203 : i1
    }
    cf.cond_br %200, ^bb33, ^bb34
    ^bb33:
      %204 = arith.constant 1 : i32
      func.return %204 : i32
    ^bb34:
      cf.br ^bb35
    ^bb35:
    %205 = arith.constant 1 : i32
    %206 = arith.constant 0 : i32
    %207 = arith.constant 1 : i32
    %208 = arith.addi %59, %207 : i32
    %209 = arith.muli %206, %208 : i32
    %210 = arith.constant 0 : i32
    %211 = arith.addi %209, %210 : i32
    %212 = arith.extsi %205 : i32 to i64
    %213 = arith.extsi %211 : i32 to i64
    %214 = llvm.getelementptr %182[%213] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %212, %214 : i64, !llvm.ptr
    %215 = arith.constant 0 : i32
    %216 = llvm.mlir.constant(1 : i64) : i64
    %217 = llvm.alloca %216 x i32 : (i64) -> !llvm.ptr
    llvm.store %215, %217 : i32, !llvm.ptr
    cf.br ^bb36
    ^bb36:
    %218 = llvm.load %217 : !llvm.ptr -> i32
    %219 = arith.constant 13 : i32
    %220 = arith.cmpi slt, %218, %219 : i32
    cf.cond_br %220, ^bb37, ^bb38
    ^bb37:
      %221 = arith.constant 0 : i32
      %222 = arith.extsi %221 : i32 to i64
      %223 = llvm.mlir.constant(1 : i64) : i64
      %224 = llvm.alloca %223 x i64 : (i64) -> !llvm.ptr
      llvm.store %222, %224 : i64, !llvm.ptr
      cf.br ^bb39
      ^bb39:
      %225 = llvm.load %224 : !llvm.ptr -> i64
      %226 = llvm.load %101 : !llvm.ptr -> i32
      %227 = arith.constant 1 : i32
      %228 = arith.addi %59, %227 : i32
      %229 = arith.muli %226, %228 : i32
      %230 = arith.extsi %229 : i32 to i64
      %231 = arith.cmpi slt, %225, %230 : i64
      cf.cond_br %231, ^bb40, ^bb41
      ^bb40:
        %232 = arith.constant 0 : i32
        %233 = llvm.load %224 : !llvm.ptr -> i64
        %234 = arith.extsi %232 : i32 to i64
        %235 = llvm.getelementptr %190[%233] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %234, %235 : i64, !llvm.ptr
        %236 = llvm.load %224 : !llvm.ptr -> i64
        %237 = arith.constant 1 : i32
        %239 = arith.extsi %237 : i32 to i64
        %238 = arith.addi %236, %239 : i64
        llvm.store %238, %224 : i64, !llvm.ptr
        cf.br ^bb39
      ^bb41:
      %240 = arith.constant 0 : i32
      llvm.store %240, %79 : i32, !llvm.ptr
      cf.br ^bb42
      ^bb42:
      %241 = llvm.load %79 : !llvm.ptr -> i32
      %242 = llvm.load %101 : !llvm.ptr -> i32
      %243 = arith.cmpi slt, %241, %242 : i32
      cf.cond_br %243, ^bb43, ^bb44
      ^bb43:
        %244 = arith.constant 0 : i32
        %245 = llvm.mlir.constant(1 : i64) : i64
        %246 = llvm.alloca %245 x i32 : (i64) -> !llvm.ptr
        llvm.store %244, %246 : i32, !llvm.ptr
        %247 = llvm.load %79 : !llvm.ptr -> i32
        %248 = arith.constant 1 : i32
        %249 = arith.addi %59, %248 : i32
        %250 = arith.muli %247, %249 : i32
        %251 = arith.constant 0 : i32
        %252 = llvm.mlir.constant(1 : i64) : i64
        %253 = llvm.alloca %252 x i32 : (i64) -> !llvm.ptr
        llvm.store %251, %253 : i32, !llvm.ptr
        cf.br ^bb45
        ^bb45:
        %254 = llvm.load %246 : !llvm.ptr -> i32
        %255 = arith.cmpi sle, %254, %59 : i32
        cf.cond_br %255, ^bb46, ^bb47
        ^bb46:
          %257 = llvm.load %246 : !llvm.ptr -> i32
          %258 = arith.addi %250, %257 : i32
          %259 = arith.extsi %258 : i32 to i64
          %260 = llvm.getelementptr %182[%259] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %256 = llvm.load %260 : !llvm.ptr -> i64
          %261 = arith.constant 0 : i32
          %263 = arith.extsi %261 : i32 to i64
          %262 = arith.cmpi ne, %256, %263 : i64
          cf.cond_br %262, ^bb48, ^bb49
          ^bb48:
            %264 = arith.constant 1 : i32
            llvm.store %264, %253 : i32, !llvm.ptr
            cf.br ^bb47
          ^bb49:
            cf.br ^bb50
          ^bb50:
          %265 = llvm.load %246 : !llvm.ptr -> i32
          %266 = arith.constant 1 : i32
          %267 = arith.addi %265, %266 : i32
          llvm.store %267, %246 : i32, !llvm.ptr
          cf.br ^bb45
        ^bb47:
        %268 = llvm.load %253 : !llvm.ptr -> i32
        %269 = arith.constant 1 : i32
        %270 = arith.cmpi eq, %268, %269 : i32
        cf.cond_br %270, ^bb51, ^bb52
        ^bb51:
          %271 = arith.constant 0 : i32
          %272 = llvm.mlir.constant(1 : i64) : i64
          %273 = llvm.alloca %272 x i32 : (i64) -> !llvm.ptr
          llvm.store %271, %273 : i32, !llvm.ptr
          cf.br ^bb54
          ^bb54:
          %274 = llvm.load %273 : !llvm.ptr -> i32
          %275 = arith.constant 16 : i32
          %276 = arith.cmpi slt, %274, %275 : i32
          cf.cond_br %276, ^bb55, ^bb56
          ^bb55:
            %278 = llvm.load %79 : !llvm.ptr -> i32
            %279 = arith.constant 16 : i32
            %280 = arith.muli %278, %279 : i32
            %281 = llvm.load %273 : !llvm.ptr -> i32
            %282 = arith.addi %280, %281 : i32
            %283 = arith.extsi %282 : i32 to i64
            %284 = llvm.getelementptr %140[%283] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %277 = llvm.load %284 : !llvm.ptr -> i32
            %286 = llvm.load %273 : !llvm.ptr -> i32
            %285 = func.call @popcount4(%286) : (i32) -> i32
            %287 = arith.constant 0 : i32
            llvm.store %287, %246 : i32, !llvm.ptr
            cf.br ^bb57
            ^bb57:
            %288 = llvm.load %246 : !llvm.ptr -> i32
            %289 = arith.cmpi sle, %288, %59 : i32
            cf.cond_br %289, ^bb58, ^bb59
            ^bb58:
              %291 = llvm.load %246 : !llvm.ptr -> i32
              %292 = arith.addi %250, %291 : i32
              %293 = arith.extsi %292 : i32 to i64
              %294 = llvm.getelementptr %182[%293] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %290 = llvm.load %294 : !llvm.ptr -> i64
              %295 = llvm.load %246 : !llvm.ptr -> i32
              %296 = arith.addi %295, %285 : i32
              %297 = arith.constant 0 : i32
              %299 = arith.extsi %297 : i32 to i64
              %298 = arith.cmpi ne, %290, %299 : i64
              %300 = scf.if %298 -> (i1) {
                %301 = arith.cmpi sle, %296, %59 : i32
                scf.yield %301 : i1
              } else {
                %302 = arith.constant false
                scf.yield %302 : i1
              }
              cf.cond_br %300, ^bb60, ^bb61
              ^bb60:
                %304 = arith.constant 1 : i32
                %305 = arith.addi %59, %304 : i32
                %306 = arith.muli %277, %305 : i32
                %307 = arith.addi %306, %296 : i32
                %308 = arith.extsi %307 : i32 to i64
                %309 = llvm.getelementptr %190[%308] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                %303 = llvm.load %309 : !llvm.ptr -> i64
                %310 = arith.addi %303, %290 : i64
                %311 = arith.constant 1 : i32
                %312 = arith.addi %59, %311 : i32
                %313 = arith.muli %277, %312 : i32
                %314 = arith.addi %313, %296 : i32
                %315 = arith.extsi %314 : i32 to i64
                %316 = llvm.getelementptr %190[%315] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                llvm.store %310, %316 : i64, !llvm.ptr
                cf.br ^bb62
              ^bb61:
                cf.br ^bb62
              ^bb62:
              %317 = llvm.load %246 : !llvm.ptr -> i32
              %318 = arith.constant 1 : i32
              %319 = arith.addi %317, %318 : i32
              llvm.store %319, %246 : i32, !llvm.ptr
              cf.br ^bb57
            ^bb59:
            %320 = llvm.load %273 : !llvm.ptr -> i32
            %321 = arith.constant 1 : i32
            %322 = arith.addi %320, %321 : i32
            llvm.store %322, %273 : i32, !llvm.ptr
            cf.br ^bb54
          ^bb56:
          cf.br ^bb53
        ^bb52:
          cf.br ^bb53
        ^bb53:
        %323 = llvm.load %79 : !llvm.ptr -> i32
        %324 = arith.constant 1 : i32
        %325 = arith.addi %323, %324 : i32
        llvm.store %325, %79 : i32, !llvm.ptr
        cf.br ^bb42
      ^bb44:
      %326 = arith.constant 0 : i32
      %327 = arith.extsi %326 : i32 to i64
      llvm.store %327, %224 : i64, !llvm.ptr
      cf.br ^bb63
      ^bb63:
      %328 = llvm.load %224 : !llvm.ptr -> i64
      %329 = llvm.load %101 : !llvm.ptr -> i32
      %330 = arith.constant 1 : i32
      %331 = arith.addi %59, %330 : i32
      %332 = arith.muli %329, %331 : i32
      %333 = arith.extsi %332 : i32 to i64
      %334 = arith.cmpi slt, %328, %333 : i64
      cf.cond_br %334, ^bb64, ^bb65
      ^bb64:
        %336 = llvm.load %224 : !llvm.ptr -> i64
        %337 = llvm.getelementptr %190[%336] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %335 = llvm.load %337 : !llvm.ptr -> i64
        %338 = llvm.load %224 : !llvm.ptr -> i64
        %339 = llvm.getelementptr %182[%338] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %335, %339 : i64, !llvm.ptr
        %340 = llvm.load %224 : !llvm.ptr -> i64
        %341 = arith.constant 1 : i32
        %343 = arith.extsi %341 : i32 to i64
        %342 = arith.addi %340, %343 : i64
        llvm.store %342, %224 : i64, !llvm.ptr
        cf.br ^bb63
      ^bb65:
      %344 = llvm.load %217 : !llvm.ptr -> i32
      %345 = arith.constant 1 : i32
      %346 = arith.addi %344, %345 : i32
      llvm.store %346, %217 : i32, !llvm.ptr
      cf.br ^bb36
    ^bb38:
    %347 = arith.constant 1 : i32
    %348 = arith.constant 15 : i32
    %349 = arith.shli %347, %348 : i32
    %350 = arith.constant 0 : i32
    %351 = arith.extsi %350 : i32 to i64
    %352 = llvm.mlir.constant(1 : i64) : i64
    %353 = llvm.alloca %352 x i64 : (i64) -> !llvm.ptr
    llvm.store %351, %353 : i64, !llvm.ptr
    %354 = arith.constant 0 : i32
    llvm.store %354, %79 : i32, !llvm.ptr
    cf.br ^bb66
    ^bb66:
    %355 = llvm.load %79 : !llvm.ptr -> i32
    %356 = llvm.load %101 : !llvm.ptr -> i32
    %357 = arith.cmpi slt, %355, %356 : i32
    cf.cond_br %357, ^bb67, ^bb68
    ^bb67:
      %359 = llvm.load %79 : !llvm.ptr -> i32
      %360 = arith.extsi %359 : i32 to i64
      %361 = llvm.getelementptr %60[%360] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %358 = llvm.load %361 : !llvm.ptr -> i32
      %362 = arith.andi %358, %349 : i32
      %363 = arith.constant 0 : i32
      %364 = arith.cmpi ne, %362, %363 : i32
      cf.cond_br %364, ^bb69, ^bb70
      ^bb69:
        %365 = arith.constant 4 : i32
        %366 = llvm.mlir.constant(1 : i64) : i64
        %367 = llvm.alloca %366 x i32 : (i64) -> !llvm.ptr
        llvm.store %365, %367 : i32, !llvm.ptr
        cf.br ^bb72
        ^bb72:
        %368 = llvm.load %367 : !llvm.ptr -> i32
        %369 = arith.cmpi sle, %368, %59 : i32
        cf.cond_br %369, ^bb73, ^bb74
        ^bb73:
          %370 = llvm.load %353 : !llvm.ptr -> i64
          %372 = llvm.load %79 : !llvm.ptr -> i32
          %373 = arith.constant 1 : i32
          %374 = arith.addi %59, %373 : i32
          %375 = arith.muli %372, %374 : i32
          %376 = llvm.load %367 : !llvm.ptr -> i32
          %377 = arith.addi %375, %376 : i32
          %378 = arith.extsi %377 : i32 to i64
          %379 = llvm.getelementptr %182[%378] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %371 = llvm.load %379 : !llvm.ptr -> i64
          %380 = arith.addi %370, %371 : i64
          llvm.store %380, %353 : i64, !llvm.ptr
          %381 = llvm.load %367 : !llvm.ptr -> i32
          %382 = arith.constant 1 : i32
          %383 = arith.addi %381, %382 : i32
          llvm.store %383, %367 : i32, !llvm.ptr
          cf.br ^bb72
        ^bb74:
        cf.br ^bb71
      ^bb70:
        cf.br ^bb71
      ^bb71:
      %384 = llvm.load %79 : !llvm.ptr -> i32
      %385 = arith.constant 1 : i32
      %386 = arith.addi %384, %385 : i32
      llvm.store %386, %79 : i32, !llvm.ptr
      cf.br ^bb66
    ^bb68:
    %387 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %388 = llvm.load %353 : !llvm.ptr -> i64
    %389 = llvm.call @printf(%387, %388) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%190) : (!llvm.ptr) -> ()
    func.call @free(%182) : (!llvm.ptr) -> ()
    func.call @free(%140) : (!llvm.ptr) -> ()
    func.call @free(%65) : (!llvm.ptr) -> ()
    func.call @free(%60) : (!llvm.ptr) -> ()
    %395 = arith.constant 0 : i32
    func.return %395 : i32
  }
}