Conjectures.io

5CAkr5…FDPt3n

MinerAcceptedInconclusive
Submitted 28 Sept 2026, 13:29 UTC5CAkr5wr3eyH5FnciQ4N7NqLN3a6UxpUxBozrbfC8EFDPt3nDigest 2e443e2355f94a46…

Not on the frontier · Speed gain not established · 6.296 α of 3,600 α earned

Time vs incumbent
0.63×
Mean compressed size
36.06%
Compression time
0.68 s
Size, byte-weighted
33.42%

Gate

  1. Rust checksPassed
  2. Lean proofPassed
  3. BenchmarkPassed
  4. AggregationPassed

Where it sits

  • Miner
  • Reference parser
  • Not admitted
  • Pareto frontier
  • Scoring limit
35%36%37%38%39%0.5×1×2×5×10×Time vs incumbent, log scaleMean compressed size, %Better

Standing

Share of pay
0%
Not paid
Speed gain not established
Bounty earned
6.296 α of 3,600 α

Scoring limits

  • Time vs incumbent0.63× · limit 10.0×Inside
  • Mean compressed size36.06% · limit 40.00%Inside

Admission

The measurements do not establish a speed improvement at the required confidence.

Speed test

Gain over hc-scan-endNot established

Estimate 0.75% · Lower bound -0.61% · needs to stay above 0.00% · 90% interval · 56 files across corpus-stage1, corpus-stage2

Time vs incumbent, 95% intervals

The frontier it was judged against

  • Miner
  • Reference parser
  • Not admitted
  • Pareto frontier
35%36%37%38%39%0.5×1×2×5×10×Time vs incumbent, log scaleMean compressed size, %Better

Source

parse.rs167 lines
//! # The slot: LZ77 parsing.
//!
//! This whole file is what a miner replaces. It must be compilable as its own
//! crate root (`charon rustc … src/parse.rs`), so it may not `use crate::…`.
//!
//! ## The contract
//!
//! `parse` reads `input` and writes a token stream into `out`, returning how many
//! tokens it wrote. A token is a `u32`:
//!
//! * `t < 256`                           — emit the literal byte `t`
//! * `t = 2^24 + (dist-1)*256 + (len-3)` — copy `len` bytes from `dist` back
//!
//! with `1 ≤ dist ≤ 32768` and `3 ≤ len ≤ 258`. The arithmetic encoding (rather
//! than shifts and masks) is deliberate: `Nat` `+`, `*`, `/` and `%` are what
//! `omega` reasons about on the Lean side, and `&&&`/`<<<` are not.
//!
//! The only thing that must be proved is that the token stream **decodes back to
//! `input`**, and that `parse` neither panics nor diverges.
//!
//! ## What is *not* constrained
//!
//! Nothing about the search. The hash chains below could be a suffix automaton, a
//! binary tree, or a full optimal-parse dynamic program and the proof would not
//! grow, because correctness rests only on the bytes `match_len` actually
//! compared before a match was emitted. `hash3_spec` in the proof says the hash
//! lands in range and says nothing whatever about what it computes.
//!
//! ## Prover-friendly Rust — the rules
//!
//! 1. No labelled `break`/`continue`, no early `return` from a nested loop, no
//!    trait objects, no iterator adapters. Indices, `while`, and plain `if`.
//! 2. Prefer `i <= n - k` to `i + k <= n`. In the extracted model a slice may
//!    have length `usize::MAX`, and then the *addition* overflows and the program
//!    is not total. The guarded subtraction cannot.
//! 3. Bound every array index with `%`, not `&`. `h % 32768 < 32768` is one
//!    `omega` step; the same fact about `h & 0x7fff` is a bitvector argument.
//! 4. Give every loop a decreasing counter that does not depend on the data. The
//!    chain walk below terminates because `probes` increases, not because the
//!    chain is acyclic — which it need not be.

pub const MIN_MATCH: usize = 3;
pub const MAX_MATCH: usize = 258;
pub const WINDOW: usize = 32768;
pub const HASH_SIZE: usize = 32768;

/// How far down a hash chain to look. The whole speed/ratio dial.
pub const MAX_PROBES: usize = 16;

/// Hash of the three bytes at a position. Any function of the right range works;
/// `% 32768` rather than `& 0x7fff` so that the index bound is arithmetic.
pub fn hash3(a: u8, b: u8, c: u8) -> usize {
    let x = (a as u32)
        .wrapping_mul(2654435761)
        .wrapping_add((b as u32).wrapping_mul(2246822519))
        .wrapping_add((c as u32).wrapping_mul(3266489917));
    ((x >> 15) % 32768) as usize
}

/// How many bytes match at `a` and `b`, up to `cap`. This is the *only* function
/// whose result the correctness proof depends on.
pub fn match_len(input: &[u8], a: usize, b: usize, cap: usize) -> usize {
    let mut l = 0usize;
    while l < cap && input[b + l] == input[a + l] {
        l += 1;
    }
    l
}

/// Walk a hash chain and return the best `(length, distance)` it finds.
///
/// A separate function rather than a loop inside `parse`, and that is **not**
/// cosmetic: Aeneas reports `Unimplemented` for a second loop nested in the body
/// of `parse`'s outer loop when that loop also reads a local array of the
/// enclosing scope. Lifting it out, with the array as a `&[u32]` parameter,
/// translates. Prover-friendly rule 5.
///
/// `prev` must be at least 32768 long; `parse` passes a `[u32; 32768]`.
pub fn find_match(
    input: &[u8],
    prev: &[u32],
    pos: usize,
    cap: usize,
    start: usize,
) -> (usize, usize) {
    let mut best_len = 0usize;
    let mut best_dist = 0usize;
    let mut cur = start;
    let mut probes = 0usize;
    while probes < 16 && cur > 0 && cur <= pos {
        let cpos = cur - 1;
        if pos - cpos <= 32768 {
            // A candidate can improve best_len only if its next byte agrees.
            // The cap guard also keeps both lookahead indices in bounds.
            if best_len < cap && input[cpos + best_len] == input[pos + best_len] {
                let l = match_len(input, cpos, pos, cap);
                if l > best_len {
                    best_len = l;
                    best_dist = pos - cpos;
                }
            }
            cur = prev[cpos % 32768] as usize;
        } else {
            // Everything further down the chain is older still, so the walk is
            // over. `cur = 0` ends it without a `break`.
            cur = 0;
        }
        probes += 1;
    }
    (best_len, best_dist)
}

/// Greedy matching over hash chains.
///
/// `head[h]` is the most recent position whose three bytes hash to `h`, plus one
/// (zero means "none"). `prev[p % 32768]` is the position before `p` in the same
/// chain, plus one. The `+ 1` is what lets zero be the sentinel without a
/// separate occupancy array, and `% 32768` keeps `prev` a fixed-size array rather
/// than one allocation per input.
pub fn parse(input: &[u8], out: &mut [u32]) -> usize {
    let n = input.len();
    let mut head = [0u32; 32768];
    let mut prev = [0u32; 32768];
    let mut ntok = 0usize;
    let mut pos = 0usize;
    let has3 = n >= 3;
    let lim = if has3 { n - 3 } else { 0 };
    while pos < n {
        let mut best_len = 0usize;
        let mut best_dist = 0usize;
        if has3 && pos <= lim {
            let h = hash3(input[pos], input[pos + 1], input[pos + 2]);
            let start = head[h] as usize;
            prev[pos % 32768] = head[h];
            head[h] = (pos + 1) as u32;

            let mut cap = n - pos;
            if cap > 258 {
                cap = 258;
            }
            // The chain walk. It terminates on `probes`, never on the chain
            // being acyclic — a truncated `as u32` can point anywhere, and the
            // byte comparison inside `match_len` is what keeps that harmless.
            let found = find_match(input, &prev, pos, cap, start);
            best_len = found.0;
            best_dist = found.1;
        }
        if best_len >= 3 {
            out[ntok] = 16777216u32 + ((best_dist - 1) as u32) * 256 + ((best_len - 3) as u32);
            ntok += 1;
            let end = pos + best_len;
            let mut k = pos + 1;
            while k < end && has3 && k <= lim {
                let h2 = hash3(input[k], input[k + 1], input[k + 2]);
                prev[k % 32768] = head[h2];
                head[h2] = (k + 1) as u32;
                k += 1;
            }
            pos = end;
        } else {
            out[ntok] = input[pos] as u32;
            ntok += 1;
            pos += 1;
        }
    }
    ntok
}
Parse.lean275 lines
import Lz77
import Slot

/-!
# The submission's proof

This file is what a **miner** writes. Everything it imports is fixed: `Lz77` is
the published contract and its lemmas, `Slot` is `charon`+`aeneas` output that the
verifier regenerates from the submitted `parse.rs` and never takes on trust.

The obligation is `parse_spec` at the bottom, whose statement is pinned by the
verifier. Nothing else in this file is checked, so a miner may restructure it
freely.
-/

namespace Submission
open Aeneas Aeneas.Std Result ControlFlow

set_option maxRecDepth 8192
set_option maxHeartbeats 1000000

open LZ77 (toks bytes bytes_length bytes_getElem! toks_update bytes_congr
  Matches Found Pending emitted emitted_ge emitted_lt pending_of_found emit_lit emit_match)

/-! ## The hash

Nothing about correctness depends on what `hash3` computes, only that it lands in
range: a wrong hash finds a worse match, never an invalid one. That is the
property that lets a miner replace the whole search with anything they like. -/

@[local step]
theorem hash3_spec (a b c : Std.U8) :
    slot.hash3 a b c ⦃ fun h => h.val < 32768 ⦄ := by
  prove_hash3

/-! ## The match-length loop

The one function whose *result* the proof depends on. Its postcondition is
precisely the hypothesis `LZ77.valid_match` wants, which is why the rest of the
submission never mentions `copyN`. -/

theorem match_len_loop_spec (input : Slice Std.U8) (a b cap l0 : Std.Usize)
    (ha : a.val + cap.val ≤ input.length) (hb : b.val + cap.val ≤ input.length)
    (hl0 : l0.val ≤ cap.val) (h0 : Matches input a.val b.val l0.val) :
    slot.match_len_loop input a b cap l0 ⦃ fun l =>
      l.val ≤ cap.val ∧ Matches input a.val b.val l.val ⦄ := by
  prove_match_len_loop

@[local step]
theorem match_len_spec (input : Slice Std.U8) (a b cap : Std.Usize)
    (ha : a.val + cap.val ≤ input.length) (hb : b.val + cap.val ≤ input.length) :
    slot.match_len input a b cap ⦃ fun l =>
      l.val ≤ cap.val ∧ Matches input a.val b.val l.val ⦄ := by
  prove_match_len

/-! ## The hash-insert loop

Pure bookkeeping: it writes into the search structure and nothing else, so its
postcondition is `True`. What still has to be proved is that it *terminates* and
never fails — which is the price of total correctness, and the reason a miner's
search structure is free but not free of obligations. -/

@[local step]
theorem parse_loop0_loop0_spec (input : Slice Std.U8)
    (head0 prev0 : Array Std.U32 32768#usize)
    (has30 : Bool) (lim «end» k0 : Std.Usize)
    (hlim : has30 = true → lim.val + 3 ≤ input.length) :
    slot.parse_loop0_loop0 input head0 prev0 has30 lim «end» k0
      ⦃ fun r => r.2.2 = true → lim.val + 3 ≤ input.length ⦄ := by
  rw [slot.parse_loop0_loop0]
  apply Std.loop.spec_decr_nat
    (measure := fun s => «end».val - s.2.2.2.val)
    (inv := fun s => s.2.2.1 = true → lim.val + 3 ≤ input.length)
  · rintro ⟨hd, pv, h3, k⟩ hinv
    have hmax : input.length ≤ Std.Usize.max := Std.Slice.length_ineq input
    simp only [slot.parse_loop0_loop0.body]
    step*
  · exact hlim

/-! ## The search

`find_match` walks a hash chain. Its whole postcondition is `Found`, and `Found`
is also its loop invariant — which is the point of the design: a submission that
replaces this with a suffix automaton or an optimal parse rewrites *this lemma
only*, and everything below is untouched.

Note what is **not** proved: nothing says the chain is acyclic, nothing says
`prev` points anywhere sensible, and nothing says the match found is the best one.
The walk terminates because `probes` counts up, and a wrong candidate is harmless
because `match_len` compares the bytes.
-/

theorem find_match_loop_spec (input : Slice Std.U8) (prev : Slice Std.U32)
    (n pos cap bl0 bd0 cur0 probes0 : Std.Usize)
    (hn : n.val = input.length) (hprev : prev.length = 32768)
    (hcap : pos.val + cap.val ≤ n.val) (hcap258 : cap.val ≤ 258)
    (h0 : Found input n pos bl0 bd0) (h0len : bl0.val ≤ cap.val) :
    slot.find_match_loop input prev pos cap bl0 bd0 cur0 probes0
      ⦃ fun r => Found input n pos r.1 r.2 ⦄ := by
  rw [slot.find_match_loop]
  apply Std.loop.spec_decr_nat
    (measure := fun s => slot.MAX_PROBES.val - s.2.2.2.val)
    (inv := fun s => Found input n pos s.1 s.2.1 ∧ s.1.val ≤ cap.val)
  · rintro ⟨bl, bd, cur, probes⟩ hinv
    simp only at hinv
    have hmax : input.length ≤ Std.Usize.max := Std.Slice.length_ineq input
    simp only [slot.find_match_loop.body]
    step*
    apply Std.WP.spec_bind (Pₘ := fun r => Found input n pos r.1 r.2.1 ∧ r.1.val ≤ cap.val)
    · split
      case isTrue hw =>
        apply Std.WP.spec_bind (Pₘ := fun r => Found input n pos r.1 r.2 ∧ r.1.val ≤ cap.val)
        · split
          case isTrue hlt =>
            step*
            refine ⟨?_, by scalar_tac⟩
            rcases Nat.lt_or_ge l.val 3 with h | h
            · exact Or.inl h
            · exact Or.inr ⟨h, by scalar_tac, by scalar_tac, by scalar_tac,
                by scalar_tac, by scalar_tac,
                by rw [show pos.val - i.val = cpos.val by scalar_tac]; exact l_post2⟩
          case isFalse => step*
        · rintro ⟨bl1, bd1⟩ hf
          step*
      case isFalse => exact hinv
    · rintro ⟨bl1, bd1, cur1⟩ hf
      step*
  · exact ⟨h0, h0len⟩

@[local step]
theorem find_match_spec (input : Slice Std.U8) (prev : Slice Std.U32)
    (n pos cap start : Std.Usize)
    (hn : n.val = input.length) (hprev : prev.length = 32768)
    (hcap : pos.val + cap.val ≤ n.val) (hcap258 : cap.val ≤ 258) :
    slot.find_match input prev pos cap start
      ⦃ fun r => Found input n pos r.1 r.2 ⦄ :=
  find_match_loop_spec input prev n pos cap 0#usize 0#usize start 0#usize
    hn hprev hcap hcap258 (Or.inl (by scalar_tac)) (by scalar_tac)

/-! ## The parse loop

The invariant is one line of English: *the tokens written so far decode to the
input consumed so far*. Everything else in it — `pos ≤ n`, `ntok ≤ pos`, the
buffer keeps its length — is bookkeeping that exists to make the writes legal. -/

theorem parse_loop0_spec (input : Slice Std.U8) (out0 : Slice Std.U32)
    (n lim : Std.Usize) (head0 prev0 : Array Std.U32 32768#usize)
    (ntok0 pos0 : Std.Usize) (has30 : Bool)
    (hn : n.val = input.length)
    (hout : input.length ≤ out0.length)
    (hlim : has30 = true → lim.val + 3 ≤ input.length)
    (hpos : pos0.val ≤ n.val) (hntok : ntok0.val ≤ pos0.val)
    (hdec : LZ77.decode (toks out0 ntok0.val) = some ((bytes input).take pos0.val)) :
    slot.parse_loop0 input out0 n head0 prev0 ntok0 pos0 has30 lim ⦃ fun r =>
      r.1.val ≤ input.length ∧ r.2.length = out0.length ∧
      LZ77.decode (toks r.2 r.1.val) = some (bytes input) ⦄ := by
  rw [slot.parse_loop0]
  apply Std.loop.spec_decr_nat
    (measure := fun s => n.val - s.2.2.2.2.1.val)
    (inv := fun s =>
      s.2.2.2.2.1.val ≤ n.val ∧ s.2.2.2.1.val ≤ s.2.2.2.2.1.val ∧
      s.1.length = out0.length ∧
      (s.2.2.2.2.2 = true → lim.val + 3 ≤ input.length) ∧
      LZ77.decode (toks s.1 s.2.2.2.1.val) = some ((bytes input).take s.2.2.2.2.1.val))
  · rintro ⟨out, hd, pv, ntok, pos, h3⟩ ⟨hp, hnt, hlen, hh3, hde⟩
    simp only at hp hnt hlen hh3 hde
    have hmax : input.length ≤ Std.Usize.max := Std.Slice.length_ineq input
    simp only [slot.parse_loop0.body]
    split
    case isTrue hposlt =>
      -- `step*` will not enter a `do` block whose first statement is an `if`, so
      -- the search is cut off here with its own postcondition. That is also the
      -- right division of labour: `Found` is everything the emission needs to
      -- know, and it is all a *different* search would have to establish.
      apply Std.WP.spec_bind (Pₘ := fun (r : (Array Std.U32 32768#usize) ×
          (Array Std.U32 32768#usize) × Std.Usize × Std.Usize) =>
        Found input n pos r.2.2.1 r.2.2.2)
      · split
        case isTrue hb3 =>
          split
          case isTrue hpl =>
            have hlim3 : lim.val + 3 ≤ input.length := hh3 hb3
            have hposl : pos.val ≤ lim.val := by scalar_tac
            step*
            -- `if b then ok x else ok y` is a choice of *value*; `step*` needs
            -- it in that form before it will go on.
            rw [show ((if cap > 258#usize then ok 258#usize else ok cap)
                  : Result Std.Usize)
                = ok (if cap > 258#usize then 258#usize else cap) from by
                  split <;> rfl]
            step*
            -- `find_match`'s two range preconditions, on the capped length
            · split <;> scalar_tac
            · split <;> scalar_tac
          case isFalse => exact Or.inl (by scalar_tac)
        case isFalse => exact Or.inl (by scalar_tac)
      · rintro ⟨head1, prev1, best_len, best_dist⟩ hfound
        have hntok_lt : ntok.val < out.length := by scalar_tac
        have hlim3 : h3 = true → lim.val + 3 ≤ input.length := hh3
        replace hfound : Found input n pos best_len best_dist := hfound
        simp only [Found] at hfound
        step*
        -- Unfolding `Found` before `step*` is worth doing: its side-goal solver
        -- then case-splits the disjunction itself and discharges all five range
        -- obligations of the token encoding, leaving only the two invariants.
        -- The invariant, after emitting a match.
        · rcases hfound with _ | ⟨hl3, hlmax, hend, hd1, hdmax, hdpos, hmatch⟩
          · exfalso; scalar_tac
          have htok : i6.val = LZ77.mkMatch best_dist.val best_len.val := by
            simp only [LZ77.mkMatch, LZ77.MATCH_BASE, i6_post, i3_post, i2_post,
              i5_post, i1_post, i4_post1, i_post1, Std.UScalar.cast_val_eq]
            scalar_tac
          refine ⟨by scalar_tac, by scalar_tac, by rw [s_post]; simpa [Std.Slice.set_val_eq] using hlen, head2_post, ?_,
            by scalar_tac⟩
          rw [s_post, show ntok1.val = ntok.val + 1 by scalar_tac,
            toks_update out ntok i6 hntok_lt, htok,
            show «end».val = pos.val + best_len.val by scalar_tac]
          refine LZ77.valid_match (bytes input) (toks out ntok.val) pos.val
            best_dist.val best_len.val hde hd1 hdpos
            (by simpa [LZ77.MAX_DIST] using hdmax) hl3
            (by simpa [LZ77.MAX_LEN] using hlmax) (by rw [bytes_length]; scalar_tac) ?_
          intro k hk
          exact (bytes_congr input _ _ (by scalar_tac) (by scalar_tac)
            (hmatch k hk)).symm
        -- The invariant, after emitting a literal.
        · have hposlen : pos.val < input.length := by scalar_tac
          have hval : i1.val = (bytes input)[pos.val]! := by
            rw [bytes_getElem! input pos.val hposlen, i1_post,
              Std.U8.cast_U32_val_eq, i_post]
          refine ⟨by scalar_tac, by scalar_tac, by rw [s_post]; simpa [Std.Slice.set_val_eq] using hlen, hlim3, ?_,
            by scalar_tac⟩
          rw [s_post, show ntok1.val = ntok.val + 1 by scalar_tac,
            toks_update out ntok i1 hntok_lt, hval,
            show pos1.val = pos.val + 1 by scalar_tac]
          exact LZ77.valid_lit (bytes input) (toks out ntok.val) pos.val hde
            (by rw [bytes_length]; scalar_tac) (by rw [← hval]; scalar_tac)
    case isFalse hge =>
      have hpn : pos.val = n.val := by scalar_tac
      refine ⟨by scalar_tac, hlen, ?_⟩
      rw [hde, hpn, hn]
      simp
  · exact ⟨hpos, hntok, rfl, hlim, hdec⟩

/-! ## The obligation

This is the statement the verifier pins. A submission is accepted when *this*
theorem, with this statement, elaborates against a `Slot` the verifier generated
itself, and `#print axioms` on it shows nothing but Lean's own three.

Read it as: `parse` writes `ntok` tokens into `out`, does not disturb its length,
never fails and always terminates, and **the tokens it wrote decode back to the
input**. -/

theorem parse_spec (input : Slice Std.U8) (out : Slice Std.U32)
    (hlen : input.length ≤ out.length) :
    slot.parse input out ⦃ fun r =>
      r.1.val ≤ input.length ∧
      r.2.length = out.length ∧
      LZ77.Valid (bytes input) (toks r.2 r.1.val) ⦄ := by
  rw [slot.parse]
  apply Std.WP.spec_bind (Pₘ := fun r => r.1 = true → r.2.val + 3 ≤ input.length)
  · split
    case isTrue h3 =>
      have hmax : input.length ≤ Std.Usize.max := Std.Slice.length_ineq input
      step*
    case isFalse h3 =>
      intro hc; exact absurd hc (by simp)
  · rintro ⟨has3, lim⟩ hlim
    exact parse_loop0_spec input out (Std.Slice.len input) lim
      (Std.Array.repeat 32768#usize 0#u32) (Std.Array.repeat 32768#usize 0#u32)
      0#usize 0#usize has3
      (by simp) hlen hlim (by scalar_tac) (by scalar_tac)
      (by simp [toks, LZ77.decode])

end Submission

Gate report

Show report
verifying [internal-path]
workspace: [internal-path]

0 intake      ok — 12: parse.rs, Parse.lean
1 policy      ok — source prefilters passed
2 static      ok — resolved operations: core::num::{impl}::wrapping_add, core::num::{impl}::wrapping_mul, core::slice::{impl}::len
3 extract     ok — charon+aeneas re-run by the verifier, no new axioms
4 statement   ok — `LZ77.Obligation slot.parse` typechecks (bwrap, 900s, 16384 MB)
5 axioms      ok — ['Classical.choice', 'Quot.sound', 'propext']; extraction intact
6 score       running…

Corpus: corpus-stage1
file                       raw  incumbent  submission
-----------------------------------------------------
binary.db.bin           500000      76338       79282
bundle.min.js.txt      1000000     301618      315263
catalog.xml.txt         500000      62314       65746
compressed.bin          300000     300194      300196
config.yaml.txt         400000      85384       88838
docs.md.txt             800000     226973      236532
dump.sql.txt            150000      20817       22308
genome.fasta            900000     292479      300190
images.bin              250000     223767      223973
lean.txt               1000000     235059      246184
machine-code.bin        500000     167357      171152
metrics.csv.txt        1300000     287282      301903
multibyte.txt          1100000     273630      283900
page.html.txt           600000     103618      108853
prose.txt              1500000     579041      604762
records.json.txt        400000      72255       73352
server.log              300000      29404       31422
source.c.txt           1400000     354325      368854
source.py.txt           600000     132748      138413
source.rs.txt           700000     134069      139922
sourcemap.map.txt       350000      68389       71993
sparse.bin               40000       1234        1235
tiny-app.log             28000        965         981
tiny-config.json.txt     12000       2107        2139
weights-bf16.bin        450000     362200      362212
weights-f16.bin         250000     216274      216285
weights-f32.bin         350000     284747      285093
weights-q8.bin          250000     236246      236246
-----------------------------------------------------
TOTAL                 15930000    5130834     5277229

method        bytes     ratio    lz77  encode   total  slowdown
-------------------------------------------------------------------------------------------------------------------
incumbent   5130834  1.00000x  0.481s  0.177s  0.658s     1.00x  the incumbent
submission  5277229  1.02853x  0.165s  0.176s  0.341s     0.52x  no improvement — 2.853% larger than the incumbent.

no improvement — 2.853% larger than the incumbent.
Corpus: corpus-stage2
corpus corpus-stage2 is held out; totals only.

method        bytes     ratio    lz77  encode   total  slowdown
-------------------------------------------------------------------------------------------------------------------
incumbent   5218788  1.00000x  0.494s  0.183s  0.679s     1.00x  the incumbent
submission  5371174  1.02920x  0.170s  0.181s  0.353s     0.52x  no improvement — 2.920% larger than the incumbent.

no improvement — 2.920% larger than the incumbent.