{"id":44473999,"url":"https://github.com/jhinrichsen/adventofcode2017","last_synced_at":"2026-02-12T22:07:41.713Z","repository":{"id":57584187,"uuid":"133978563","full_name":"jhinrichsen/adventofcode2017","owner":"jhinrichsen","description":"Solutions for Advent of Code 2017, in Go","archived":false,"fork":false,"pushed_at":"2025-11-27T10:24:12.000Z","size":637,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-29T13:34:56.977Z","etag":null,"topics":["advent-of-code-2017","adventofcode2017","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jhinrichsen.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-05-18T16:23:51.000Z","updated_at":"2025-11-27T10:24:15.000Z","dependencies_parsed_at":"2022-09-10T06:50:58.098Z","dependency_job_id":null,"html_url":"https://github.com/jhinrichsen/adventofcode2017","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/jhinrichsen/adventofcode2017","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhinrichsen%2Fadventofcode2017","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhinrichsen%2Fadventofcode2017/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhinrichsen%2Fadventofcode2017/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhinrichsen%2Fadventofcode2017/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jhinrichsen","download_url":"https://codeload.github.com/jhinrichsen/adventofcode2017/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhinrichsen%2Fadventofcode2017/sbom","scorecard":{"id":518898,"data":{"date":"2025-08-11","repo":{"name":"github.com/jhinrichsen/adventofcode2017","commit":"42ab4a4a7096290d6566eb94fd70e479fa526556"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/25 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-20T02:27:55.327Z","repository_id":57584187,"created_at":"2025-08-20T02:27:55.327Z","updated_at":"2025-08-20T02:27:55.327Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29382969,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T20:34:40.886Z","status":"ssl_error","status_checked_at":"2026-02-12T20:23:00.490Z","response_time":55,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["advent-of-code-2017","adventofcode2017","golang"],"created_at":"2026-02-12T22:07:38.623Z","updated_at":"2026-02-12T22:07:41.707Z","avatar_url":"https://github.com/jhinrichsen.png","language":"Go","readme":"= Advent of code, 2017\n:doctype: book\n:toc:\n\nimage:https://godoc.org/gitlab.com/jhinrichsen/adventofcode2017?status.svg[\"godoc\", link=\"https://godoc.org/gitlab.com/jhinrichsen/adventofcode2017\"]\nimage:https://goreportcard.com/badge/gitlab.com/jhinrichsen/adventofcode2017[\"Go report card\", link=\"https://goreportcard.com/report/gitlab.com/jhinrichsen/adventofcode2017\"]\nimage:https://gitlab.com/jhinrichsen/adventofcode2017/badges/master/pipeline.svg[link=\"https://gitlab.com/jhinrichsen/adventofcode2017/-/commits/master\",title=\"pipeline status\"]\nimage:https://gitlab.com/jhinrichsen/adventofcode2017/badges/master/coverage.svg[link=\"https://gitlab.com/jhinrichsen/adventofcode2017/-/commits/master\",title=\"coverage report\"]\n\nimage::static/dashboard.png[AOC result for 2017]\n\n== Introduction\n\nI don't aim for speed of implementation, meaning being the first to submit.\nWhile Advent of Code emphasizes speed, I prioritize completeness and getting the first answer correct on the first try.\nThe number of tries is priority number one, so you will find exhaustive test cases.\nAlthough puzzle solutions are user specific, the test cases (`day{{NN}}_test.go`) contain the hardcoded results, so you can safely look at the solutions (`day{{NN}}.go`).\n\nAfter correctness, I use the problems for performance tuning: minimize runtime and memory allocations.\n\nimage::static/dev-compass-640.png[Source: devcompass.com]\n\nMy usual setup for Advent of Code according to https://treeform.github.io/devcompas/[Dev Compass].\n\n== Overview\n\nNumber of tries for a correct answer:\n\n|===\n| Day | Part 1 | Part 2\n| 1   |   1    |   1\n| 2   |   1    |   1\n| 3   |   1    |   3\n| 4   |   1    |   1\n| 5   |   1    |   1\n| 6   |   1    |   1\n| 7   |   1    |   1\n| 8   |   1    |   1\n| 9   |   1    |   1\n| 10  |   2    |   1\n| 11  |   1    |   1\n| 12  |   1    |   1\n| 13  |   1    |   1\n| 14  |   1    |   1\n| 15  |   1    |   1\n| 16  |   1    |   1\n| 17  |   1    |   1\n| 18  |   1    |   1\n| 19  |   1    |   1\n| 20  |   1    |   1\n| 21  |   1    |   1\n| 22  |   1    |   1\n| 23  |   1    |   1\n| 24  |   1    |   1\n| 25  |   1    |\n|===\n\n=== Benchmark runtime on different machines\n\nThis is the sum of all individual benchmarks.\nUse `make total` to create a unique report in `./benches` folder.\n\nOn Linux systems, `make total` automatically:\n\n1. Saves the current CPU governor setting\n2. Switches to performance mode for accurate benchmarking\n3. Runs all benchmarks\n4. Restores the original CPU governor setting\n\nThis ensures consistent, reproducible benchmark results by preventing CPU frequency scaling from affecting measurements.\n\n|===\n| OS    | Architecture | CPU | Runtime [second]\n| Linux |     Amd64    | AMD Ryzen 7 7840HS w/ Radeon 780M Graphics | 1.36s\n| Linux |     Amd64    | Intel Core i7-14700K | 1.22s\n|===\n\n== Day 1: Inverse Captcha\n\n== Day 2: Corruption Checksum\n\n== Day 3: Spiral Memory\n\n=== Part 2\n\nhttps://oeis.org/A141481\n\n----\n{\n\tm=5;\n\th=2*m-1;\n\tA=matrix(h, h);\n\tprint1(A[m, m]=1, \", \");\n\tT=[[1, 0], [1, -1], [0, -1], [ -1, -1], [ -1, 0], [ -1, 1], [0, 1], [1, 1]];\n\n\tfor (n=1, (h-2)^2-1,\n\t\tg=sqrtint(n);\n\t\tr=(g+g%2)\\2;\n\t\tq=4*r^2;\n\t\td=n-q;\n\t\tif (n\u003c=q-2*r,\n\t\t\tj=d+3*r;\n\t\t\tk=r, if(n\u003c=q, j=r; k=-d-r, if(n\u003c=q+2*r, j=r-d; k=-r, j=-r; k=d-3*r)));\n\t\tj=j+m;\n\t\tk=k+m;\n\t\ts=0;\n\t\tfor (c=1, 8, v=[j, k];\n\t\t\tv+=T[c];\n\t\t\ts=s+A[v[1], v[2]]);\n\n\t\tA[j, k]=s;\n\t\tprint1(s, \", \"))\n}\n----\n\nI know a thing or two about C but this is just too dense to translate to Go.\nThe PARI based implementation uses no blocks, but comma operators all over the place and for loops in the arguments of a for loop.\nI'll take the easy route and use the [https://oeis.org/A141481/b141481.txt] result table.\n\n== Day 4: High-Entropy Passphrases\n\n== Day 5: A Maze of Twisty Trampolines, All Alike\n\n== Day 6: Memory Reallocation\n\n== Day 7: Recursive Circus\n\n== Day 8: I Heard You Like Registers\n\n== Day 9: Stream Processing\n\n== Day 10: Knot Hash\n\nFirst try 52530 is too high.\nClassical off-by-one in index (0..255 \u003c-\u003e 1..256).\n\n== Day 11: Hex Ed\n\n== Day 12: Digital Plumber\n\n== Day 13: Packet Scanners\n\n== Day 14: Disk Defragmentation\n\n=== Performance Optimizations\n\nDay 14 requires computing 128 knot hashes (Day 10 Part 2), making it computationally intensive.\nThree optimization iterations were benchmarked:\n\n**b0 (baseline)**: Initial implementation\n- Switch statement for hex conversion\n- Inner loop for bit extraction\n- `fmt.Sprintf` for string formatting\n- Recursive flood fill\n\n**b1**: Parsing optimizations\n- Hex lookup table `[256]byte` instead of switch\n- Unrolled 4-bit extraction (no inner loop)\n- `strconv.Itoa` instead of `fmt.Sprintf`\n- Iterative flood fill with explicit stack\n\n**b2**: Inlined knot hash\n- Inlined Day10Part2 into NewDay14\n- Reused buffers across 128 iterations (lengths, list, dense)\n- Direct byte→bit conversion (no hex string intermediate)\n- Eliminated 128 function calls and string allocations\n\n==== Benchmark Results\n\nb0 → b1:\n----\n              │  b0.clean   │              b1.clean              │\n              │   sec/op    │   sec/op     vs base               │\nDay14Part1-16   4.803m ± 1%   4.816m ± 1%       ~ (p=0.631 n=10)\nDay14Part2-16   5.018m ± 1%   4.991m ± 1%  -0.55% (p=0.009 n=10)\n\n              │   b0.clean   │              b1.clean               │\n              │     B/op     │     B/op      vs base               │\nDay14Part1-16   48.65Ki ± 0%   44.76Ki ± 0%  -8.00% (p=0.000 n=10)\nDay14Part2-16   48.65Ki ± 0%   44.75Ki ± 0%  -8.01% (p=0.000 n=10)\n\n              │  b0.clean   │              b1.clean              │\n              │  allocs/op  │  allocs/op   vs base               │\nDay14Part1-16   2.568k ± 0%   2.340k ± 0%  -8.88% (p=0.000 n=10)\nDay14Part2-16   2.568k ± 0%   2.340k ± 0%  -8.88% (p=0.000 n=10)\n----\n\nb1 → b2:\n----\n              │  b1.clean   │              b2.clean              │\n              │   sec/op    │   sec/op     vs base               │\nDay14Part1-16   4.816m ± 1%   4.971m ± 1%  +3.22% (p=0.000 n=10)\nDay14Part2-16   4.991m ± 1%   5.113m ± 1%  +2.46% (p=0.000 n=10)\n\n              │   b1.clean   │               b2.clean               │\n              │     B/op     │     B/op      vs base                │\nDay14Part1-16   44.76Ki ± 0%   20.29Ki ± 0%  -54.67% (p=0.000 n=10)\nDay14Part2-16   44.75Ki ± 0%   20.29Ki ± 0%  -54.67% (p=0.000 n=10)\n\n              │   b1.clean   │              b2.clean              │\n              │  allocs/op   │ allocs/op   vs base                │\nDay14Part1-16   2340.00 ± 0%   36.00 ± 0%  -98.46% (p=0.000 n=10)\nDay14Part2-16   2340.00 ± 0%   36.00 ± 0%  -98.46% (p=0.000 n=10)\n----\n\nb0 → b2 (final):\n----\n              │  b0.clean   │              b2.clean              │\n              │   sec/op    │   sec/op     vs base               │\nDay14Part1-16   4.803m ± 1%   4.971m ± 1%  +3.49% (p=0.000 n=10)\nDay14Part2-16   5.018m ± 1%   5.113m ± 1%  +1.90% (p=0.000 n=10)\n\n              │   b0.clean   │               b2.clean               │\n              │     B/op     │     B/op      vs base                │\nDay14Part1-16   48.65Ki ± 0%   20.29Ki ± 0%  -58.30% (p=0.000 n=10)\nDay14Part2-16   48.65Ki ± 0%   20.29Ki ± 0%  -58.30% (p=0.000 n=10)\n\n              │   b0.clean   │              b2.clean              │\n              │  allocs/op   │ allocs/op   vs base                │\nDay14Part1-16   2568.00 ± 0%   36.00 ± 0%  -98.60% (p=0.000 n=10)\nDay14Part2-16   2568.00 ± 0%   36.00 ± 0%  -98.60% (p=0.000 n=10)\n----\n\nOverall: **-58% memory**, **-99% allocations** at the cost of +3% runtime.\nThe slight slowdown is likely due to larger function body reducing instruction cache efficiency, but the massive reduction in allocations significantly reduces GC pressure.\n\n== Day 15: Dueling Generators\n\n=== Performance Optimizations\n\nDay 15 implements linear congruential generators (LCG) requiring billions of modulo operations.\nTwo implementations were benchmarked to compare Go compiler optimizations versus hand-written assembly.\n\n**b0 (baseline)**: Pure Go implementation\n- Simple modulo arithmetic: `(a * factor) % 2147483647`\n- Bitwise comparison: `a\u00260xFFFF == b\u00260xFFFF`\n- 40 million iterations (Part 1), 5 million pairs (Part 2)\n\n**b1**: Hand-written AMD64 assembly\n- Direct use of MULQ and DIVQ instructions for modulo\n- Explicit register allocation (R14=a, R15=b, R8=matches)\n- Same algorithm as b0, translated to assembly\n\n==== Benchmark Results\n\n----\n              │    b0     │     b1      │\n              │  sec/op   │   sec/op    │\nDay15Part1-16   109ms       139ms         +27% slower\nDay15Part2-16   196ms       231ms         +18% slower\n\nBoth: 0 B/op, 0 allocs/op\n----\n\n**Surprising result**: The assembly version is significantly slower than Go.\n\nThe Go compiler's optimizer produces faster code because:\n- Modern Go compiler uses sophisticated optimizations for modulo operations\n- The DIV instruction on x86-64 is notoriously slow (not well-pipelined, high latency)\n- Go may use strength reduction or other algebraic optimizations\n- Assembly version suffers from instruction decode overhead\n\nThis demonstrates that hand-written assembly is not always faster on modern architectures with sophisticated compilers.\nBoth implementations achieve zero allocations.\n\n== Day 16: Permutation Promenade\n\n== Day 17: Spinlock\n\n=== Performance Optimizations\n\nDay 17 implements a circular buffer with 2017 insertions.\nThe maximum buffer size is known (2018 elements), enabling pre-allocation.\n\nTwo approaches were compared:\n\n**Array-backed linked list**: O(1) insertion\n- Pre-allocate array of 2018 nodes\n- Each node stores value and next index\n- Insert by updating pointers only\n- Requires ~661,000 pointer chases (328 steps × 2017 insertions)\n\n**Pre-allocated slice**: O(n) insertion with copy()\n- Pre-allocate with capacity 2018: `make([]int, 1, 2018)`\n- Insert using `append()` + `copy()` to shift elements\n- Uses highly optimized `memmove` (vectorized CPU instructions)\n\n==== Benchmark Results\n\n----\n                        │  Linked List  │  Slice + copy()  │\n                        │    sec/op     │     sec/op       │\nDay17Part1-16 (2017)      816μs           68μs              12x faster\n\nBoth: 0 B/op, 0 allocs/op\n----\n\n**Surprising result**: The O(n) slice approach is 12x faster than O(1) linked list.\n\nWhy slice + copy() wins:\n- `copy()` uses optimized `memmove` with vectorized SIMD instructions\n- Sequential memory access is cache-friendly (spatial locality)\n- CPU prefetcher can predict and preload data\n- Modern CPUs excel at bulk memory operations\n\nWhy linked list loses:\n- Pointer chasing causes random memory access (cache misses)\n- Each step requires dereferencing: `current = nodes[current].next`\n- Poor spatial locality defeats CPU cache hierarchy\n- No opportunity for SIMD vectorization\n\n**Lesson**: Algorithmic complexity (Big-O) doesn't predict real-world performance.\nHardware characteristics (cache, SIMD, prefetching) often dominate constant factors.\nThe \"theoretically slower\" O(n) algorithm wins due to hardware realities.\n\n== Day 18: Duet\n\n== Day 19: A Series of Tubes\n\n== Day 20: Particle Swarm\n\n== Day 21: Fractal Art\n\n----\n              │      b0      │               b1                │\n              │    sec/op    │   sec/op     vs base            │\nDay21Part1-16   184.4µ ± ∞ ¹   403.9µ ± ∞ ¹  +119.08% (p=1.000 n=1)\nDay21Part2-16   106.5m ± ∞ ¹   30.56m ± ∞ ¹   -71.31% (p=1.000 n=1)\n\n              │      b0       │               b1                │\n              │     B/op      │     B/op       vs base          │\nDay21Part1-16   236.1Ki ± ∞ ¹   240.0Ki ± ∞ ¹   +1.65% (p=1.000 n=1)\nDay21Part2-16   88.38Mi ± ∞ ¹   8.682Mi ± ∞ ¹  -90.18% (p=1.000 n=1)\n\n              │      b0      │               b1                │\n              │  allocs/op   │  allocs/op   vs base            │\nDay21Part1-16   6.725k ± ∞ ¹   6.424k ± ∞ ¹    -4.48% (p=1.000 n=1)\nDay21Part2-16   3.868M ± ∞ ¹   6.437k ± ∞ ¹   -99.83% (p=1.000 n=1)\n----\n\nOptimization: Replaced 2D `[][]byte` grid with 1D slice representation (`Grid1D`) for better cache locality.\n\nCombined with uint16 bitset pattern matching to eliminate string conversions and grid copying.\n\nPart2 improved 3.6x (107ms → 30ms) with 90% less memory and 99.8% fewer allocations (3.87M → 6.4k).\n\n== Day 22: Sporifica Virus\n\n----\n              │      b0       │               b1                │\n              │    sec/op     │   sec/op     vs base            │\nDay22Part1-16   418.2µ ± ∞ ¹   365.4µ ± ∞ ¹  -12.63% (p=1.000 n=1)\nDay22Part2-16   401.6m ± ∞ ¹   303.1m ± ∞ ¹  -24.53% (p=1.000 n=1)\n\n              │      b0       │               b1                │\n              │     B/op      │    B/op      vs base            │\nDay22Part1-16   106.3Ki ± ∞ ¹   89.67Ki ± ∞ ¹  -15.64% (p=1.000 n=1)\nDay22Part2-16   6.666Mi ± ∞ ¹   4.527Mi ± ∞ ¹  -32.10% (p=1.000 n=1)\n\n              │      b0      │              b1               │\n              │  allocs/op   │ allocs/op   vs base           │\nDay22Part1-16    23.00 ± ∞ ¹   26.00 ± ∞ ¹  +13.04% (p=1.000 n=1)\nDay22Part2-16    533.0 ± ∞ ¹   536.0 ± ∞ ¹   +0.56% (p=1.000 n=1)\n----\n\nOptimizations: packed int64 coordinates, inlined burst logic, direction delta lookup table.\n\n== Day 23: Coprocessor Conflagration\n\n== Day 24: Electromagnetic Moat\n\n== Day 25: The Halting Problem\n\n== Benchmarks\n\n----\ngoos: linux\ngoarch: amd64\npkg: gitlab.com/jhinrichsen/adventofcode2017\ncpu: Intel(R) Core(TM) i7-14700K\nBenchmarkDay01Part2\nBenchmarkDay01Part2-28    \t  210760\t      5516 ns/op\t    2048 B/op\t       1 allocs/op\nBenchmarkDay01Part1\nBenchmarkDay01Part1-28    \t  199624\t      5291 ns/op\t    2048 B/op\t       1 allocs/op\nBenchmarkDay02Part1\nBenchmarkDay02Part1-28    \t14416908\t        82.54 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay02Part2\nBenchmarkDay02Part2-28    \t  351073\t      3413 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay03Part1\nBenchmarkDay03Part1-28    \t      67\t  17072238 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay03Part2\nBenchmarkDay03Part2-28    \t64485747\t        18.58 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay04Part1\nBenchmarkDay04Part1-28    \t    8886\t    257762 ns/op\t  137056 B/op\t    1016 allocs/op\nBenchmarkDay04Part2\nBenchmarkDay04Part2-28    \t     703\t   1729363 ns/op\t  936510 B/op\t   18964 allocs/op\nBenchmarkDay05Part1\nBenchmarkDay05Part1-28    \t    3030\t    393158 ns/op\t    9472 B/op\t       1 allocs/op\nBenchmarkDay05Part2\nBenchmarkDay05Part2-28    \t      24\t  47536789 ns/op\t    9472 B/op\t       1 allocs/op\nBenchmarkDay06Part1\nBenchmarkDay06Part1-28    \t 8534137\t       140.4 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay06Part2\nBenchmarkDay06Part2-28    \t     285\t   4705583 ns/op\t 3544878 B/op\t      75 allocs/op\nBenchmarkDay07Part1\nBenchmarkDay07Part1-28    \t    2322\t    437938 ns/op\t  237720 B/op\t    1472 allocs/op\nBenchmarkDay07Part2\nBenchmarkDay07Part2-28    \t     896\t   1234042 ns/op\t  665520 B/op\t    2505 allocs/op\nBenchmarkDay08Part1\nBenchmarkDay08Part1-28    \t    4647\t    536285 ns/op\t  292168 B/op\t    2018 allocs/op\nBenchmarkDay08Part2\nBenchmarkDay08Part2-28    \t    2372\t    588171 ns/op\t  292168 B/op\t    2018 allocs/op\nBenchmarkDay09Part1\nBenchmarkDay09Part1-28    \t   25558\t     46511 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay09Part2\nBenchmarkDay09Part2-28    \t   35662\t     33686 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay10Part1\nBenchmarkDay10Part1-28    \t  276610\t      3895 ns/op\t    2048 B/op\t       1 allocs/op\nBenchmarkDay10Part2\nBenchmarkDay10Part2-28    \t   16506\t     72651 ns/op\t     576 B/op\t      19 allocs/op\nBenchmarkDay11Part1\nBenchmarkDay11Part1-28    \t   74281\t     15418 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay11Part2\nBenchmarkDay11Part2-28    \t   63178\t     18906 ns/op\t       0 B/op\t       0 allocs/op\nBenchmarkDay12Part1\nBenchmarkDay12Part1-28    \t    2065\t    979302 ns/op\t  555865 B/op\t    9707 allocs/op\nBenchmarkDay12Part2\nBenchmarkDay12Part2-28    \t     897\t   1444676 ns/op\t  694666 B/op\t    9725 allocs/op\n----\n\n\n== SAST (Static Application Security Testing)\n\nThis project uses custom SAST tooling in GitLab CI, optimized for the free tier.\n\n=== GitLab Free Tier Limitations\n\nGitLab's built-in SAST features (Security Dashboard, vulnerability management, merge request security widgets) require the Ultimate tier. On the free tier, SAST scans can run but results are only available as downloadable JSON artifacts.\n\n=== Current Setup\n\nOur CI pipeline uses:\n\n- Code Quality Reports: golangci-lint → JSON → banyansecurity/golint-convert → CodeClimate JSON format\n  * Displays findings in merge request Code Quality widget (available in free tier since GitLab 13.2)\n  * Shows code quality degradations/improvements directly in MRs\n\n- Test Reports: go-junit-report/v2 → JUnit XML format\n  * Integrates test results into GitLab's test report UI\n\n- Coverage Reports: gocover-cobertura → Cobertura XML format  \n  * Shows coverage metrics and trends in merge requests\n\n- Vulnerability Scanning: govulncheck (periodic, scheduled pipeline)\n  * Scans for known vulnerabilities in Go dependencies\n  * Runs on a schedule to catch newly disclosed vulnerabilities\n  * Results available as JSON artifacts (no UI on free tier)\n\n=== Note on Deprecation\n\nGitLab deprecated its built-in CodeClimate scanning template in version 17.3 (planned removal in 19.0). This only affects GitLab's bundled scanning engine. Custom pipelines that generate CodeClimate-format JSON (like ours) continue to work and are the recommended approach for free tier users.\n\nThe Code Quality widget will continue to display results from custom CodeClimate JSON reports.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhinrichsen%2Fadventofcode2017","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjhinrichsen%2Fadventofcode2017","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhinrichsen%2Fadventofcode2017/lists"}