#!/usr/bin/env python3 """Reproduces the digit-cipher counts in cipher-arguments.html (Entries 1-4) on shakespeare-enquiry.org. One rule throughout: pool the digits of the page numbers in a group (a single page, an adjacent grid pair, or a consecutive run) and count the group as a hit if any non-empty subset of the pooled digits sums to the target. Nothing is discarded and no digit is added. Edit the data blocks and re-run.""" from itertools import combinations def digits(n): return [int(c) for c in str(n)] def hit(pages, target): ds = [d for p in pages for d in digits(p)] return any(sum(c) == target for r in range(1, len(ds)+1) for c in combinations(ds, r)) def solo(pages, t): return sum(hit([p], t) for p in pages) def runs(pages, t, k): return sum(hit(pages[i:i+k], t) for i in range(len(pages)-k+1)) def grid_pairs(pages, cols=4): cell = {i: (i//cols, i%cols) for i in range(len(pages))} def adj(a, b): (r1, c1), (r2, c2) = cell[a], cell[b] return (abs(r1-r2), abs(c1-c2)) in [(0, 1), (1, 0)] return [(a, b) for a in range(len(pages)) for b in range(a+1, len(pages)) if adj(a, b)] def grid_hits(pages, t, cols=4): return sum(hit([pages[a], pages[b]], t) for a, b in grid_pairs(pages, cols)) # --- data --- # 1623 First Folio catalogue: 35 plays (Troilus has no catalogue entry), section # page numbers, in catalogue order (Comedies, Histories, Tragedies). SHK_CATALOGUE = [1,20,38,61,85,101,122,145,163,185,208,230,255,304, 1,23,46,74,69,96,120,147,173,205, 1,31,53,80,109,131,152,283,310,346,369] # Every printed page number of the three sections (verified against the ISE/SLNSW facsimile). SHK_SECTIONS = [list(range(1,305)), list(range(1,233)), list(range(1,294))] # Jonson 1616 Workes: 13 section start-pages (from the collation formula), and the whole book. JON_TOC = [1,73,177,271,355,439,525,601,679,765,819,841,891] JON_BOOK = list(range(1,1016)) if __name__ == "__main__": print(f"Shakespeare ToC grid: {len(grid_pairs(SHK_CATALOGUE))} pairs; " f"17={grid_hits(SHK_CATALOGUE,17)} 6={grid_hits(SHK_CATALOGUE,6)}") tot = sum(len(s)-1 for s in SHK_SECTIONS) print(f"Shakespeare full sections: {tot} pairs; " f"17={sum(runs(s,17,2) for s in SHK_SECTIONS)} 6={sum(runs(s,6,2) for s in SHK_SECTIONS)}") print(f"Jonson full book: solo17={solo(JON_BOOK,17)} pairs17={runs(JON_BOOK,17,2)} " f"pairs6={runs(JON_BOOK,6,2)} triples17={runs(JON_BOOK,17,3)}") print(f"Jonson ToC: solo17={solo(JON_TOC,17)} adj pairs {len(grid_pairs(JON_TOC))}; " f"hits17={grid_hits(JON_TOC,17)}")