Problem 796

Expected stopping time for drawing cards without replacement from 10 decks (540 cards) until every suit, rank, and deck design has appeared. Uses inclusion-exclusion over missing suits (a), ranks (b), and deck designs (c). For each combination the allowed card count is M(a,b,c) = (4-a)*(13-b)*(10-c) + 2*(10-c) and the coefficient is (-1)^(a+b+c+1) * C(4,a)*C(13,b)*C(10,c). E[T] = sum_M coeff[M] * S(M, N) where S(M,N) = sum_{k=0}^{N-1} C(M,k)/C(N,k), computed via the recurrence r_0 = 1, r_k = r_{k-1} * (M-k+1)/(N-k+1). Uses i128 fixed-point arithmetic (scale 10^24) for precision.

Answer43.20649061
Output43.20649061
StatusPASS
Native helperno
Runtime0 ms
Peak memory1072 KB
Time complexityO(n^3) (estimated)
Space complexityO(n) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)O(1)
Space complexityO(n)O(1)
ApproachFlow solutionClosed-form formula
VerdictSuboptimal

Flow source

# Project Euler 796: A Grand Shuffle
#
# Expected stopping time for drawing cards without replacement from 10 decks
# (540 cards) until every suit, rank, and deck design has appeared.
#
# Uses inclusion-exclusion over missing suits (a), ranks (b), and deck
# designs (c). For each combination the allowed card count is
#   M(a,b,c) = (4-a)*(13-b)*(10-c) + 2*(10-c)
# and the coefficient is (-1)^(a+b+c+1) * C(4,a)*C(13,b)*C(10,c).
#
# E[T] = sum_M coeff[M] * S(M, N)
# where S(M,N) = sum_{k=0}^{N-1} C(M,k)/C(N,k), computed via the recurrence
#   r_0 = 1, r_k = r_{k-1} * (M-k+1)/(N-k+1).
#
# Uses i128 fixed-point arithmetic (scale 10^24) for precision.

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

function pow10(n: i32) -> i128 {
    let mut result: i128 = 1
    for i in 0..n {
        result = result * (10 as i128)
    }
    return result
}

function binom(n: i32, k: i32) -> i64 {
    if k < 0 || k > n {
        return 0
    }
    let mut kk: i32 = k
    if kk > n - kk {
        kk = n - kk
    }
    let mut result: i64 = 1
    for i in 0..kk {
        result = result * ((n - i) as i64) / ((i + 1) as i64)
    }
    return result
}

function main() -> i32 {
    let N: i64 = 540
    let max_M: i32 = 540

    let SCALE: i128 = pow10(24)

    # Compute coefficients via inclusion-exclusion.
    let coeffs: ptr<i64> = calloc((max_M + 1) as i64, 8)
    if coeffs == null {
        return 1
    }
    for i in 0..((max_M + 1) as i64) {
        coeffs[i] = 0
    }

    for a in 0..5 {
        for b in 0..14 {
            for c in 0..11 {
                if a == 0 && b == 0 && c == 0 {
                    continue
                }
                let mut coef: i64 = binom(4, a) * binom(13, b) * binom(10, c)
                if (a + b + c) % 2 == 0 {
                    coef = -coef
                }
                let decks_left: i32 = 10 - c
                let M: i32 = (4 - a) * (13 - b) * decks_left + 2 * decks_left
                coeffs[M] = coeffs[M] + coef
            }
        }
    }

    # Compute S(M, N) for each M with nonzero coefficient, in fixed-point.
    let mut total_scaled: i128 = 0
    for M in 0..(max_M + 1) {
        if coeffs[M] == 0 {
            continue
        }

        let mut r: i128 = SCALE
        let mut s_val: i128 = SCALE

        let mut max_k: i64 = N - 1
        if (M as i64) < max_k {
            max_k = M as i64
        }

        for k in 1..(max_k + 1) {
            r = (r * ((M as i64 - k + 1) as i128)) / ((N - k + 1) as i128)
            s_val = s_val + r
        }

        total_scaled = total_scaled + (coeffs[M] as i128) * s_val
    }

    # Round to 8 decimal places and output.
    # rounded = (total_scaled + 5*10^15) / 10^16
    let half_round: i128 = pow10(15) * (5 as i128)
    let round_div: i128 = pow10(16)
    let ten_p_8: i128 = pow10(8)

    let rounded: i128 = (total_scaled + half_round) / round_div
    let int_part: i64 = (rounded / ten_p_8) as i64
    let frac_part: i64 = (rounded % ten_p_8) as i64
    printf("%lld.%08lld\n", int_part, frac_part)

    free(coeffs)
    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; }

__int128 pow10_i32(int32_t n);
int64_t binom_i32_i32(int32_t n, int32_t k);
int32_t main(void);



__int128 pow10_i32(int32_t n) {
    __int128 result = 1;
    int32_t __flow_step_1 = 1;
    for (int32_t i = 0; (0 <= n) ? i < n : i > n; i += (0 <= n) ? 1 : -1) {
        result = (result * ((__int128)(10)));
    }
    return result;
}

int64_t binom_i32_i32(int32_t n, int32_t k) {
    if ((k < 0 || k > n)) {
        return 0;
    }
    int32_t kk = k;
    if (kk > (n - kk)) {
        kk = (n - kk);
    }
    int64_t result = 1;
    int32_t __flow_step_2 = 1;
    for (int32_t i = 0; (0 <= kk) ? i < kk : i > kk; i += (0 <= kk) ? 1 : -1) {
        result = FLOW_CHECKED_DIV(((result * ((int64_t)((n - i))))), (((int64_t)((i + 1)))));
    }
    return result;
}

int32_t main(void) {
    int64_t N = 540;
    int32_t max_M = 540;
    __int128 SCALE = pow10_i32(24);
    int64_t* coeffs = (int64_t*)(calloc(((int64_t)((max_M + 1))), 8));
    if (coeffs == NULL) {
        return 1;
    }
    int32_t __flow_step_3 = 1;
    for (int32_t i = 0; (0 <= ((int64_t)((max_M + 1)))) ? i < ((int64_t)((max_M + 1))) : i > ((int64_t)((max_M + 1))); i += (0 <= ((int64_t)((max_M + 1)))) ? 1 : -1) {
        coeffs[i] = 0;
    }
    int32_t __flow_step_4 = 1;
    for (int32_t a = 0; (0 <= 5) ? a < 5 : a > 5; a += (0 <= 5) ? 1 : -1) {
        int32_t __flow_step_5 = 1;
        for (int32_t b = 0; (0 <= 14) ? b < 14 : b > 14; b += (0 <= 14) ? 1 : -1) {
            int32_t __flow_step_6 = 1;
            for (int32_t c = 0; (0 <= 11) ? c < 11 : c > 11; c += (0 <= 11) ? 1 : -1) {
                if (((a == 0 && b == 0) && c == 0)) {
                    continue;
                }
                int64_t coef = ((binom_i32_i32(4, a) * binom_i32_i32(13, b)) * binom_i32_i32(10, c));
                if (FLOW_CHECKED_MOD((((a + b) + c)), (2)) == 0) {
                    coef = (-coef);
                }
                int32_t decks_left = (10 - c);
                int32_t M = ((((4 - a) * (13 - b)) * decks_left) + (2 * decks_left));
                coeffs[M] = (coeffs[M] + coef);
            }
        }
    }
    __int128 total_scaled = 0;
    int32_t __flow_step_7 = 1;
    for (int32_t M = 0; (0 <= (max_M + 1)) ? M < (max_M + 1) : M > (max_M + 1); M += (0 <= (max_M + 1)) ? 1 : -1) {
        if (coeffs[M] == 0) {
            continue;
        }
        __int128 r = SCALE;
        __int128 s_val = SCALE;
        int64_t max_k = (N - 1);
        if (((int64_t)(M)) < max_k) {
            max_k = ((int64_t)(M));
        }
        int32_t __flow_step_8 = 1;
        for (int32_t k = 1; (1 <= (max_k + 1)) ? k < (max_k + 1) : k > (max_k + 1); k += (1 <= (max_k + 1)) ? 1 : -1) {
            r = FLOW_CHECKED_DIV(((r * ((__int128)(((((int64_t)(M)) - k) + 1))))), (((__int128)(((N - k) + 1)))));
            s_val = (s_val + r);
        }
        total_scaled = (total_scaled + (((__int128)(coeffs[M])) * s_val));
    }
    __int128 half_round = (pow10_i32(15) * ((__int128)(5)));
    __int128 round_div = pow10_i32(16);
    __int128 ten_p_8 = pow10_i32(8);
    __int128 rounded = FLOW_CHECKED_DIV(((total_scaled + half_round)), (round_div));
    int64_t int_part = ((int64_t)(FLOW_CHECKED_DIV((rounded), (ten_p_8))));
    int64_t frac_part = ((int64_t)(FLOW_CHECKED_MOD((rounded), (ten_p_8))));
    printf("%lld.%08lld\n", int_part, frac_part);
    free(coeffs);
    return 0;
}

Generated MLIR

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