# patterns.ludic - a msgid with holes ("Day {1}"): its literal pieces, how much English they pin # down, and a chain by its first (else last) four bytes so a lookup tries only its own kind function holes(s: string) -> int { let n = len(s) var h = 0 var i = 0 while i < n { if hole_at(s, i) >= 0 { h += 1 i = hole_end(s, i) continue } i += 1 } return h } function add_pattern(i18n_st: mut I18nState, id: string, tr: string) -> void { let p = i18n_st.pat_n i18n_st.pat_n += 1 let l0 = len(i18n_st.lits) let n = len(id) var seg = 0 var i = 0 var nl = 0 var score = 0 while i < n { let num = hole_at(id, i) if num >= 0 { push(i18n_st.lits, id[seg..i]) score += i - seg i18n_st.pat_ph[l0 + nl] = num nl += 1 i = hole_end(id, i) seg = i continue } i += 1 } push(i18n_st.lits, id[seg..n]) score += n - seg nl += 1 i18n_st.pat_l0[p] = l0 i18n_st.pat_nl[p] = nl i18n_st.pat_sc[p] = score push(i18n_st.pat_out, tr) chain(i18n_st, p, i18n_st.lits[l0], i18n_st.lits[l0 + nl - 1]) } function chain(i18n_st: mut I18nState, p: int, first: string, last: string) -> void { if len(first) >= 4 { let key: string = first[0..4] i18n_st.nx_p[p] = Dict.get_or(i18n_st.pfx, key, 0) Dict.set(i18n_st.pfx, key, p + 1) } else if len(last) >= 4 { let key: string = last[len(last) - 4..len(last)] i18n_st.nx_s[p] = Dict.get_or(i18n_st.sfx, key, 0) Dict.set(i18n_st.sfx, key, p + 1) } else { i18n_st.nx_g[p] = i18n_st.gen_head i18n_st.gen_head = p + 1 } } # a translation with its holes filled from caps, by number: a translation may reorder or drop them function fill_holes(i18n_st: I18nState, t: string, l0: int, nl: int, cs: []string) -> string { let n = len(t) var r = "" var seg = 0 var i = 0 while i < n { let num = hole_at(t, i) if num >= 0 { r = r + t[seg..i] for g in 0 .. nl - 1 { if i18n_st.pat_ph[l0 + g] == num { r = r + cs[g] } } i = hole_end(t, i) seg = i continue } i += 1 } return r + t[seg..n] }